Skip to content
This repository has been archived by the owner on Feb 22, 2018. It is now read-only.

Commit

Permalink
feat(selector): DirectiveSelector is real now: matchElement, matchText
Browse files Browse the repository at this point in the history
  • Loading branch information
jbdeboer committed Mar 11, 2014
1 parent 8016340 commit eb4422a
Show file tree
Hide file tree
Showing 4 changed files with 117 additions and 98 deletions.
209 changes: 114 additions & 95 deletions lib/core_dom/selector.dart
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,6 @@ part of angular.core.dom;
*
*
*/
typedef ElementBinder DirectiveSelector(dom.Node node);

class _Directive {
final Type type;
final NgAnnotation annotation;
Expand Down Expand Up @@ -239,21 +237,19 @@ List<_SelectorPart> _splitCss(String selector, Type type) {
return parts;
}

/**
* Factory for creating a [DirectiveSelector].
*/
@NgInjectableService()
class DirectiveSelectorFactory {
ElementBinderFactory _binderFactory;

DirectiveSelectorFactory(this._binderFactory);

DirectiveSelector selector(DirectiveMap directives) {

var elementSelector = new _ElementSelector('');
var attrSelector = <_ContainsSelector>[];
var textSelector = <_ContainsSelector>[];
directives.forEach((NgAnnotation annotation, Type type) {
class DirectiveSelector {
ElementBinderFactory _binderFactory;
DirectiveMap _directives;
var elementSelector;
var attrSelector;
var textSelector;

DirectiveSelector(this._directives, this._binderFactory) {
elementSelector = new _ElementSelector('');
attrSelector = <_ContainsSelector>[];
textSelector = <_ContainsSelector>[];
_directives.forEach((NgAnnotation annotation, Type type) {
var match;
var selector = annotation.selector;
List<_SelectorPart> selectorParts;
Expand All @@ -267,93 +263,116 @@ class DirectiveSelectorFactory {
attrSelector.add(new _ContainsSelector(annotation, match[1]));
} else if ((selectorParts = _splitCss(selector, type)) != null){
elementSelector.addDirective(selectorParts,
new _Directive(type, annotation));
new _Directive(type, annotation));
} else {
throw new ArgumentError('Unsupported Selector: $selector');
}
});
}

ElementBinder matchElement(dom.Node node) {
assert(node is dom.Element);

ElementBinder binder = _binderFactory.binder();
List<_ElementSelector> partialSelection;
var classes = <String, bool>{};
Map<String, String> attrs = {};

dom.Element element = node;
String nodeName = element.tagName.toLowerCase();

// Set default attribute
if (nodeName == 'input' && !element.attributes.containsKey('type')) {
element.attributes['type'] = 'text';
}

// Select node
partialSelection = elementSelector.selectNode(binder,
partialSelection, element, nodeName);

// Select .name
if ((element.classes) != null) {
for (var name in element.classes) {
classes[name] = true;
partialSelection = elementSelector.selectClass(binder,
partialSelection, element, name);
}
}

return (dom.Node node) {
//var directiveRefs = <DirectiveRef>[];
ElementBinder binder = _binderFactory.binder();
List<_ElementSelector> partialSelection;
var classes = <String, bool>{};
var attrs = <String, String>{};

switch(node.nodeType) {
case 1: // Element
dom.Element element = node;
String nodeName = element.tagName.toLowerCase();
Map<String, String> attrs = {};

// Set default attribute
if (nodeName == 'input' && !element.attributes.containsKey('type')) {
element.attributes['type'] = 'text';
}

// Select node
partialSelection = elementSelector.selectNode(binder,
partialSelection, element, nodeName);

// Select .name
if ((element.classes) != null) {
for (var name in element.classes) {
classes[name] = true;
partialSelection = elementSelector.selectClass(binder,
partialSelection, element, name);
}
}

// Select [attributes]
element.attributes.forEach((attrName, value) {
attrs[attrName] = value;
for (var k = 0; k < attrSelector.length; k++) {
_ContainsSelector selectorRegExp = attrSelector[k];
if (selectorRegExp.regexp.hasMatch(value)) {
// this directive is matched on any attribute name, and so
// we need to pass the name to the directive by prefixing it to
// the value. Yes it is a bit of a hack.
directives[selectorRegExp.annotation].forEach((type) {
binder.addDirective(new DirectiveRef(
node, type, selectorRegExp.annotation, '$attrName=$value'));
});
}
}

partialSelection = elementSelector.selectAttr(binder,
partialSelection, node, attrName, value);
// Select [attributes]
element.attributes.forEach((attrName, value) {
attrs[attrName] = value;
for (var k = 0; k < attrSelector.length; k++) {
_ContainsSelector selectorRegExp = attrSelector[k];
if (selectorRegExp.regexp.hasMatch(value)) {
// this directive is matched on any attribute name, and so
// we need to pass the name to the directive by prefixing it to
// the value. Yes it is a bit of a hack.
_directives[selectorRegExp.annotation].forEach((type) {
binder.addDirective(new DirectiveRef(
node, type, selectorRegExp.annotation, '$attrName=$value'));
});
}
}

partialSelection = elementSelector.selectAttr(binder,
partialSelection, node, attrName, value);
});

while(partialSelection != null) {
List<_ElementSelector> elementSelectors = partialSelection;
partialSelection = null;
elementSelectors.forEach((_ElementSelector elementSelector) {
classes.forEach((className, _) {
partialSelection = elementSelector.selectClass(binder,
partialSelection, node, className);
});
attrs.forEach((attrName, value) {
partialSelection = elementSelector.selectAttr(binder,
partialSelection, node, attrName, value);
});
});
}
break;
case 3: // Text Node
var value = node.nodeValue;
for (var k = 0; k < textSelector.length; k++) {
var selectorRegExp = textSelector[k];
if (selectorRegExp.regexp.hasMatch(value)) {
directives[selectorRegExp.annotation].forEach((type) {
binder.addDirective(new DirectiveRef(node, type,
selectorRegExp.annotation, value));
});
}
}
break;
while(partialSelection != null) {
List<_ElementSelector> elementSelectors = partialSelection;
partialSelection = null;
elementSelectors.forEach((_ElementSelector elementSelector) {
classes.forEach((className, _) {
partialSelection = elementSelector.selectClass(binder,
partialSelection, node, className);
});
attrs.forEach((attrName, value) {
partialSelection = elementSelector.selectAttr(binder,
partialSelection, node, attrName, value);
});
});
}
return binder;
}

ElementBinder matchText(dom.Node node) {
ElementBinder binder = _binderFactory.binder();

var value = node.nodeValue;
for (var k = 0; k < textSelector.length; k++) {
var selectorRegExp = textSelector[k];
if (selectorRegExp.regexp.hasMatch(value)) {
_directives[selectorRegExp.annotation].forEach((type) {
binder.addDirective(new DirectiveRef(node, type,
selectorRegExp.annotation, value));
});
}
}
return binder;
}
ElementBinder match(dom.Node node) {
switch(node.nodeType) {
case 1: // Element
return matchElement(node);

case 3: // Text Node
return matchText(node);
}
// TODO: This is wrong.
return _binderFactory.binder();
}
}
/**
* Factory for creating a [DirectiveSelector].
*/
@NgInjectableService()
class DirectiveSelectorFactory {
ElementBinderFactory _binderFactory;

return binder;
};
DirectiveSelectorFactory(this._binderFactory);

DirectiveSelector selector(DirectiveMap directives) {
return new DirectiveSelector(directives, _binderFactory);
}
}
2 changes: 1 addition & 1 deletion lib/core_dom/tagging_compiler.dart
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ class TaggingCompiler implements Compiler {

// TODO: selector will return null for non-useful bindings.
ElementBinder elementBinder = useExistingElementBinder == null
? directives.selector(node)
? directives.selector.match(node)
: useExistingElementBinder;

if (elementBinder.hasTemplate) {
Expand Down
2 changes: 1 addition & 1 deletion lib/core_dom/walking_compiler.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class WalkingCompiler implements Compiler {
var subtrees, binder;

ElementBinder elementBinder = existingElementBinder == null
? directives.selector(domCursor.current)
? directives.selector.match(domCursor.current)
: existingElementBinder;

if (elementBinder.hasTemplate) {
Expand Down
2 changes: 1 addition & 1 deletion test/core_dom/selector_spec.dart
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ main() {
..type(_TwoOfTwoDirectives);
}));
beforeEach(inject((DirectiveMap directives) {
selector = directives.selector;
selector = (node) => directives.selector.match(node);
}));

it('should match directive on element', () {
Expand Down

0 comments on commit eb4422a

Please sign in to comment.