/*--------------------------------------------------------- * OpenERP Web core *--------------------------------------------------------*/ openerp.web.core = function(openerp) { openerp.web.qweb = new QWeb2.Engine(); openerp.web.qweb.debug = (window.location.search.indexOf('?debug') !== -1); /** * John Resig Class with factory improvement */ (function() { var initializing = false, fnTest = /xyz/.test(function(){xyz;}) ? /\b_super\b/ : /.*/; // The web Class implementation (does nothing) /** * Extended version of John Resig's Class pattern * * @class */ openerp.web.Class = function(){}; /** * Subclass an existing class * * @param {Object} prop class-level properties (class attributes and instance methods) to set on the new class */ openerp.web.Class.extend = function(prop) { var _super = this.prototype; // Instantiate a web class (but only create the instance, // don't run the init constructor) initializing = true; var prototype = new this(); initializing = false; // Copy the properties over onto the new prototype for (var name in prop) { // Check if we're overwriting an existing function prototype[name] = typeof prop[name] == "function" && typeof _super[name] == "function" && fnTest.test(prop[name]) ? (function(name, fn) { return function() { var tmp = this._super; // Add a new ._super() method that is the same // method but on the super-class this._super = _super[name]; // The method only need to be bound temporarily, so // we remove it when we're done executing var ret = fn.apply(this, arguments); this._super = tmp; return ret; }; })(name, prop[name]) : prop[name]; } // The dummy class constructor function Class() { // All construction is actually done in the init method if (!initializing && this.init) { var ret = this.init.apply(this, arguments); if (ret) { return ret; } } return this; } Class.include = function (properties) { for (var name in properties) { if (typeof properties[name] !== 'function' || !fnTest.test(properties[name])) { prototype[name] = properties[name]; } else if (typeof prototype[name] === 'function' && prototype.hasOwnProperty(name)) { prototype[name] = (function (name, fn, previous) { return function () { var tmp = this._super; this._super = previous; var ret = fn.apply(this, arguments); this._super = tmp; return ret; } })(name, properties[name], prototype[name]); } else if (typeof _super[name] === 'function') { prototype[name] = (function (name, fn) { return function () { var tmp = this._super; this._super = _super[name]; var ret = fn.apply(this, arguments); this._super = tmp; return ret; } })(name, properties[name]); } } }; // Populate our constructed prototype object Class.prototype = prototype; // Enforce the constructor to be what we expect Class.constructor = Class; // And make this class extendable Class.extend = arguments.callee; return Class; }; })(); openerp.web.callback = function(obj, method) { var callback = function() { var args = Array.prototype.slice.call(arguments); var r; for(var i = 0; i < callback.callback_chain.length; i++) { var c = callback.callback_chain[i]; if(c.unique) { callback.callback_chain.splice(i, 1); i -= 1; } r = c.callback.apply(c.self, c.args.concat(args)); // TODO special value to stop the chain // openerp.web.callback_stop } return r; }; callback.callback_chain = []; callback.add = function(f) { if(typeof(f) == 'function') { f = { callback: f, args: Array.prototype.slice.call(arguments, 1) }; } f.self = f.self || null; f.args = f.args || []; f.unique = !!f.unique; if(f.position == 'last') { callback.callback_chain.push(f); } else { callback.callback_chain.unshift(f); } return callback; }; callback.add_first = function(f) { return callback.add.apply(null,arguments); }; callback.add_last = function(f) { return callback.add({ callback: f, args: Array.prototype.slice.call(arguments, 1), position: "last" }); }; return callback.add({ callback: method, self:obj, args:Array.prototype.slice.call(arguments, 2) }); }; /** * Generates an inherited class that replaces all the methods by null methods (methods * that does nothing and always return undefined). * * @param {Class} claz * @param {Object} add Additional functions to override. * @return {Class} */ openerp.web.generate_null_object_class = function(claz, add) { var newer = {}; var copy_proto = function(prototype) { for (var name in prototype) { if(typeof prototype[name] == "function") { newer[name] = function() {}; } } if (prototype.prototype) copy_proto(prototype.prototype); }; copy_proto(claz.prototype); newer.init = openerp.web.Widget.prototype.init; var tmpclass = claz.extend(newer); return tmpclass.extend(add || {}); }; /** * web error for lookup failure * * @class */ openerp.web.NotFound = openerp.web.Class.extend( /** @lends openerp.web.NotFound# */ { }); openerp.web.KeyNotFound = openerp.web.NotFound.extend( /** @lends openerp.web.KeyNotFound# */ { /** * Thrown when a key could not be found in a mapping * * @constructs openerp.web.KeyNotFound * @extends openerp.web.NotFound * @param {String} key the key which could not be found */ init: function (key) { this.key = key; }, toString: function () { return "The key " + this.key + " was not found"; } }); openerp.web.ObjectNotFound = openerp.web.NotFound.extend( /** @lends openerp.web.ObjectNotFound# */ { /** * Thrown when an object path does not designate a valid class or object * in the openerp hierarchy. * * @constructs openerp.web.ObjectNotFound * @extends openerp.web.NotFound * @param {String} path the invalid object path */ init: function (path) { this.path = path; }, toString: function () { return "Could not find any object of path " + this.path; } }); openerp.web.Registry = openerp.web.Class.extend( /** @lends openerp.web.Registry# */ { /** * Stores a mapping of arbitrary key (strings) to object paths (as strings * as well). * * Resolves those paths at query time in order to always fetch the correct * object, even if those objects have been overloaded/replaced after the * registry was created. * * An object path is simply a dotted name from the openerp root to the * object pointed to (e.g. ``"openerp.web.Session"`` for an OpenERP * session object). * * @constructs openerp.web.Registry * @param {Object} mapping a mapping of keys to object-paths */ init: function (mapping) { this.map = mapping || {}; }, /** * Retrieves the object matching the provided key string. * * @param {String} key the key to fetch the object for * @returns {Class} the stored class, to initialize * * @throws {openerp.web.KeyNotFound} if the object was not in the mapping * @throws {openerp.web.ObjectNotFound} if the object path was invalid */ get_object: function (key) { var path_string = this.map[key]; if (path_string === undefined) { throw new openerp.web.KeyNotFound(key); } var object_match = openerp; var path = path_string.split('.'); // ignore first section for(var i=1; i'); var complete = function () { if (options.complete) { options.complete(); } clearTimeout(timer); $form_data.remove(); $target.remove(); if (remove_form && $form) { $form.remove(); } }; var $target = $('