Skip to content

Commit 08af2fb

Browse files
ivaynbergkevin-brown
authored andcommitted
decorators idea
1 parent 7693301 commit 08af2fb

8 files changed

Lines changed: 12074 additions & 0 deletions

File tree

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
2+
QUnit.test("decorator", function (assert) {
3+
4+
var A = clazz(Object, {
5+
hello: function () {
6+
return "A";
7+
}
8+
});
9+
10+
var Decorator = clazz(Object, {
11+
hello: function () {
12+
return "B" + this.decorated() + "B";
13+
}
14+
});
15+
16+
var a = new A();
17+
assert.strictEqual(a.hello(), "A");
18+
19+
20+
a.decorateWith(new Decorator());
21+
var value = a.hello();
22+
assert.strictEqual(value, "BAB");
23+
24+
});
25+
26+
QUnit.test("super", function (assert) {
27+
28+
var A = clazz(Object, {
29+
hello: function () {
30+
return "A";
31+
}
32+
});
33+
34+
var B = clazz(A, {
35+
hello: function () {
36+
return "B" + this.super() + "B";
37+
}
38+
});
39+
40+
var C = clazz(B, {
41+
hello: function () {
42+
return "C" + this.super() + "C";
43+
}
44+
});
45+
46+
var D = clazz(B, {
47+
hello: function () {
48+
return "D";
49+
}
50+
});
51+
52+
assert.strictEqual(new C().hello(), "CBABC");
53+
assert.strictEqual(new D().hello(), "D");
54+
55+
});
56+
57+
QUnit.test("super - constructors", function (assert) {
58+
59+
var A = clazz(Object, {
60+
construct: function () {
61+
this.message = "A";
62+
}
63+
});
64+
65+
var B = clazz(A, {
66+
construct: function () {
67+
this.super();
68+
this.message = "B" + this.message + "B";
69+
}
70+
});
71+
72+
var C = clazz(B, {
73+
construct: function () {
74+
this.super();
75+
this.message = "C" + this.message + "C";
76+
}
77+
});
78+
79+
var D = clazz(B, {
80+
construct: function () {
81+
this.message = "D";
82+
}
83+
});
84+
85+
assert.strictEqual(new C().message, "CBABC");
86+
assert.strictEqual(new D().message, "D");
87+
88+
});
89+
90+
91+
QUnit.test("inheritance", function (assert) {
92+
93+
var counter = 0;
94+
95+
var A = clazz(Object, {
96+
hello: function () {
97+
return "A";
98+
}
99+
});
100+
101+
var B = clazz(A, {
102+
103+
});
104+
105+
var a = new A(), b = new B();
106+
assert.ok(a.hello() === "A", "instance of A has hello()");
107+
assert.ok(b.hello() === "A", "instance of B has hello()");
108+
assert.ok(b instanceof B, "b is instance of B");
109+
assert.ok(b instanceof Object, "b is instance of Object");
110+
assert.ok(b instanceof A, "b is instance of A");
111+
});
112+
113+
114+
QUnit.test("initialization", function (assert) {
115+
116+
var counter = 0;
117+
118+
var A = clazz(Object, {
119+
construct: function () {
120+
counter++;
121+
}
122+
});
123+
124+
var B = clazz(A, {
125+
126+
});
127+
128+
assert.strictEqual(counter, 0);
129+
130+
var a = new A();
131+
132+
assert.strictEqual(counter, 1);
133+
134+
var b = new B();
135+
136+
assert.strictEqual(counter, 2);
137+
138+
});
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<meta charset="utf-8">
5+
<title>QUnit Example</title>
6+
<link rel="stylesheet" href="qunit-1.14.0.css">
7+
<script src="jquery-2.1.0.js" type="text/javascript"></script>
8+
<script src="jquery.sortable.js" type="text/javascript"></script>
9+
<script src="decorators.js"></script>
10+
11+
12+
<script>
13+
14+
15+
$(function () {
16+
17+
var Selection = clazz(Object, {
18+
construct: function () {
19+
this.data = ["value1", "value2"]
20+
},
21+
render: function () {
22+
23+
var markup = "<ul>";
24+
for (var i = 0; i < this.data.length; i++) {
25+
markup += "<li>" + this.renderItem(this.data[i]) + "</li>";
26+
}
27+
markup += "</ul>";
28+
return markup;
29+
},
30+
renderItem: function (item) {
31+
return item;
32+
},
33+
bind: function (container) {
34+
$(container).on("click", "li", function () {
35+
alert("clicked: " + $(this).text());
36+
})
37+
}
38+
});
39+
40+
var ClearExtension = clazz(Object, {
41+
construct: function (opts) {
42+
this.opts = opts;
43+
},
44+
45+
renderItem: function (item) {
46+
var markup = this.decorated(item);
47+
48+
if (this.opts.position === "right") {
49+
markup += " <a href='#' class='clear'>x</a>";
50+
} else {
51+
markup = " <a href='#' class='clear'>x</a>" + markup;
52+
}
53+
return markup;
54+
},
55+
bind: function (container) {
56+
this.decorated(container);
57+
container.on("click", "a.clear", function (e) {
58+
alert("clear: " + $(this).parents("li").text());
59+
e.stopPropagation();
60+
});
61+
}
62+
});
63+
64+
var SortableExtension = clazz(Object, {
65+
bind: function (container) {
66+
this.decorated(container);
67+
$(container).find("ul").sortable().bind('sortupdate', function () {
68+
alert("sorted");
69+
});
70+
}
71+
});
72+
73+
74+
var selection = new Selection();
75+
76+
selection
77+
.decorateWith(new ClearExtension({position: "right"}))
78+
.decorateWith(new SortableExtension());
79+
80+
var markup = selection.render();
81+
$("#container").html(markup);
82+
selection.bind($("#container"));
83+
84+
});
85+
86+
</script>
87+
88+
89+
</head>
90+
<body>
91+
92+
93+
<div id="container"></div>
94+
95+
96+
</body>
97+
</html>
98+
99+
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
var clazz = (function () {
2+
3+
var creatingPrototype = {};
4+
5+
var methods = function (object) {
6+
var methods = {};
7+
var proto = object.__proto__;
8+
while (proto !== Object.prototype) {
9+
for (var methodName in proto) {
10+
if (!methods[methodName] && typeof(proto[methodName]) === "function") {
11+
methods[methodName] = proto[methodName];
12+
}
13+
}
14+
proto = proto.__proto__;
15+
16+
}
17+
return methods;
18+
}
19+
20+
var decorateWith = function (decorator) {
21+
var decoratorMethods = methods(decorator);
22+
for (var methodName in decoratorMethods) {
23+
var decoratorMethod = decoratorMethods[methodName];
24+
if (typeof(decoratorMethod) === "function" && !(methodName === "construct" || methodName.name === "onDelegateAttached" || methodName === "decorateWith")) {
25+
this[methodName] = (function (prototype, methodName, method, decorator) {
26+
return function () {
27+
var delegate = this;
28+
try {
29+
decorator.decorated = function () {
30+
return prototype.apply(delegate, arguments);
31+
}
32+
return method.apply(decorator, arguments);
33+
} finally {
34+
delete decorator.decorated;
35+
}
36+
};
37+
})(this[methodName], methodName, decoratorMethod, decorator);
38+
this[methodName].displayName = methodName + "#decorator";
39+
}
40+
}
41+
42+
if (decorator.onDelegateAttached) {
43+
decorator.onDelegateAttached(this);
44+
}
45+
46+
decorator.delegate = this;
47+
48+
return this;
49+
50+
};
51+
52+
return function (SuperClass, methods) {
53+
54+
var constructor = function (arg) {
55+
if (arg === creatingPrototype) {
56+
return;
57+
}
58+
if (this.construct) {
59+
this.construct.apply(this, arguments);
60+
}
61+
};
62+
63+
constructor.prototype = SuperClass !== Object ? new SuperClass(creatingPrototype) : new SuperClass;
64+
65+
for (var methodName in methods) {
66+
67+
constructor.prototype[methodName] = (function (prototype, methodName, method) {
68+
return function () {
69+
var currentSuper = this.super;
70+
try {
71+
this.super = prototype;
72+
return method.apply(this, arguments);
73+
} finally {
74+
this.super = currentSuper;
75+
}
76+
};
77+
})(constructor.prototype[methodName], methodName, methods[methodName]);
78+
79+
constructor.prototype[methodName].displayName = methodName;
80+
81+
82+
}
83+
84+
85+
if (!constructor.prototype.decorateWith) {
86+
constructor.prototype.decorateWith = decorateWith;
87+
}
88+
89+
90+
return constructor;
91+
92+
}
93+
})();
94+
95+

0 commit comments

Comments
 (0)