diff --git a/addons/web/static/lib/nivjs/src/niv.js b/addons/web/static/lib/nivjs/src/niv.js
index 76707864a91..bc8d1564523 100644
--- a/addons/web/static/lib/nivjs/src/niv.js
+++ b/addons/web/static/lib/nivjs/src/niv.js
@@ -94,7 +94,7 @@ niv = (function() {
return Class;
};
}).call(lib);
-
+
lib.DestroyableMixin = {
isDestroyed : function() {
return this.__destroyable_destroyed;
@@ -137,5 +137,108 @@ niv = (function() {
}
});
+ /*
+ * We steal backbone's events :)
+ */
+ // (c) 2010-2012 Jeremy Ashkenas, DocumentCloud Inc.
+ // Backbone may be freely distributed under the MIT license.
+ // For all details and documentation:
+ // http://backbonejs.org
+ lib.EventDispatcher = lib.Class.extend({
+
+ // Bind an event, specified by a string name, `ev`, to a `callback`
+ // function. Passing `"all"` will bind the callback to all events fired.
+ on : function(events, callback, context) {
+ var ev;
+ events = events.split(/\s+/);
+ var calls = this._callbacks || (this._callbacks = {});
+ while (ev = events.shift()) {
+ // Create an immutable callback list, allowing traversal during
+ // modification. The tail is an empty object that will always be
+ // used
+ // as the next node.
+ var list = calls[ev] || (calls[ev] = {});
+ var tail = list.tail || (list.tail = list.next = {});
+ tail.callback = callback;
+ tail.context = context;
+ list.tail = tail.next = {};
+ }
+ return this;
+ },
+
+ // Remove one or many callbacks. If `context` is null, removes all
+ // callbacks
+ // with that function. If `callback` is null, removes all callbacks for
+ // the
+ // event. If `ev` is null, removes all bound callbacks for all events.
+ off : function(events, callback, context) {
+ var ev, calls, node;
+ if (!events) {
+ delete this._callbacks;
+ } else if (calls = this._callbacks) {
+ events = events.split(/\s+/);
+ while (ev = events.shift()) {
+ node = calls[ev];
+ delete calls[ev];
+ if (!callback || !node)
+ continue;
+ // Create a new list, omitting the indicated event/context
+ // pairs.
+ while ((node = node.next) && node.next) {
+ if (node.callback === callback
+ && (!context || node.context === context))
+ continue;
+ this.on(ev, node.callback, node.context);
+ }
+ }
+ }
+ return this;
+ },
+
+ // Trigger an event, firing all bound callbacks. Callbacks are passed
+ // the
+ // same arguments as `trigger` is, apart from the event name.
+ // Listening for `"all"` passes the true event name as the first
+ // argument.
+ trigger : function(events) {
+ var event, node, calls, tail, args, all, rest;
+ if (!(calls = this._callbacks))
+ return this;
+ all = calls['all'];
+ (events = events.split(/\s+/)).push(null);
+ // Save references to the current heads & tails.
+ while (event = events.shift()) {
+ if (all)
+ events.push({
+ next : all.next,
+ tail : all.tail,
+ event : event
+ });
+ if (!(node = calls[event]))
+ continue;
+ events.push({
+ next : node.next,
+ tail : node.tail
+ });
+ }
+ // Traverse each list, stopping when the saved tail is reached.
+ rest = slice.call(arguments, 1);
+ while (node = events.pop()) {
+ tail = node.tail;
+ args = node.event ? [ node.event ].concat(rest) : rest;
+ while ((node = node.next) !== tail) {
+ node.callback.apply(node.context || this, args);
+ }
+ }
+ return this;
+ },
+ bind: function() {
+ return this.on.apply(this, arguments);
+ },
+ unbind: function() {
+ return this.on.apply(this, arguments);
+ }
+ });
+
return lib;
})();
diff --git a/addons/web/static/lib/nivjs/test/test.html b/addons/web/static/lib/nivjs/test/test.html
index 08cd9fce4ab..a229d373f51 100644
--- a/addons/web/static/lib/nivjs/test/test.html
+++ b/addons/web/static/lib/nivjs/test/test.html
@@ -6,6 +6,8 @@
+
+
diff --git a/addons/web/static/lib/nivjs/test/test.js b/addons/web/static/lib/nivjs/test/test.js
index 5ef89fa5da8..0328b7d0574 100644
--- a/addons/web/static/lib/nivjs/test/test.js
+++ b/addons/web/static/lib/nivjs/test/test.js
@@ -6,3 +6,34 @@ test("Class exists", function() {
ok(!!niv.Class.extend, "extend does not exist");
});
+test("Inheritance works", function() {
+ var Claz = niv.Class.extend({
+ test: function() {
+ return "ok";
+ }
+ })
+ equal("ok", new Claz().test());
+});
+
+module("DestroyableMixin");
+
+test("DestroyableMixin works", function() {
+ var Claz = niv.Class.extend(_.extend({}, niv.DestroyableMixin, {}));
+ var x = new Claz();
+ equal(false, !!x.isDestroyed());
+ x.destroy();
+ equal(true, x.isDestroyed());
+});
+
+module("ParentedMixin");
+
+test("ParentedMixin works", function() {
+ var Claz = niv.Class.extend(_.extend({}, niv.ParentedMixin, {}));
+ var x = new Claz();
+ var y = new Claz();
+ y.setParent(x);
+ equal(x, y.getParent());
+ equal(y, x.getChildren()[0]);
+ x.destroy();
+ equal(true, y.isDestroyed());
+});