[Merged] Merged trunk.
bzr revid: jra@tinyerp.com-20121120125207-gjcwghoi0fjm88q4
This commit is contained in:
commit
c1da45fade
|
@ -18,7 +18,7 @@ This module provides the core of the OpenERP Web Client.
|
|||
"static/lib/datejs/parser.js",
|
||||
"static/lib/datejs/sugarpak.js",
|
||||
"static/lib/datejs/extras.js",
|
||||
"static/lib/jquery/jquery-1.8.2.js",
|
||||
"static/lib/jquery/jquery-1.8.3.js",
|
||||
"static/lib/jquery.MD5/jquery.md5.js",
|
||||
"static/lib/jquery.form/jquery.form.js",
|
||||
"static/lib/jquery.validate/jquery.validate.js",
|
||||
|
|
|
@ -82,7 +82,6 @@ def rjsmin(script):
|
|||
return result
|
||||
|
||||
def db_list(req):
|
||||
dbs = []
|
||||
proxy = req.session.proxy("db")
|
||||
dbs = proxy.list()
|
||||
h = req.httprequest.environ['HTTP_HOST'].split(':')[0]
|
||||
|
@ -92,7 +91,7 @@ def db_list(req):
|
|||
return dbs
|
||||
|
||||
def db_monodb(req):
|
||||
# if only one db is listed returns it else return False
|
||||
# if only one db exists, return it else return False
|
||||
try:
|
||||
dbs = db_list(req)
|
||||
if len(dbs) == 1:
|
||||
|
@ -189,14 +188,14 @@ def module_installed_bypass_session(dbname):
|
|||
sorted_modules = module_topological_sort(modules)
|
||||
return sorted_modules
|
||||
|
||||
def module_boot(req):
|
||||
def module_boot(req, db=None):
|
||||
server_wide_modules = openerp.conf.server_wide_modules or ['web']
|
||||
serverside = []
|
||||
dbside = []
|
||||
for i in server_wide_modules:
|
||||
if i in openerpweb.addons_manifest:
|
||||
serverside.append(i)
|
||||
monodb = db_monodb(req)
|
||||
monodb = db or db_monodb(req)
|
||||
if monodb:
|
||||
dbside = module_installed_bypass_session(monodb)
|
||||
dbside = [i for i in dbside if i not in serverside]
|
||||
|
@ -273,9 +272,9 @@ def fs2web(path):
|
|||
"""convert FS path into web path"""
|
||||
return '/'.join(path.split(os.path.sep))
|
||||
|
||||
def manifest_glob(req, addons, key):
|
||||
def manifest_glob(req, extension, addons=None, db=None):
|
||||
if addons is None:
|
||||
addons = module_boot(req)
|
||||
addons = module_boot(req, db=db)
|
||||
else:
|
||||
addons = addons.split(',')
|
||||
r = []
|
||||
|
@ -285,19 +284,21 @@ def manifest_glob(req, addons, key):
|
|||
continue
|
||||
# ensure does not ends with /
|
||||
addons_path = os.path.join(manifest['addons_path'], '')[:-1]
|
||||
globlist = manifest.get(key, [])
|
||||
globlist = manifest.get(extension, [])
|
||||
for pattern in globlist:
|
||||
for path in glob.glob(os.path.normpath(os.path.join(addons_path, addon, pattern))):
|
||||
r.append((path, fs2web(path[len(addons_path):])))
|
||||
return r
|
||||
|
||||
def manifest_list(req, mods, extension):
|
||||
def manifest_list(req, extension, mods=None, db=None):
|
||||
if not req.debug:
|
||||
path = '/web/webclient/' + extension
|
||||
if mods is not None:
|
||||
path += '?mods=' + mods
|
||||
elif db:
|
||||
path += '?db=' + db
|
||||
return [path]
|
||||
files = manifest_glob(req, mods, extension)
|
||||
files = manifest_glob(req, extension, addons=mods, db=db)
|
||||
i_am_diabetic = req.httprequest.environ["QUERY_STRING"].count("no_sugar") >= 1 or \
|
||||
req.httprequest.environ.get('HTTP_REFERER', '').count("no_sugar") >= 1
|
||||
if i_am_diabetic:
|
||||
|
@ -366,13 +367,13 @@ def load_actions_from_ir_values(req, key, key2, models, meta):
|
|||
Values = req.session.model('ir.values')
|
||||
actions = Values.get(key, key2, models, meta, context)
|
||||
|
||||
return [(id, name, clean_action(req, action))
|
||||
return [(id, name, clean_action(req, action, context))
|
||||
for id, name, action in actions]
|
||||
|
||||
def clean_action(req, action, do_not_eval=False):
|
||||
def clean_action(req, action, context, do_not_eval=False):
|
||||
action.setdefault('flags', {})
|
||||
|
||||
context = req.session.eval_context(req.context)
|
||||
context = context or {}
|
||||
eval_ctx = req.session.evaluation_context(context)
|
||||
|
||||
if not do_not_eval:
|
||||
|
@ -598,14 +599,14 @@ class Home(openerpweb.Controller):
|
|||
_cp_path = '/'
|
||||
|
||||
@openerpweb.httprequest
|
||||
def index(self, req, s_action=None, **kw):
|
||||
js = "\n ".join('<script type="text/javascript" src="%s"></script>' % i for i in manifest_list(req, None, 'js'))
|
||||
css = "\n ".join('<link rel="stylesheet" href="%s">' % i for i in manifest_list(req, None, 'css'))
|
||||
def index(self, req, s_action=None, db=None, **kw):
|
||||
js = "\n ".join('<script type="text/javascript" src="%s"></script>' % i for i in manifest_list(req, 'js', db=db))
|
||||
css = "\n ".join('<link rel="stylesheet" href="%s">' % i for i in manifest_list(req, 'css', db=db))
|
||||
|
||||
r = html_template % {
|
||||
'js': js,
|
||||
'css': css,
|
||||
'modules': simplejson.dumps(module_boot(req)),
|
||||
'modules': simplejson.dumps(module_boot(req, db=db)),
|
||||
'init': 'var wc = new s.web.WebClient();wc.appendTo($(document.body));'
|
||||
}
|
||||
return r
|
||||
|
@ -619,19 +620,19 @@ class WebClient(openerpweb.Controller):
|
|||
|
||||
@openerpweb.jsonrequest
|
||||
def csslist(self, req, mods=None):
|
||||
return manifest_list(req, mods, 'css')
|
||||
return manifest_list(req, 'css', mods=mods)
|
||||
|
||||
@openerpweb.jsonrequest
|
||||
def jslist(self, req, mods=None):
|
||||
return manifest_list(req, mods, 'js')
|
||||
return manifest_list(req, 'js', mods=mods)
|
||||
|
||||
@openerpweb.jsonrequest
|
||||
def qweblist(self, req, mods=None):
|
||||
return manifest_list(req, mods, 'qweb')
|
||||
return manifest_list(req, 'qweb', mods=mods)
|
||||
|
||||
@openerpweb.httprequest
|
||||
def css(self, req, mods=None):
|
||||
files = list(manifest_glob(req, mods, 'css'))
|
||||
def css(self, req, mods=None, db=None):
|
||||
files = list(manifest_glob(req, 'css', addons=mods, db=db))
|
||||
last_modified = get_last_modified(f[0] for f in files)
|
||||
if req.httprequest.if_modified_since and req.httprequest.if_modified_since >= last_modified:
|
||||
return werkzeug.wrappers.Response(status=304)
|
||||
|
@ -669,8 +670,8 @@ class WebClient(openerpweb.Controller):
|
|||
last_modified, checksum)
|
||||
|
||||
@openerpweb.httprequest
|
||||
def js(self, req, mods=None):
|
||||
files = [f[0] for f in manifest_glob(req, mods, 'js')]
|
||||
def js(self, req, mods=None, db=None):
|
||||
files = [f[0] for f in manifest_glob(req, 'js', addons=mods, db=db)]
|
||||
last_modified = get_last_modified(files)
|
||||
if req.httprequest.if_modified_since and req.httprequest.if_modified_since >= last_modified:
|
||||
return werkzeug.wrappers.Response(status=304)
|
||||
|
@ -682,8 +683,8 @@ class WebClient(openerpweb.Controller):
|
|||
last_modified, checksum)
|
||||
|
||||
@openerpweb.httprequest
|
||||
def qweb(self, req, mods=None):
|
||||
files = [f[0] for f in manifest_glob(req, mods, 'qweb')]
|
||||
def qweb(self, req, mods=None, db=None):
|
||||
files = [f[0] for f in manifest_glob(req, 'qweb', addons=mods, db=db)]
|
||||
last_modified = get_last_modified(files)
|
||||
if req.httprequest.if_modified_since and req.httprequest.if_modified_since >= last_modified:
|
||||
return werkzeug.wrappers.Response(status=304)
|
||||
|
@ -1236,9 +1237,10 @@ class DataSet(openerpweb.Controller):
|
|||
|
||||
@openerpweb.jsonrequest
|
||||
def call_button(self, req, model, method, args, domain_id=None, context_id=None):
|
||||
context = req.session.eval_context(req.context)
|
||||
action = self.call_common(req, model, method, args, domain_id, context_id)
|
||||
if isinstance(action, dict) and action.get('type') != '':
|
||||
return clean_action(req, action)
|
||||
return clean_action(req, action, context)
|
||||
return False
|
||||
|
||||
@openerpweb.jsonrequest
|
||||
|
@ -1617,10 +1619,11 @@ class Action(openerpweb.Controller):
|
|||
_cp_path = "/web/action"
|
||||
|
||||
@openerpweb.jsonrequest
|
||||
def load(self, req, action_id, do_not_eval=False):
|
||||
def load(self, req, action_id, do_not_eval=False, eval_context=None):
|
||||
Actions = req.session.model('ir.actions.actions')
|
||||
value = False
|
||||
context = req.session.eval_context(req.context)
|
||||
eval_context = req.session.eval_context(nonliterals.CompoundContext(context, eval_context or {}))
|
||||
|
||||
try:
|
||||
action_id = int(action_id)
|
||||
|
@ -1641,15 +1644,16 @@ class Action(openerpweb.Controller):
|
|||
ctx.update(context)
|
||||
action = req.session.model(action_type).read([action_id], False, ctx)
|
||||
if action:
|
||||
value = clean_action(req, action[0], do_not_eval)
|
||||
value = clean_action(req, action[0], eval_context, do_not_eval)
|
||||
return value
|
||||
|
||||
@openerpweb.jsonrequest
|
||||
def run(self, req, action_id):
|
||||
context = req.session.eval_context(req.context)
|
||||
return_action = req.session.model('ir.actions.server').run(
|
||||
[action_id], req.session.eval_context(req.context))
|
||||
if return_action:
|
||||
return clean_action(req, return_action)
|
||||
return clean_action(req, return_action, context)
|
||||
else:
|
||||
return False
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*!
|
||||
* jQuery JavaScript Library v1.8.2
|
||||
* jQuery JavaScript Library v1.8.3
|
||||
* http://jquery.com/
|
||||
*
|
||||
* Includes Sizzle.js
|
||||
|
@ -9,7 +9,7 @@
|
|||
* Released under the MIT license
|
||||
* http://jquery.org/license
|
||||
*
|
||||
* Date: Thu Sep 20 2012 21:13:05 GMT-0400 (Eastern Daylight Time)
|
||||
* Date: Tue Nov 13 2012 08:20:33 GMT-0500 (Eastern Standard Time)
|
||||
*/
|
||||
(function( window, undefined ) {
|
||||
var
|
||||
|
@ -186,7 +186,7 @@ jQuery.fn = jQuery.prototype = {
|
|||
selector: "",
|
||||
|
||||
// The current version of jQuery being used
|
||||
jquery: "1.8.2",
|
||||
jquery: "1.8.3",
|
||||
|
||||
// The default length of a jQuery object is 0
|
||||
length: 0,
|
||||
|
@ -999,8 +999,10 @@ jQuery.Callbacks = function( options ) {
|
|||
(function add( args ) {
|
||||
jQuery.each( args, function( _, arg ) {
|
||||
var type = jQuery.type( arg );
|
||||
if ( type === "function" && ( !options.unique || !self.has( arg ) ) ) {
|
||||
list.push( arg );
|
||||
if ( type === "function" ) {
|
||||
if ( !options.unique || !self.has( arg ) ) {
|
||||
list.push( arg );
|
||||
}
|
||||
} else if ( arg && arg.length && type !== "string" ) {
|
||||
// Inspect recursively
|
||||
add( arg );
|
||||
|
@ -1149,14 +1151,7 @@ jQuery.extend({
|
|||
deferred = {};
|
||||
|
||||
// Keep pipe for back-compat
|
||||
//promise.pipe = promise.then;
|
||||
promise.pipe = function() {
|
||||
if (window.console) {
|
||||
console.error && console.error("$.Deferred().pipe() is deprecated. Use .then() instead.");
|
||||
console.trace && console.trace();
|
||||
}
|
||||
return promise.then.apply(this, arguments);
|
||||
};
|
||||
promise.pipe = promise.then;
|
||||
|
||||
// Add list-specific methods
|
||||
jQuery.each( tuples, function( i, tuple ) {
|
||||
|
@ -1260,24 +1255,23 @@ jQuery.support = (function() {
|
|||
clickFn,
|
||||
div = document.createElement("div");
|
||||
|
||||
// Preliminary tests
|
||||
// Setup
|
||||
div.setAttribute( "className", "t" );
|
||||
div.innerHTML = " <link/><table></table><a href='/a'>a</a><input type='checkbox'/>";
|
||||
|
||||
// Support tests won't run in some limited or non-browser environments
|
||||
all = div.getElementsByTagName("*");
|
||||
a = div.getElementsByTagName("a")[ 0 ];
|
||||
a.style.cssText = "top:1px;float:left;opacity:.5";
|
||||
|
||||
// Can't get basic test support
|
||||
if ( !all || !all.length ) {
|
||||
if ( !all || !a || !all.length ) {
|
||||
return {};
|
||||
}
|
||||
|
||||
// First batch of supports tests
|
||||
// First batch of tests
|
||||
select = document.createElement("select");
|
||||
opt = select.appendChild( document.createElement("option") );
|
||||
input = div.getElementsByTagName("input")[ 0 ];
|
||||
|
||||
a.style.cssText = "top:1px;float:left;opacity:.5";
|
||||
support = {
|
||||
// IE strips leading whitespace when .innerHTML is used
|
||||
leadingWhitespace: ( div.firstChild.nodeType === 3 ),
|
||||
|
@ -1319,7 +1313,7 @@ jQuery.support = (function() {
|
|||
// Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7)
|
||||
getSetAttribute: div.className !== "t",
|
||||
|
||||
// Tests for enctype support on a form(#6743)
|
||||
// Tests for enctype support on a form (#6743)
|
||||
enctype: !!document.createElement("form").enctype,
|
||||
|
||||
// Makes sure cloning an html5 element does not cause problems
|
||||
|
@ -2224,26 +2218,25 @@ jQuery.extend({
|
|||
},
|
||||
select: {
|
||||
get: function( elem ) {
|
||||
var value, i, max, option,
|
||||
index = elem.selectedIndex,
|
||||
values = [],
|
||||
var value, option,
|
||||
options = elem.options,
|
||||
one = elem.type === "select-one";
|
||||
|
||||
// Nothing was selected
|
||||
if ( index < 0 ) {
|
||||
return null;
|
||||
}
|
||||
index = elem.selectedIndex,
|
||||
one = elem.type === "select-one" || index < 0,
|
||||
values = one ? null : [],
|
||||
max = one ? index + 1 : options.length,
|
||||
i = index < 0 ?
|
||||
max :
|
||||
one ? index : 0;
|
||||
|
||||
// Loop through all the selected options
|
||||
i = one ? index : 0;
|
||||
max = one ? index + 1 : options.length;
|
||||
for ( ; i < max; i++ ) {
|
||||
option = options[ i ];
|
||||
|
||||
// Don't return options that are disabled or in a disabled optgroup
|
||||
if ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null) &&
|
||||
(!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" )) ) {
|
||||
// oldIE doesn't update selected after form reset (#2551)
|
||||
if ( ( option.selected || i === index ) &&
|
||||
// Don't return options that are disabled or in a disabled optgroup
|
||||
( jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null ) &&
|
||||
( !option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" ) ) ) {
|
||||
|
||||
// Get the specific value for the option
|
||||
value = jQuery( option ).val();
|
||||
|
@ -2258,11 +2251,6 @@ jQuery.extend({
|
|||
}
|
||||
}
|
||||
|
||||
// Fixes Bug #2551 -- select.val() broken in IE after form.reset()
|
||||
if ( one && !values.length && options.length ) {
|
||||
return jQuery( options[ index ] ).val();
|
||||
}
|
||||
|
||||
return values;
|
||||
},
|
||||
|
||||
|
@ -3240,7 +3228,7 @@ jQuery.removeEvent = document.removeEventListener ?
|
|||
|
||||
if ( elem.detachEvent ) {
|
||||
|
||||
// #8545, #7054, preventing memory leaks for custom events in IE6-8 –
|
||||
// #8545, #7054, preventing memory leaks for custom events in IE6-8
|
||||
// detachEvent needed property on element, by name of that event, to properly expose it to GC
|
||||
if ( typeof elem[ name ] === "undefined" ) {
|
||||
elem[ name ] = null;
|
||||
|
@ -3732,7 +3720,8 @@ var cachedruns,
|
|||
delete cache[ keys.shift() ];
|
||||
}
|
||||
|
||||
return (cache[ key ] = value);
|
||||
// Retrieve with (key + " ") to avoid collision with native Object.prototype properties (see Issue #157)
|
||||
return (cache[ key + " " ] = value);
|
||||
}, cache );
|
||||
},
|
||||
|
||||
|
@ -4266,13 +4255,13 @@ Expr = Sizzle.selectors = {
|
|||
},
|
||||
|
||||
"CLASS": function( className ) {
|
||||
var pattern = classCache[ expando ][ className ];
|
||||
if ( !pattern ) {
|
||||
pattern = classCache( className, new RegExp("(^|" + whitespace + ")" + className + "(" + whitespace + "|$)") );
|
||||
}
|
||||
return function( elem ) {
|
||||
return pattern.test( elem.className || (typeof elem.getAttribute !== strundefined && elem.getAttribute("class")) || "" );
|
||||
};
|
||||
var pattern = classCache[ expando ][ className + " " ];
|
||||
|
||||
return pattern ||
|
||||
(pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) &&
|
||||
classCache( className, function( elem ) {
|
||||
return pattern.test( elem.className || (typeof elem.getAttribute !== strundefined && elem.getAttribute("class")) || "" );
|
||||
});
|
||||
},
|
||||
|
||||
"ATTR": function( name, operator, check ) {
|
||||
|
@ -4518,7 +4507,7 @@ Expr = Sizzle.selectors = {
|
|||
|
||||
"focus": function( elem ) {
|
||||
var doc = elem.ownerDocument;
|
||||
return elem === doc.activeElement && (!doc.hasFocus || doc.hasFocus()) && !!(elem.type || elem.href);
|
||||
return elem === doc.activeElement && (!doc.hasFocus || doc.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex);
|
||||
},
|
||||
|
||||
"active": function( elem ) {
|
||||
|
@ -4526,11 +4515,11 @@ Expr = Sizzle.selectors = {
|
|||
},
|
||||
|
||||
// Positional types
|
||||
"first": createPositionalPseudo(function( matchIndexes, length, argument ) {
|
||||
"first": createPositionalPseudo(function() {
|
||||
return [ 0 ];
|
||||
}),
|
||||
|
||||
"last": createPositionalPseudo(function( matchIndexes, length, argument ) {
|
||||
"last": createPositionalPseudo(function( matchIndexes, length ) {
|
||||
return [ length - 1 ];
|
||||
}),
|
||||
|
||||
|
@ -4538,14 +4527,14 @@ Expr = Sizzle.selectors = {
|
|||
return [ argument < 0 ? argument + length : argument ];
|
||||
}),
|
||||
|
||||
"even": createPositionalPseudo(function( matchIndexes, length, argument ) {
|
||||
"even": createPositionalPseudo(function( matchIndexes, length ) {
|
||||
for ( var i = 0; i < length; i += 2 ) {
|
||||
matchIndexes.push( i );
|
||||
}
|
||||
return matchIndexes;
|
||||
}),
|
||||
|
||||
"odd": createPositionalPseudo(function( matchIndexes, length, argument ) {
|
||||
"odd": createPositionalPseudo(function( matchIndexes, length ) {
|
||||
for ( var i = 1; i < length; i += 2 ) {
|
||||
matchIndexes.push( i );
|
||||
}
|
||||
|
@ -4666,7 +4655,9 @@ baseHasDuplicate = !hasDuplicate;
|
|||
// Document sorting and removing duplicates
|
||||
Sizzle.uniqueSort = function( results ) {
|
||||
var elem,
|
||||
i = 1;
|
||||
duplicates = [],
|
||||
i = 1,
|
||||
j = 0;
|
||||
|
||||
hasDuplicate = baseHasDuplicate;
|
||||
results.sort( sortOrder );
|
||||
|
@ -4674,9 +4665,12 @@ Sizzle.uniqueSort = function( results ) {
|
|||
if ( hasDuplicate ) {
|
||||
for ( ; (elem = results[i]); i++ ) {
|
||||
if ( elem === results[ i - 1 ] ) {
|
||||
results.splice( i--, 1 );
|
||||
j = duplicates.push( i );
|
||||
}
|
||||
}
|
||||
while ( j-- ) {
|
||||
results.splice( duplicates[ j ], 1 );
|
||||
}
|
||||
}
|
||||
|
||||
return results;
|
||||
|
@ -4687,8 +4681,9 @@ Sizzle.error = function( msg ) {
|
|||
};
|
||||
|
||||
function tokenize( selector, parseOnly ) {
|
||||
var matched, match, tokens, type, soFar, groups, preFilters,
|
||||
cached = tokenCache[ expando ][ selector ];
|
||||
var matched, match, tokens, type,
|
||||
soFar, groups, preFilters,
|
||||
cached = tokenCache[ expando ][ selector + " " ];
|
||||
|
||||
if ( cached ) {
|
||||
return parseOnly ? 0 : cached.slice( 0 );
|
||||
|
@ -4703,7 +4698,8 @@ function tokenize( selector, parseOnly ) {
|
|||
// Comma and first run
|
||||
if ( !matched || (match = rcomma.exec( soFar )) ) {
|
||||
if ( match ) {
|
||||
soFar = soFar.slice( match[0].length );
|
||||
// Don't consume trailing commas as valid
|
||||
soFar = soFar.slice( match[0].length ) || soFar;
|
||||
}
|
||||
groups.push( tokens = [] );
|
||||
}
|
||||
|
@ -4722,8 +4718,7 @@ function tokenize( selector, parseOnly ) {
|
|||
// Filters
|
||||
for ( type in Expr.filter ) {
|
||||
if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] ||
|
||||
// The last two arguments here are (context, xml) for backCompat
|
||||
(match = preFilters[ type ]( match, document, true ))) ) {
|
||||
(match = preFilters[ type ]( match ))) ) {
|
||||
|
||||
tokens.push( matched = new Token( match.shift() ) );
|
||||
soFar = soFar.slice( matched.length );
|
||||
|
@ -4843,18 +4838,13 @@ function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postS
|
|||
postFinder = setMatcher( postFinder, postSelector );
|
||||
}
|
||||
return markFunction(function( seed, results, context, xml ) {
|
||||
// Positional selectors apply to seed elements, so it is invalid to follow them with relative ones
|
||||
if ( seed && postFinder ) {
|
||||
return;
|
||||
}
|
||||
|
||||
var i, elem, postFilterIn,
|
||||
var temp, i, elem,
|
||||
preMap = [],
|
||||
postMap = [],
|
||||
preexisting = results.length,
|
||||
|
||||
// Get initial elements from seed or context
|
||||
elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [], seed ),
|
||||
elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ),
|
||||
|
||||
// Prefilter to get matcher input, preserving a map for seed-results synchronization
|
||||
matcherIn = preFilter && ( seed || !selector ) ?
|
||||
|
@ -4879,27 +4869,45 @@ function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postS
|
|||
|
||||
// Apply postFilter
|
||||
if ( postFilter ) {
|
||||
postFilterIn = condense( matcherOut, postMap );
|
||||
postFilter( postFilterIn, [], context, xml );
|
||||
temp = condense( matcherOut, postMap );
|
||||
postFilter( temp, [], context, xml );
|
||||
|
||||
// Un-match failing elements by moving them back to matcherIn
|
||||
i = postFilterIn.length;
|
||||
i = temp.length;
|
||||
while ( i-- ) {
|
||||
if ( (elem = postFilterIn[i]) ) {
|
||||
if ( (elem = temp[i]) ) {
|
||||
matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Keep seed and results synchronized
|
||||
if ( seed ) {
|
||||
// Ignore postFinder because it can't coexist with seed
|
||||
i = preFilter && matcherOut.length;
|
||||
while ( i-- ) {
|
||||
if ( (elem = matcherOut[i]) ) {
|
||||
seed[ preMap[i] ] = !(results[ preMap[i] ] = elem);
|
||||
if ( postFinder || preFilter ) {
|
||||
if ( postFinder ) {
|
||||
// Get the final matcherOut by condensing this intermediate into postFinder contexts
|
||||
temp = [];
|
||||
i = matcherOut.length;
|
||||
while ( i-- ) {
|
||||
if ( (elem = matcherOut[i]) ) {
|
||||
// Restore matcherIn since elem is not yet a final match
|
||||
temp.push( (matcherIn[i] = elem) );
|
||||
}
|
||||
}
|
||||
postFinder( null, (matcherOut = []), temp, xml );
|
||||
}
|
||||
|
||||
// Move matched elements from seed to results to keep them synchronized
|
||||
i = matcherOut.length;
|
||||
while ( i-- ) {
|
||||
if ( (elem = matcherOut[i]) &&
|
||||
(temp = postFinder ? indexOf.call( seed, elem ) : preMap[i]) > -1 ) {
|
||||
|
||||
seed[temp] = !(results[temp] = elem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add elements to results, through postFinder if defined
|
||||
} else {
|
||||
matcherOut = condense(
|
||||
matcherOut === results ?
|
||||
|
@ -4940,7 +4948,6 @@ function matcherFromTokens( tokens ) {
|
|||
if ( (matcher = Expr.relative[ tokens[i].type ]) ) {
|
||||
matchers = [ addCombinator( elementMatcher( matchers ), matcher ) ];
|
||||
} else {
|
||||
// The concatenated values are (context, xml) for backCompat
|
||||
matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches );
|
||||
|
||||
// Return special upon seeing a positional matcher
|
||||
|
@ -5069,7 +5076,7 @@ compile = Sizzle.compile = function( selector, group /* Internal Use Only */ ) {
|
|||
var i,
|
||||
setMatchers = [],
|
||||
elementMatchers = [],
|
||||
cached = compilerCache[ expando ][ selector ];
|
||||
cached = compilerCache[ expando ][ selector + " " ];
|
||||
|
||||
if ( !cached ) {
|
||||
// Generate a function of recursive functions that can be used to check each element
|
||||
|
@ -5092,11 +5099,11 @@ compile = Sizzle.compile = function( selector, group /* Internal Use Only */ ) {
|
|||
return cached;
|
||||
};
|
||||
|
||||
function multipleContexts( selector, contexts, results, seed ) {
|
||||
function multipleContexts( selector, contexts, results ) {
|
||||
var i = 0,
|
||||
len = contexts.length;
|
||||
for ( ; i < len; i++ ) {
|
||||
Sizzle( selector, contexts[i], results, seed );
|
||||
Sizzle( selector, contexts[i], results );
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
@ -5174,15 +5181,14 @@ if ( document.querySelectorAll ) {
|
|||
rescape = /'|\\/g,
|
||||
rattributeQuotes = /\=[\x20\t\r\n\f]*([^'"\]]*)[\x20\t\r\n\f]*\]/g,
|
||||
|
||||
// qSa(:focus) reports false when true (Chrome 21),
|
||||
// qSa(:focus) reports false when true (Chrome 21), no need to also add to buggyMatches since matches checks buggyQSA
|
||||
// A support test would require too much code (would include document ready)
|
||||
rbuggyQSA = [":focus"],
|
||||
rbuggyQSA = [ ":focus" ],
|
||||
|
||||
// matchesSelector(:focus) reports false when true (Chrome 21),
|
||||
// matchesSelector(:active) reports false when true (IE9/Opera 11.5)
|
||||
// A support test would require too much code (would include document ready)
|
||||
// just skip matchesSelector for :active
|
||||
rbuggyMatches = [ ":active", ":focus" ],
|
||||
rbuggyMatches = [ ":active" ],
|
||||
matches = docElem.matchesSelector ||
|
||||
docElem.mozMatchesSelector ||
|
||||
docElem.webkitMatchesSelector ||
|
||||
|
@ -5236,7 +5242,7 @@ if ( document.querySelectorAll ) {
|
|||
// Only use querySelectorAll when not filtering,
|
||||
// when this is not xml,
|
||||
// and when no QSA bugs apply
|
||||
if ( !seed && !xml && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) {
|
||||
if ( !seed && !xml && !rbuggyQSA.test( selector ) ) {
|
||||
var groups, i,
|
||||
old = true,
|
||||
nid = expando,
|
||||
|
@ -5305,7 +5311,7 @@ if ( document.querySelectorAll ) {
|
|||
expr = expr.replace( rattributeQuotes, "='$1']" );
|
||||
|
||||
// rbuggyMatches always contains :active, so no need for an existence check
|
||||
if ( !isXML( elem ) && !rbuggyMatches.test( expr ) && (!rbuggyQSA || !rbuggyQSA.test( expr )) ) {
|
||||
if ( !isXML( elem ) && !rbuggyMatches.test( expr ) && !rbuggyQSA.test( expr ) ) {
|
||||
try {
|
||||
var ret = matches.call( elem, expr );
|
||||
|
||||
|
@ -6540,7 +6546,7 @@ var curCSS, iframe, iframeDoc,
|
|||
rnumsplit = new RegExp( "^(" + core_pnum + ")(.*)$", "i" ),
|
||||
rnumnonpx = new RegExp( "^(" + core_pnum + ")(?!px)[a-z%]+$", "i" ),
|
||||
rrelNum = new RegExp( "^([-+])=(" + core_pnum + ")", "i" ),
|
||||
elemdisplay = {},
|
||||
elemdisplay = { BODY: "block" },
|
||||
|
||||
cssShow = { position: "absolute", visibility: "hidden", display: "block" },
|
||||
cssNormalTransform = {
|
||||
|
@ -6821,7 +6827,9 @@ if ( window.getComputedStyle ) {
|
|||
|
||||
if ( computed ) {
|
||||
|
||||
ret = computed[ name ];
|
||||
// getPropertyValue is only needed for .css('filter') in IE9, see #12537
|
||||
ret = computed.getPropertyValue( name ) || computed[ name ];
|
||||
|
||||
if ( ret === "" && !jQuery.contains( elem.ownerDocument, elem ) ) {
|
||||
ret = jQuery.style( elem, name );
|
||||
}
|
||||
|
@ -7850,9 +7858,12 @@ jQuery.extend({
|
|||
|
||||
// A cross-domain request is in order when we have a protocol:host:port mismatch
|
||||
if ( s.crossDomain == null ) {
|
||||
parts = rurl.exec( s.url.toLowerCase() ) || false;
|
||||
s.crossDomain = parts && ( parts.join(":") + ( parts[ 3 ] ? "" : parts[ 1 ] === "http:" ? 80 : 443 ) ) !==
|
||||
( ajaxLocParts.join(":") + ( ajaxLocParts[ 3 ] ? "" : ajaxLocParts[ 1 ] === "http:" ? 80 : 443 ) );
|
||||
parts = rurl.exec( s.url.toLowerCase() );
|
||||
s.crossDomain = !!( parts &&
|
||||
( parts[ 1 ] !== ajaxLocParts[ 1 ] || parts[ 2 ] !== ajaxLocParts[ 2 ] ||
|
||||
( parts[ 3 ] || ( parts[ 1 ] === "http:" ? 80 : 443 ) ) !=
|
||||
( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === "http:" ? 80 : 443 ) ) )
|
||||
);
|
||||
}
|
||||
|
||||
// Convert data if not already a string
|
||||
|
@ -8471,7 +8482,7 @@ if ( jQuery.support.ajax ) {
|
|||
// on any attempt to access responseText (#11426)
|
||||
try {
|
||||
responses.text = xhr.responseText;
|
||||
} catch( _ ) {
|
||||
} catch( e ) {
|
||||
}
|
||||
|
||||
// Firefox throws an exception when accessing
|
||||
|
@ -8624,7 +8635,9 @@ function Animation( elem, properties, options ) {
|
|||
tick = function() {
|
||||
var currentTime = fxNow || createFxNow(),
|
||||
remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ),
|
||||
percent = 1 - ( remaining / animation.duration || 0 ),
|
||||
// archaic crash bug won't allow us to use 1 - ( 0.5 || 0 ) (#12497)
|
||||
temp = remaining / animation.duration || 0,
|
||||
percent = 1 - temp,
|
||||
index = 0,
|
||||
length = animation.tweens.length;
|
||||
|
||||
|
@ -8776,7 +8789,7 @@ jQuery.Animation = jQuery.extend( Animation, {
|
|||
});
|
||||
|
||||
function defaultPrefilter( elem, props, opts ) {
|
||||
var index, prop, value, length, dataShow, tween, hooks, oldfire,
|
||||
var index, prop, value, length, dataShow, toggle, tween, hooks, oldfire,
|
||||
anim = this,
|
||||
style = elem.style,
|
||||
orig = {},
|
||||
|
@ -8850,6 +8863,7 @@ function defaultPrefilter( elem, props, opts ) {
|
|||
value = props[ index ];
|
||||
if ( rfxtypes.exec( value ) ) {
|
||||
delete props[ index ];
|
||||
toggle = toggle || value === "toggle";
|
||||
if ( value === ( hidden ? "hide" : "show" ) ) {
|
||||
continue;
|
||||
}
|
||||
|
@ -8860,6 +8874,14 @@ function defaultPrefilter( elem, props, opts ) {
|
|||
length = handled.length;
|
||||
if ( length ) {
|
||||
dataShow = jQuery._data( elem, "fxshow" ) || jQuery._data( elem, "fxshow", {} );
|
||||
if ( "hidden" in dataShow ) {
|
||||
hidden = dataShow.hidden;
|
||||
}
|
||||
|
||||
// store state if its toggle - enables .stop().toggle() to "reverse"
|
||||
if ( toggle ) {
|
||||
dataShow.hidden = !hidden;
|
||||
}
|
||||
if ( hidden ) {
|
||||
jQuery( elem ).show();
|
||||
} else {
|
||||
|
@ -9156,6 +9178,8 @@ jQuery.fx.tick = function() {
|
|||
timers = jQuery.timers,
|
||||
i = 0;
|
||||
|
||||
fxNow = jQuery.now();
|
||||
|
||||
for ( ; i < timers.length; i++ ) {
|
||||
timer = timers[ i ];
|
||||
// Checks the timer has not already been removed
|
||||
|
@ -9167,6 +9191,7 @@ jQuery.fx.tick = function() {
|
|||
if ( !timers.length ) {
|
||||
jQuery.fx.stop();
|
||||
}
|
||||
fxNow = undefined;
|
||||
};
|
||||
|
||||
jQuery.fx.timer = function( timer ) {
|
|
@ -66,50 +66,48 @@ instance.web.Dialog = instance.web.Widget.extend({
|
|||
max_width: '95%',
|
||||
height: 'auto',
|
||||
min_height: 0,
|
||||
max_height: this.get_height('100%') - 200,
|
||||
max_height: $(window.top).height() - 200,
|
||||
autoOpen: false,
|
||||
position: [false, 40],
|
||||
buttons: {},
|
||||
buttons: null,
|
||||
beforeClose: function () {
|
||||
self.trigger("closing");
|
||||
},
|
||||
resizeStop: this.on_resized
|
||||
resizeStop: function() {
|
||||
self.trigger("resized");
|
||||
},
|
||||
};
|
||||
for (var f in this) {
|
||||
if (f.substr(0, 10) == 'on_button_') {
|
||||
this.dialog_options.buttons[f.substr(10)] = this[f];
|
||||
}
|
||||
}
|
||||
if (options) {
|
||||
_.extend(this.dialog_options, options);
|
||||
}
|
||||
this.on("closing", this, this._closing);
|
||||
},
|
||||
get_options: function(options) {
|
||||
var self = this,
|
||||
o = _.extend({}, this.dialog_options, options || {});
|
||||
_.each(['width', 'height'], function(unit) {
|
||||
o[unit] = self['get_' + unit](o[unit]);
|
||||
o['min_' + unit] = self['get_' + unit](o['min_' + unit] || 0);
|
||||
o['max_' + unit] = self['get_' + unit](o['max_' + unit] || 0);
|
||||
if (o[unit] !== 'auto' && o['min_' + unit] && o[unit] < o['min_' + unit]) o[unit] = o['min_' + unit];
|
||||
if (o[unit] !== 'auto' && o['max_' + unit] && o[unit] > o['max_' + unit]) o[unit] = o['max_' + unit];
|
||||
_get_options: function(options) {
|
||||
var self = this;
|
||||
var o = _.extend({}, this.dialog_options, options || {});
|
||||
var sizes = {
|
||||
width: $(window.top).width(),
|
||||
height: $(window.top).height(),
|
||||
};
|
||||
_.each(sizes, function(available_size, unit) {
|
||||
o[unit] = self._get_size(o[unit]);
|
||||
o['min_' + unit] = self._get_size(o['min_' + unit] || 0, available_size);
|
||||
o['max_' + unit] = self._get_size(o['max_' + unit] || 0, available_size);
|
||||
if (o[unit] !== 'auto' && o['min_' + unit] && o[unit] < o['min_' + unit]) {
|
||||
o[unit] = o['min_' + unit];
|
||||
}
|
||||
if (o[unit] !== 'auto' && o['max_' + unit] && o[unit] > o['max_' + unit]) {
|
||||
o[unit] = o['max_' + unit];
|
||||
}
|
||||
});
|
||||
if (!o.title && this.dialog_title) {
|
||||
o.title = this.dialog_title;
|
||||
}
|
||||
o.title = o.title || this.dialog_title;
|
||||
return o;
|
||||
},
|
||||
get_width: function(val) {
|
||||
return this.get_size(val.toString(), $(window.top).width());
|
||||
},
|
||||
get_height: function(val) {
|
||||
return this.get_size(val.toString(), $(window.top).height());
|
||||
},
|
||||
get_size: function(val, available_size) {
|
||||
_get_size: function(val, available_size) {
|
||||
val = val.toString();
|
||||
if (val === 'auto') {
|
||||
return val;
|
||||
} else if (val.slice(-1) == "%") {
|
||||
} else if (val.slice(-1) === "%") {
|
||||
return Math.round(available_size / 100 * parseInt(val.slice(0, -1), 10));
|
||||
} else {
|
||||
return parseInt(val, 10);
|
||||
|
@ -123,11 +121,14 @@ instance.web.Dialog = instance.web.Widget.extend({
|
|||
}
|
||||
},
|
||||
open: function(options) {
|
||||
if (! this.dialog_inited)
|
||||
this.init_dialog();
|
||||
var o = this.get_options(options);
|
||||
this.add_buttons(o.buttons);
|
||||
delete(o.buttons);
|
||||
var o = this._get_options(options);
|
||||
if (!this.dialog_inited) {
|
||||
this.init_dialog(o);
|
||||
}
|
||||
if (o.buttons) {
|
||||
this._add_buttons(o.buttons);
|
||||
delete(o.buttons);
|
||||
}
|
||||
this.$buttons.appendTo($("body"));
|
||||
instance.web.dialog(this.$el, o).dialog('open');
|
||||
this.$el.dialog("widget").find(".ui-dialog-buttonpane").remove();
|
||||
|
@ -137,10 +138,15 @@ instance.web.Dialog = instance.web.Widget.extend({
|
|||
}
|
||||
return this;
|
||||
},
|
||||
add_buttons: function(buttons) {
|
||||
_add_buttons: function(buttons) {
|
||||
var self = this;
|
||||
_.each(buttons, function(fn, but) {
|
||||
var $but = $(QWeb.render('WidgetButton', { widget : { string: but, node: { attrs: {} }}}));
|
||||
_.each(buttons, function(fn, text) {
|
||||
// buttons can be object or array
|
||||
if (!_.isFunction(fn)) {
|
||||
text = fn.text;
|
||||
fn = fn.click;
|
||||
}
|
||||
var $but = $(QWeb.render('WidgetButton', { widget : { string: text, node: { attrs: {} }}}));
|
||||
self.$buttons.append($but);
|
||||
$but.on('click', function(ev) {
|
||||
fn.call(self.$el, ev);
|
||||
|
@ -149,8 +155,7 @@ instance.web.Dialog = instance.web.Widget.extend({
|
|||
},
|
||||
init_dialog: function(options) {
|
||||
this.renderElement();
|
||||
var o = this.get_options(options);
|
||||
instance.web.dialog(this.$el, o);
|
||||
instance.web.dialog(this.$el, options);
|
||||
this.$buttons = $('<div class="ui-dialog-buttonpane ui-widget-content ui-helper-clearfix" />');
|
||||
this.$el.dialog("widget").append(this.$buttons);
|
||||
this.dialog_inited = true;
|
||||
|
@ -171,8 +176,6 @@ instance.web.Dialog = instance.web.Widget.extend({
|
|||
this.__tmp_dialog_closing = undefined;
|
||||
}
|
||||
},
|
||||
on_resized: function() {
|
||||
},
|
||||
destroy: function () {
|
||||
_.each(this.getChildren(), function(el) {
|
||||
el.destroy();
|
||||
|
@ -665,13 +668,19 @@ instance.web.Login = instance.web.Widget.extend({
|
|||
self.$el.find('.oe_login_manage_db').click(function() {
|
||||
self.do_action("database_manager");
|
||||
});
|
||||
var d;
|
||||
if (self.params.db) {
|
||||
if (self.params.login && self.params.password) {
|
||||
d = self.do_login(self.params.db, self.params.login, self.params.password);
|
||||
}
|
||||
var d = $.when();
|
||||
if ($.deparam.querystring().db) {
|
||||
self.params.db = $.deparam.querystring().db;
|
||||
}
|
||||
// used by dbmanager.do_create via internal client action
|
||||
if (self.params.db && self.params.login && self.params.password) {
|
||||
d = self.do_login(self.params.db, self.params.login, self.params.password);
|
||||
} else {
|
||||
d = self.rpc("/web/database/get_list", {}).done(self.on_db_loaded).fail(self.on_db_failed);
|
||||
if (self.params.db) {
|
||||
self.on_db_loaded([self.params.db])
|
||||
} else {
|
||||
d = self.rpc("/web/database/get_list", {}).done(self.on_db_loaded).fail(self.on_db_failed);
|
||||
}
|
||||
}
|
||||
return d;
|
||||
},
|
||||
|
@ -1081,7 +1090,7 @@ instance.web.Client = instance.web.Widget.extend({
|
|||
start: function() {
|
||||
var self = this;
|
||||
return instance.session.session_bind(this.origin).then(function() {
|
||||
var $e = $(QWeb.render(self._template, {}));
|
||||
var $e = $(QWeb.render(self._template, {widget: self}));
|
||||
self.replaceElement($e);
|
||||
$e.openerpClass();
|
||||
self.bind_events();
|
||||
|
|
|
@ -22,7 +22,6 @@ instance.web.DataExport = instance.web.Dialog.extend({
|
|||
start: function() {
|
||||
var self = this;
|
||||
this._super.apply(this, arguments);
|
||||
this.open();
|
||||
self.$el.removeClass('ui-dialog-content ui-widget-content');
|
||||
self.$el.find('#add_field').click(function() {
|
||||
if ($('#field-tree-structure tr.ui-selected')) {
|
||||
|
|
|
@ -1025,8 +1025,8 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM
|
|||
}
|
||||
return true;
|
||||
},
|
||||
sidebar_context: function () {
|
||||
return this.save().then(_.bind(function() {return this.get_fields_values();}, this));
|
||||
sidebar_eval_context: function () {
|
||||
return $.when(this.build_eval_context());
|
||||
},
|
||||
open_defaults_dialog: function () {
|
||||
var self = this;
|
||||
|
@ -1231,7 +1231,7 @@ instance.web.form.FormRenderingEngine = instance.web.form.FormRenderingEngineInt
|
|||
|
||||
var doc = $.parseXML('<div class="oe_form">' + xml + '</div>');
|
||||
$('button', doc).each(function() {
|
||||
$(this).attr('data-button-type', $(this).attr('type'));
|
||||
$(this).attr('data-button-type', $(this).attr('type')).attr('type', 'button');
|
||||
});
|
||||
xml = instance.web.xml_to_str(doc);
|
||||
return $(xml);
|
||||
|
|
|
@ -78,12 +78,13 @@ openerp.web.list_editable = function (instance) {
|
|||
_.extend(this.dataset, dataset);
|
||||
},
|
||||
do_delete: function (ids) {
|
||||
var nonfalse = _.compact(ids);
|
||||
var _super = this._super.bind(this);
|
||||
var next = this.editor.is_editing()
|
||||
? this.cancel_edition(true)
|
||||
: $.when();
|
||||
return next.then(function () {
|
||||
return _super(ids);
|
||||
return _super(nonfalse);
|
||||
});
|
||||
},
|
||||
editable: function () {
|
||||
|
|
|
@ -26,6 +26,7 @@ instance.web.ActionManager = instance.web.Widget.extend({
|
|||
if (this.dialog) {
|
||||
this.dialog.destroy();
|
||||
}
|
||||
this.dialog = null;
|
||||
},
|
||||
/**
|
||||
* Add a new item to the breadcrumb
|
||||
|
@ -1060,23 +1061,24 @@ instance.web.Sidebar = instance.web.Widget.extend({
|
|||
},
|
||||
on_item_action_clicked: function(item) {
|
||||
var self = this;
|
||||
self.getParent().sidebar_context().done(function (context) {
|
||||
self.getParent().sidebar_eval_context().done(function (sidebar_eval_context) {
|
||||
var ids = self.getParent().get_selected_ids();
|
||||
if (ids.length == 0) {
|
||||
instance.web.dialog($("<div />").text(_t("You must choose at least one record.")), { title: _t("Warning"), modal: true });
|
||||
return false;
|
||||
}
|
||||
var additional_context = _.extend({
|
||||
var active_ids_context = {
|
||||
active_id: ids[0],
|
||||
active_ids: ids,
|
||||
active_model: self.getParent().dataset.model
|
||||
}, context);
|
||||
};
|
||||
self.rpc("/web/action/load", {
|
||||
action_id: item.action.id,
|
||||
context: additional_context
|
||||
context: active_ids_context,
|
||||
eval_context: new instance.web.CompoundContext(sidebar_eval_context, active_ids_context),
|
||||
}).done(function(result) {
|
||||
result.context = _.extend(result.context || {},
|
||||
additional_context);
|
||||
console.log(result.context);
|
||||
result.context = new instance.web.CompoundContext(result.context || {}, active_ids_context);
|
||||
result.flags = result.flags || {};
|
||||
result.flags.new_window = true;
|
||||
self.do_action(result, {
|
||||
|
@ -1329,7 +1331,7 @@ instance.web.View = instance.web.Widget.extend({
|
|||
on_sidebar_export: function() {
|
||||
new instance.web.DataExport(this, this.dataset).open();
|
||||
},
|
||||
sidebar_context: function () {
|
||||
sidebar_eval_context: function () {
|
||||
return $.when();
|
||||
},
|
||||
/**
|
||||
|
|
Loading…
Reference in New Issue