[MERGE] trunk
bzr revid: fva@openerp.com-20120522160110-l39lmwrtih9srnkg
This commit is contained in:
commit
ea2175525b
|
@ -36,19 +36,6 @@
|
|||
"static/lib/underscore/underscore.string.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/py.js/lib/py.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.notify/css/ui.notify.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.css",
|
||||
"static/src/css/data_export.css",
|
||||
|
|
|
@ -1287,25 +1287,6 @@ class SearchView(View):
|
|||
del filter['domain']
|
||||
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
|
||||
def add_to_dashboard(self, req, menu_id, action_id, context_to_save, domain, view_mode, name=''):
|
||||
ctx = common.nonliterals.CompoundContext(context_to_save)
|
||||
|
|
|
@ -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.
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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;
|
||||
}
|
|
@ -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
|
@ -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"> </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">»</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"> </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">»</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>
|
|
@ -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"> </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">»</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><script src="visualsearch.js" type="text/javascript"></script>
|
||||
<!--[if (!IE)|(gte IE 8)]><!-->
|
||||
<link href="visualsearch-datauri.css" media="screen" rel="stylesheet" type="text/css" />
|
||||
<!--<![endif]-->
|
||||
<!--[if lte IE 7]><!-->
|
||||
<link href="visualsearch.css" media="screen" rel="stylesheet" type="text/css" />
|
||||
<!--<![endif]--></code></pre>
|
||||
</li>
|
||||
<li>Initialize the Visual Search box:<br />
|
||||
<pre class="javascript"><code><div class="visual_search"></div>
|
||||
|
||||
<script type="text/javascript" charset="utf-8">
|
||||
$(document).ready(function() {
|
||||
var visualSearch = VS.init({
|
||||
container : $('.visual_search'),
|
||||
query : '',
|
||||
callbacks : {
|
||||
search : function(query, searchCollection) {},
|
||||
facetMatches : function(callback) {},
|
||||
valueMatches : function(facet, searchTerm, callback) {}
|
||||
}
|
||||
});
|
||||
});
|
||||
</script></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<country:"South Africa">,
|
||||
// FacetModel<account:5-samuel>,
|
||||
// FacetModel<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>
|
|
@ -1160,140 +1160,164 @@
|
|||
white-space: nowrap;
|
||||
}
|
||||
.openerp .oe_searchview {
|
||||
cursor: text;
|
||||
position: relative;
|
||||
float: right;
|
||||
}
|
||||
.openerp .oe_searchview .VS-search .VS-search-box {
|
||||
min-height: 0;
|
||||
padding: 0;
|
||||
width: 480px;
|
||||
padding-right: 20px;
|
||||
width: 410px;
|
||||
border: 1px solid #ababab;
|
||||
-moz-border-radius: 13px;
|
||||
-webkit-border-radius: 13px;
|
||||
border-radius: 13px;
|
||||
background: white;
|
||||
-moz-border-radius: 1em;
|
||||
-webkit-border-radius: 1em;
|
||||
border-radius: 1em;
|
||||
-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;
|
||||
-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2) inset;
|
||||
}
|
||||
.openerp .oe_searchview .VS-search .VS-icon {
|
||||
top: 6px;
|
||||
.openerp .oe_searchview.oe_focused {
|
||||
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 {
|
||||
left: 2px;
|
||||
top: 3px;
|
||||
height: 18px;
|
||||
width: 18px;
|
||||
.openerp .oe_searchview .oe_searchview_clear {
|
||||
cursor: pointer;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 22px;
|
||||
width: 15px;
|
||||
height: 100%;
|
||||
background: url(../img/attachments-close.png) center center no-repeat;
|
||||
}
|
||||
.openerp .oe_searchview .VS-search .VS-search-inner {
|
||||
margin: 0 40px 0 17px;
|
||||
padding: 1px 0;
|
||||
font-size: 13px;
|
||||
.openerp .oe_searchview .oe_searchview_unfold_drawer {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
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 {
|
||||
font-size: inherit;
|
||||
line-height: inherit;
|
||||
height: auto;
|
||||
padding: 0;
|
||||
.openerp .oe_searchview .oe_searchview_unfold_drawer:hover {
|
||||
color: #999999;
|
||||
}
|
||||
.openerp .oe_searchview .VS-search .VS-search-inner .VS-input-width-tester {
|
||||
font-size: inherit;
|
||||
padding: 0;
|
||||
.openerp .oe_searchview .oe_searchview_unfold_drawer:before {
|
||||
content: "◀";
|
||||
}
|
||||
.openerp .oe_searchview .VS-search .VS-search-inner .search_input {
|
||||
margin-left: 0;
|
||||
height: 22px;
|
||||
.openerp .oe_searchview .oe_searchview_facets:before {
|
||||
color: #cccccc;
|
||||
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 {
|
||||
height: inherit;
|
||||
margin: 0;
|
||||
.openerp .oe_searchview .oe_searchview_facets * {
|
||||
vertical-align: top;
|
||||
display: inline-block;
|
||||
line-height: 26px;
|
||||
}
|
||||
.openerp .oe_searchview .VS-search .VS-search-inner .search_facet {
|
||||
padding: 0;
|
||||
margin: 1px 0;
|
||||
.openerp .oe_searchview .oe_searchview_facets .oe_searchview_input, .openerp .oe_searchview .oe_searchview_facets .oe_searchview_facet {
|
||||
height: 26px;
|
||||
}
|
||||
.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;
|
||||
-moz-border-radius: 3px;
|
||||
-webkit-border-radius: 3px;
|
||||
border-radius: 3px;
|
||||
background: #f0f0fa;
|
||||
height: 18px;
|
||||
background: #8786b7;
|
||||
-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;
|
||||
-moz-box-shadow: 0 0 3px 1px #a6a6fe;
|
||||
-webkit-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 {
|
||||
margin-left: 0;
|
||||
.openerp .oe_searchview .oe_searchview_facets .oe_searchview_facet .oe_facet_values {
|
||||
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 {
|
||||
filter: alpha(opacity=100);
|
||||
opacity: 1;
|
||||
background-position: center 0;
|
||||
.openerp .oe_searchview .oe_searchview_facets .oe_searchview_facet .oe_facet_category, .openerp .oe_searchview .oe_searchview_facets .oe_searchview_facet .oe_facet_value {
|
||||
height: 24px;
|
||||
padding: 1px 0.1em;
|
||||
}
|
||||
.openerp .oe_searchview .VS-search .VS-search-inner .search_facet .category {
|
||||
padding: 0 4px 0 14px;
|
||||
.openerp .oe_searchview .oe_searchview_facets .oe_searchview_facet .oe_facet_category {
|
||||
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;
|
||||
}
|
||||
.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;
|
||||
height: 18px;
|
||||
line-height: 18px;
|
||||
padding: 0 4px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.openerp .oe_searchview .VS-search .VS-search-inner .search_facet .search_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 {
|
||||
.openerp .oe_searchview .oe_searchview_facets .oe_searchview_facet .oe_facet_remove {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
height: 100%;
|
||||
line-height: 23px;
|
||||
padding: 0 7px 0 4px;
|
||||
color: #4c4c4c;
|
||||
cursor: pointer;
|
||||
left: 2px;
|
||||
color: white;
|
||||
}
|
||||
.openerp .oe_searchview .VS-search .oe_vs_unfold_drawer:before {
|
||||
position: absolute;
|
||||
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_facets .oe_searchview_facet .oe_facet_remove:hover {
|
||||
color: #cccccc;
|
||||
}
|
||||
.openerp .oe_searchview.oe_searchview_open_drawer .oe_searchview_drawer {
|
||||
display: block;
|
||||
}
|
||||
.openerp .oe_searchview.oe_searchview_open_drawer .oe_searchview_unfold_drawer:before {
|
||||
content: "▼";
|
||||
}
|
||||
.openerp .oe_searchview .oe_searchview_drawer {
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
margin-top: 3px;
|
||||
top: 100%;
|
||||
right: 0;
|
||||
background-color: white;
|
||||
width: 480px;
|
||||
min-width: 100%;
|
||||
display: none;
|
||||
border: 1px solid #cccccc;
|
||||
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 {
|
||||
display: table;
|
||||
|
@ -1317,23 +1341,49 @@
|
|||
}
|
||||
.openerp .oe_searchview .oe_searchview_drawer .oe_searchview_filters li {
|
||||
list-style: none;
|
||||
padding: 3px 6px;
|
||||
height: 14px;
|
||||
padding: 3px 6px 3px 18px;
|
||||
line-height: 14px;
|
||||
color: inherit;
|
||||
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 {
|
||||
background-color: #f0f0fa;
|
||||
}
|
||||
.openerp .oe_searchview .oe_searchview_drawer .oe_searchview_advanced h4 {
|
||||
border-top: 1px solid #cccccc;
|
||||
margin: 5px 0 3px;
|
||||
.openerp .oe_searchview .oe_searchview_drawer .oe_searchview_custom form {
|
||||
display: none;
|
||||
}
|
||||
.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;
|
||||
position: relative;
|
||||
line-height: 1.2em;
|
||||
padding: 2px 20px 2px 25px;
|
||||
}
|
||||
.openerp .oe_searchview .oe_searchview_drawer .oe_searchview_advanced h4:before {
|
||||
content: "▸ ";
|
||||
.openerp .oe_searchview .oe_searchview_drawer .oe_searchview_custom li.oe_searchview_custom_private {
|
||||
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;
|
||||
}
|
||||
.openerp .oe_searchview .oe_searchview_drawer .oe_searchview_advanced button.oe_add_condition:before {
|
||||
|
@ -1349,13 +1399,25 @@
|
|||
.openerp .oe_searchview .oe_searchview_drawer .oe_searchview_advanced li {
|
||||
list-style: none;
|
||||
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: "▾ ";
|
||||
}
|
||||
.openerp .oe_searchview .oe_searchview_drawer .oe_searchview_advanced.oe_opened div {
|
||||
.openerp .oe_searchview .oe_searchview_drawer .oe_opened form {
|
||||
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 {
|
||||
float: left;
|
||||
margin: 1.5em;
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
$section-title-color: #8786b7
|
||||
$facets-border: #afafb6
|
||||
$facets-border-selected: #a6a6fe
|
||||
$hover-background: #f0f0fa
|
||||
$colour4: #8a89ba
|
||||
// }}}
|
||||
// Mixins {{{
|
||||
|
@ -74,6 +75,18 @@ $colour4: #8a89ba
|
|||
-webkit-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
|
||||
|
@ -918,132 +931,145 @@ $colour4: #8a89ba
|
|||
// }}}
|
||||
// SearchView xmo {{{
|
||||
.oe_searchview
|
||||
cursor: text
|
||||
position: relative
|
||||
float: right
|
||||
.VS-search
|
||||
.VS-search-box
|
||||
min-height: 0
|
||||
padding: 0
|
||||
width: 480px
|
||||
padding-right: 20px
|
||||
width: 410px
|
||||
border: 1px solid #ababab
|
||||
@include radius(13px)
|
||||
background: white
|
||||
@include radius(1em)
|
||||
@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
|
||||
left: 2px
|
||||
top: 3px
|
||||
height: 18px
|
||||
width: 18px
|
||||
|
||||
.VS-search-inner
|
||||
margin: 0 40px 0 17px
|
||||
padding: 1px 0
|
||||
font-size: 13px
|
||||
|
||||
input
|
||||
font-size: inherit
|
||||
line-height: inherit
|
||||
height: auto
|
||||
padding: 0
|
||||
|
||||
.VS-input-width-tester
|
||||
font-size: inherit
|
||||
padding: 0
|
||||
|
||||
.search_input
|
||||
margin-left: 0
|
||||
height: 22px
|
||||
input, .VS-input-width-tester
|
||||
height: inherit
|
||||
margin: 0
|
||||
|
||||
.search_facet
|
||||
padding: 0
|
||||
margin: 1px 0
|
||||
border: 1px solid $facets-border
|
||||
@include radius(3px)
|
||||
background: #f0f0fa
|
||||
height: 18px
|
||||
|
||||
&.is_selected
|
||||
&.oe_focused
|
||||
border-color: $facets-border-selected
|
||||
@include box-shadow(0 0 3px 1px $facets-border-selected)
|
||||
@include box-shadow(0 1px 2px $facets-border-selected inset)
|
||||
|
||||
.category
|
||||
margin-left: 0
|
||||
.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
|
||||
.oe_searchview_clear
|
||||
cursor: pointer
|
||||
position: absolute
|
||||
top: 0
|
||||
right: 22px
|
||||
width: 15px
|
||||
height: 100%
|
||||
background: url(../img/attachments-close.png) center center no-repeat
|
||||
|
||||
.search_facet_remove
|
||||
left: 1px
|
||||
top: 3px
|
||||
|
||||
.VS-icon-cancel
|
||||
right: 24px
|
||||
|
||||
.oe_vs_unfold_drawer
|
||||
.oe_searchview_unfold_drawer
|
||||
position: absolute
|
||||
top: 0
|
||||
right: 0
|
||||
height: 100%
|
||||
line-height: 23px
|
||||
line-height: 2.5em
|
||||
padding: 0 7px 0 4px
|
||||
color: #4c4c4c
|
||||
color: #ccc
|
||||
cursor: pointer
|
||||
&:hover
|
||||
color: #999
|
||||
&:before
|
||||
position: absolute
|
||||
top: 9px
|
||||
right: 8px
|
||||
width: 0
|
||||
height: 0
|
||||
display: inline-block
|
||||
content: ""
|
||||
content: "◀"
|
||||
|
||||
.oe_searchview_facets
|
||||
&:before
|
||||
color: #ccc
|
||||
font-family: "mnmliconsRegular"
|
||||
content: "r"
|
||||
font-size: 150%
|
||||
padding: 0 1px 0 3px
|
||||
display: inline
|
||||
|
||||
*
|
||||
vertical-align: top
|
||||
border-top: 5px solid #4c4c4c
|
||||
border-left: 5px solid transparent
|
||||
border-right: 5px solid transparent
|
||||
@include opacity(0.5)
|
||||
display: inline-block
|
||||
line-height: 26px
|
||||
|
||||
.oe_searchview_input, .oe_searchview_facet
|
||||
height: 26px
|
||||
&:focus
|
||||
outline: none
|
||||
|
||||
.oe_searchview_input
|
||||
padding: 0 3px
|
||||
|
||||
.oe_searchview_facet
|
||||
position: relative
|
||||
cursor: pointer
|
||||
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
|
||||
top: 0
|
||||
left: 2px
|
||||
color: white
|
||||
|
||||
&:hover
|
||||
color: #ccc
|
||||
|
||||
&.oe_searchview_open_drawer
|
||||
.oe_searchview_drawer
|
||||
display: block
|
||||
.oe_searchview_unfold_drawer:before
|
||||
content: "▼"
|
||||
|
||||
.oe_searchview_drawer
|
||||
position: absolute
|
||||
z-index: 1
|
||||
// detach drawer from field slightly
|
||||
margin-top: 3px
|
||||
top: 100%
|
||||
right: 0
|
||||
background-color: white
|
||||
width: 480px
|
||||
min-width: 100%
|
||||
display: none
|
||||
border: 1px solid #ccc
|
||||
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
|
||||
display: table
|
||||
|
@ -1065,24 +1091,44 @@ $colour4: #8a89ba
|
|||
|
||||
li
|
||||
list-style: none
|
||||
padding: 3px 6px
|
||||
height: 14px
|
||||
padding: 3px 6px 3px 18px
|
||||
line-height: 14px
|
||||
color: inherit
|
||||
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
|
||||
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
|
||||
h4
|
||||
border-top: 1px solid #ccc
|
||||
margin: 5px 0 3px
|
||||
cursor: pointer
|
||||
|
||||
h4:before
|
||||
content: "▸ "
|
||||
|
||||
div
|
||||
form
|
||||
display: none
|
||||
|
||||
button.oe_add_condition:before
|
||||
|
@ -1096,12 +1142,17 @@ $colour4: #8a89ba
|
|||
li
|
||||
list-style: none
|
||||
margin: 0
|
||||
white-space: nowrap
|
||||
|
||||
&.oe_opened
|
||||
.oe_opened
|
||||
h4:before
|
||||
content: "▾ "
|
||||
div
|
||||
form
|
||||
display: block
|
||||
|
||||
// delete buttons
|
||||
.oe_searchview_custom_delete, .searchview_extended_delete_prop
|
||||
@include text-to-icon("d")
|
||||
// }}}
|
||||
// Views Common {{{
|
||||
.oe_view_nocontent
|
||||
|
|
|
@ -111,7 +111,7 @@ instance.web.format_value = function (value, descriptor, value_if_empty) {
|
|||
return value_if_empty === undefined ? '' : value_if_empty;
|
||||
}
|
||||
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':
|
||||
return value.toString();
|
||||
case 'integer':
|
||||
|
@ -171,7 +171,7 @@ instance.web.parse_value = function (value, descriptor, value_if_empty) {
|
|||
case "":
|
||||
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':
|
||||
var tmp;
|
||||
do {
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -794,41 +794,36 @@ instance.web.FormView = instance.web.View.extend(_.extend({}, instance.web.form.
|
|||
var self = this;
|
||||
var fields = _.chain(this.fields)
|
||||
.map(function (field, name) {
|
||||
var value_ = field.get_value();
|
||||
var value = field.get_value();
|
||||
// ignore fields which are empty, invisible, readonly, o2m
|
||||
// or m2m
|
||||
if (!value_
|
||||
if (!value
|
||||
|| field.get('invisible')
|
||||
|| field.get("readonly")
|
||||
|| field.field.type === 'one2many'
|
||||
|| field.field.type === 'many2many') {
|
||||
return false;
|
||||
}
|
||||
var displayed;
|
||||
var displayed = value;
|
||||
switch (field.field.type) {
|
||||
case 'selection':
|
||||
displayed = _(field.values).find(function (option) {
|
||||
return option[0] === value_;
|
||||
return option[0] === value;
|
||||
})[1];
|
||||
break;
|
||||
case 'many2one':
|
||||
displayed = value_;
|
||||
break;
|
||||
default:
|
||||
displayed = value_;
|
||||
}
|
||||
|
||||
return {
|
||||
name: name,
|
||||
string: field.node_atts.string,
|
||||
value: value_,
|
||||
string: field.node.attrs.string || field.field.string,
|
||||
value: value,
|
||||
displayed: displayed,
|
||||
// convert undefined to false
|
||||
change_default: !!field.field.change_default
|
||||
}
|
||||
})
|
||||
.compact()
|
||||
.sortBy(function (field) { return field.node_atts.string; })
|
||||
.sortBy(function (field) { return field.string; })
|
||||
.value();
|
||||
var conditions = _.chain(fields)
|
||||
.filter(function (field) { return field.change_default; })
|
||||
|
|
|
@ -69,8 +69,7 @@ instance.web.ListView = instance.web.View.extend( /** @lends instance.web.ListVi
|
|||
this.groups.datagroup = new instance.web.DataGroup(
|
||||
this, this.model,
|
||||
dataset.get_domain(),
|
||||
dataset.get_context(),
|
||||
{});
|
||||
dataset.get_context());
|
||||
this.groups.datagroup.sort = this.dataset._sort;
|
||||
}
|
||||
|
||||
|
|
|
@ -615,6 +615,17 @@ instance.web.ViewManagerAction = instance.web.ViewManager.extend({
|
|||
case 'edit':
|
||||
this.do_edit_resource($option.data('model'), $option.data('id'), { name : $option.text() });
|
||||
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:
|
||||
if (val) {
|
||||
console.log("No debug handler for ", val);
|
||||
|
|
|
@ -264,32 +264,6 @@
|
|||
</div>
|
||||
</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">
|
||||
<ul class="oe_menu" t-if="widget.data">
|
||||
<li t-foreach="widget.data.data.children" t-as="menu">
|
||||
|
@ -409,7 +383,10 @@
|
|||
</tr>
|
||||
<tr>
|
||||
<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_footer">
|
||||
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 value="fields">View Fields</option>
|
||||
<option value="fvg">Fields View Get</option>
|
||||
<option value="manage_filters">Manage Filters</option>
|
||||
<t t-if="view_manager.session.uid === 1">
|
||||
<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>
|
||||
|
@ -998,11 +976,12 @@
|
|||
</div>
|
||||
</t>
|
||||
<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">
|
||||
<input type="text" class="oe_datepicker_container" disabled="disabled" style="display: none;"/>
|
||||
<input type="text"
|
||||
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}"
|
||||
/><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"/>
|
||||
|
@ -1318,7 +1297,31 @@
|
|||
</t>
|
||||
|
||||
<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 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">
|
||||
<option class="oe-filters-title" value="">Filters</option>
|
||||
<optgroup label="-- Filters --">
|
||||
|
@ -1375,8 +1378,9 @@
|
|||
<t t-esc="attrs.string"/>
|
||||
</button>
|
||||
<ul t-name="SearchView.filters">
|
||||
<li t-foreach="widget.filters" t-as="filter">
|
||||
<t t-esc="filter.attrs.string or filter.attrs.name or 'Ω'"/>
|
||||
<li t-foreach="widget.filters" t-as="filter"
|
||||
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>
|
||||
</ul>
|
||||
<t t-name="SearchView.filters.facet">
|
||||
|
@ -1471,8 +1475,22 @@
|
|||
</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">
|
||||
<h4>Advanced Search...</h4>
|
||||
<h4>Advanced Search</h4>
|
||||
<form>
|
||||
<ul>
|
||||
|
||||
|
@ -1494,26 +1512,23 @@
|
|||
</select>
|
||||
<select class="searchview_extended_prop_op"/>
|
||||
<span class="searchview_extended_prop_value"/>
|
||||
<a class="searchview_extended_delete_prop"
|
||||
href="javascript:void(0)"><span> </span></a>
|
||||
<button type="button" class="searchview_extended_delete_prop">Delete</button>
|
||||
</li>
|
||||
</t>
|
||||
<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-name="SearchView.extended_search.proposition.empty">
|
||||
<span t-att-id="widget.element_id"></span>
|
||||
<span/>
|
||||
</t>
|
||||
<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-name="SearchView.extended_search.proposition.float">
|
||||
<input type="number" t-att-id="widget.element_id" class="field_float" step="0.01"/>
|
||||
</t>
|
||||
<t t-name="SearchView.extended_search.proposition.boolean">
|
||||
<input type="number" class="field_float" step="0.01"/>
|
||||
</t>
|
||||
<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">
|
||||
<option t-att-value="element[0]"><t t-esc="element[1]"/></option>
|
||||
</t>
|
||||
|
|
|
@ -66,7 +66,7 @@ $(document).ready(function () {
|
|||
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 d1 = $.Deferred(), d2 = $.Deferred(),
|
||||
|
@ -80,7 +80,7 @@ $(document).ready(function () {
|
|||
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(),
|
||||
done1 = false, done2 = false,
|
||||
fail1 = false, fail2 = false;
|
||||
|
@ -104,7 +104,7 @@ $(document).ready(function () {
|
|||
ok(!fail2);
|
||||
}, 400);
|
||||
});
|
||||
asyncTest('Fail mis-ordered flag, sync', 4, function () {
|
||||
asyncTest('Fail mis-ordered flag, async', 4, function () {
|
||||
var dm = new openerp.web.DropMisordered(true),
|
||||
done1 = false, done2 = false,
|
||||
fail1 = false, fail2 = false;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -10,9 +10,10 @@
|
|||
|
||||
<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/backbone/backbone.js" type="text/javascript"></script>
|
||||
|
||||
<!-- 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.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/rpc.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>
|
||||
|
|
|
@ -247,6 +247,7 @@ texinfo_documents = [
|
|||
# How to display URL addresses: 'footnote', 'no', or 'inline'.
|
||||
#texinfo_show_urls = 'footnote'
|
||||
|
||||
todo_include_todos = True
|
||||
|
||||
# Example configuration for intersphinx: refer to the Python standard library.
|
||||
intersphinx_mapping = {
|
||||
|
|
|
@ -16,14 +16,14 @@ Contents:
|
|||
async
|
||||
rpc
|
||||
|
||||
search-view
|
||||
|
||||
Older stuff
|
||||
-----------
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
search-view
|
||||
|
||||
getting-started
|
||||
production
|
||||
widgets
|
||||
|
|
|
@ -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
|
||||
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 is based on `Backbone
|
||||
<http://documentcloud.github.com/backbone/>`_ and makes significant
|
||||
use of Backbone's models and views. As a result, understanding the
|
||||
implementation of the OpenERP Web 6.2 search view also requires a
|
||||
basic understanding of Backbone.
|
||||
[#previous]_.
|
||||
|
||||
As does VisualSearch, the new search view is based on `Backbone`_ and
|
||||
makes significant use of Backbone's models and collections (OpenERP
|
||||
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::
|
||||
|
||||
This document may mention *fetching* data. This is a shortcut for
|
||||
"returning a deferred to [whatever is being fetched]". Unless
|
||||
further noted, the function or method may opt to return nothing by
|
||||
fetching ``null`` (which can easily be done by returning
|
||||
``$.when(null)``, which simply wraps the ``null`` in a Deferred).
|
||||
"returning a :js:class:`Deferred` to [whatever is being
|
||||
fetched]". Unless further noted, the function or method may opt to
|
||||
return nothing by fetching ``null`` (which can easily be done by
|
||||
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
|
||||
:js:class:`VS.model.SearchQuery`, a backbone Collection holding
|
||||
instances of the :js:class:`VS.model.SearchFacet` backbone Model.
|
||||
The primary component of search views, as with all other OpenERP
|
||||
views, are inputs. The search view has two types of inputs — filters
|
||||
and fields — but only one is easly customizable: fields.
|
||||
|
||||
Backbone models can hold any number of informal properties interacted
|
||||
with through the :js:func:`~Backbone.Model.get` and
|
||||
:js:func:`~Backbone.Model.set` methods. VisualSearch reserves three
|
||||
such properties for its behavior, these properties *must* be correctly
|
||||
set on all search facets created programmatically:
|
||||
The mapping from OpenERP field types (and widgets) to search view
|
||||
objects is stored in the ``openerp.web.search.fields``
|
||||
:js:class:`~openerp.web.Registry` where new field types and widgets
|
||||
can be added.
|
||||
|
||||
``app``
|
||||
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.
|
||||
Search view inputs have four main roles:
|
||||
|
||||
``category``
|
||||
the *name* of the facet, displayed in the first section of a facet
|
||||
view.
|
||||
Loading defaults
|
||||
++++++++++++++++
|
||||
|
||||
``value``
|
||||
the *displayed value* of the facet, it is directly printed to the
|
||||
right of the category.
|
||||
Once the search view has initialized all its inputs, it will call
|
||||
:js:func:`~openerp.web.search.Input.facet_for_defaults` on each input,
|
||||
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
|
||||
to associate with facet objects:
|
||||
This method should fetch a :js:class:`~openerp.web.search.Facet` (or
|
||||
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``
|
||||
the search field instance which created the facet, used when the
|
||||
search view needs to serialize the facets.
|
||||
A default implementation is provided which checks if ``defaults``
|
||||
contains a non-falsy value for the field's ``@name`` and calls
|
||||
:js:func:`openerp.web.search.Input.facet_for` with that value.
|
||||
|
||||
``json``
|
||||
the "logical" value of the facet, can be absent if the logical and
|
||||
"printable" values of the facet are the same (e.g. for a basic text
|
||||
field).
|
||||
There is no default implementation of
|
||||
:js:func:`openerp.web.search.Input.facet_for` [#no_impl]_, but
|
||||
:js:class:`openerp.web.search.Field` provides one, which uses the
|
||||
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
|
||||
name stands for json-compatible value, it is not a JSON-encoded
|
||||
string).
|
||||
Providing completions
|
||||
+++++++++++++++++++++
|
||||
|
||||
.. 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
|
||||
model, :js:class:`VS.model.SearchFacet` has been extended with a
|
||||
:js:func:`~VS.model.SearchFacet.value` method
|
||||
This method should take a single argument (the string being typed by
|
||||
the user) and should fetch an ``Array`` of possible completions
|
||||
[#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
|
||||
order to get the logical value of a facet.
|
||||
``label``
|
||||
|
||||
.. 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
|
||||
new search facet *view*. By default this is not supported by
|
||||
VisualSearch, and requires monkey-patching
|
||||
:js:func:`VS.ui.SearchBox.renderFacet`.
|
||||
``facet``
|
||||
|
||||
This patch should not alter any behavior if
|
||||
:js:attr:`~VS.options.callbacks.make_facet` is not used.
|
||||
Either a :js:class:`~openerp.web.search.Facet` object or (more
|
||||
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
|
||||
when the :js:class:`~VS.ui.SearchBox` needs to create a search
|
||||
input view. It requires monkey-patching
|
||||
:js:func:`VS.ui.SearchBox.renderSearchInput`.
|
||||
Providing drawer/supplementary UI
|
||||
+++++++++++++++++++++++++++++++++
|
||||
|
||||
Finally, :js:func:`VS.ui.SearchBox.searchEvent` is monkey-patched to
|
||||
get rid of its serialize/load round-tripping of facet data: the
|
||||
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.
|
||||
For some inputs (fields or not), interaction via autocompletion may be
|
||||
awkward or even impossible.
|
||||
|
||||
.. 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
|
||||
correctly serializes facet categories containing spaces but is
|
||||
unable to load them back in. It also does not handle facets with
|
||||
*empty* categories correctly.
|
||||
.. Found no good type-based way to handle this, since there is no MI
|
||||
(so no type-tagging) and it's possible for both Field and non-Field
|
||||
input to be put into the drawer, for whatever reason (e.g. some
|
||||
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
|
||||
:js:func:`openerp.web.search.Input.facet_for_defaults` on each of its
|
||||
inputs with the ``defaults`` mapping of key:values (where each key
|
||||
corresponds to an input). This method should look into the
|
||||
``defaults`` mapping and fetch the field's default value as a
|
||||
:js:class:`~VS.models.SearchFacet` if applicable.
|
||||
By default, :js:func:`~openerp.web.search.Input.in_drawer` returns the
|
||||
value of :js:attr:`~openerp.web.search.Input._in_drawer`, which is
|
||||
``false``. The behavior can be toggled either by redefining the
|
||||
attribute to ``true`` (either on the class or on the input), or by
|
||||
overriding :js:func:`~openerp.web.search.Input.in_drawer` itself.
|
||||
|
||||
The default implementation is to check if there is a default value for
|
||||
the current input's name (via
|
||||
: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`.
|
||||
The input will be rendered in the full width of the drawer, it will be
|
||||
started only once (per view).
|
||||
|
||||
There is no built-in (default) implementation of
|
||||
:js:func:`openerp.web.search.Input.facet_for`. This method should
|
||||
fetch the :js:class:`~VS.models.SearchFacet` corresponding to the
|
||||
"raw" value passed as argument.
|
||||
.. todo:: drawer API (if a widget wants to close the drawer in some
|
||||
way), part of the low-level SearchView API/interactions?
|
||||
|
||||
Providing auto-completion
|
||||
-------------------------
|
||||
|
||||
An important component of the unified search view is the faceted
|
||||
autocompletion pane. In order to provide good user and developer
|
||||
experiences, this pane is pluggable (value-wise): each and every
|
||||
control of the search view can check for (and provide) categorized
|
||||
auto-completions for a given value being typed by the user.
|
||||
.. todo:: handle filters and filter groups via a "driver" input which
|
||||
dynamically collects, lays out and renders filters? =>
|
||||
exercises drawer thingies
|
||||
|
||||
This is done by implementing
|
||||
: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/>`_.
|
||||
Programmatic interactions: internal model
|
||||
-----------------------------------------
|
||||
|
||||
Because the search view uses a custom renderer for its completion, it
|
||||
was possible to fix some incompatibilities between the attributes of
|
||||
completion items and VisualSearch's facet model:
|
||||
This new searchview is built around an instance of
|
||||
:js:class:`~openerp.web.search.SearchQuery` available as
|
||||
: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
|
||||
search facet objects. They should have all the properties of a search
|
||||
facet (as described above) and can have one more optional property:
|
||||
``label``.
|
||||
.. js:class:: openerp.web.search.SearchQuery
|
||||
|
||||
When rendering an item in the list, the renderer will first try to use
|
||||
the ``label`` property if it exists (``label`` can contain HTML and
|
||||
will be inserted as-is, so it can bold or emphasize some of its
|
||||
elements), if it does not the ``value`` property will be used.
|
||||
The current search query of the search view, provides convenience
|
||||
behaviors for manipulating :js:class:`~openerp.web.search.Facet`
|
||||
on top of the usual `backbone collection`_ methods.
|
||||
|
||||
.. note:: the ``app`` key should not be specified on completion item,
|
||||
it will be set automatically when the search view creates
|
||||
the facet from the item.
|
||||
The query ensures all of its facets contain at least one
|
||||
:js:class:`~openerp.web.search.FacetValue` instance. Otherwise,
|
||||
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
|
||||
titles are similar to completion items but only have a ``category``
|
||||
property. They will be rendered in a different style and can not be
|
||||
selected in the auto-completion (they will be skipped).
|
||||
Overridden from the base ``add`` method so that adding a facet
|
||||
which is *already* in the collection will merge the value of
|
||||
the new facet into the old one rather than add a second facet
|
||||
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
|
||||
*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.
|
||||
.. js:function:: openerp.web.search.SearchQuery.toggle(value, options)
|
||||
|
||||
If an input *may* fetch more than one completion item, it *should*
|
||||
prepend a section title (using its own name) to the completion items.
|
||||
Convenience method for toggling facet values in a query:
|
||||
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
|
||||
-----------------------------
|
||||
|
||||
Ultimately, the point of the search view is to allow searching. In
|
||||
OpenERP this is done via :ref:`domains <openerpserver:domains>`. On
|
||||
the other hand, the OpenERP Web 6.2 search view's state is modelled
|
||||
after a collection of :js:class:`~VS.model.SearchFacet`, and each
|
||||
the other hand, the OpenERP Web 7 search view's state is modelled
|
||||
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
|
||||
the domains it produces [#]_.
|
||||
the domains it produces [#special]_.
|
||||
|
||||
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
|
||||
:js:func:`~openerp.web.search.Input.get_domain` and
|
||||
:js:func:`~openerp.web.search.Input.get_context`. Each takes a
|
||||
:js:class:`~VS.model.SearchFacet` and returns whatever it's supposed
|
||||
to generate (a domain or a context, respectively). Either can return
|
||||
``null`` if the current value does not map to a domain or context, and
|
||||
can throw an :js:class:`~openerp.web.search.Invalid` exception if the
|
||||
value is not valid at all for the field.
|
||||
:js:class:`~openerp.web.search.Facet` and returns whatever it's
|
||||
supposed to generate (a domain or a context, respectively). Either can
|
||||
return ``null`` if the current value does not map to a domain or
|
||||
context, and can throw an :js:class:`~openerp.web.search.Invalid`
|
||||
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
|
||||
-------
|
||||
|
||||
.. todo:: merge in changelog instead
|
||||
.. todo:: merge in changelog instead?
|
||||
|
||||
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
|
||||
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
|
||||
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_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
|
||||
|
||||
* :js:func:`~openerp.web.search.Input.get_groupby` has been added. It returns
|
||||
|
@ -271,19 +442,16 @@ Filters
|
|||
Fields
|
||||
++++++
|
||||
|
||||
* ``get_value`` now takes a :js:class:`~VS.model.SearchFacet` (instead
|
||||
of taking no argument).
|
||||
|
||||
A default implementation is provided as
|
||||
:js:func:`openerp.web.search.Field.get_value` and simply calls
|
||||
:js:func:`VS.model.SearchFacet.value`.
|
||||
* ``get_value`` has been replaced by
|
||||
:js:func:`~openerp.web.search.Field.value_from` as it now takes a
|
||||
:js:class:`~openerp.web.search.FacetValue` argument (instead of no
|
||||
argument). It provides a default implementation returning the
|
||||
``value`` property of its argument.
|
||||
|
||||
* The third argument to
|
||||
:js:func:`~openerp.web.search.Field.make_domain` is now the
|
||||
:js:class:`~VS.model.SearchFacet` received by
|
||||
:js:func:`~openerp.web.search.Field.get_domain`, so child classes
|
||||
have all the information they need to derive the "right" resulting
|
||||
domain.
|
||||
:js:func:`~openerp.web.search.Field.make_domain` is now a
|
||||
:js:class:`~openerp.web.search.FacetValue` so child classes have all
|
||||
the information they need to derive the "right" resulting domain.
|
||||
|
||||
Custom filters
|
||||
++++++++++++++
|
||||
|
@ -300,12 +468,82 @@ Many To One
|
|||
:js:func:`openerp.web.search.ManyToOneField.setup_autocomplete` has
|
||||
been removed.
|
||||
|
||||
.. [#] the library code is untouched, all patching is performed in the
|
||||
Search view's implementation module. Changes to the
|
||||
VisualSearch code should only update the library to new
|
||||
revisions or releases.
|
||||
.. [#] search view fields may also bundle context data to add to the
|
||||
Advanced Search
|
||||
+++++++++++++++
|
||||
|
||||
* The advanced search is now a more standard
|
||||
:js:class:`~openerp.web.search.Input` configured to be rendered in
|
||||
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:
|
||||
https://github.com/documentcloud/visualsearch/commit/3fca87101d
|
||||
|
|
Loading…
Reference in New Issue