@@ -7,26 +7,159 @@ part of angular.core.dom_internal;
7
7
* DirectiveSelector is used by the [Compiler] during the template walking
8
8
* to extract the [DirectiveRef] s.
9
9
*
10
- * DirectiveSelector can be created using the [directiveSelectorFactory]
11
- * method.
10
+ * DirectiveSelector can be created using the [DirectiveSelectorFactory] .
12
11
*
13
12
* The DirectiveSelector supports CSS selectors which do not cross
14
13
* element boundaries only. The selectors can have any mix of element-name,
15
14
* class-names and attribute-names.
16
15
*
17
16
* Examples:
18
17
*
19
- * <pre>
20
- * element
21
- * .class
22
- * [attribute]
23
- * [attribute=value]
24
- * element[attribute1][attribute2=value]
25
- * :contains(/abc/)
26
- * </pre>
27
- *
28
- *
18
+ * * element
19
+ * * .class
20
+ * * [attribute]
21
+ * * [attribute=value]
22
+ * * element[attribute1][attribute2=value]
23
+ * * :contains(/abc/)
29
24
*/
25
+ class DirectiveSelector {
26
+ ElementBinderFactory _binderFactory;
27
+ DirectiveMap _directives;
28
+ var elementSelector;
29
+ var attrSelector;
30
+ var textSelector;
31
+
32
+ DirectiveSelector (this ._directives, this ._binderFactory) {
33
+ elementSelector = new _ElementSelector ('' );
34
+ attrSelector = < _ContainsSelector > [];
35
+ textSelector = < _ContainsSelector > [];
36
+ _directives.forEach ((Directive annotation, Type type) {
37
+ var match;
38
+ var selector = annotation.selector;
39
+ List <_SelectorPart > selectorParts;
40
+ if (selector == null ) {
41
+ throw new ArgumentError ('Missing selector annotation for $type ' );
42
+ }
43
+
44
+ if ((match = _CONTAINS_REGEXP .firstMatch (selector)) != null ) {
45
+ textSelector.add (new _ContainsSelector (annotation, match.group (1 )));
46
+ } else if ((match = _ATTR_CONTAINS_REGEXP .firstMatch (selector)) != null ) {
47
+ attrSelector.add (new _ContainsSelector (annotation, match[1 ]));
48
+ } else if ((selectorParts = _splitCss (selector, type)) != null ){
49
+ elementSelector.addDirective (selectorParts,
50
+ new _Directive (type, annotation));
51
+ } else {
52
+ throw new ArgumentError ('Unsupported Selector: $selector ' );
53
+ }
54
+ });
55
+ }
56
+
57
+ ElementBinder matchElement (dom.Node node) {
58
+ assert (node is dom.Element );
59
+
60
+ ElementBinderBuilder builder = _binderFactory.builder ();
61
+ List <_ElementSelector > partialSelection;
62
+ var classes = < String , bool > {};
63
+ Map <String , String > attrs = {};
64
+
65
+ dom.Element element = node;
66
+ String nodeName = element.tagName.toLowerCase ();
67
+
68
+ // Set default attribute
69
+ if (nodeName == 'input' && ! element.attributes.containsKey ('type' )) {
70
+ element.attributes['type' ] = 'text' ;
71
+ }
72
+
73
+ // Select node
74
+ partialSelection = elementSelector.selectNode (builder,
75
+ partialSelection, element, nodeName);
76
+
77
+ // Select .name
78
+ if ((element.classes) != null ) {
79
+ for (var name in element.classes) {
80
+ classes[name] = true ;
81
+ partialSelection = elementSelector.selectClass (builder,
82
+ partialSelection, element, name);
83
+ }
84
+ }
85
+
86
+ // Select [attributes]
87
+ element.attributes.forEach ((attrName, value) {
88
+
89
+ if (attrName.startsWith ("on-" )) {
90
+ builder.onEvents[attrName] = value;
91
+ } else if (attrName.startsWith ("bind-" )) {
92
+ builder.bindAttrs[attrName] = value;
93
+ }
94
+
95
+ attrs[attrName] = value;
96
+ for (var k = 0 ; k < attrSelector.length; k++ ) {
97
+ _ContainsSelector selectorRegExp = attrSelector[k];
98
+ if (selectorRegExp.regexp.hasMatch (value)) {
99
+ // this directive is matched on any attribute name, and so
100
+ // we need to pass the name to the directive by prefixing it to
101
+ // the value. Yes it is a bit of a hack.
102
+ _directives[selectorRegExp.annotation].forEach ((type) {
103
+ builder.addDirective (new DirectiveRef (
104
+ node, type, selectorRegExp.annotation, '$attrName =$value ' ));
105
+ });
106
+ }
107
+ }
108
+
109
+ partialSelection = elementSelector.selectAttr (builder,
110
+ partialSelection, node, attrName, value);
111
+ });
112
+
113
+ while (partialSelection != null ) {
114
+ List <_ElementSelector > elementSelectors = partialSelection;
115
+ partialSelection = null ;
116
+ elementSelectors.forEach ((_ElementSelector elementSelector) {
117
+ classes.forEach ((className, _) {
118
+ partialSelection = elementSelector.selectClass (builder,
119
+ partialSelection, node, className);
120
+ });
121
+ attrs.forEach ((attrName, value) {
122
+ partialSelection = elementSelector.selectAttr (builder,
123
+ partialSelection, node, attrName, value);
124
+ });
125
+ });
126
+ }
127
+ return builder.binder;
128
+ }
129
+
130
+ ElementBinder matchText (dom.Node node) {
131
+ ElementBinderBuilder builder = _binderFactory.builder ();
132
+
133
+ var value = node.nodeValue;
134
+ for (var k = 0 ; k < textSelector.length; k++ ) {
135
+ var selectorRegExp = textSelector[k];
136
+ if (selectorRegExp.regexp.hasMatch (value)) {
137
+ _directives[selectorRegExp.annotation].forEach ((type) {
138
+ builder.addDirective (new DirectiveRef (node, type,
139
+ selectorRegExp.annotation, value));
140
+ });
141
+ }
142
+ }
143
+ return builder.binder;
144
+ }
145
+
146
+ ElementBinder matchComment (dom.Node node) =>
147
+ _binderFactory.builder ().binder;
148
+ }
149
+
150
+ /**
151
+ * Factory for creating a [DirectiveSelector] .
152
+ */
153
+ @Injectable ()
154
+ class DirectiveSelectorFactory {
155
+ ElementBinderFactory _binderFactory;
156
+
157
+ DirectiveSelectorFactory (this ._binderFactory);
158
+
159
+ DirectiveSelector selector (DirectiveMap directives) =>
160
+ new DirectiveSelector (directives, _binderFactory);
161
+ }
162
+
30
163
class _Directive {
31
164
final Type type;
32
165
final Directive annotation;
@@ -36,7 +169,6 @@ class _Directive {
36
169
toString () => annotation.selector;
37
170
}
38
171
39
-
40
172
class _ContainsSelector {
41
173
final Directive annotation;
42
174
final RegExp regexp;
@@ -239,145 +371,3 @@ List<_SelectorPart> _splitCss(String selector, Type type) {
239
371
}
240
372
return parts;
241
373
}
242
-
243
-
244
- class DirectiveSelector {
245
- ElementBinderFactory _binderFactory;
246
- DirectiveMap _directives;
247
- var elementSelector;
248
- var attrSelector;
249
- var textSelector;
250
-
251
- DirectiveSelector (this ._directives, this ._binderFactory) {
252
- elementSelector = new _ElementSelector ('' );
253
- attrSelector = < _ContainsSelector > [];
254
- textSelector = < _ContainsSelector > [];
255
- _directives.forEach ((Directive annotation, Type type) {
256
- var match;
257
- var selector = annotation.selector;
258
- List <_SelectorPart > selectorParts;
259
- if (selector == null ) {
260
- throw new ArgumentError ('Missing selector annotation for $type ' );
261
- }
262
-
263
- if ((match = _CONTAINS_REGEXP .firstMatch (selector)) != null ) {
264
- textSelector.add (new _ContainsSelector (annotation, match.group (1 )));
265
- } else if ((match = _ATTR_CONTAINS_REGEXP .firstMatch (selector)) != null ) {
266
- attrSelector.add (new _ContainsSelector (annotation, match[1 ]));
267
- } else if ((selectorParts = _splitCss (selector, type)) != null ){
268
- elementSelector.addDirective (selectorParts,
269
- new _Directive (type, annotation));
270
- } else {
271
- throw new ArgumentError ('Unsupported Selector: $selector ' );
272
- }
273
- });
274
- }
275
-
276
- ElementBinder matchElement (dom.Node node) {
277
- assert (node is dom.Element );
278
-
279
- ElementBinderBuilder builder = _binderFactory.builder ();
280
- List <_ElementSelector > partialSelection;
281
- var classes = < String , bool > {};
282
- Map <String , String > attrs = {};
283
-
284
- dom.Element element = node;
285
- String nodeName = element.tagName.toLowerCase ();
286
-
287
- // Set default attribute
288
- if (nodeName == 'input' && ! element.attributes.containsKey ('type' )) {
289
- element.attributes['type' ] = 'text' ;
290
- }
291
-
292
- // Select node
293
- partialSelection = elementSelector.selectNode (builder,
294
- partialSelection, element, nodeName);
295
-
296
- // Select .name
297
- if ((element.classes) != null ) {
298
- for (var name in element.classes) {
299
- classes[name] = true ;
300
- partialSelection = elementSelector.selectClass (builder,
301
- partialSelection, element, name);
302
- }
303
- }
304
-
305
- // Select [attributes]
306
- element.attributes.forEach ((attrName, value) {
307
-
308
- if (attrName.startsWith ("on-" )) {
309
- builder.onEvents[attrName] = value;
310
- }
311
-
312
- if (attrName.startsWith ("bind-" )) {
313
- builder.bindAttrs[attrName] = value;
314
- }
315
-
316
- attrs[attrName] = value;
317
- for (var k = 0 ; k < attrSelector.length; k++ ) {
318
- _ContainsSelector selectorRegExp = attrSelector[k];
319
- if (selectorRegExp.regexp.hasMatch (value)) {
320
- // this directive is matched on any attribute name, and so
321
- // we need to pass the name to the directive by prefixing it to
322
- // the value. Yes it is a bit of a hack.
323
- _directives[selectorRegExp.annotation].forEach ((type) {
324
- builder.addDirective (new DirectiveRef (
325
- node, type, selectorRegExp.annotation, '$attrName =$value ' ));
326
- });
327
- }
328
- }
329
-
330
- partialSelection = elementSelector.selectAttr (builder,
331
- partialSelection, node, attrName, value);
332
- });
333
-
334
- while (partialSelection != null ) {
335
- List <_ElementSelector > elementSelectors = partialSelection;
336
- partialSelection = null ;
337
- elementSelectors.forEach ((_ElementSelector elementSelector) {
338
- classes.forEach ((className, _) {
339
- partialSelection = elementSelector.selectClass (builder,
340
- partialSelection, node, className);
341
- });
342
- attrs.forEach ((attrName, value) {
343
- partialSelection = elementSelector.selectAttr (builder,
344
- partialSelection, node, attrName, value);
345
- });
346
- });
347
- }
348
- return builder.binder;
349
- }
350
-
351
- ElementBinder matchText (dom.Node node) {
352
- ElementBinderBuilder builder = _binderFactory.builder ();
353
-
354
- var value = node.nodeValue;
355
- for (var k = 0 ; k < textSelector.length; k++ ) {
356
- var selectorRegExp = textSelector[k];
357
- if (selectorRegExp.regexp.hasMatch (value)) {
358
- _directives[selectorRegExp.annotation].forEach ((type) {
359
- builder.addDirective (new DirectiveRef (node, type,
360
- selectorRegExp.annotation, value));
361
- });
362
- }
363
- }
364
- return builder.binder;
365
- }
366
-
367
- ElementBinder matchComment (dom.Node node) {
368
- return _binderFactory.builder ().binder;
369
- }
370
- }
371
- /**
372
- * Factory for creating a [DirectiveSelector] .
373
- */
374
- @Injectable ()
375
- class DirectiveSelectorFactory {
376
- ElementBinderFactory _binderFactory;
377
-
378
- DirectiveSelectorFactory (this ._binderFactory);
379
-
380
- DirectiveSelector selector (DirectiveMap directives) {
381
- return new DirectiveSelector (directives, _binderFactory);
382
- }
383
- }
0 commit comments