diff --git a/lib/angular.dart b/lib/angular.dart index bfa6e80bd..20da6376f 100644 --- a/lib/angular.dart +++ b/lib/angular.dart @@ -16,80 +16,4 @@ import 'exception_handler.dart'; export 'exception_handler.dart'; import 'parser/parser_library.dart'; export 'parser/parser_library.dart'; import 'dom/all.dart'; export 'dom/all.dart'; import 'directives/all.dart'; export 'directives/all.dart'; - - -class AngularModule extends Module { - DirectiveRegistry _directives = new DirectiveRegistry(); - ControllerRegistry _controllers = new ControllerRegistry(); - - AngularModule() { - value(DirectiveRegistry, _directives); - value(ControllerRegistry, _controllers); - type(Compiler); - type(ExceptionHandler); - type(Scope); - type(Parser, implementedBy: DynamicParser); - type(DynamicParser); - type(Lexer); - type(ParserBackend); - type(Interpolate); - type(Http); - type(UrlRewriter); - type(HttpBackend); - type(BlockCache); - type(TemplateCache); - type(GetterSetter); - type(Profiler); - type(ScopeDigestTTL); - type(dom.NodeTreeSanitizer, implementedBy: NullTreeSanitizer); - - - directive(NgTextMustacheDirective); - directive(NgAttrMustacheDirective); - - directive(NgBindAttrDirective); - directive(NgClassAttrDirective); - directive(NgClickAttrDirective); - directive(NgCloakAttrDirective); - directive(NgControllerAttrDirective); - directive(NgDisabledAttrDirective); - directive(NgHideAttrDirective); - directive(NgIfAttrDirective); - directive(NgIncludeAttrDirective); - directive(NgRepeatAttrDirective); - directive(NgShowAttrDirective); - - directive(InputTextDirective); - directive(InputCheckboxDirective); - directive(NgModel); - } - - directive(Type directive) { - _directives.register(directive); - return this; - } - - controller(String name, Type controllerType) { - _controllers.register(name, controllerType); - type(controllerType); - } -} - - -// helper for bootstrapping angular -bootstrapAngular(modules, [rootElementSelector = '[ng-app]']) { - var allModules = new List.from(modules); - List topElt = dom.query(rootElementSelector).nodes.toList(); - assert(topElt.length > 0); - - // The injector must be created inside the zone, so we create the - // zone manually and give it back to the injector as a value. - Zone zone = new Zone(); - allModules.add(new Module()..value(Zone, zone)); - - zone.run(() { - Injector injector = new DynamicInjector(modules: allModules); - injector.get(Compiler)(topElt)(injector, topElt); - }); -} - +import 'bootstrap.dart'; export 'bootstrap.dart'; diff --git a/lib/bootstrap.dart b/lib/bootstrap.dart new file mode 100644 index 000000000..7799bf60b --- /dev/null +++ b/lib/bootstrap.dart @@ -0,0 +1,77 @@ +library angular; + +import 'package:di/di.dart'; +import 'package:di/dynamic_injector.dart'; +import 'package:perf_api/perf_api.dart'; + +import 'dart:html' as dom; // TODO(misko): to be deleted +import 'controller.dart'; + +import 'zone.dart'; +import 'cache.dart'; +import 'interpolate.dart'; +import 'dom/http.dart'; +import 'scope.dart'; +import 'exception_handler.dart'; +import 'parser/parser_library.dart'; +import 'dom/all.dart'; +import 'directives/all.dart'; + + +class AngularModule extends Module { + DirectiveRegistry _directives = new DirectiveRegistry(); + ControllerRegistry _controllers = new ControllerRegistry(); + + AngularModule() { + value(DirectiveRegistry, _directives); + value(ControllerRegistry, _controllers); + type(Compiler); + type(ExceptionHandler); + type(Scope); + type(Parser, implementedBy: DynamicParser); + type(DynamicParser); + type(Lexer); + type(ParserBackend); + type(Interpolate); + type(Http); + type(UrlRewriter); + type(HttpBackend); + type(BlockCache); + type(TemplateCache); + type(GetterSetter); + type(Profiler); + type(ScopeDigestTTL); + type(dom.NodeTreeSanitizer, implementedBy: NullTreeSanitizer); + + registerDirectives(this); + } + + directive(Type directive) { + _directives.register(directive); + return this; + } + + controller(String name, Type controllerType) { + _controllers.register(name, controllerType); + type(controllerType); + } +} + + +// helper for bootstrapping angular +bootstrapAngular(modules, [rootElementSelector = '[ng-app]']) { + var allModules = new List.from(modules); + List topElt = dom.query(rootElementSelector).nodes.toList(); + assert(topElt.length > 0); + + // The injector must be created inside the zone, so we create the + // zone manually and give it back to the injector as a value. + Zone zone = new Zone(); + allModules.add(new Module()..value(Zone, zone)); + + zone.run(() { + Injector injector = new DynamicInjector(modules: allModules); + injector.get(Compiler)(topElt)(injector, topElt); + }); +} + diff --git a/lib/directives/all.dart b/lib/directives/all.dart index 8196e553b..b2dc2a678 100644 --- a/lib/directives/all.dart +++ b/lib/directives/all.dart @@ -1,9 +1,11 @@ library angular.directives.all; +import '../bootstrap.dart'; + import "ng_mustache.dart"; import 'ng_bind.dart'; import 'ng_class.dart'; -import 'ng_click.dart'; +import 'ng_events.dart'; import 'ng_cloak.dart'; import 'ng_controller.dart'; import 'ng_disabled.dart'; @@ -17,7 +19,7 @@ import 'ng_show.dart'; export "ng_mustache.dart"; export 'ng_bind.dart'; export 'ng_class.dart'; -export 'ng_click.dart'; +export 'ng_events.dart'; export 'ng_cloak.dart'; export 'ng_controller.dart'; export 'ng_disabled.dart'; @@ -28,3 +30,49 @@ export 'ng_model.dart'; export 'ng_repeat.dart'; export 'ng_show.dart'; +void registerDirectives(AngularModule module) { + module.directive(NgTextMustacheDirective); + module.directive(NgAttrMustacheDirective); + module.directive(NgBindAttrDirective); + module.directive(NgClassAttrDirective); + module.directive(NgCloakAttrDirective); + module.directive(NgControllerAttrDirective); + module.directive(NgDisabledAttrDirective); + module.directive(NgHideAttrDirective); + module.directive(NgIfAttrDirective); + module.directive(NgIncludeAttrDirective); + module.directive(NgRepeatAttrDirective); + module.directive(NgShowAttrDirective); + module.directive(InputTextDirective); + module.directive(InputCheckboxDirective); + module.directive(NgModel); + + module.directive(NgBlurAttrDirective); + module.directive(NgChangeAttrDirective); + module.directive(NgClickAttrDirective); + module.directive(NgContextMenuAttrDirective); + module.directive(NgDragAttrDirective); + module.directive(NgDragEndAttrDirective); + module.directive(NgDragEnterAttrDirective); + module.directive(NgDragLeaveAttrDirective); + module.directive(NgDragOverAttrDirective); + module.directive(NgDragStartAttrDirective); + module.directive(NgDropAttrDirective); + module.directive(NgFocusAttrDirective); + module.directive(NgKeyDownAttrDirective); + module.directive(NgKeyPressAttrDirective); + module.directive(NgKeyUpAttrDirective); + module.directive(NgMouseDownAttrDirective); + module.directive(NgMouseEnterAttrDirective); + module.directive(NgMouseLeaveAttrDirective); + module.directive(NgMouseMoveAttrDirective); + module.directive(NgMouseOutAttrDirective); + module.directive(NgMouseOverAttrDirective); + module.directive(NgMouseUpAttrDirective); + module.directive(NgMouseWheelAttrDirective); + module.directive(NgScrollAttrDirective); + module.directive(NgTouchCancelAttrDirective); + module.directive(NgTouchEndAttrDirective); + module.directive(NgTouchMoveAttrDirective); + module.directive(NgTouchStartAttrDirective); +} \ No newline at end of file diff --git a/lib/directives/ng_click.dart b/lib/directives/ng_click.dart deleted file mode 100644 index 0d92c5e4a..000000000 --- a/lib/directives/ng_click.dart +++ /dev/null @@ -1,19 +0,0 @@ -library angular.directive.ng_click; - -import "dart:html" as dom; -import "../dom/directive.dart"; -import "../scope.dart"; - -@NgDirective( - selector: '[ng-click]', - map: const {'ng-click': '&.onClick'} -) -class NgClickAttrDirective { - Function onClick; - - NgClickAttrDirective(dom.Element element, Scope scope) { - element.onClick.listen((event) => scope.$apply(() { - onClick({r"$event": event}); - })); - } -} diff --git a/lib/directives/ng_events.dart b/lib/directives/ng_events.dart new file mode 100644 index 000000000..f4a5b8892 --- /dev/null +++ b/lib/directives/ng_events.dart @@ -0,0 +1,424 @@ +library angular.directive.ng_click; + +import "dart:html" as dom; +import "../dom/directive.dart"; +import "../scope.dart"; + +@NgDirective( + selector: '[ng-blur]', + map: const {'ng-blur': '&.onBlur'} +) +class NgBlurAttrDirective { + Getter onBlur; + + NgBlurAttrDirective(dom.Element element, Scope scope) { + element.onBlur.listen((event) => scope.$apply(() { + onBlur({r"$event": event}); + })); + } +} + + +@NgDirective( + selector: '[ng-change]', + map: const {'ng-change': '&.onChange'} +) +class NgChangeAttrDirective { + Getter onChange; + + NgChangeAttrDirective(dom.Element element, Scope scope) { + element.onChange.listen((event) => scope.$apply(() { + onChange({r"$event": event}); + })); + } +} + + +@NgDirective( + selector: '[ng-click]', + map: const {'ng-click': '&.onClick'} +) +class NgClickAttrDirective { + Getter onClick; + + NgClickAttrDirective(dom.Element element, Scope scope) { + element.onClick.listen((event) => scope.$apply(() { + onClick({r"$event": event}); + })); + } +} + + +@NgDirective( + selector: '[ng-contextmenu]', + map: const {'ng-contextmenu': '&.onContextMenu'} +) +class NgContextMenuAttrDirective { + Getter onContextMenu; + + NgContextMenuAttrDirective(dom.Element element, Scope scope) { + element.onContextMenu.listen((event) => scope.$apply(() { + onContextMenu({r"$event": event}); + })); + } +} + + +@NgDirective( + selector: '[ng-drag]', + map: const {'ng-drag': '&.onDrag'} +) +class NgDragAttrDirective { + Getter onDrag; + + NgDragAttrDirective(dom.Element element, Scope scope) { + element.onDrag.listen((event) => scope.$apply(() { + onDrag({r"$event": event}); + })); + } +} + + +@NgDirective( + selector: '[ng-dragend]', + map: const {'ng-dragend': '&.onDragEnd'} +) +class NgDragEndAttrDirective { + Getter onDragEnd; + + NgDragEndAttrDirective(dom.Element element, Scope scope) { + element.onDragEnd.listen((event) => scope.$apply(() { + onDragEnd({r"$event": event}); + })); + } +} + + +@NgDirective( + selector: '[ng-dragenter]', + map: const {'ng-dragenter': '&.onDragEnter'} +) +class NgDragEnterAttrDirective { + Getter onDragEnter; + + NgDragEnterAttrDirective(dom.Element element, Scope scope) { + element.onDragEnter.listen((event) => scope.$apply(() { + onDragEnter({r"$event": event}); + })); + } +} + + +@NgDirective( + selector: '[ng-dragleave]', + map: const {'ng-dragleave': '&.onDragLeave'} +) +class NgDragLeaveAttrDirective { + Getter onDragLeave; + + NgDragLeaveAttrDirective(dom.Element element, Scope scope) { + element.onDragLeave.listen((event) => scope.$apply(() { + onDragLeave({r"$event": event}); + })); + } +} + + +@NgDirective( + selector: '[ng-dragover]', + map: const {'ng-dragover': '&.onDragOver'} +) +class NgDragOverAttrDirective { + Getter onDragOver; + + NgDragOverAttrDirective(dom.Element element, Scope scope) { + element.onDragOver.listen((event) => scope.$apply(() { + onDragOver({r"$event": event}); + })); + } +} + + +@NgDirective( + selector: '[ng-dragstart]', + map: const {'ng-dragstart': '&.onDragStart'} +) +class NgDragStartAttrDirective { + Getter onDragStart; + + NgDragStartAttrDirective(dom.Element element, Scope scope) { + element.onDragStart.listen((event) => scope.$apply(() { + onDragStart({r"$event": event}); + })); + } +} + + +@NgDirective( + selector: '[ng-drop]', + map: const {'ng-drop': '&.onDrop'} +) +class NgDropAttrDirective { + Getter onDrop; + + NgDropAttrDirective(dom.Element element, Scope scope) { + element.onDrop.listen((event) => scope.$apply(() { + onDrop({r"$event": event}); + })); + } +} + + +@NgDirective( + selector: '[ng-focus]', + map: const {'ng-focus': '&.onFocus'} +) +class NgFocusAttrDirective { + Getter onFocus; + + NgFocusAttrDirective(dom.Element element, Scope scope) { + element.onFocus.listen((event) => scope.$apply(() { + onFocus({r"$event": event}); + })); + } +} + + +@NgDirective( + selector: '[ng-keydown]', + map: const {'ng-keydown': '&.onKeyDown'} +) +class NgKeyDownAttrDirective { + Getter onKeyDown; + + NgKeyDownAttrDirective(dom.Element element, Scope scope) { + element.onKeyDown.listen((event) => scope.$apply(() { + onKeyDown({r"$event": event}); + })); + } +} + + +@NgDirective( + selector: '[ng-keypress]', + map: const {'ng-keypress': '&.onKeyPress'} +) +class NgKeyPressAttrDirective { + Getter onKeyPress; + + NgKeyPressAttrDirective(dom.Element element, Scope scope) { + element.onKeyPress.listen((event) => scope.$apply(() { + onKeyPress({r"$event": event}); + })); + } +} + + +@NgDirective( + selector: '[ng-keyup]', + map: const {'ng-keyup': '&.onKeyUp'} +) +class NgKeyUpAttrDirective { + Getter onKeyUp; + + NgKeyUpAttrDirective(dom.Element element, Scope scope) { + element.onKeyUp.listen((event) => scope.$apply(() { + onKeyUp({r"$event": event}); + })); + } +} + + +@NgDirective( + selector: '[ng-mousedown]', + map: const {'ng-mousedown': '&.onMouseDown'} +) +class NgMouseDownAttrDirective { + Getter onMouseDown; + + NgMouseDownAttrDirective(dom.Element element, Scope scope) { + element.onMouseDown.listen((event) => scope.$apply(() { + onMouseDown({r"$event": event}); + })); + } +} + + +@NgDirective( + selector: '[ng-mouseenter]', + map: const {'ng-mouseenter': '&.onMouseEnter'} +) +class NgMouseEnterAttrDirective { + Getter onMouseEnter; + + NgMouseEnterAttrDirective(dom.Element element, Scope scope) { + element.onMouseEnter.listen((event) => scope.$apply(() { + onMouseEnter({r"$event": event}); + })); + } +} + + +@NgDirective( + selector: '[ng-mouseleave]', + map: const {'ng-mouseleave': '&.onMouseLeave'} +) +class NgMouseLeaveAttrDirective { + Getter onMouseLeave; + + NgMouseLeaveAttrDirective(dom.Element element, Scope scope) { + element.onMouseLeave.listen((event) => scope.$apply(() { + onMouseLeave({r"$event": event}); + })); + } +} + + +@NgDirective( + selector: '[ng-mousemove]', + map: const {'ng-mousemove': '&.onMouseMove'} +) +class NgMouseMoveAttrDirective { + Getter onMouseMove; + + NgMouseMoveAttrDirective(dom.Element element, Scope scope) { + element.onMouseMove.listen((event) => scope.$apply(() { + onMouseMove({r"$event": event}); + })); + } +} + + +@NgDirective( + selector: '[ng-mouseout]', + map: const {'ng-mouseout': '&.onMouseOut'} +) +class NgMouseOutAttrDirective { + Getter onMouseOut; + + NgMouseOutAttrDirective(dom.Element element, Scope scope) { + element.onMouseOut.listen((event) => scope.$apply(() { + onMouseOut({r"$event": event}); + })); + } +} + + +@NgDirective( + selector: '[ng-mouseover]', + map: const {'ng-mouseover': '&.onMouseOver'} +) +class NgMouseOverAttrDirective { + Getter onMouseOver; + + NgMouseOverAttrDirective(dom.Element element, Scope scope) { + element.onMouseOver.listen((event) => scope.$apply(() { + onMouseOver({r"$event": event}); + })); + } +} + + +@NgDirective( + selector: '[ng-mouseup]', + map: const {'ng-mouseup': '&.onMouseUp'} +) +class NgMouseUpAttrDirective { + Getter onMouseUp; + + NgMouseUpAttrDirective(dom.Element element, Scope scope) { + element.onMouseUp.listen((event) => scope.$apply(() { + onMouseUp({r"$event": event}); + })); + } +} + + +@NgDirective( + selector: '[ng-mousewheel]', + map: const {'ng-mousewheel': '&.onMouseWheel'} +) +class NgMouseWheelAttrDirective { + Getter onMouseWheel; + + NgMouseWheelAttrDirective(dom.Element element, Scope scope) { + element.onMouseWheel.listen((event) => scope.$apply(() { + onMouseWheel({r"$event": event}); + })); + } +} + + +@NgDirective( + selector: '[ng-scroll]', + map: const {'ng-scroll': '&.onScroll'} +) +class NgScrollAttrDirective { + Getter onScroll; + + NgScrollAttrDirective(dom.Element element, Scope scope) { + element.onScroll.listen((event) => scope.$apply(() { + onScroll({r"$event": event}); + })); + } +} + + +@NgDirective( + selector: '[ng-touchcancel]', + map: const {'ng-touchcancel': '&.onTouchCancel'} +) +class NgTouchCancelAttrDirective { + Getter onTouchCancel; + + NgTouchCancelAttrDirective(dom.Element element, Scope scope) { + element.onTouchCancel.listen((event) => scope.$apply(() { + onTouchCancel({r"$event": event}); + })); + } +} + + +@NgDirective( + selector: '[ng-touchend]', + map: const {'ng-touchend': '&.onTouchEnd'} +) +class NgTouchEndAttrDirective { + Getter onTouchEnd; + + NgTouchEndAttrDirective(dom.Element element, Scope scope) { + element.onTouchEnd.listen((event) => scope.$apply(() { + onTouchEnd({r"$event": event}); + })); + } +} + + +@NgDirective( + selector: '[ng-touchmove]', + map: const {'ng-touchmove': '&.onTouchMove'} +) +class NgTouchMoveAttrDirective { + Getter onTouchMove; + + NgTouchMoveAttrDirective(dom.Element element, Scope scope) { + element.onTouchMove.listen((event) => scope.$apply(() { + onTouchMove({r"$event": event}); + })); + } +} + + +@NgDirective( + selector: '[ng-touchstart]', + map: const {'ng-touchstart': '&.onTouchStart'} +) +class NgTouchStartAttrDirective { + Getter onTouchStart; + + NgTouchStartAttrDirective(dom.Element element, Scope scope) { + element.onTouchStart.listen((event) => scope.$apply(() { + onTouchStart({r"$event": event}); + })); + } +} \ No newline at end of file diff --git a/test/directives/ng_click_spec.dart b/test/directives/ng_click_spec.dart deleted file mode 100644 index 494d2a7e7..000000000 --- a/test/directives/ng_click_spec.dart +++ /dev/null @@ -1,32 +0,0 @@ -library ng_click_spec; - -import '../_specs.dart'; -import 'dart:html' as dom; - - -main() { - describe('NgClick', () { - var compile, element, rootScope; - - triggerEvent(elementWrapper, name) { - elementWrapper[0].dispatchEvent(new dom.Event.eventType('MouseEvent', name)); - } - - beforeEach(inject((Scope scope, Compiler compiler, Injector injector) { - compile = (html, [applyFn]) { - element = $(html); - rootScope = scope; - compiler(element)(injector, element); - scope.$apply(applyFn); - }; - })); - - - it('should evaluate the expression on click', () { - compile(r''); - triggerEvent(element, 'click'); - expect(rootScope['abc']).toEqual(true); - expect(rootScope['event'] is dom.MouseEvent).toEqual(true); - }); - }); -} diff --git a/test/directives/ng_events_spec.dart b/test/directives/ng_events_spec.dart new file mode 100644 index 000000000..4419e72bc --- /dev/null +++ b/test/directives/ng_events_spec.dart @@ -0,0 +1,30 @@ +library ng_click_spec; + +import '../_specs.dart'; +import "../_test_bed.dart"; +import 'dart:html' as dom; + + +main() { + var events = ['blur', 'change', 'click', 'contextmenu', 'drag', 'dragend', + 'dragenter', 'dragleave', 'dragover', 'dragstart', 'drop', + 'focus', 'keydown', 'keypress', 'keyup', 'mousedown', + 'mouseenter', 'mouseleave', 'mousemove', 'mouseout', + 'mouseover', 'mouseup', 'mousewheel', 'scroll', 'touchcancel', + 'touchend', 'touchmove', 'touchstart']; + + events.forEach((name) { + ddescribe('ng-$name', () { + TestBed _; + + beforeEach(beforeEachTestBed((tb) => _ = tb)); + + it('should evaluate the expression on $name', inject(() { + _.compile(''); + _.triggerEvent(_.rootElement, '$name'); + expect(_.rootScope['abc']).toEqual(true); + expect(_.rootScope['event'] is dom.MouseEvent).toEqual(true); + })); + }); + }); +}