From eb4422a9a2d0d0dbdb2fb9d04fdcbcae99b65757 Mon Sep 17 00:00:00 2001 From: James deBoer Date: Thu, 6 Mar 2014 16:42:34 -0800 Subject: [PATCH] feat(selector): DirectiveSelector is real now: matchElement, matchText --- lib/core_dom/selector.dart | 209 ++++++++++++++++------------- lib/core_dom/tagging_compiler.dart | 2 +- lib/core_dom/walking_compiler.dart | 2 +- test/core_dom/selector_spec.dart | 2 +- 4 files changed, 117 insertions(+), 98 deletions(-) diff --git a/lib/core_dom/selector.dart b/lib/core_dom/selector.dart index fb6eaa8a8..94528d605 100644 --- a/lib/core_dom/selector.dart +++ b/lib/core_dom/selector.dart @@ -27,8 +27,6 @@ part of angular.core.dom; * * */ -typedef ElementBinder DirectiveSelector(dom.Node node); - class _Directive { final Type type; final NgAnnotation annotation; @@ -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; @@ -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 = {}; + Map 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 = []; - ElementBinder binder = _binderFactory.binder(); - List<_ElementSelector> partialSelection; - var classes = {}; - var attrs = {}; - - switch(node.nodeType) { - case 1: // Element - dom.Element element = node; - String nodeName = element.tagName.toLowerCase(); - Map 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); } } diff --git a/lib/core_dom/tagging_compiler.dart b/lib/core_dom/tagging_compiler.dart index 2d0455172..885bdc587 100644 --- a/lib/core_dom/tagging_compiler.dart +++ b/lib/core_dom/tagging_compiler.dart @@ -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) { diff --git a/lib/core_dom/walking_compiler.dart b/lib/core_dom/walking_compiler.dart index 2c9acbc39..2fea5f088 100644 --- a/lib/core_dom/walking_compiler.dart +++ b/lib/core_dom/walking_compiler.dart @@ -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) { diff --git a/test/core_dom/selector_spec.dart b/test/core_dom/selector_spec.dart index beeebec7c..ebb345979 100644 --- a/test/core_dom/selector_spec.dart +++ b/test/core_dom/selector_spec.dart @@ -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', () {