Skip to content

Commit 051a7f8

Browse files
committed
+ slot event handlers
1 parent aadd501 commit 051a7f8

File tree

8 files changed

+271
-10
lines changed

8 files changed

+271
-10
lines changed

README.md

+3-2
Original file line numberDiff line numberDiff line change
@@ -253,8 +253,9 @@ Most simple MaskJS sample to show where you could start from:
253253
###Changelog
254254
------------
255255
- 0.12.2
256-
- `style` node syntax support with
257-
- `:host` support
256+
- `slot` and `event` javascript handlers ([handler](/test/dom/handler.test))
257+
- `style` node syntax support with ([style](/test/dom/style.test))
258+
- `:host`, `:host()` support
258259
- scoped css support (IE6+)
259260
```sass
260261
section {

lib/mask.js

+133-2
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,55 @@
304304
};
305305
}());
306306
// end:source /src/fn.js
307+
// source /src/class.js
308+
var class_create;
309+
(function(){
310+
class_create = function () {
311+
var args = _Array_slice.call(arguments),
312+
Proto = args.pop();
313+
if (Proto == null) {
314+
Proto = {};
315+
}
316+
var Ctor = Proto.hasOwnProperty('constructor')
317+
? Proto.constructor
318+
: null,
319+
BaseCtor;
320+
321+
322+
var i = args.length, x, Parent;
323+
while ( --i > -1 ) {
324+
x = args[i];
325+
if (typeof x === 'function') {
326+
if (Ctor == null && BaseCtor == null)
327+
BaseCtor = x;
328+
329+
x = x.prototype;
330+
}
331+
for(var key in x){
332+
if (Proto[key] == null) {
333+
Proto[key] = x[key];
334+
}
335+
}
336+
if (Parent == null) {
337+
Parent = x;
338+
}
339+
}
340+
341+
Proto.Parent = Parent
342+
343+
if (Ctor == null) {
344+
Ctor = function(){
345+
var args = _Array_slice.call(arguments);
346+
if (BaseCtor)
347+
return BaseCtor.apply(this, args);
348+
};
349+
}
350+
351+
Ctor.prototype = Proto;
352+
return Ctor;
353+
};
354+
}());
355+
// end:source /src/class.js
307356

308357
// source /src/refs.js
309358
var _Array_slice = Array.prototype.slice,
@@ -3604,6 +3653,90 @@
36043653
}
36053654
}());
36063655
// end:source ./parsers/var.js
3656+
// source ./parsers/slot.js
3657+
(function(){
3658+
3659+
function create(Ctor){
3660+
return function(str, i, imax, parent) {
3661+
var start = str.indexOf('{', i) + 1,
3662+
head = parseHead(
3663+
str.substring(i, start - 1)
3664+
),
3665+
end = cursor_groupEnd(str, start, imax, 123, 125),
3666+
body = str.substring(start, end)
3667+
;
3668+
3669+
return [ new Ctor(head, body, parent), end + 1 ];
3670+
};
3671+
}
3672+
3673+
function parseHead(head) {
3674+
var parts = /(\w+)\s*\(([^\)]*)\)/.exec(head);
3675+
if (parts == null) {
3676+
log_error('`slot` has invalid head syntax', head);
3677+
return null;
3678+
}
3679+
var arr = [ parts[1] ];
3680+
arr = arr.concat(
3681+
parts[2].replace(/\s/g, '').split(',')
3682+
);
3683+
return arr;
3684+
}
3685+
3686+
function Handler(head, body, parent) {
3687+
this.name = head.shift();
3688+
this.args = head;
3689+
this.body = body;
3690+
this.fn = this.compile();
3691+
this.parent = parent;
3692+
}
3693+
Handler.prototype = {
3694+
type: Dom.COMPONENT,
3695+
controller: null,
3696+
elements: null,
3697+
model: null,
3698+
stringify: function(){
3699+
return this.tagName
3700+
+ this.name
3701+
+ '('
3702+
+ this.args.join(',')
3703+
+ ') {'
3704+
+ this.body
3705+
+ '}'
3706+
;
3707+
},
3708+
compile: function(){
3709+
var arr = _Array_slice.call(this.args);
3710+
arr.push(this.body);
3711+
3712+
return new (Function.bind.apply(Function, [null].concat(arr)));
3713+
},
3714+
render: function() {}
3715+
};
3716+
3717+
var Slot = class_create(Handler, {
3718+
tagName: 'slot',
3719+
render: function(model, ctx, container, ctr) {
3720+
var slots = ctr.slots;
3721+
if (slots == null) {
3722+
slots = ctr.slots = {};
3723+
}
3724+
3725+
slots[this.name] = this.fn;
3726+
}
3727+
});
3728+
var Event = class_create(Handler, {
3729+
tagName: 'event',
3730+
render: function(model, ctx, container) {
3731+
container.addEventListener(this.name, this.fn, false);
3732+
}
3733+
});
3734+
3735+
custom_Parsers['slot' ] = create(Slot);
3736+
custom_Parsers['event'] = create(Event);
3737+
3738+
}());
3739+
// end:source ./parsers/slot.js
36073740
// source ./parsers/style.js
36083741
(function(){
36093742
custom_Parsers['style'] = function(str, i, imax, parent){
@@ -3722,8 +3855,6 @@
37223855
}());
37233856
// end:source ./parsers/style.js
37243857

3725-
3726-
37273858
var go_tag = 2,
37283859
state_tag = 3,
37293860
state_attr = 5,

lib/mask.min.js

+2-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/mask.min.js.map

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/parse/parser.js

+1-2
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,9 @@ var parser_parse,
2727
// import ./cursor.js
2828
// import ./function.js
2929
// import ./parsers/var.js
30+
// import ./parsers/slot.js
3031
// import ./parsers/style.js
3132

32-
33-
3433
var go_tag = 2,
3534
state_tag = 3,
3635
state_attr = 5,

src/parse/parsers/slot.js

+82
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
(function(){
2+
3+
function create(Ctor){
4+
return function(str, i, imax, parent) {
5+
var start = str.indexOf('{', i) + 1,
6+
head = parseHead(
7+
str.substring(i, start - 1)
8+
),
9+
end = cursor_groupEnd(str, start, imax, 123, 125),
10+
body = str.substring(start, end)
11+
;
12+
13+
return [ new Ctor(head, body, parent), end + 1 ];
14+
};
15+
}
16+
17+
function parseHead(head) {
18+
var parts = /(\w+)\s*\(([^\)]*)\)/.exec(head);
19+
if (parts == null) {
20+
log_error('`slot` has invalid head syntax', head);
21+
return null;
22+
}
23+
var arr = [ parts[1] ];
24+
arr = arr.concat(
25+
parts[2].replace(/\s/g, '').split(',')
26+
);
27+
return arr;
28+
}
29+
30+
function Handler(head, body, parent) {
31+
this.name = head.shift();
32+
this.args = head;
33+
this.body = body;
34+
this.fn = this.compile();
35+
this.parent = parent;
36+
}
37+
Handler.prototype = {
38+
type: Dom.COMPONENT,
39+
controller: null,
40+
elements: null,
41+
model: null,
42+
stringify: function(){
43+
return this.tagName
44+
+ this.name
45+
+ '('
46+
+ this.args.join(',')
47+
+ ') {'
48+
+ this.body
49+
+ '}'
50+
;
51+
},
52+
compile: function(){
53+
var arr = _Array_slice.call(this.args);
54+
arr.push(this.body);
55+
56+
return new (Function.bind.apply(Function, [null].concat(arr)));
57+
},
58+
render: function() {}
59+
};
60+
61+
var Slot = class_create(Handler, {
62+
tagName: 'slot',
63+
render: function(model, ctx, container, ctr) {
64+
var slots = ctr.slots;
65+
if (slots == null) {
66+
slots = ctr.slots = {};
67+
}
68+
69+
slots[this.name] = this.fn;
70+
}
71+
});
72+
var Event = class_create(Handler, {
73+
tagName: 'event',
74+
render: function(model, ctx, container) {
75+
container.addEventListener(this.name, this.fn, false);
76+
}
77+
});
78+
79+
custom_Parsers['slot' ] = create(Slot);
80+
custom_Parsers['event'] = create(Event);
81+
82+
}());

test/dom/compo/handler.test

+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
UTest({
2+
'slot test' () {
3+
mask.registerHandler(':foo', Compo({}));
4+
5+
var template = `
6+
section {
7+
:foo {
8+
slot fooTest (event) {
9+
$(event.currentTarget).text('Baz');
10+
}
11+
12+
button x-signal='click: fooTest' > 'Foo'
13+
}
14+
}
15+
`
16+
17+
var $dom = $(mask.render(template)).appendTo('body');
18+
19+
$dom
20+
.find('button')
21+
.eq_('text', 'Foo')
22+
.click()
23+
.eq_('text', 'Baz')
24+
.remove();
25+
},
26+
27+
'event test' () {
28+
var template = `
29+
section {
30+
button {
31+
event click (event) {
32+
this.textContent = 'Baz'
33+
}
34+
'Foo'
35+
}
36+
}
37+
`
38+
39+
var $dom = $(mask.render(template)).appendTo('body');
40+
41+
$dom
42+
.find('button')
43+
.eq_('text', 'Foo')
44+
.click()
45+
.eq_('text', 'Baz')
46+
.remove();
47+
}
48+
})

0 commit comments

Comments
 (0)