├── .idea ├── .name ├── misc.xml ├── scopes │ └── scope_settings.xml ├── watcherTasks.xml ├── encodings.xml ├── vcs.xml ├── dictionaries │ ├── KG_Chromium.xml │ └── Rob.xml ├── inspectionProfiles │ ├── profiles_settings.xml │ └── Project_Default.xml ├── jsLibraryMappings.xml ├── modules.xml ├── libraries │ └── angular_next_node_modules.xml ├── webResources.xml └── angular-next.iml ├── .npmignore ├── lib └── systemjs-register │ └── initialize-register.js ├── examples ├── hello-jspm │ ├── jspm_packages │ │ ├── .loaderversions │ │ └── github │ │ │ └── robianmcd │ │ │ └── angular-next@0.0.3 │ │ │ ├── .jspm-hash │ │ │ ├── ng2 │ │ │ ├── ngElement.js │ │ │ ├── bootstrap.js │ │ │ ├── template.js │ │ │ ├── templateConfig.js │ │ │ ├── decorator.js │ │ │ ├── component.js │ │ │ └── directive.js │ │ │ ├── ngNext │ │ │ ├── injectNgOne.js │ │ │ ├── polyfillPromise.js │ │ │ └── angular2Adapter.js │ │ │ ├── angular2.js │ │ │ ├── .jspm.json │ │ │ └── rtts-assert.js │ ├── package.json │ ├── app.js │ ├── config.js │ ├── index.html │ └── README.md ├── color-slider │ ├── build │ │ ├── css │ │ │ ├── css │ │ │ │ └── styles.css │ │ │ ├── styles.css │ │ │ └── blue-grey-theme.css │ │ ├── app.js │ │ ├── components │ │ │ ├── colorSettings │ │ │ │ ├── colorSettings.html │ │ │ │ ├── ng1ColorSettings.js │ │ │ │ └── ng2ColorSettings.js │ │ │ └── base │ │ │ │ ├── baseComponent.html │ │ │ │ └── baseComponent.js │ │ ├── index.html │ │ ├── decorators │ │ │ └── backgroundColor.js │ │ ├── services │ │ │ └── colorUtil.js │ │ └── vendor │ │ │ └── angular-aria.js │ ├── bower.json │ ├── src │ │ ├── app.ats.js │ │ ├── css │ │ │ └── styles.css │ │ ├── decorators │ │ │ └── backgroundColor.ats.js │ │ ├── components │ │ │ ├── base │ │ │ │ ├── baseComponent.ats.js │ │ │ │ └── baseComponent.html │ │ │ └── colorSettings │ │ │ │ ├── colorSettings.html │ │ │ │ ├── ng1ColorSettings.js │ │ │ │ └── ng2ColorSettings.ats.js │ │ ├── services │ │ │ └── colorUtil.ats.js │ │ └── index.html │ ├── package.json │ ├── readme.md │ └── gulpfile.js ├── feature-sandbox │ ├── src │ │ ├── myChildService.js │ │ ├── app.js │ │ ├── myService.js │ │ ├── colorDec.js │ │ ├── helloComponent.js │ │ ├── index.html │ │ └── childComponent.js │ ├── package.json │ ├── bower.json │ └── gulpfile.js └── hello-world │ ├── package.json │ ├── src │ └── app.js │ ├── index.html │ ├── build │ └── app.js │ └── README.md ├── src └── angular2 │ ├── ng2 │ ├── ngElement.js │ ├── template.js │ ├── bootstrap.js │ ├── decorator.js │ ├── component.js │ └── directive.js │ ├── ngNext │ ├── injectNgOne.js │ ├── polyfillPromise.js │ ├── registerNg2Directives.js │ └── angular2Adapter.js │ ├── angular2.js │ └── rtts-assert.js ├── dist └── es6 │ └── angular2 │ ├── ng2 │ ├── ngElement.js │ ├── template.js │ ├── bootstrap.js │ ├── templateConfig.js │ ├── decorator.js │ ├── component.js │ └── directive.js │ ├── ngNext │ ├── injectNgOne.js │ ├── polyfillPromise.js │ ├── registerNg2Directives.js │ └── angular2Adapter.js │ ├── angular2.js │ └── rtts-assert.js ├── .gitignore ├── karma.conf.js ├── .travis.yml ├── package.json ├── bower.json ├── testMain.js ├── CHANGELOG.md ├── gulpfile.js ├── test └── ngNext │ └── angular2AdapterTest.js ├── README.md └── LICENSE /.idea/.name: -------------------------------------------------------------------------------- 1 | angular-next -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | /* 2 | /*/ 3 | !/src/ 4 | !src/* -------------------------------------------------------------------------------- /lib/systemjs-register/initialize-register.js: -------------------------------------------------------------------------------- 1 | register(System); -------------------------------------------------------------------------------- /examples/hello-jspm/jspm_packages/.loaderversions: -------------------------------------------------------------------------------- 1 | ^0.13.1,^0.13.2,^0.0.82, -------------------------------------------------------------------------------- /examples/color-slider/build/css/css/styles.css: -------------------------------------------------------------------------------- 1 | .container { 2 | width:600px;margin:auto; 3 | } -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/angular2/ng2/ngElement.js: -------------------------------------------------------------------------------- 1 | class NgElement { 2 | constructor($element) { 3 | this.domElement = $element[0]; 4 | } 5 | } 6 | 7 | export {NgElement}; -------------------------------------------------------------------------------- /dist/es6/angular2/ng2/ngElement.js: -------------------------------------------------------------------------------- 1 | class NgElement { 2 | constructor($element) { 3 | this.domElement = $element[0]; 4 | } 5 | } 6 | 7 | export {NgElement}; -------------------------------------------------------------------------------- /examples/hello-jspm/jspm_packages/github/robianmcd/angular-next@0.0.3/.jspm-hash: -------------------------------------------------------------------------------- 1 | b0e6be91820f18c079f193246a374791d3eceb3899914b932bd37a50b983c5e7c90ae93bjspm-github@0.100.13 -------------------------------------------------------------------------------- /src/angular2/ngNext/injectNgOne.js: -------------------------------------------------------------------------------- 1 | class InjectNgOne { 2 | constructor(typeStr: assert.string) { 3 | this.typeStr = typeStr; 4 | } 5 | } 6 | 7 | export {InjectNgOne}; -------------------------------------------------------------------------------- /.idea/scopes/scope_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | -------------------------------------------------------------------------------- /.idea/watcherTasks.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /dist/es6/angular2/ngNext/injectNgOne.js: -------------------------------------------------------------------------------- 1 | class InjectNgOne { 2 | constructor(typeStr: assert.string) { 3 | this.typeStr = typeStr; 4 | } 5 | } 6 | 7 | export {InjectNgOne}; -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | /.idea/workspace.xml 3 | /bower_components 4 | /test-build 5 | 6 | /examples/feature-sandbox/build/ 7 | /examples/feature-sandbox/bower_components 8 | 9 | /examples/color-slider/bower_components -------------------------------------------------------------------------------- /examples/feature-sandbox/src/myChildService.js: -------------------------------------------------------------------------------- 1 | class MyChildService { 2 | constructor() { 3 | 4 | } 5 | 6 | getChildStr() { 7 | return 'child service' 8 | } 9 | } 10 | 11 | export default MyChildService; -------------------------------------------------------------------------------- /examples/hello-jspm/jspm_packages/github/robianmcd/angular-next@0.0.3/ng2/ngElement.js: -------------------------------------------------------------------------------- 1 | /* */ 2 | class NgElement { 3 | constructor($element) { 4 | this.domElement = $element[0]; 5 | } 6 | } 7 | 8 | export {NgElement}; -------------------------------------------------------------------------------- /examples/feature-sandbox/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angularNextExample", 3 | "version": "0.0.0", 4 | "dependencies": { 5 | "bower": "~1.3.12", 6 | "gulp": "~3.8.10", 7 | "gulp-traceur": "0.15.0" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /karma.conf.js: -------------------------------------------------------------------------------- 1 | module.exports = function(config) { 2 | config.set({ 3 | basePath: '', 4 | autoWatch: true, 5 | frameworks: ['jasmine'], 6 | reporters: ['progress'], 7 | browsers: ['Firefox'] 8 | }); 9 | }; 10 | -------------------------------------------------------------------------------- /src/angular2/ng2/template.js: -------------------------------------------------------------------------------- 1 | class Template { 2 | constructor(options) { 3 | this.inline = options.inline; 4 | this.url = options.url; 5 | this.directives = options.directives; 6 | } 7 | } 8 | 9 | export {Template}; -------------------------------------------------------------------------------- /dist/es6/angular2/ng2/template.js: -------------------------------------------------------------------------------- 1 | class Template { 2 | constructor(options) { 3 | this.inline = options.inline; 4 | this.url = options.url; 5 | this.directives = options.directives; 6 | } 7 | } 8 | 9 | export {Template}; -------------------------------------------------------------------------------- /examples/color-slider/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angularNextColorSlider", 3 | "version": "1.0.0", 4 | "dependencies": { 5 | "angular": "1.3.8", 6 | "angular-next": "0.0.3", 7 | "angular-material": "~0.6.1" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /examples/feature-sandbox/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angular-next-example", 3 | "private": true, 4 | "version": "0.0.0", 5 | "license": "Apache License, Version 2.0", 6 | "dependencies": { 7 | "angular": "1.3.1" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /examples/hello-jspm/jspm_packages/github/robianmcd/angular-next@0.0.3/ngNext/injectNgOne.js: -------------------------------------------------------------------------------- 1 | /* */ 2 | class InjectNgOne { 3 | constructor(typeStr: assert.string) { 4 | this.typeStr = typeStr; 5 | } 6 | } 7 | 8 | export {InjectNgOne}; -------------------------------------------------------------------------------- /examples/color-slider/src/app.ats.js: -------------------------------------------------------------------------------- 1 | import {bootstrap} from 'angular2/angular2.js'; 2 | import BaseComponent from 'components/base/baseComponent.js'; 3 | 4 | export function main() { 5 | bootstrap(BaseComponent, {moduleName: 'colorSlider'}); 6 | } 7 | -------------------------------------------------------------------------------- /src/angular2/ng2/bootstrap.js: -------------------------------------------------------------------------------- 1 | import {Angular2Adapter} from '../ngNext/angular2Adapter.js'; 2 | 3 | export function bootstrap (component, config = {}) { 4 | var adapter = new Angular2Adapter(config); 5 | adapter.bootstrapComponent(component); 6 | }; 7 | -------------------------------------------------------------------------------- /.idea/dictionaries/KG_Chromium.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | backport 5 | livereload 6 | versioning 7 | 8 | 9 | -------------------------------------------------------------------------------- /dist/es6/angular2/ng2/bootstrap.js: -------------------------------------------------------------------------------- 1 | import {Angular2Adapter} from '../ngNext/angular2Adapter'; 2 | 3 | export function bootstrap (component, config = {}) { 4 | var adapter = new Angular2Adapter(config); 5 | adapter.bootstrapComponent(component); 6 | }; 7 | -------------------------------------------------------------------------------- /dist/es6/angular2/ng2/templateConfig.js: -------------------------------------------------------------------------------- 1 | class TemplateConfig { 2 | constructor(options) { 3 | this.inline = options.inline; 4 | this.url = options.url; 5 | this.directives = options.directives; 6 | } 7 | } 8 | 9 | export {TemplateConfig}; -------------------------------------------------------------------------------- /examples/hello-jspm/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "jspm": { 3 | "directories": { 4 | "lib": ".", 5 | "packages": "jspm_packages" 6 | }, 7 | "dependencies": { 8 | "angular2": "github:robianmcd/angular-next@^0.0.3" 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /examples/feature-sandbox/src/app.js: -------------------------------------------------------------------------------- 1 | import {bootstrap} from 'angular2/angular2.js'; 2 | import HelloComponent from 'helloComponent.js'; 3 | 4 | export function main() { 5 | var app = angular.module('myApp', []); 6 | 7 | bootstrap(HelloComponent, {moduleName: 'myApp'}); 8 | } 9 | -------------------------------------------------------------------------------- /examples/color-slider/build/css/styles.css: -------------------------------------------------------------------------------- 1 | .container { 2 | width: 550px; 3 | margin: 50px auto; 4 | border: 2px solid #777; 5 | } 6 | 7 | .title { 8 | text-align: center; 9 | } 10 | 11 | .content { 12 | padding: 10px; 13 | } 14 | 15 | p { 16 | margin-top: 0; 17 | } -------------------------------------------------------------------------------- /examples/color-slider/src/css/styles.css: -------------------------------------------------------------------------------- 1 | .container { 2 | width: 550px; 3 | margin: 50px auto; 4 | border: 2px solid #777; 5 | } 6 | 7 | .title { 8 | text-align: center; 9 | } 10 | 11 | .content { 12 | padding: 10px; 13 | } 14 | 15 | p { 16 | margin-top: 0; 17 | } -------------------------------------------------------------------------------- /.idea/inspectionProfiles/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | -------------------------------------------------------------------------------- /examples/color-slider/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angularNextColorSlider", 3 | "version": "1.0.0", 4 | "dependencies": { 5 | "bower": "~1.3.12", 6 | "gulp": "~3.8.10", 7 | "gulp-connect": "^2.2.0", 8 | "gulp-traceur": "0.15.0", 9 | "lazypipe": "~0.2.2" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /.idea/dictionaries/Rob.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | anno 5 | hammerjs 6 | lazypipe 7 | transpile 8 | uninjectable 9 | 10 | 11 | -------------------------------------------------------------------------------- /.idea/jsLibraryMappings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /examples/hello-jspm/jspm_packages/github/robianmcd/angular-next@0.0.3/ng2/bootstrap.js: -------------------------------------------------------------------------------- 1 | /* */ 2 | import {Angular2Adapter} from '../ngNext/angular2Adapter'; 3 | 4 | export function bootstrap (component, config = {}) { 5 | var adapter = new Angular2Adapter(config); 6 | adapter.bootstrapComponent(component); 7 | }; 8 | -------------------------------------------------------------------------------- /examples/hello-jspm/jspm_packages/github/robianmcd/angular-next@0.0.3/ng2/template.js: -------------------------------------------------------------------------------- 1 | /* */ 2 | class Template { 3 | constructor(options) { 4 | this.inline = options.inline; 5 | this.url = options.url; 6 | this.directives = options.directives; 7 | } 8 | } 9 | 10 | export {Template}; -------------------------------------------------------------------------------- /dist/es6/angular2/angular2.js: -------------------------------------------------------------------------------- 1 | export * from './ng2/bootstrap'; 2 | export * from './ng2/directive'; 3 | export * from './ng2/component'; 4 | export * from './ng2/decorator'; 5 | export * from './ng2/template'; 6 | export * from './ng2/ngElement'; 7 | 8 | export * from './ngNext/injectNgOne'; 9 | export * from './ngNext/angular2Adapter'; -------------------------------------------------------------------------------- /examples/hello-jspm/jspm_packages/github/robianmcd/angular-next@0.0.3/ng2/templateConfig.js: -------------------------------------------------------------------------------- 1 | /* */ 2 | class TemplateConfig { 3 | constructor(options) { 4 | this.inline = options.inline; 5 | this.url = options.url; 6 | this.directives = options.directives; 7 | } 8 | } 9 | 10 | export {TemplateConfig}; -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "0.10" 4 | before_script: 5 | - export DISPLAY=:99.0 6 | - sh -e /etc/init.d/xvfb start 7 | - npm install 8 | - npm install -g gulp 9 | - npm install -g bower 10 | - bower install 11 | script: 12 | - gulp build 13 | - gulp test 14 | branches: 15 | only: 16 | - gh-pages -------------------------------------------------------------------------------- /src/angular2/angular2.js: -------------------------------------------------------------------------------- 1 | export * from './ng2/bootstrap.js'; 2 | export * from './ng2/directive.js'; 3 | export * from './ng2/component.js'; 4 | export * from './ng2/decorator.js'; 5 | export * from './ng2/template.js'; 6 | export * from './ng2/ngElement.js'; 7 | 8 | export * from './ngNext/injectNgOne.js'; 9 | export * from './ngNext/angular2Adapter.js'; -------------------------------------------------------------------------------- /examples/hello-world/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angularNextHelloWorld", 3 | "version": "1.0.0", 4 | "dependencies": { 5 | "traceur": "0.0.74", 6 | "http-server": "0.7.1" 7 | }, 8 | "scripts": { 9 | "build": "traceur --dir src build --modules=instantiate --annotations=true", 10 | "start": "http-server" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /examples/hello-jspm/jspm_packages/github/robianmcd/angular-next@0.0.3/angular2.js: -------------------------------------------------------------------------------- 1 | /* */ 2 | export * from './ng2/bootstrap'; 3 | export * from './ng2/directive'; 4 | export * from './ng2/component'; 5 | export * from './ng2/decorator'; 6 | export * from './ng2/template'; 7 | export * from './ng2/ngElement'; 8 | 9 | export * from './ngNext/injectNgOne'; 10 | export * from './ngNext/angular2Adapter'; -------------------------------------------------------------------------------- /examples/hello-jspm/app.js: -------------------------------------------------------------------------------- 1 | import {bootstrap, Component, Template} from 'angular2/angular2'; 2 | 3 | @Component({ 4 | selector: 'hello-component' 5 | }) 6 | @Template({inline: '

{{ctrl.message}}

'}) 7 | class HelloComponent { 8 | constructor() { 9 | this.message = 'Hello jspm'; 10 | } 11 | } 12 | 13 | export function main() { 14 | angular.module('myApp', []); 15 | 16 | bootstrap(HelloComponent, {moduleName: 'myApp'}); 17 | } -------------------------------------------------------------------------------- /examples/hello-jspm/config.js: -------------------------------------------------------------------------------- 1 | System.config({ 2 | "baseURL": ".", 3 | "paths": { 4 | "*": "*.js", 5 | "github:*": "jspm_packages/github/*.js" 6 | }, 7 | "traceurOptions": { 8 | "annotations": true, 9 | "types": true, 10 | "typeAssertions": true, 11 | "typeAssertionModule": "angular2/rtts-assert" 12 | } 13 | }); 14 | 15 | System.config({ 16 | "map": { 17 | "angular2": "github:robianmcd/angular-next@0.0.3" 18 | } 19 | }); 20 | 21 | -------------------------------------------------------------------------------- /examples/hello-world/src/app.js: -------------------------------------------------------------------------------- 1 | import {bootstrap, Component, Template} from 'angular2/angular2.js'; 2 | 3 | @Component({ 4 | selector: 'hello-component' 5 | }) 6 | @Template({ 7 | inline: '

{{ctrl.message}}

' 8 | }) 9 | class HelloComponent { 10 | constructor() { 11 | this.message = 'Hello World'; 12 | } 13 | } 14 | 15 | export function main() { 16 | angular.module('myApp', []); 17 | 18 | bootstrap(HelloComponent, {moduleName: 'myApp'}); 19 | } -------------------------------------------------------------------------------- /examples/feature-sandbox/src/myService.js: -------------------------------------------------------------------------------- 1 | import MyChildService from 'myChildService.js'; 2 | import {InjectNgOne} from 'angular2/angular2.js'; 3 | 4 | class MyService { 5 | constructor(childService: MyChildService, @InjectNgOne('$log') $log) { 6 | $log.info('successfully injected angular 1 service'); 7 | this.childService = childService; 8 | } 9 | 10 | getStr() { 11 | return this.childService.getChildStr(); 12 | } 13 | } 14 | 15 | export default MyService; -------------------------------------------------------------------------------- /.idea/libraries/angular_next_node_modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /examples/feature-sandbox/src/colorDec.js: -------------------------------------------------------------------------------- 1 | import {Decorator, NgElement} from 'angular2/angular2.js'; 2 | 3 | @Decorator({ 4 | selector: '[color]', 5 | bind: {color: 'color'}, 6 | observe: {color: 'onColorChange'} 7 | }) 8 | class ColorDec { 9 | constructor(el:NgElement) { 10 | this.element = el; 11 | this.onColorChange(this.color); 12 | } 13 | 14 | onColorChange(newValue) { 15 | this.element.domElement.style.color = newValue; 16 | } 17 | } 18 | 19 | export default ColorDec; -------------------------------------------------------------------------------- /.idea/webResources.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /examples/hello-world/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Angular Next - Hello World 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /examples/hello-jspm/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /examples/color-slider/build/app.js: -------------------------------------------------------------------------------- 1 | System.register("app.js", ["angular2/angular2.js", "components/base/baseComponent.js"], function($__export) { 2 | "use strict"; 3 | var __moduleName = "app.js"; 4 | var bootstrap, 5 | BaseComponent; 6 | function main() { 7 | bootstrap(BaseComponent, {moduleName: 'colorSlider'}); 8 | } 9 | $__export("main", main); 10 | return { 11 | setters: [function(m) { 12 | bootstrap = m.bootstrap; 13 | }, function(m) { 14 | BaseComponent = m.default; 15 | }], 16 | execute: function() { 17 | } 18 | }; 19 | }); 20 | //# sourceURL=app.js -------------------------------------------------------------------------------- /examples/color-slider/src/decorators/backgroundColor.ats.js: -------------------------------------------------------------------------------- 1 | import {Decorator, NgElement} from 'angular2/angular2.js'; 2 | 3 | @Decorator({ 4 | selector: '[background-color]', 5 | bind: {backgroundColor: 'backgroundColor'}, 6 | observe: {backgroundColor: 'onColorChange'} 7 | }) 8 | class BackgroundColor { 9 | constructor(el:NgElement) { 10 | this.element = el; 11 | this.onColorChange(this.backgroundColor); 12 | } 13 | 14 | onColorChange(newValue) { 15 | this.element.domElement.style['background-color'] = newValue; 16 | } 17 | } 18 | 19 | export default BackgroundColor; 20 | -------------------------------------------------------------------------------- /examples/feature-sandbox/src/helloComponent.js: -------------------------------------------------------------------------------- 1 | import {Component, Template, NgElement} from 'angular2/angular2.js'; 2 | import ChildComponent from 'childComponent.js'; 3 | import MyService from 'myService.js'; 4 | import MyChildService from 'myChildService.js'; 5 | 6 | 7 | @Component({ 8 | selector: '[hello-component]', 9 | componentServices: [MyService, MyChildService, NgElement] 10 | }) 11 | @Template({ 12 | inline: '

Hello {{ctrl.test}}

', 13 | directives: [ChildComponent] 14 | }) 15 | class HelloComponent { 16 | constructor(test: MyService) { 17 | this.test = test.getStr(); 18 | } 19 | } 20 | 21 | export default HelloComponent; -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angularNext", 3 | "version": "0.0.3", 4 | "repository": { 5 | "type": "git", 6 | "url": "https://github.com/robianmcd/angular-next.git" 7 | }, 8 | "devDependencies": { 9 | "bower": "~1.3.12", 10 | "gulp": "~3.8.10", 11 | "gulp-concat": "~2.4.1", 12 | "gulp-insert": "~0.4.0", 13 | "gulp-traceur": "0.17.0", 14 | "gulp-rename": "~1.2.0", 15 | "gulp-replace": "~0.5.3", 16 | "karma": "~0.12.30", 17 | "gulp-karma": "0.0.4", 18 | "jasmine-core": "~2.1.3", 19 | "karma-jasmine": "~0.3.3", 20 | "karma-firefox-launcher": "~0.1.4" 21 | }, 22 | "main": false, 23 | "directories": { 24 | "lib": "dist/es6/angular2" 25 | }, 26 | "format": "es6" 27 | } 28 | -------------------------------------------------------------------------------- /examples/color-slider/src/components/base/baseComponent.ats.js: -------------------------------------------------------------------------------- 1 | import {Component, Template} from 'angular2/angular2.js'; 2 | import BackgroundColor from 'decorators/backgroundColor.js'; 3 | import ColorUtil from 'services/colorUtil.js'; 4 | import Ng2ColorSettings from 'components/colorSettings/ng2ColorSettings.js'; 5 | 6 | @Component({ 7 | selector: 'base-component', 8 | componentServices: [ColorUtil] 9 | }) 10 | @Template({ 11 | url: 'components/base/baseComponent.html', 12 | directives: [BackgroundColor, Ng2ColorSettings] 13 | }) 14 | class BaseComponent { 15 | constructor() { 16 | this.backgroundColor = '#fff'; 17 | } 18 | 19 | setBackgroundColor(hash) { 20 | this.backgroundColor = hash; 21 | } 22 | } 23 | 24 | export default BaseComponent; -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angular-next", 3 | "description": "Angular Next brings the power of Angular 2 to Angular 1 and gives you an incremental migration path.", 4 | "version": "0.0.3", 5 | "homepage": "https://github.com/robianmcd/angular-next", 6 | "authors": [ 7 | "Rob " 8 | ], 9 | "keywords": [ 10 | "javascript", 11 | "angularjs", 12 | "angular" 13 | ], 14 | "license": "Apache License, Version 2.0", 15 | "ignore": [ 16 | "*", 17 | "!dist/", 18 | "!dist/*" 19 | ], 20 | "repository": { 21 | "type": "git", 22 | "url": "https://github.com/robianmcd/angular-next.git" 23 | }, 24 | "devDependencies": { 25 | "traceur-runtime": "0.0.84", 26 | "es6-module-loader": "~0.10.0", 27 | "angular": "~1.3.8" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /examples/hello-jspm/jspm_packages/github/robianmcd/angular-next@0.0.3/.jspm.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angularNext", 3 | "version": "0.0.2", 4 | "repository": { 5 | "type": "git", 6 | "url": "https://github.com/robianmcd/angular-next.git" 7 | }, 8 | "devDependencies": { 9 | "bower": "~1.3.12", 10 | "gulp": "~3.8.10", 11 | "gulp-concat": "~2.4.1", 12 | "gulp-insert": "~0.4.0", 13 | "gulp-traceur": "0.17.0", 14 | "gulp-rename": "~1.2.0", 15 | "gulp-replace": "~0.5.3", 16 | "karma": "~0.12.30", 17 | "gulp-karma": "0.0.4", 18 | "jasmine-core": "~2.1.3", 19 | "karma-jasmine": "~0.3.3", 20 | "karma-firefox-launcher": "~0.1.4" 21 | }, 22 | "main": false, 23 | "directories": { 24 | "lib": "dist/es6/angular2" 25 | }, 26 | "format": "es6", 27 | "jspm": {} 28 | } -------------------------------------------------------------------------------- /testMain.js: -------------------------------------------------------------------------------- 1 | //This file is based off of: https://github.com/gocardless/es6-angularjs/blob/master/config/karma-spec-loader.config.js 2 | 3 | // make karma wait for a call to __karma__.start() to start running tests. 4 | __karma__.loaded = function () { 5 | }; 6 | 7 | Promise.all( 8 | // All files served by Karma. 9 | Object.keys(__karma__.files) 10 | //Filter out everything other than test spec files 11 | .filter(function (path) { 12 | return /test-build/.test(path); 13 | }) 14 | //Import all the test spec modules 15 | .map(function (path) { 16 | return System.import(path.replace('/base/test-build/', '')); 17 | }) 18 | ) 19 | .then(function () { 20 | __karma__.start(); 21 | }, function (error) { 22 | console.error(error.stack || error); 23 | __karma__.start(); 24 | }); -------------------------------------------------------------------------------- /examples/feature-sandbox/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Angular Next 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /examples/feature-sandbox/src/childComponent.js: -------------------------------------------------------------------------------- 1 | import {Component, Template, NgElement} from 'angular2/angular2.js'; 2 | import ColorDec from 'colorDec.js'; 3 | import HelloComponent from 'helloComponent.js'; 4 | 5 | @Component({ 6 | selector: 'child-component', 7 | controllerAs: 'ctrl' 8 | }) 9 | @Template({ 10 | inline: '' + 11 | '
child: {{ctrl.test}}
' + 12 | '
' + 13 | '
decorated {{ctrl.color}} text
', 14 | directives: [ColorDec] 15 | }) 16 | class ChildComponent { 17 | constructor(element: NgElement, hello: HelloComponent) { 18 | element.domElement.style.color = 'blue'; 19 | 20 | this.color = 'red'; 21 | this.test = hello.test; 22 | } 23 | 24 | getTestStr() { 25 | return 'blue text'; 26 | } 27 | 28 | clicked() { 29 | console.log('clicked'); 30 | } 31 | } 32 | 33 | export default ChildComponent; -------------------------------------------------------------------------------- /examples/color-slider/build/components/colorSettings/colorSettings.html: -------------------------------------------------------------------------------- 1 |
2 |
3 | Use the slider to adjust the background color of the parent component. 4 |
5 |
6 |

Preview:

7 | 8 |
9 |
10 |
11 |
12 | Hue 13 |
14 | 15 |
16 | 17 |
18 |
19 |
20 | Set Parent Color 21 |
22 |
-------------------------------------------------------------------------------- /examples/color-slider/src/components/colorSettings/colorSettings.html: -------------------------------------------------------------------------------- 1 |
2 |
3 | Use the slider to adjust the background color of the parent component. 4 |
5 |
6 |

Preview:

7 | 8 |
9 |
10 |
11 |
12 | Hue 13 |
14 | 15 |
16 | 17 |
18 |
19 |
20 | Set Parent Color 21 |
22 |
-------------------------------------------------------------------------------- /examples/hello-world/build/app.js: -------------------------------------------------------------------------------- 1 | System.register(["angular2/angular2.js"], function($__export) { 2 | "use strict"; 3 | var bootstrap, 4 | Component, 5 | Template, 6 | HelloComponent; 7 | function main() { 8 | angular.module('myApp', []); 9 | bootstrap(HelloComponent, {moduleName: 'myApp'}); 10 | } 11 | $__export("main", main); 12 | return { 13 | setters: [function(m) { 14 | bootstrap = m.bootstrap; 15 | Component = m.Component; 16 | Template = m.Template; 17 | }], 18 | execute: function() { 19 | HelloComponent = (function() { 20 | var HelloComponent = function HelloComponent() { 21 | this.message = 'Hello World'; 22 | }; 23 | return ($traceurRuntime.createClass)(HelloComponent, {}, {}); 24 | }()); 25 | Object.defineProperty(HelloComponent, "annotations", {get: function() { 26 | return [new Component({selector: 'hello-component'}), new Template({inline: '

{{ctrl.message}}

'})]; 27 | }}); 28 | } 29 | }; 30 | }); 31 | -------------------------------------------------------------------------------- /src/angular2/ng2/decorator.js: -------------------------------------------------------------------------------- 1 | import {Directive} from './directive.js'; 2 | 3 | //Like ng-class, ng-show 4 | class Decorator extends Directive { 5 | constructor(options:Object) { 6 | super(options); 7 | } 8 | } 9 | 10 | var DecoratorClass = assert.define('DecoratorClass', function (decoratorClass) { 11 | assert.type(decoratorClass, Object); 12 | 13 | var numDirAnnos; 14 | var numComponentAnnos; 15 | if (decoratorClass.annotations) { 16 | numDirAnnos = decoratorClass.annotations.filter(anno => anno instanceof Directive).length; 17 | numComponentAnnos = decoratorClass.annotations.filter(anno => anno instanceof Decorator).length; 18 | } else { 19 | numDirAnnos = 0; 20 | numComponentAnnos = 0; 21 | } 22 | 23 | 24 | if (numComponentAnnos === 0) { 25 | assert.fail('A DecoratorClass must have a Decorator annotation'); 26 | } 27 | if (numDirAnnos > 1) { 28 | asssert.fail('You cannot have more than one Directive annotations on a class.'); 29 | } 30 | }); 31 | 32 | export {Decorator, DecoratorClass}; -------------------------------------------------------------------------------- /dist/es6/angular2/ng2/decorator.js: -------------------------------------------------------------------------------- 1 | import {Directive} from './directive'; 2 | 3 | //Like ng-class, ng-show 4 | class Decorator extends Directive { 5 | constructor(options:Object) { 6 | super(options); 7 | } 8 | } 9 | 10 | var DecoratorClass = assert.define('DecoratorClass', function (decoratorClass) { 11 | assert.type(decoratorClass, Object); 12 | 13 | var numDirAnnos; 14 | var numComponentAnnos; 15 | if (decoratorClass.annotations) { 16 | numDirAnnos = decoratorClass.annotations.filter(anno => anno instanceof Directive).length; 17 | numComponentAnnos = decoratorClass.annotations.filter(anno => anno instanceof Decorator).length; 18 | } else { 19 | numDirAnnos = 0; 20 | numComponentAnnos = 0; 21 | } 22 | 23 | 24 | if (numComponentAnnos === 0) { 25 | assert.fail('A DecoratorClass must have a Decorator annotation'); 26 | } 27 | if (numDirAnnos > 1) { 28 | asssert.fail('You cannot have more than one Directive annotations on a class.'); 29 | } 30 | }); 31 | 32 | export {Decorator, DecoratorClass}; -------------------------------------------------------------------------------- /examples/feature-sandbox/gulpfile.js: -------------------------------------------------------------------------------- 1 | var gulp = require('gulp'), 2 | traceur = require('gulp-traceur'); 3 | 4 | var appFiles = 'src/**/*.js'; 5 | var vendorFiles = [ 6 | 'bower_components/angular/angular.js', 7 | '../../dist/angularNext-standalone.js' 8 | ]; 9 | var indexFile = 'src/index.html'; 10 | 11 | gulp.task('vendor', function () { 12 | return gulp.src(vendorFiles) 13 | .pipe(gulp.dest('build/vendor')); 14 | }); 15 | 16 | gulp.task('app', function () { 17 | return gulp.src(appFiles) 18 | .pipe(traceur({experimental: true, modules: 'instantiate', moduleName: true, annotations: true, types: true, typeAssertions: true, typeAssertionModule: "angular2/rtts-assert.js"})) 19 | .pipe(gulp.dest('build')); 20 | }); 21 | 22 | gulp.task('index', function () { 23 | return gulp.src(indexFile) 24 | .pipe(gulp.dest('build')); 25 | }); 26 | 27 | gulp.task('build', ['vendor', 'app', 'index']); 28 | 29 | gulp.task('default', ['build'], function () { 30 | gulp.watch(appFiles, ['app']); 31 | gulp.watch(vendorFiles, ['vendor']); 32 | gulp.watch(indexFile, ['index']); 33 | }); -------------------------------------------------------------------------------- /examples/hello-world/README.md: -------------------------------------------------------------------------------- 1 | # Angular Next - Hello World 2 | 3 | This is a bare bones, self contained example that uses Angular Next to create a directive that says "Hello World". 4 | 5 | ### Demo 6 | 7 | [http://robianmcd.github.io/angular-next/examples/hello-world/](http://robianmcd.github.io/angular-next/examples/hello-world/) - **Spoiler Alert:** It says "Hello World"... 8 | 9 | ### Run locally 10 | 11 | ```sh 12 | git clone https://github.com/robianmcd/angular-next.git 13 | cd angular-next/examples/hello-world 14 | npm install 15 | npm run build 16 | npm start 17 | ``` 18 | 19 | You can now access the app at [http://localhost:8080/](http://localhost:8080/) 20 | 21 | 22 | ### Files 23 | 24 | * *build/* 25 | * *app.js* - The result of compiling src/app.js into ES5 with Traceur 26 | * *src/* 27 | * *app.js* - Sets up the angular app and defines the `helloComponent` directive 28 | * *index.html* - Runs the app's main function which bootstraps the angular app. 29 | * *package.json* - This just includes Traceur which is used to compile src/app.js into ES5, and http-server which is used to statically serve the app 30 | -------------------------------------------------------------------------------- /examples/hello-jspm/jspm_packages/github/robianmcd/angular-next@0.0.3/ng2/decorator.js: -------------------------------------------------------------------------------- 1 | /* */ 2 | import {Directive} from './directive'; 3 | 4 | //Like ng-class, ng-show 5 | class Decorator extends Directive { 6 | constructor(options:Object) { 7 | super(options); 8 | } 9 | } 10 | 11 | var DecoratorClass = assert.define('DecoratorClass', function (decoratorClass) { 12 | assert.type(decoratorClass, Object); 13 | 14 | var numDirAnnos; 15 | var numComponentAnnos; 16 | if (decoratorClass.annotations) { 17 | numDirAnnos = decoratorClass.annotations.filter(anno => anno instanceof Directive).length; 18 | numComponentAnnos = decoratorClass.annotations.filter(anno => anno instanceof Decorator).length; 19 | } else { 20 | numDirAnnos = 0; 21 | numComponentAnnos = 0; 22 | } 23 | 24 | 25 | if (numComponentAnnos === 0) { 26 | assert.fail('A DecoratorClass must have a Decorator annotation'); 27 | } 28 | if (numDirAnnos > 1) { 29 | asssert.fail('You cannot have more than one Directive annotations on a class.'); 30 | } 31 | }); 32 | 33 | export {Decorator, DecoratorClass}; -------------------------------------------------------------------------------- /examples/color-slider/src/components/colorSettings/ng1ColorSettings.js: -------------------------------------------------------------------------------- 1 | (function(){ 2 | angular.module('colorSlider').directive('ng1ColorSettings', function () { 3 | return { 4 | restrict: 'E', 5 | templateUrl: 'components/colorSettings/colorSettings.html', 6 | controller: Ng1ColorSettingsCtrl, 7 | controllerAs: 'ctrl', 8 | require: '^baseComponent', 9 | link: function (scope, lElement, attrs, base) { 10 | scope.ctrl.base = base; 11 | } 12 | }; 13 | }); 14 | 15 | var Ng1ColorSettingsCtrl = function (colorUtil, $log) { 16 | this.colorUtil = colorUtil; 17 | this.$log = $log; 18 | 19 | this.hue = 0; 20 | }; 21 | 22 | Ng1ColorSettingsCtrl.$inject = ['colorUtil', '$log']; 23 | 24 | Ng1ColorSettingsCtrl.prototype.hueToHash = function(hue) { 25 | return this.colorUtil.hslToHash(hue / 100, 0.7, 0.4); 26 | }; 27 | 28 | Ng1ColorSettingsCtrl.prototype.setParentColor = function() { 29 | var hash = this.hueToHash(this.hue); 30 | this.$log.info("setting the base component's background color to " + hash); 31 | this.base.setBackgroundColor(hash); 32 | }; 33 | 34 | })(); -------------------------------------------------------------------------------- /examples/color-slider/build/components/colorSettings/ng1ColorSettings.js: -------------------------------------------------------------------------------- 1 | (function(){ 2 | angular.module('colorSlider').directive('ng1ColorSettings', function () { 3 | return { 4 | restrict: 'E', 5 | templateUrl: 'components/colorSettings/colorSettings.html', 6 | controller: Ng1ColorSettingsCtrl, 7 | controllerAs: 'ctrl', 8 | require: '^baseComponent', 9 | link: function (scope, lElement, attrs, base) { 10 | scope.ctrl.base = base; 11 | } 12 | }; 13 | }); 14 | 15 | var Ng1ColorSettingsCtrl = function (colorUtil, $log) { 16 | this.colorUtil = colorUtil; 17 | this.$log = $log; 18 | 19 | this.hue = 0; 20 | }; 21 | 22 | Ng1ColorSettingsCtrl.$inject = ['colorUtil', '$log']; 23 | 24 | Ng1ColorSettingsCtrl.prototype.hueToHash = function(hue) { 25 | return this.colorUtil.hslToHash(hue / 100, 0.7, 0.4); 26 | }; 27 | 28 | Ng1ColorSettingsCtrl.prototype.setParentColor = function() { 29 | var hash = this.hueToHash(this.hue); 30 | this.$log.info("setting the base component's background color to " + hash); 31 | this.base.setBackgroundColor(hash); 32 | }; 33 | 34 | })(); -------------------------------------------------------------------------------- /examples/color-slider/src/components/colorSettings/ng2ColorSettings.ats.js: -------------------------------------------------------------------------------- 1 | import {Component, Template, InjectNgOne} from 'angular2/angular2.js'; 2 | import BackgroundColor from 'decorators/backgroundColor.js'; 3 | import ColorUtil from 'services/colorUtil.js'; 4 | import BaseComponent from 'components/base/baseComponent.js'; 5 | 6 | @Component({ 7 | selector: 'ng2-color-settings' 8 | }) 9 | @Template({ 10 | url: 'components/colorSettings/colorSettings.html', 11 | directives: [BackgroundColor] 12 | }) 13 | class Ng2ColorSettings { 14 | //Notice how this constructor injects a service, a parent component, and an Angular 1 service. 15 | constructor(colorUtil:ColorUtil, base: BaseComponent, @InjectNgOne('$log') $log) { 16 | this.colorUtil = colorUtil; 17 | this.base = base; 18 | this.$log = $log; 19 | 20 | this.hue = 0; 21 | } 22 | 23 | hueToHash(hue) { 24 | return this.colorUtil.hslToHash(hue / 100, 0.8, 0.5); 25 | } 26 | 27 | setParentColor() { 28 | var hash = this.hueToHash(this.hue); 29 | this.$log.info(`setting the base component's background color to ${hash}`); 30 | this.base.setBackgroundColor(hash); 31 | } 32 | } 33 | 34 | export default Ng2ColorSettings; -------------------------------------------------------------------------------- /examples/color-slider/src/services/colorUtil.ats.js: -------------------------------------------------------------------------------- 1 | class ColorUtil { 2 | constructor() { 3 | 4 | } 5 | 6 | //Taken from http://stackoverflow.com/a/9493060/373655 7 | hslToRgb(h, s, l) { 8 | var r, g, b; 9 | 10 | if (s == 0) { 11 | r = g = b = l; // achromatic 12 | } else { 13 | function hue2rgb(p, q, t) { 14 | if (t < 0) t += 1; 15 | if (t > 1) t -= 1; 16 | if (t < 1 / 6) return p + (q - p) * 6 * t; 17 | if (t < 1 / 2) return q; 18 | if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6; 19 | return p; 20 | } 21 | 22 | var q = l < 0.5 ? l * (1 + s) : l + s - l * s; 23 | var p = 2 * l - q; 24 | r = hue2rgb(p, q, h + 1 / 3); 25 | g = hue2rgb(p, q, h); 26 | b = hue2rgb(p, q, h - 1 / 3); 27 | } 28 | 29 | return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)]; 30 | } 31 | 32 | hslToHash(h, s, l) { 33 | return this.rgbToHash(...this.hslToRgb(h, s, l)); 34 | } 35 | 36 | rgbToHash(r, g, b) { 37 | return `#${r.toString(16)}${g.toString(16)}${b.toString(16)}` 38 | } 39 | } 40 | 41 | export default ColorUtil; -------------------------------------------------------------------------------- /examples/hello-jspm/README.md: -------------------------------------------------------------------------------- 1 | # Angular Next - Hello jspm 2 | 3 | This is a hello world app that uses Angular Next and [jspm](http://jspm.io/). 4 | 5 | ### Demo 6 | 7 | [http://robianmcd.github.io/angular-next/examples/hello-jspm/](http://robianmcd.github.io/angular-next/examples/hello-jspm/) 8 | 9 | ### Run locally 10 | 11 | ```sh 12 | git clone https://github.com/robianmcd/angular-next.git 13 | cd angular-next/examples/hello-jspm 14 | npm insatll -g jspm 15 | jspm install 16 | python -m SimpleHTTPServer 17 | ``` 18 | 19 | You can now access the app at [http://localhost:8000/](http://localhost:8000/). Note: the `python` command depends on Python 2.7 and just serves your files. In Python 3 the command would be `python -m http.server`. 20 | 21 | 22 | ### Files 23 | 24 | * *jspm_packages/* - Generated by running `jspm install`. This is basically node_modules for jspm. 25 | * *app.js* - Sets up the angular app and defines the `helloComponent` directive. 26 | * *config.js* - Configuration file for jspm. Note the custom `traceurOptions` that are required to work with Angular Next. This file also aliases the Angular Next module as angular2. 27 | * *index.html* - Runs the app's main function which bootstraps the angular app. 28 | * *package.json* - Specifies the dependency on Angular Next. 29 | -------------------------------------------------------------------------------- /examples/color-slider/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Angular Next - Color Slider 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /examples/color-slider/build/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Angular Next - Color Slider 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | All notable changes to this project will be documented in this file. 3 | 4 | ## [Unreleased][unreleased] 5 | 6 | ### Added 7 | - Added support for Angular 2 style events and property bindings in templates 8 | 9 | ## [0.0.3] - 2015-02-23 10 | 11 | ### Added 12 | - Replaced ES6 Promise implementation with one based on $q so they are integrated with Angular's digest cycle. 13 | - Created an example using jspm 14 | 15 | ### Changed 16 | - Replaced template option in Component directives with a new `@Template` annotation 17 | - Renamed assert.js module to angular2/rtts-assert.js 18 | 19 | ## [0.0.2] - 2015-01-26 20 | 21 | ### Changed 22 | - replace core/core.js module with angular/angular.js to reflect [this change in angular 2.0](https://github.com/angular/angular/commit/ec5cb3eb66aa343bbc7f67c182c1cc021ce04096) 23 | 24 | ### Added 25 | - Started versioning releases in the dist folder 26 | - Created a changelog based on [keepachangelog.com](http://keepachangelog.com/) 27 | 28 | ## [0.0.1] - 2015-01-18 29 | ### Added 30 | - Setup foundation for Angular Next 31 | 32 | [unreleased]: https://github.com/robianmcd/angular-next/compare/...HEAD 33 | [0.0.3]: https://github.com/robianmcd/angular-next/compare/0.0.2...0.0.3 34 | [0.0.2]: https://github.com/robianmcd/angular-next/compare/0.0.1...0.0.2 35 | [0.0.1]: https://github.com/robianmcd/angular-next/compare/0.0.0...0.0.1 -------------------------------------------------------------------------------- /src/angular2/ngNext/polyfillPromise.js: -------------------------------------------------------------------------------- 1 | export default function polyfillPromise(ngModule) { 2 | ngModule.run(['$q', '$window', function ($q, $window) { 3 | $window.Promise = function (executor) { 4 | return $q(executor); 5 | }; 6 | 7 | $window.Promise.all = $q.all.bind($q); 8 | $window.Promise.reject = $q.reject.bind($q); 9 | $window.Promise.resolve = $q.when.bind($q); 10 | 11 | $window.Promise.race = function (promises) { 12 | var promiseMgr = $q.defer(); 13 | 14 | for (var i = 0; i < promises.length; i++) { 15 | promises[i].then(function (result) { 16 | if (promiseMgr) { 17 | promiseMgr.resolve(result); 18 | promiseMgr = null; 19 | } 20 | }); 21 | 22 | promises[i].catch(function (result) { 23 | if (promiseMgr) { 24 | promiseMgr.reject(result); 25 | promiseMgr = null; 26 | } 27 | }); 28 | } 29 | 30 | return promiseMgr.promise; 31 | }; 32 | 33 | }]); 34 | 35 | //Make sure the run block we just added gets executed before any other run blocks 36 | if (angular.isArray(ngModule._runBlocks)) { 37 | ngModule._runBlocks.unshift(ngModule._runBlocks.pop()); 38 | } 39 | } -------------------------------------------------------------------------------- /dist/es6/angular2/ngNext/polyfillPromise.js: -------------------------------------------------------------------------------- 1 | export default function polyfillPromise(ngModule) { 2 | ngModule.run(['$q', '$window', function ($q, $window) { 3 | $window.Promise = function (executor) { 4 | return $q(executor); 5 | }; 6 | 7 | $window.Promise.all = $q.all.bind($q); 8 | $window.Promise.reject = $q.reject.bind($q); 9 | $window.Promise.resolve = $q.when.bind($q); 10 | 11 | $window.Promise.race = function (promises) { 12 | var promiseMgr = $q.defer(); 13 | 14 | for (var i = 0; i < promises.length; i++) { 15 | promises[i].then(function (result) { 16 | if (promiseMgr) { 17 | promiseMgr.resolve(result); 18 | promiseMgr = null; 19 | } 20 | }); 21 | 22 | promises[i].catch(function (result) { 23 | if (promiseMgr) { 24 | promiseMgr.reject(result); 25 | promiseMgr = null; 26 | } 27 | }); 28 | } 29 | 30 | return promiseMgr.promise; 31 | }; 32 | 33 | }]); 34 | 35 | //Make sure the run block we just added gets executed before any other run blocks 36 | if (angular.isArray(ngModule._runBlocks)) { 37 | ngModule._runBlocks.unshift(ngModule._runBlocks.pop()); 38 | } 39 | } -------------------------------------------------------------------------------- /examples/hello-jspm/jspm_packages/github/robianmcd/angular-next@0.0.3/ngNext/polyfillPromise.js: -------------------------------------------------------------------------------- 1 | /* */ 2 | export default function polyfillPromise(ngModule) { 3 | ngModule.run(['$q', '$window', function ($q, $window) { 4 | $window.Promise = function (executor) { 5 | return $q(executor); 6 | }; 7 | 8 | $window.Promise.all = $q.all.bind($q); 9 | $window.Promise.reject = $q.reject.bind($q); 10 | $window.Promise.resolve = $q.when.bind($q); 11 | 12 | $window.Promise.race = function (promises) { 13 | var promiseMgr = $q.defer(); 14 | 15 | for (var i = 0; i < promises.length; i++) { 16 | promises[i].then(function (result) { 17 | if (promiseMgr) { 18 | promiseMgr.resolve(result); 19 | promiseMgr = null; 20 | } 21 | }); 22 | 23 | promises[i].catch(function (result) { 24 | if (promiseMgr) { 25 | promiseMgr.reject(result); 26 | promiseMgr = null; 27 | } 28 | }); 29 | } 30 | 31 | return promiseMgr.promise; 32 | }; 33 | 34 | }]); 35 | 36 | //Make sure the run block we just added gets executed before any other run blocks 37 | if (angular.isArray(ngModule._runBlocks)) { 38 | ngModule._runBlocks.unshift(ngModule._runBlocks.pop()); 39 | } 40 | } -------------------------------------------------------------------------------- /examples/color-slider/build/components/base/baseComponent.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |

Angular Next - Color Slider

4 |
5 |
6 |
7 |

8 | This app is built using Angular Next and Angular Material. The two tabs below are 9 | identical except that the one on the left is implemented with a standard 10 | Angular 1 directive 11 | while the one on the right is implemented with an 12 | Angular 2 style component. 13 |

14 |

15 | Back to code 16 |

17 |
18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 |
28 |
29 |
-------------------------------------------------------------------------------- /examples/color-slider/src/components/base/baseComponent.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |

Angular Next - Color Slider

4 |
5 |
6 |
7 |

8 | This app is built using Angular Next and Angular Material. The two tabs below are 9 | identical except that the one on the left is implemented with a standard 10 | Angular 1 directive 11 | while the one on the right is implemented with an 12 | Angular 2 style component. 13 |

14 |

15 | Back to code 16 |

17 |
18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 |
28 |
29 |
-------------------------------------------------------------------------------- /.idea/inspectionProfiles/Project_Default.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 31 | -------------------------------------------------------------------------------- /examples/color-slider/build/decorators/backgroundColor.js: -------------------------------------------------------------------------------- 1 | System.register("decorators/backgroundColor.js", ["angular2/rtts-assert.js", "angular2/angular2.js"], function($__export) { 2 | "use strict"; 3 | var __moduleName = "decorators/backgroundColor.js"; 4 | var assert, 5 | Decorator, 6 | NgElement, 7 | BackgroundColor; 8 | return { 9 | setters: [function(m) { 10 | assert = m.assert; 11 | }, function(m) { 12 | Decorator = m.Decorator; 13 | NgElement = m.NgElement; 14 | }], 15 | execute: function() { 16 | BackgroundColor = (function() { 17 | var BackgroundColor = function BackgroundColor(el) { 18 | assert.argumentTypes(el, NgElement); 19 | this.element = el; 20 | this.onColorChange(this.backgroundColor); 21 | }; 22 | return ($traceurRuntime.createClass)(BackgroundColor, {onColorChange: function(newValue) { 23 | this.element.domElement.style['background-color'] = newValue; 24 | }}, {}); 25 | }()); 26 | Object.defineProperty(BackgroundColor, "annotations", {get: function() { 27 | return [new Decorator({ 28 | selector: '[background-color]', 29 | bind: {backgroundColor: 'backgroundColor'}, 30 | observe: {backgroundColor: 'onColorChange'} 31 | })]; 32 | }}); 33 | Object.defineProperty(BackgroundColor, "parameters", {get: function() { 34 | return [[NgElement]]; 35 | }}); 36 | $__export('default', BackgroundColor); 37 | } 38 | }; 39 | }); 40 | //# sourceURL=decorators/backgroundColor.js -------------------------------------------------------------------------------- /.idea/angular-next.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /examples/hello-jspm/jspm_packages/github/robianmcd/angular-next@0.0.3/ng2/component.js: -------------------------------------------------------------------------------- 1 | /* */ 2 | import {Directive} from './directive'; 3 | 4 | //Like a panel 5 | class Component extends Directive { 6 | constructor(options: ComponentOptions) { 7 | this.componentServices = options.componentServices; 8 | delete options.componentServices; 9 | super(options); 10 | } 11 | } 12 | 13 | var ComponentOptions = assert.define('ComponentOptions', function(options) { 14 | //Required fields 15 | assert(options).is(assert.structure({ 16 | selector: assert.string 17 | })); 18 | 19 | //Optional fields 20 | if(options.componentServices) { 21 | assert(options.componentServices).is(assert.arrayOf(Object)); 22 | } 23 | }); 24 | 25 | var ComponentClass = assert.define('ComponentClass', function (componentClass) { 26 | assert.type(componentClass, Object); 27 | 28 | var numDirAnnos; 29 | var numComponentAnnos; 30 | if(componentClass.annotations) { 31 | numDirAnnos = componentClass.annotations.filter(anno => anno instanceof Directive).length; 32 | numComponentAnnos = componentClass.annotations.filter(anno => anno instanceof Component).length; 33 | } else { 34 | numDirAnnos = 0; 35 | numComponentAnnos = 0; 36 | } 37 | 38 | 39 | if (numComponentAnnos === 0) { 40 | assert.fail('A ComponentClass must have a Component annotation'); 41 | } 42 | if(numDirAnnos > 1) { 43 | asssert.fail('You cannot have more than one Directive annotations on a class.'); 44 | } 45 | }); 46 | 47 | export {Component, ComponentOptions, ComponentClass}; -------------------------------------------------------------------------------- /examples/color-slider/build/components/base/baseComponent.js: -------------------------------------------------------------------------------- 1 | System.register("components/base/baseComponent.js", ["angular2/angular2.js", "decorators/backgroundColor.js", "services/colorUtil.js", "components/colorSettings/ng2ColorSettings.js"], function($__export) { 2 | "use strict"; 3 | var __moduleName = "components/base/baseComponent.js"; 4 | var Component, 5 | Template, 6 | BackgroundColor, 7 | ColorUtil, 8 | Ng2ColorSettings, 9 | BaseComponent; 10 | return { 11 | setters: [function(m) { 12 | Component = m.Component; 13 | Template = m.Template; 14 | }, function(m) { 15 | BackgroundColor = m.default; 16 | }, function(m) { 17 | ColorUtil = m.default; 18 | }, function(m) { 19 | Ng2ColorSettings = m.default; 20 | }], 21 | execute: function() { 22 | BaseComponent = (function() { 23 | var BaseComponent = function BaseComponent() { 24 | this.backgroundColor = '#fff'; 25 | }; 26 | return ($traceurRuntime.createClass)(BaseComponent, {setBackgroundColor: function(hash) { 27 | this.backgroundColor = hash; 28 | }}, {}); 29 | }()); 30 | Object.defineProperty(BaseComponent, "annotations", {get: function() { 31 | return [new Component({ 32 | selector: 'base-component', 33 | componentServices: [ColorUtil] 34 | }), new Template({ 35 | url: 'components/base/baseComponent.html', 36 | directives: [BackgroundColor, Ng2ColorSettings] 37 | })]; 38 | }}); 39 | $__export('default', BaseComponent); 40 | } 41 | }; 42 | }); 43 | //# sourceURL=components/base/baseComponent.js -------------------------------------------------------------------------------- /src/angular2/ng2/component.js: -------------------------------------------------------------------------------- 1 | import {Directive} from './directive.js'; 2 | 3 | //Like a panel 4 | class Component extends Directive { 5 | constructor(options: ComponentOptions) { 6 | //We can't assign this to `this` before calling super 7 | var componentServices = options.componentServices; 8 | delete options.componentServices; 9 | super(options); 10 | 11 | this.componentServices = componentServices; 12 | } 13 | } 14 | 15 | var ComponentOptions = assert.define('ComponentOptions', function(options) { 16 | //Required fields 17 | assert(options).is(assert.structure({ 18 | selector: assert.string 19 | })); 20 | 21 | //Optional fields 22 | if(options.componentServices) { 23 | assert(options.componentServices).is(assert.arrayOf(Object)); 24 | } 25 | }); 26 | 27 | var ComponentClass = assert.define('ComponentClass', function (componentClass) { 28 | assert.type(componentClass, Object); 29 | 30 | var numDirAnnos; 31 | var numComponentAnnos; 32 | if(componentClass.annotations) { 33 | numDirAnnos = componentClass.annotations.filter(anno => anno instanceof Directive).length; 34 | numComponentAnnos = componentClass.annotations.filter(anno => anno instanceof Component).length; 35 | } else { 36 | numDirAnnos = 0; 37 | numComponentAnnos = 0; 38 | } 39 | 40 | 41 | if (numComponentAnnos === 0) { 42 | assert.fail('A ComponentClass must have a Component annotation'); 43 | } 44 | if(numDirAnnos > 1) { 45 | asssert.fail('You cannot have more than one Directive annotations on a class.'); 46 | } 47 | }); 48 | 49 | export {Component, ComponentOptions, ComponentClass}; -------------------------------------------------------------------------------- /dist/es6/angular2/ng2/component.js: -------------------------------------------------------------------------------- 1 | import {Directive} from './directive'; 2 | 3 | //Like a panel 4 | class Component extends Directive { 5 | constructor(options: ComponentOptions) { 6 | //We can't assign this to `this` before calling super 7 | var componentServices = options.componentServices; 8 | delete options.componentServices; 9 | super(options); 10 | 11 | this.componentServices = componentServices; 12 | } 13 | } 14 | 15 | var ComponentOptions = assert.define('ComponentOptions', function(options) { 16 | //Required fields 17 | assert(options).is(assert.structure({ 18 | selector: assert.string 19 | })); 20 | 21 | //Optional fields 22 | if(options.componentServices) { 23 | assert(options.componentServices).is(assert.arrayOf(Object)); 24 | } 25 | }); 26 | 27 | var ComponentClass = assert.define('ComponentClass', function (componentClass) { 28 | assert.type(componentClass, Object); 29 | 30 | var numDirAnnos; 31 | var numComponentAnnos; 32 | if(componentClass.annotations) { 33 | numDirAnnos = componentClass.annotations.filter(anno => anno instanceof Directive).length; 34 | numComponentAnnos = componentClass.annotations.filter(anno => anno instanceof Component).length; 35 | } else { 36 | numDirAnnos = 0; 37 | numComponentAnnos = 0; 38 | } 39 | 40 | 41 | if (numComponentAnnos === 0) { 42 | assert.fail('A ComponentClass must have a Component annotation'); 43 | } 44 | if(numDirAnnos > 1) { 45 | asssert.fail('You cannot have more than one Directive annotations on a class.'); 46 | } 47 | }); 48 | 49 | export {Component, ComponentOptions, ComponentClass}; -------------------------------------------------------------------------------- /examples/color-slider/build/services/colorUtil.js: -------------------------------------------------------------------------------- 1 | System.register("services/colorUtil.js", [], function($__export) { 2 | "use strict"; 3 | var __moduleName = "services/colorUtil.js"; 4 | var ColorUtil; 5 | return { 6 | setters: [], 7 | execute: function() { 8 | ColorUtil = (function() { 9 | var ColorUtil = function ColorUtil() {}; 10 | return ($traceurRuntime.createClass)(ColorUtil, { 11 | hslToRgb: function(h, s, l) { 12 | var r, 13 | g, 14 | b; 15 | if (s == 0) { 16 | r = g = b = l; 17 | } else { 18 | var hue2rgb = function(p, q, t) { 19 | if (t < 0) 20 | t += 1; 21 | if (t > 1) 22 | t -= 1; 23 | if (t < 1 / 6) 24 | return p + (q - p) * 6 * t; 25 | if (t < 1 / 2) 26 | return q; 27 | if (t < 2 / 3) 28 | return p + (q - p) * (2 / 3 - t) * 6; 29 | return p; 30 | }; 31 | var q = l < 0.5 ? l * (1 + s) : l + s - l * s; 32 | var p = 2 * l - q; 33 | r = hue2rgb(p, q, h + 1 / 3); 34 | g = hue2rgb(p, q, h); 35 | b = hue2rgb(p, q, h - 1 / 3); 36 | } 37 | return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)]; 38 | }, 39 | hslToHash: function(h, s, l) { 40 | var $__1; 41 | return ($__1 = this).rgbToHash.apply($__1, $traceurRuntime.spread(this.hslToRgb(h, s, l))); 42 | }, 43 | rgbToHash: function(r, g, b) { 44 | return ("#" + r.toString(16) + g.toString(16) + b.toString(16)); 45 | } 46 | }, {}); 47 | }()); 48 | $__export('default', ColorUtil); 49 | } 50 | }; 51 | }); 52 | //# sourceURL=services/colorUtil.js -------------------------------------------------------------------------------- /src/angular2/ng2/directive.js: -------------------------------------------------------------------------------- 1 | //See here for detailed annotation implimentations https://github.com/angular/angular/tree/master/modules/core/src/annotations 2 | class Directive { 3 | constructor(options:DirectiveOptions) { 4 | this.selector = options.selector; 5 | this.bind = options.bind; 6 | this.controllerAs = options.controllerAs || 'ctrl'; 7 | this.observe = options.observe; 8 | } 9 | } 10 | 11 | var DirectiveOptions = assert.define('DirectiveOptions', function (options) { 12 | //Required fields 13 | assert(options).is(assert.structure({ 14 | selector: assert.string 15 | })); 16 | 17 | //Optional fields 18 | if (options.bind) { 19 | assert.type(options.bind, Object); 20 | } 21 | if (options.controllerAs) { 22 | assert.type(options.controllerAs, assert.string); 23 | } 24 | if (options.observe) { 25 | assert.type(options.observe, Object); 26 | } 27 | 28 | for (var key in options) { 29 | if (options.hasOwnProperty(key)) { 30 | if (key !== 'selector' && key !== 'bind' && key !== 'controllerAs' && key !== 'observe') { 31 | assert.fail(`${key} is not a valid directive field`); 32 | } 33 | } 34 | } 35 | }); 36 | 37 | var DirectiveClass = assert.define('DirectiveClass', function (dirClass) { 38 | assert.type(dirClass, Object); 39 | 40 | var numDirAnnos; 41 | if(dirClass.annotations) { 42 | numDirAnnos = dirClass.annotations.filter(anno => anno instanceof Directive).length; 43 | } else { 44 | numDirAnnos = 0; 45 | } 46 | 47 | 48 | if (numDirAnnos === 0) { 49 | assert.fail('A DirectiveClass must have a Directive annotation'); 50 | } else if(numDirAnnos > 1) { 51 | asssert.fail('You cannot have more than one Directive annotations on a class.'); 52 | } 53 | }); 54 | 55 | export {Directive, DirectiveOptions, DirectiveClass}; -------------------------------------------------------------------------------- /dist/es6/angular2/ng2/directive.js: -------------------------------------------------------------------------------- 1 | //See here for detailed annotation implimentations https://github.com/angular/angular/tree/master/modules/core/src/annotations 2 | class Directive { 3 | constructor(options:DirectiveOptions) { 4 | this.selector = options.selector; 5 | this.bind = options.bind; 6 | this.controllerAs = options.controllerAs || 'ctrl'; 7 | this.observe = options.observe; 8 | } 9 | } 10 | 11 | var DirectiveOptions = assert.define('DirectiveOptions', function (options) { 12 | //Required fields 13 | assert(options).is(assert.structure({ 14 | selector: assert.string 15 | })); 16 | 17 | //Optional fields 18 | if (options.bind) { 19 | assert.type(options.bind, Object); 20 | } 21 | if (options.controllerAs) { 22 | assert.type(options.controllerAs, assert.string); 23 | } 24 | if (options.observe) { 25 | assert.type(options.observe, Object); 26 | } 27 | 28 | for (var key in options) { 29 | if (options.hasOwnProperty(key)) { 30 | if (key !== 'selector' && key !== 'bind' && key !== 'controllerAs' && key !== 'observe') { 31 | assert.fail(`${key} is not a valid directive field`); 32 | } 33 | } 34 | } 35 | }); 36 | 37 | var DirectiveClass = assert.define('DirectiveClass', function (dirClass) { 38 | assert.type(dirClass, Object); 39 | 40 | var numDirAnnos; 41 | if(dirClass.annotations) { 42 | numDirAnnos = dirClass.annotations.filter(anno => anno instanceof Directive).length; 43 | } else { 44 | numDirAnnos = 0; 45 | } 46 | 47 | 48 | if (numDirAnnos === 0) { 49 | assert.fail('A DirectiveClass must have a Directive annotation'); 50 | } else if(numDirAnnos > 1) { 51 | asssert.fail('You cannot have more than one Directive annotations on a class.'); 52 | } 53 | }); 54 | 55 | export {Directive, DirectiveOptions, DirectiveClass}; -------------------------------------------------------------------------------- /examples/hello-jspm/jspm_packages/github/robianmcd/angular-next@0.0.3/ng2/directive.js: -------------------------------------------------------------------------------- 1 | //See here for detailed annotation implimentations https://github.com/angular/angular/tree/master/modules/core/src/annotations 2 | class Directive { 3 | constructor(options:DirectiveOptions) { 4 | this.selector = options.selector; 5 | this.bind = options.bind; 6 | this.controllerAs = options.controllerAs || 'ctrl'; 7 | this.observe = options.observe; 8 | } 9 | } 10 | 11 | var DirectiveOptions = assert.define('DirectiveOptions', function (options) { 12 | //Required fields 13 | assert(options).is(assert.structure({ 14 | selector: assert.string 15 | })); 16 | 17 | //Optional fields 18 | if (options.bind) { 19 | assert.type(options.bind, Object); 20 | } 21 | if (options.controllerAs) { 22 | assert.type(options.controllerAs, assert.string); 23 | } 24 | if (options.observe) { 25 | assert.type(options.observe, Object); 26 | } 27 | 28 | for (var key in options) { 29 | if (options.hasOwnProperty(key)) { 30 | if (key !== 'selector' && key !== 'bind' && key !== 'controllerAs' && key !== 'observe') { 31 | assert.fail(`${key} is not a valid directive field`); 32 | } 33 | } 34 | } 35 | }); 36 | 37 | var DirectiveClass = assert.define('DirectiveClass', function (dirClass) { 38 | assert.type(dirClass, Object); 39 | 40 | var numDirAnnos; 41 | if(dirClass.annotations) { 42 | numDirAnnos = dirClass.annotations.filter(anno => anno instanceof Directive).length; 43 | } else { 44 | numDirAnnos = 0; 45 | } 46 | 47 | 48 | if (numDirAnnos === 0) { 49 | assert.fail('A DirectiveClass must have a Directive annotation'); 50 | } else if(numDirAnnos > 1) { 51 | asssert.fail('You cannot have more than one Directive annotations on a class.'); 52 | } 53 | }); 54 | 55 | export {Directive, DirectiveOptions, DirectiveClass}; -------------------------------------------------------------------------------- /examples/color-slider/readme.md: -------------------------------------------------------------------------------- 1 | # Angular Next - Color Slider 2 | 3 | This app demonstrates many of the Angular 2 features that Angular Next lets you start using. It also shows how you use these features along side existing Angular 1 code. Angular 2 relies on ES6 modules but you may not want to use modules for your existing Angular 1 code. To deal with this the [gulpfile](https://github.com/robianmcd/angular-next/blob/gh-pages/examples/color-slider/gulpfile.js#L29-L49) for this project will only treat files ending with `.ats.js` as ES6 modules and compile them into ES5 with Traceur. 4 | 5 | ### Demo 6 | 7 | [http://robianmcd.github.io/angular-next/examples/color-slider/build](http://robianmcd.github.io/angular-next/examples/color-slider/build) 8 | 9 | ### Demonstrated Features 10 | * [Bootstrapping an app](https://github.com/robianmcd/angular-next/blob/gh-pages/examples/color-slider/src/app.ats.js#L5) 11 | * [Component directive](https://github.com/robianmcd/angular-next/blob/gh-pages/examples/color-slider/src/components/colorSettings/ng2ColorSettings.ats.js) 12 | * [Decorator directive](https://github.com/robianmcd/angular-next/blob/gh-pages/examples/color-slider/src/decorators/backgroundColor.ats.js) 13 | * [Directive selector](https://github.com/robianmcd/angular-next/blob/gh-pages/examples/color-slider/src/components/colorSettings/ng2ColorSettings.ats.js#L7) 14 | * [Directive bind and observe](https://github.com/robianmcd/angular-next/blob/gh-pages/examples/color-slider/src/decorators/backgroundColor.ats.js#L5-L6) 15 | * [Service](https://github.com/robianmcd/angular-next/blob/gh-pages/examples/color-slider/src/services/colorUtil.ats.js) 16 | * [Injecting NgElement into directive controller](https://github.com/robianmcd/angular-next/blob/gh-pages/examples/color-slider/src/decorators/backgroundColor.ats.js#L9) 17 | * [Injecting an Angular 2 Service, a parent component, and an Angular 1 Service](https://github.com/robianmcd/angular-next/blob/gh-pages/examples/color-slider/src/components/colorSettings/ng2ColorSettings.ats.js#L15) 18 | 19 | ### Run locally 20 | 21 | ```sh 22 | git clone https://github.com/robianmcd/angular-next.git 23 | cd angular-next/examples/color-slider 24 | npm install 25 | bower install 26 | gulp 27 | ``` 28 | 29 | You can now access the app at [http://localhost:8080/](http://localhost:8080/) -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | var gulp = require('gulp'), 2 | traceur = require('gulp-traceur'), 3 | concat = require('gulp-concat'), 4 | karma = require('gulp-karma'), 5 | replace = require('gulp-replace'); 6 | 7 | var appFiles = 'src/**/*.js'; 8 | var testFiles = 'test/**/*.js'; 9 | 10 | var filesForKarma = [ 11 | 'bower_components/angular/angular.js', 12 | 'dist/angularNext-standalone.js', 13 | 'test-build/**/*.js', 14 | 'testMain.js' 15 | ]; 16 | 17 | var traceurOptions = { 18 | experimental: true, 19 | modules: 'instantiate', 20 | moduleName: true, 21 | annotations: true, 22 | types: true, 23 | typeAssertions: true, 24 | typeAssertionModule: "angular2/rtts-assert.js" 25 | }; 26 | 27 | gulp.task('build-angular-next', function () { 28 | gulp.src(appFiles) 29 | .pipe(replace(/(import|export)( .*? from '.*?)\.js(';)/g, '$1$2$3')) 30 | .pipe(gulp.dest('dist/es6')); 31 | 32 | return gulp.src(appFiles) 33 | .pipe(traceur(traceurOptions)) 34 | .pipe(concat('angularNext.js')) 35 | .pipe(gulp.dest('dist')); 36 | }); 37 | 38 | gulp.task('build-test-files', function () { 39 | return gulp.src(testFiles) 40 | .pipe(traceur(traceurOptions)) 41 | .pipe(gulp.dest('test-build')); 42 | }); 43 | 44 | gulp.task('build', ['build-angular-next', 'build-test-files'], function () { 45 | gulp.src([ 46 | 'bower_components/traceur-runtime/traceur-runtime.js', 47 | 'bower_components/es6-module-loader/dist/es6-module-loader.src.js', 48 | 'lib/systemjs-register/extension-register.js', 49 | 'lib/systemjs-register/initialize-register.js', 50 | 'dist/angularNext.js']) 51 | .pipe(concat('angularNext-standalone.js')) 52 | .pipe(gulp.dest('dist')); 53 | }); 54 | 55 | gulp.task('test', function () { 56 | return gulp.src(filesForKarma) 57 | .pipe(karma({ 58 | configFile: 'karma.conf.js', 59 | action: 'run' 60 | })); 61 | }); 62 | 63 | gulp.task('default', ['build'], function () { 64 | gulp.watch([appFiles], ['build']); 65 | gulp.watch([testFiles], ['build-test-files']); 66 | 67 | gulp.src(filesForKarma) 68 | .pipe(karma({ 69 | configFile: 'karma.conf.js', 70 | action: 'watch' 71 | })); 72 | }); -------------------------------------------------------------------------------- /examples/color-slider/gulpfile.js: -------------------------------------------------------------------------------- 1 | var gulp = require('gulp'), 2 | traceur = require('gulp-traceur'), 3 | connect = require('gulp-connect'), 4 | gulpIf = require('gulp-if'), 5 | rename = require('gulp-rename'), 6 | lazypipe = require('lazypipe'); 7 | 8 | var vendorFiles = [ 9 | 'bower_components/angular-next/dist/angularNext-standalone.js', 10 | 'bower_components/angular/angular.js', 11 | 'bower_components/angular-animate/angular-animate.js', 12 | 'bower_components/angular-aria/angular-aria.js', 13 | 'bower_components/hammerjs/hammer.js', 14 | 'bower_components/angular-material/angular-material.js' 15 | ]; 16 | 17 | var cssFiles = [ 18 | 'bower_components/angular-material/angular-material.css', 19 | 'bower_components/angular-material/themes/blue-grey-theme.css', 20 | 'src/css/**/*.css' 21 | ]; 22 | 23 | gulp.task('html', function () { 24 | gulp.src('src/**/*.html') 25 | .pipe(gulp.dest('build')) 26 | .pipe(connect.reload()); 27 | }); 28 | 29 | gulp.task('js', function () { 30 | var buildAtScript = lazypipe() 31 | .pipe(rename, function (path) { 32 | //remove .ats from the filename 33 | path.basename = path.basename.substring(0, path.basename.length - 4); 34 | }) 35 | .pipe(traceur, { 36 | modules: 'instantiate', 37 | moduleName: true, 38 | annotations: true, 39 | types: true, 40 | typeAssertions: true, 41 | typeAssertionModule: 'angular2/rtts-assert.js' 42 | }); 43 | 44 | gulp.src('src/**/*.js') 45 | //Only files ending in .ats.js will be treated as AtScript and transpiled with Traceur 46 | .pipe(gulpIf(/\.ats\.js$/, buildAtScript())) 47 | .pipe(gulp.dest('build')) 48 | .pipe(connect.reload()); 49 | }); 50 | 51 | gulp.task('css', function () { 52 | gulp.src(cssFiles) 53 | .pipe(gulp.dest('build/css')) 54 | .pipe(connect.reload()); 55 | }); 56 | 57 | gulp.task('vendor', function () { 58 | gulp.src(vendorFiles) 59 | .pipe(gulp.dest('build/vendor')) 60 | }); 61 | 62 | gulp.task('default', ['js', 'html', 'css', 'vendor'], function () { 63 | connect.server({ 64 | livereload: true, 65 | root: 'build' 66 | }); 67 | 68 | gulp.watch(['src/**/*.html'], ['html']); 69 | gulp.watch(['src/**/*.js'], ['js']); 70 | gulp.watch([cssFiles], ['css']); 71 | }); -------------------------------------------------------------------------------- /examples/color-slider/build/components/colorSettings/ng2ColorSettings.js: -------------------------------------------------------------------------------- 1 | System.register("components/colorSettings/ng2ColorSettings.js", ["angular2/rtts-assert.js", "angular2/angular2.js", "decorators/backgroundColor.js", "services/colorUtil.js", "components/base/baseComponent.js"], function($__export) { 2 | "use strict"; 3 | var __moduleName = "components/colorSettings/ng2ColorSettings.js"; 4 | var assert, 5 | Component, 6 | Template, 7 | InjectNgOne, 8 | BackgroundColor, 9 | ColorUtil, 10 | BaseComponent, 11 | Ng2ColorSettings; 12 | return { 13 | setters: [function(m) { 14 | assert = m.assert; 15 | }, function(m) { 16 | Component = m.Component; 17 | Template = m.Template; 18 | InjectNgOne = m.InjectNgOne; 19 | }, function(m) { 20 | BackgroundColor = m.default; 21 | }, function(m) { 22 | ColorUtil = m.default; 23 | }, function(m) { 24 | BaseComponent = m.default; 25 | }], 26 | execute: function() { 27 | Ng2ColorSettings = (function() { 28 | var Ng2ColorSettings = function Ng2ColorSettings(colorUtil, base, $log) { 29 | assert.argumentTypes(colorUtil, ColorUtil, base, BaseComponent, $log, $traceurRuntime.type.any); 30 | this.colorUtil = colorUtil; 31 | this.base = base; 32 | this.$log = $log; 33 | this.hue = 0; 34 | }; 35 | return ($traceurRuntime.createClass)(Ng2ColorSettings, { 36 | hueToHash: function(hue) { 37 | return this.colorUtil.hslToHash(hue / 100, 0.8, 0.5); 38 | }, 39 | setParentColor: function() { 40 | var hash = this.hueToHash(this.hue); 41 | this.$log.info(("setting the base component's background color to " + hash)); 42 | this.base.setBackgroundColor(hash); 43 | } 44 | }, {}); 45 | }()); 46 | Object.defineProperty(Ng2ColorSettings, "annotations", {get: function() { 47 | return [new Component({selector: 'ng2-color-settings'}), new Template({ 48 | url: 'components/colorSettings/colorSettings.html', 49 | directives: [BackgroundColor] 50 | })]; 51 | }}); 52 | Object.defineProperty(Ng2ColorSettings, "parameters", {get: function() { 53 | return [[ColorUtil], [BaseComponent], [new InjectNgOne('$log')]]; 54 | }}); 55 | $__export('default', Ng2ColorSettings); 56 | } 57 | }; 58 | }); 59 | //# sourceURL=components/colorSettings/ng2ColorSettings.js -------------------------------------------------------------------------------- /test/ngNext/angular2AdapterTest.js: -------------------------------------------------------------------------------- 1 | import {Angular2Adapter, Decorator, Component, Template, InjectNgOne} from 'angular2/angular2.js'; 2 | 3 | describe('Angular2Adapter', function () { 4 | 5 | var adapter; 6 | 7 | class MyService { 8 | 9 | } 10 | 11 | @Decorator({selector: '[my-dec]'}) 12 | class MyDec { 13 | constructor(myService:MyService) { 14 | 15 | } 16 | } 17 | 18 | @Component({ 19 | selector: 'my-component', 20 | controllerAs: 'myCtrl', 21 | bind: {param1: 'param1'} 22 | }) 23 | @Template({inline: 'hello world'}) 24 | class MyComp { 25 | constructor(param1:Object) { 26 | 27 | } 28 | } 29 | 30 | 31 | beforeEach(function () { 32 | angular.module('myApp', []); 33 | adapter = new Angular2Adapter({moduleName: 'myApp'}); 34 | }); 35 | 36 | describe('getNg1DirectiveInfo', function () { 37 | it('should generate ddo for attribute selector directive', function () { 38 | expect(adapter.getNg1DirectiveInfo(MyDec)).toEqual({ 39 | name: 'myDec', 40 | ddo: { 41 | restrict: 'A', 42 | controller: MyDec, 43 | controllerAs: 'ctrl', 44 | scope: {}, 45 | bindToController: true 46 | } 47 | }); 48 | }); 49 | 50 | it('should generate ddo for element selector directive', function () { 51 | expect(adapter.getNg1DirectiveInfo(MyComp)).toEqual({ 52 | name: 'myComponent', 53 | ddo: { 54 | restrict: 'E', 55 | controller: MyComp, 56 | controllerAs: 'myCtrl', 57 | scope: {param1: '=param1'}, 58 | bindToController: true, 59 | template: 'hello world' 60 | } 61 | }); 62 | }); 63 | }); 64 | 65 | describe('getInjectArray', function () { 66 | it('should get a decorator\'s $inject array', function () { 67 | expect(adapter.getInjectArray(MyDec)).toEqual(['myService']); 68 | }); 69 | }); 70 | 71 | describe('getInjectStrFromParamAnnotations', function () { 72 | it('should return the correct string', function () { 73 | expect(adapter.getInjectStrFromParamAnnotations([MyDec])).toEqual('myDec'); 74 | expect(adapter.getInjectStrFromParamAnnotations([new InjectNgOne('$scope')])).toEqual('$scope'); 75 | 76 | var callWithInvalidParam = function () { 77 | adapter.getInjectStrFromParamAnnotations([]); 78 | }; 79 | expect(callWithInvalidParam).toThrow(); 80 | }); 81 | }); 82 | 83 | describe('getDirAnno', function () { 84 | it('should return the annotation', function () { 85 | var anno = adapter.getDirAnno(MyDec); 86 | expect(anno).toEqual(jasmine.any(Decorator)); 87 | expect(anno.selector).toEqual('[my-dec]'); 88 | }); 89 | }); 90 | 91 | describe('lowerCaseFirstLetter', function () { 92 | it('should make the first character lower case', function () { 93 | expect(adapter.lowerCaseFirstLetter('MyClassName')).toEqual('myClassName'); 94 | expect(adapter.lowerCaseFirstLetter('alreadyLower')).toEqual('alreadyLower'); 95 | expect(adapter.lowerCaseFirstLetter('A')).toEqual('a'); 96 | expect(adapter.lowerCaseFirstLetter('$Thing')).toEqual('$Thing'); 97 | expect(adapter.lowerCaseFirstLetter('')).toEqual(''); 98 | }); 99 | }); 100 | 101 | 102 | describe('getFunctionName', function () { 103 | it('should return the name of a class', function () { 104 | expect(adapter.getFunctionName(MyDec)).toEqual('MyDec'); 105 | }); 106 | }); 107 | 108 | describe('isDirClass', function () { 109 | it('should return true for decorator', function () { 110 | expect(adapter.isDirClass(MyDec)).toBe(true); 111 | }); 112 | 113 | it('should return false for nonDirective', function () { 114 | var MyClass = function () { 115 | 116 | }; 117 | MyClass.annotations = [{selector: 'not-a-real-directive'}]; 118 | expect(adapter.isDirClass(MyClass)).toBe(false); 119 | }); 120 | 121 | }); 122 | 123 | 124 | }); -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Bower version](https://badge.fury.io/bo/angular-next.svg)](http://badge.fury.io/bo/angular-next) [![Build Status](https://travis-ci.org/robianmcd/angular-next.svg)](https://travis-ci.org/robianmcd/angular-next) 2 | 3 | # Deprecated! This project is way out of date and is not maintained. 4 | 5 | # angular-next 6 | 7 | > Angular Next brings the power of **Angular 2** to Angular 1 and gives you an incremental **migration path**. 8 | 9 | This library lets you start writing Angular 2 style directives and services and use them in an existing Angular 1 app. This allows you to incrementally adopt features from Angular 2 instead of needing to migrate all at once. 10 | 11 | **Warning: Angular Next is still highly experimental. It could change drastically as more information is released about Angular 2.0** 12 | 13 | ## Sample App: Angular 1 + Angular Next 14 | 15 | index.html 16 | ```html 17 | 18 | 19 | 20 | 21 | 26 | ``` 27 | 28 | app.js 29 | ```javascript 30 | import {bootstrap, Component, TemplateConfig} from 'angular2/angular2.js'; 31 | 32 | @Component({ 33 | selector: 'hello-component', 34 | template: new TemplateConfig({ 35 | inline: '

{{ctrl.message}}

' 36 | }) 37 | }) 38 | class HelloComponent { 39 | constructor() { 40 | this.message = 'Hello World'; 41 | } 42 | } 43 | 44 | export function main() { 45 | angular.module('myApp', []); 46 | bootstrap(HelloComponent, {moduleName: 'myApp'}); 47 | } 48 | ``` 49 | 50 | ## Demos 51 | 52 | **[Hello World](https://github.com/robianmcd/angular-next/tree/gh-pages/examples/hello-world)** 53 | * A working demo of the hello world example shown above. 54 | 55 | **[Hello jspm](https://github.com/robianmcd/angular-next/tree/gh-pages/examples/hello-jspm)** 56 | * Uses [jspm](http://jspm.io/) to load the Angular Next modules into the browser. 57 | 58 | **[Color Slider](https://github.com/robianmcd/angular-next/tree/gh-pages/examples/color-slider)** 59 | * Demonstrates usage of: components, decorators, services, bootstrapping, selector, bind, observe, NgElement, injecting parent directives, injecting Angular 1 services, gulp, Traceur, etc. 60 | 61 | ## Get Angular Next 62 | Angular Next distributes two files 63 | * **angularNext-standalone.js** - Contains the Angular Next library along with all of its dependencies. This includes [traceur-runtime](https://github.com/jmcriffey/bower-traceur-runtime), [es6-module-loader](https://github.com/ModuleLoader/es6-module-loader), [the register extension for systemjs](https://github.com/systemjs/systemjs/blob/master/lib/extension-register.js), and [assert.js](http://angular.github.io/assert/) 64 | * **angularNext.js** - Just the Angular Next library. If you use this you'll need to manually include all of the dependencies. 65 | 66 | You can get Angular Next through bower 67 | 68 | ```sh 69 | bower install angular-next 70 | ``` 71 | 72 | or from the CDN 73 | 74 | ```html 75 | 76 | ``` 77 | 78 | or from jspm. See the [jspm example](https://github.com/robianmcd/angular-next/tree/gh-pages/examples/hello-jspm) for details. 79 | ```sh 80 | jspm install angular2=github:robianmcd/angular-next 81 | ``` 82 | 83 | ## Documentation 84 | For documentation on the supported features checkout the [Wiki](https://github.com/robianmcd/angular-next/wiki). 85 | 86 | ## Changelog 87 | 88 | ## 0.0.3 - 2015-02-23 89 | 90 | ### Added 91 | - Replaced ES6 Promise implementation with one based on $q so they are integrated with Angular's digest cycle. 92 | - Created an example using jspm 93 | 94 | ### Changed 95 | - Replaced template option in Component directives with a new `@Template` annotation 96 | - Renamed assert.js module to angular2/rtts-assert.js 97 | 98 | [Click here for the full changelog](https://github.com/robianmcd/angular-next/blob/gh-pages/CHANGELOG.md) 99 | 100 | ## Roadmap 101 | 1. support as much of the new template syntax as possible 102 | 1. improve jspm example to include bundeling 103 | 1. Improve unit tests and add e2e tests 104 | 1. Look into integrating with the new [router](https://github.com/angular/router) 105 | 1. Add better logging for common errors 106 | 1. Support template directives. **Blocked**: Waiting for more details to be released 107 | 1. Support querying child directives. **Blocked**: Waiting for more details to be released 108 | -------------------------------------------------------------------------------- /src/angular2/ngNext/registerNg2Directives.js: -------------------------------------------------------------------------------- 1 | function registerPropertyDirectives(ngModule) { 2 | const ALL_PROPERTIES = ['abbr', 'accept', 'acceptCharset', 'accessKey', 'accessKeyLabel', 'action', 'allowfullscreen', 'alt', 'areas', 'async', 'attributes', 'audioTracks', 'autocomplete', 'autofocus', 'autoplay', 'baseURI', 'buffered', 'caption', 'cellIndex', 'cells', 'challenge', 'charset', 'checked', 'childElementCount', 'childNodes', 'children', 'cite', 'classList', 'className', 'clientHeight', 'clientLeft', 'clientTop', 'clientWidth', 'color', 'cols', 'colSpan', 'complete', 'content', 'contentDocument', 'contentEditable', 'contentWindow', 'contextMenu', 'control', 'controller', 'controls', 'coords', 'crossOrigin', 'currentSrc', 'currentTime', 'data', 'dataset', 'datetime', 'default', 'defaultChecked', 'defaultMuted', 'defaultPlaybackRate', 'defaultSelected', 'defaultValue', 'defer', 'dir', 'dirName', 'disabled', 'download', 'draggable', 'dropzone', 'duration', 'elements', 'encoding', 'enctype', 'ended', 'error', 'face', 'files', 'firstChild', 'firstElementChild', 'form', 'formAction', 'formEncType', 'formMethod', 'formNoValidate', 'formTarget', 'hash', 'headers', 'height', 'hidden', 'high', 'host', 'hostname', 'href', 'hreflang', 'htmlFor', 'httpEquiv', 'id', 'images', 'indeterminate', 'index', 'innerHTML', 'inputMode', 'isContentEditable', 'isMap', 'itemId', 'itemProp', 'itemRef', 'itemScope', 'itemType', 'itemValue', 'keySystem', 'keytype', 'kind', 'label', 'labels', 'lang', 'lastChild', 'lastElementChild', 'length', 'list', 'loop', 'low', 'max', 'maxLength', 'media', 'mediaGroup', 'menu', 'method', 'min', 'multiple', 'muted', 'name', 'naturalHeight', 'naturalWidth', 'networkState', 'nextElementSibling', 'nextSibling', 'nodeName', 'nodeType', 'nodeValue', 'noValidate', 'offsetHeight', 'offsetLeft', 'offsetParent', 'offsetTop', 'offsetWidth', 'optimum', 'options', 'origin', 'outerHTML', 'ownerDocument', 'parentElement', 'parentNode', 'password', 'pathname', 'pattern', 'paused', 'placeholder', 'playbackRate', 'played', 'port', 'position', 'poster', 'preload', 'previousElementSibling', 'previousSibling', 'properties', 'protocol', 'readOnly', 'readyState', 'rel', 'relList', 'required', 'reversed', 'rowIndex', 'rows', 'rowSpan', 'sandbox', 'scope', 'scoped', 'scrollHeight', 'scrollLeft', 'scrollTop', 'scrollWidth', 'seamless', 'search', 'sectionRowIndex', 'seekable', 'seeking', 'select', 'selected', 'selectedIndex', 'selectedOptions', 'selectionDirection', 'selectionEnd', 'selectionStart', 'shadowRoot', 'sheet', 'size', 'sizes', 'sortable', 'sorted', 'span', 'spellcheck', 'src', 'srcdoc', 'srclang', 'srcset', 'start', 'step', 'style', 'tabIndex', 'tagName', 'target', 'tBodies', 'text', 'textContent', 'textLength', 'textTracks', 'tFoot', 'tHead', 'title', 'track', 'translate', 'type', 'typeMustMatch', 'undoManager', 'undoScope', 'useMap', 'username', 'validationMessage', 'validity', 'value', 'valueAsDate', 'valueAsNumber', 'videoHeight', 'videoTracks', 'videoWidth', 'volume', 'width', 'willValidate', 'wrap']; 3 | 4 | angular.forEach(ALL_PROPERTIES, function (prop) { 5 | var directiveName = `[${prop}]`; 6 | ngModule.directive(directiveName, ['$parse', '$timeout', function ($parse, $timeout) { 7 | return { 8 | restrict: 'A', 9 | link: function (scope, element, attrs) { 10 | var domElement = element[0]; 11 | 12 | var bindExpression = $parse(attrs[directiveName]); 13 | 14 | var curValue = bindExpression(scope); 15 | if (curValue === undefined) { 16 | curValue = domElement[prop]; 17 | if (curValue !== undefined) { 18 | bindExpression.assign(scope, curValue); 19 | } 20 | } else { 21 | domElement[prop] = curValue; 22 | } 23 | 24 | 25 | //Note that this will only be called on a digest and changes to a property won't necessarily trigger a digest. 26 | scope.$watch(() => domElement[prop], 27 | function (newValue) { 28 | if (newValue !== curValue) { 29 | curValue = newValue; 30 | bindExpression.assign(scope, newValue); 31 | } 32 | }); 33 | 34 | scope.$watch(attrs[directiveName], function (newValue) { 35 | if (newValue !== curValue) { 36 | curValue = newValue; 37 | domElement[prop] = newValue; 38 | } 39 | }); 40 | 41 | 42 | if (domElement.nodeName === 'INPUT' || domElement.nodeName === 'TEXTAREA') { 43 | domElement.addEventListener('input', function () { 44 | var newValue = domElement[prop]; 45 | if (newValue !== curValue) { 46 | curValue = newValue; 47 | bindExpression.assign(scope, newValue); 48 | scope.$apply(); 49 | } 50 | }); 51 | } 52 | 53 | } 54 | }; 55 | }]); 56 | }); 57 | } 58 | 59 | //Taken from https://github.com/angular/angular.js/blob/master/src/ng/directive/ngEventDirs.js 60 | function registerEventDirectives(ngModule) { 61 | var forceAsyncEvents = { 62 | 'blur': true, 63 | 'focus': true 64 | }; 65 | angular.forEach( 66 | 'click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave keydown keyup keypress submit focus blur copy cut paste'.split(' '), 67 | function (eventName) { 68 | var directiveName = `(${eventName})`; 69 | ngModule.directive(directiveName, ['$parse', '$rootScope', function ($parse, $rootScope) { 70 | return { 71 | restrict: 'A', 72 | compile: function ($element, attr) { 73 | // We expose the powerful $event object on the scope that provides access to the Window, 74 | // etc. that isn't protected by the fast paths in $parse. We explicitly request better 75 | // checks at the cost of speed since event handler expressions are not executed as 76 | // frequently as regular change detection. 77 | var fn = $parse(attr[directiveName], /* interceptorFn */ null, /* expensiveChecks */ true); 78 | return function ngEventHandler(scope, element) { 79 | element.on(eventName, function (event) { 80 | var callback = function () { 81 | fn(scope, {$event: event}); 82 | }; 83 | if (forceAsyncEvents[eventName] && $rootScope.$$phase) { 84 | scope.$evalAsync(callback); 85 | } else { 86 | scope.$apply(callback); 87 | } 88 | }); 89 | }; 90 | } 91 | }; 92 | }]); 93 | } 94 | ); 95 | } 96 | 97 | export default function (ngModule) { 98 | registerPropertyDirectives(ngModule); 99 | registerEventDirectives(ngModule); 100 | }; -------------------------------------------------------------------------------- /dist/es6/angular2/ngNext/registerNg2Directives.js: -------------------------------------------------------------------------------- 1 | function registerPropertyDirectives(ngModule) { 2 | const ALL_PROPERTIES = ['abbr', 'accept', 'acceptCharset', 'accessKey', 'accessKeyLabel', 'action', 'allowfullscreen', 'alt', 'areas', 'async', 'attributes', 'audioTracks', 'autocomplete', 'autofocus', 'autoplay', 'baseURI', 'buffered', 'caption', 'cellIndex', 'cells', 'challenge', 'charset', 'checked', 'childElementCount', 'childNodes', 'children', 'cite', 'classList', 'className', 'clientHeight', 'clientLeft', 'clientTop', 'clientWidth', 'color', 'cols', 'colSpan', 'complete', 'content', 'contentDocument', 'contentEditable', 'contentWindow', 'contextMenu', 'control', 'controller', 'controls', 'coords', 'crossOrigin', 'currentSrc', 'currentTime', 'data', 'dataset', 'datetime', 'default', 'defaultChecked', 'defaultMuted', 'defaultPlaybackRate', 'defaultSelected', 'defaultValue', 'defer', 'dir', 'dirName', 'disabled', 'download', 'draggable', 'dropzone', 'duration', 'elements', 'encoding', 'enctype', 'ended', 'error', 'face', 'files', 'firstChild', 'firstElementChild', 'form', 'formAction', 'formEncType', 'formMethod', 'formNoValidate', 'formTarget', 'hash', 'headers', 'height', 'hidden', 'high', 'host', 'hostname', 'href', 'hreflang', 'htmlFor', 'httpEquiv', 'id', 'images', 'indeterminate', 'index', 'innerHTML', 'inputMode', 'isContentEditable', 'isMap', 'itemId', 'itemProp', 'itemRef', 'itemScope', 'itemType', 'itemValue', 'keySystem', 'keytype', 'kind', 'label', 'labels', 'lang', 'lastChild', 'lastElementChild', 'length', 'list', 'loop', 'low', 'max', 'maxLength', 'media', 'mediaGroup', 'menu', 'method', 'min', 'multiple', 'muted', 'name', 'naturalHeight', 'naturalWidth', 'networkState', 'nextElementSibling', 'nextSibling', 'nodeName', 'nodeType', 'nodeValue', 'noValidate', 'offsetHeight', 'offsetLeft', 'offsetParent', 'offsetTop', 'offsetWidth', 'optimum', 'options', 'origin', 'outerHTML', 'ownerDocument', 'parentElement', 'parentNode', 'password', 'pathname', 'pattern', 'paused', 'placeholder', 'playbackRate', 'played', 'port', 'position', 'poster', 'preload', 'previousElementSibling', 'previousSibling', 'properties', 'protocol', 'readOnly', 'readyState', 'rel', 'relList', 'required', 'reversed', 'rowIndex', 'rows', 'rowSpan', 'sandbox', 'scope', 'scoped', 'scrollHeight', 'scrollLeft', 'scrollTop', 'scrollWidth', 'seamless', 'search', 'sectionRowIndex', 'seekable', 'seeking', 'select', 'selected', 'selectedIndex', 'selectedOptions', 'selectionDirection', 'selectionEnd', 'selectionStart', 'shadowRoot', 'sheet', 'size', 'sizes', 'sortable', 'sorted', 'span', 'spellcheck', 'src', 'srcdoc', 'srclang', 'srcset', 'start', 'step', 'style', 'tabIndex', 'tagName', 'target', 'tBodies', 'text', 'textContent', 'textLength', 'textTracks', 'tFoot', 'tHead', 'title', 'track', 'translate', 'type', 'typeMustMatch', 'undoManager', 'undoScope', 'useMap', 'username', 'validationMessage', 'validity', 'value', 'valueAsDate', 'valueAsNumber', 'videoHeight', 'videoTracks', 'videoWidth', 'volume', 'width', 'willValidate', 'wrap']; 3 | 4 | angular.forEach(ALL_PROPERTIES, function (prop) { 5 | var directiveName = `[${prop}]`; 6 | ngModule.directive(directiveName, ['$parse', '$timeout', function ($parse, $timeout) { 7 | return { 8 | restrict: 'A', 9 | link: function (scope, element, attrs) { 10 | var domElement = element[0]; 11 | 12 | var bindExpression = $parse(attrs[directiveName]); 13 | 14 | var curValue = bindExpression(scope); 15 | if (curValue === undefined) { 16 | curValue = domElement[prop]; 17 | if (curValue !== undefined) { 18 | bindExpression.assign(scope, curValue); 19 | } 20 | } else { 21 | domElement[prop] = curValue; 22 | } 23 | 24 | 25 | //Note that this will only be called on a digest and changes to a property won't necessarily trigger a digest. 26 | scope.$watch(() => domElement[prop], 27 | function (newValue) { 28 | if (newValue !== curValue) { 29 | curValue = newValue; 30 | bindExpression.assign(scope, newValue); 31 | } 32 | }); 33 | 34 | scope.$watch(attrs[directiveName], function (newValue) { 35 | if (newValue !== curValue) { 36 | curValue = newValue; 37 | domElement[prop] = newValue; 38 | } 39 | }); 40 | 41 | 42 | if (domElement.nodeName === 'INPUT' || domElement.nodeName === 'TEXTAREA') { 43 | domElement.addEventListener('input', function () { 44 | var newValue = domElement[prop]; 45 | if (newValue !== curValue) { 46 | curValue = newValue; 47 | bindExpression.assign(scope, newValue); 48 | scope.$apply(); 49 | } 50 | }); 51 | } 52 | 53 | } 54 | }; 55 | }]); 56 | }); 57 | } 58 | 59 | //Taken from https://github.com/angular/angular.js/blob/master/src/ng/directive/ngEventDirs.js 60 | function registerEventDirectives(ngModule) { 61 | var forceAsyncEvents = { 62 | 'blur': true, 63 | 'focus': true 64 | }; 65 | angular.forEach( 66 | 'click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave keydown keyup keypress submit focus blur copy cut paste'.split(' '), 67 | function (eventName) { 68 | var directiveName = `(${eventName})`; 69 | ngModule.directive(directiveName, ['$parse', '$rootScope', function ($parse, $rootScope) { 70 | return { 71 | restrict: 'A', 72 | compile: function ($element, attr) { 73 | // We expose the powerful $event object on the scope that provides access to the Window, 74 | // etc. that isn't protected by the fast paths in $parse. We explicitly request better 75 | // checks at the cost of speed since event handler expressions are not executed as 76 | // frequently as regular change detection. 77 | var fn = $parse(attr[directiveName], /* interceptorFn */ null, /* expensiveChecks */ true); 78 | return function ngEventHandler(scope, element) { 79 | element.on(eventName, function (event) { 80 | var callback = function () { 81 | fn(scope, {$event: event}); 82 | }; 83 | if (forceAsyncEvents[eventName] && $rootScope.$$phase) { 84 | scope.$evalAsync(callback); 85 | } else { 86 | scope.$apply(callback); 87 | } 88 | }); 89 | }; 90 | } 91 | }; 92 | }]); 93 | } 94 | ); 95 | } 96 | 97 | export default function (ngModule) { 98 | registerPropertyDirectives(ngModule); 99 | registerEventDirectives(ngModule); 100 | }; -------------------------------------------------------------------------------- /examples/color-slider/build/css/blue-grey-theme.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Angular Material Design 3 | * https://github.com/angular/material 4 | * @license MIT 5 | * v0.6.1 6 | */ 7 | md-backdrop.md-opaque.md-blue-grey-theme { 8 | background-color: rgba(0, 0, 0, 0.3); 9 | position: absolute; } 10 | 11 | md-bottom-sheet.md-blue-grey-theme { 12 | background-color: #fafafa; 13 | border-top-color: #bdbdbd; } 14 | md-bottom-sheet.md-blue-grey-theme.md-list md-item { 15 | color: rgba(0, 0, 0, 0.54); } 16 | md-bottom-sheet.md-blue-grey-theme .md-subheader { 17 | background-color: #fafafa; } 18 | md-bottom-sheet.md-blue-grey-theme .md-subheader { 19 | color: rgba(0, 0, 0, 0.54); } 20 | 21 | .md-button.md-blue-grey-theme { 22 | border-radius: 3px; } 23 | .md-button.md-blue-grey-theme:not([disabled]):hover, .md-button.md-blue-grey-theme:not([disabled]):focus { 24 | background-color: rgba(158, 158, 158, 0.2); } 25 | .md-button.md-blue-grey-theme.md-fab { 26 | border-radius: 50%; } 27 | .md-button.md-blue-grey-theme.md-primary { 28 | color: #78909c; 29 | fill: #78909c; } 30 | .md-button.md-blue-grey-theme.md-warn { 31 | color: #ef5350; 32 | fill: #ef5350; } 33 | .md-button.md-blue-grey-theme.md-raised, .md-button.md-blue-grey-theme.md-fab { 34 | background-color: rgba(158, 158, 158, 0.185); } 35 | .md-button.md-blue-grey-theme.md-raised:not([disabled]):hover, .md-button.md-blue-grey-theme.md-raised:not([disabled]):focus, .md-button.md-blue-grey-theme.md-fab:not([disabled]):hover, .md-button.md-blue-grey-theme.md-fab:not([disabled]):focus { 36 | background-color: rgba(158, 158, 158, 0.3); } 37 | .md-button.md-blue-grey-theme.md-raised.md-primary, .md-button.md-blue-grey-theme.md-fab.md-primary { 38 | color: white; 39 | background-color: #607d8b; } 40 | .md-button.md-blue-grey-theme.md-raised.md-primary:not([disabled]):hover, .md-button.md-blue-grey-theme.md-raised.md-primary:not([disabled]):focus, .md-button.md-blue-grey-theme.md-fab.md-primary:not([disabled]):hover, .md-button.md-blue-grey-theme.md-fab.md-primary:not([disabled]):focus { 41 | background-color: #546e7a; } 42 | .md-button.md-blue-grey-theme.md-raised.md-warn, .md-button.md-blue-grey-theme.md-fab.md-warn { 43 | color: white; 44 | background-color: #f44336; } 45 | .md-button.md-blue-grey-theme.md-raised.md-warn:not([disabled]):hover, .md-button.md-blue-grey-theme.md-raised.md-warn:not([disabled]):focus, .md-button.md-blue-grey-theme.md-fab.md-warn:not([disabled]):hover, .md-button.md-blue-grey-theme.md-fab.md-warn:not([disabled]):focus { 46 | background-color: #d32f2f; } 47 | .md-button.md-blue-grey-theme[disabled], .md-button.md-blue-grey-theme.md-raised[disabled], .md-button.md-blue-grey-theme.md-fab[disabled] { 48 | color: rgba(0, 0, 0, 0.26); 49 | fill: rgba(0, 0, 0, 0.26); 50 | background-color: transparent; 51 | cursor: not-allowed; } 52 | 53 | md-card.md-blue-grey-theme { 54 | border-radius: 2px; } 55 | md-card.md-blue-grey-theme .md-card-image { 56 | border-radius: 2px 2px 0 0; } 57 | 58 | md-checkbox.md-blue-grey-theme .md-ripple { 59 | color: #43a047; } 60 | md-checkbox.md-blue-grey-theme.md-checked .md-ripple { 61 | color: #757575; } 62 | md-checkbox.md-blue-grey-theme .md-icon { 63 | border-color: rgba(0, 0, 0, 0.54); } 64 | md-checkbox.md-blue-grey-theme.md-checked .md-icon { 65 | background-color: rgba(102, 187, 106, 0.87); } 66 | md-checkbox.md-blue-grey-theme.md-checked .md-icon:after { 67 | border-color: #eeeeee; } 68 | md-checkbox.md-blue-grey-theme[disabled] .md-icon { 69 | border-color: rgba(0, 0, 0, 0.26); } 70 | md-checkbox.md-blue-grey-theme[disabled].md-checked .md-icon { 71 | background-color: rgba(0, 0, 0, 0.26); } 72 | 73 | md-content.md-blue-grey-theme { 74 | background-color: #ffffff; } 75 | 76 | md-dialog.md-blue-grey-theme { 77 | border-radius: 4px; 78 | background-color: #ffffff; } 79 | md-dialog.md-blue-grey-theme.md-content-overflow .md-actions { 80 | border-top-color: rgba(0, 0, 0, 0.12); } 81 | 82 | md-divider.md-blue-grey-theme { 83 | border-top-color: rgba(0, 0, 0, 0.12); } 84 | 85 | md-progress-circular.md-blue-grey-theme { 86 | background-color: transparent; } 87 | md-progress-circular.md-blue-grey-theme .md-inner .md-gap { 88 | border-top-color: #607d8b; 89 | border-bottom-color: #607d8b; } 90 | md-progress-circular.md-blue-grey-theme .md-inner .md-left .md-half-circle, md-progress-circular.md-blue-grey-theme .md-inner .md-right .md-half-circle { 91 | border-top-color: #607d8b; } 92 | md-progress-circular.md-blue-grey-theme .md-inner .md-right .md-half-circle { 93 | border-right-color: #607d8b; } 94 | md-progress-circular.md-blue-grey-theme .md-inner .md-left .md-half-circle { 95 | border-left-color: #607d8b; } 96 | 97 | md-progress-linear.md-blue-grey-theme .md-container { 98 | background-color: #cfd8dc; } 99 | md-progress-linear.md-blue-grey-theme .md-bar { 100 | background-color: #607d8b; } 101 | md-progress-linear.md-blue-grey-theme[md-mode=buffer] .md-dashed:before { 102 | background: radial-gradient(#cfd8dc 0%, #cfd8dc 16%, transparent 42%); } 103 | md-progress-linear.md-blue-grey-theme[md-mode=buffer] .md-bar1 { 104 | background-color: #cfd8dc; } 105 | 106 | md-radio-button.md-blue-grey-theme .md-container .md-ripple, md-switch.md-blue-grey-theme .md-switch-thumb .md-container .md-ripple { 107 | color: #43a047; } 108 | md-radio-button.md-blue-grey-theme .md-off, md-switch.md-blue-grey-theme .md-switch-thumb .md-off { 109 | border-color: rgba(0, 0, 0, 0.54); } 110 | md-radio-button.md-blue-grey-theme .md-on, md-switch.md-blue-grey-theme .md-switch-thumb .md-on { 111 | background-color: rgba(102, 187, 106, 0.87); } 112 | md-radio-button.md-blue-grey-theme.md-checked .md-off, md-switch.md-blue-grey-theme .md-switch-thumb.md-checked .md-off { 113 | border-color: rgba(102, 187, 106, 0.87); } 114 | md-radio-button.md-blue-grey-theme.md-checked .md-ink-ripple, md-switch.md-blue-grey-theme .md-switch-thumb.md-checked .md-ink-ripple { 115 | color: rgba(102, 187, 106, 0.87); } 116 | 117 | md-radio-group.md-blue-grey-theme:focus { 118 | border-color: rgba(0, 0, 0, 0.73); } 119 | 120 | md-slider.md-blue-grey-theme .md-track { 121 | background-color: rgba(0, 0, 0, 0.26); } 122 | md-slider.md-blue-grey-theme .md-track-fill { 123 | background-color: #607d8b; } 124 | md-slider.md-blue-grey-theme .md-thumb:after { 125 | border-color: #607d8b; 126 | background-color: #607d8b; } 127 | md-slider.md-blue-grey-theme .md-sign { 128 | background-color: #607d8b; } 129 | md-slider.md-blue-grey-theme .md-sign:after { 130 | border-top-color: #607d8b; } 131 | md-slider.md-blue-grey-theme .md-thumb-text { 132 | color: white; } 133 | md-slider.md-blue-grey-theme .md-focus-thumb { 134 | background-color: rgba(0, 0, 0, 0.54); } 135 | md-slider.md-blue-grey-theme .md-focus-ring { 136 | border-color: rgba(0, 0, 0, 0.12); } 137 | md-slider.md-blue-grey-theme .md-disabled-thumb { 138 | border-color: #ffffff; } 139 | md-slider.md-blue-grey-theme.md-min .md-thumb:after { 140 | background-color: #ffffff; } 141 | md-slider.md-blue-grey-theme[disabled] .md-thumb:after { 142 | border-color: #bdbdbd; } 143 | md-slider.md-blue-grey-theme[disabled]:not(.md-min) .md-thumb:after { 144 | background-color: #bdbdbd; } 145 | 146 | .md-subheader.md-blue-grey-theme { 147 | color: rgba(0, 0, 0, 0.54); 148 | background-color: #ffffff; } 149 | .md-subheader.md-blue-grey-theme.md-primary { 150 | color: #607d8b; } 151 | 152 | md-switch.md-blue-grey-theme .md-switch-bar { 153 | background-color: rgba(0, 0, 0, 0.54); } 154 | md-switch.md-blue-grey-theme .md-switch-thumb:focus .md-label { 155 | border: 1px dotted black; } 156 | 157 | md-tabs.md-blue-grey-theme .md-header { 158 | background-color: #607d8b; } 159 | md-tabs.md-blue-grey-theme md-tabs-ink-bar { 160 | color: #ffff85; 161 | background: #ffff85; } 162 | md-tabs.md-blue-grey-theme md-tab { 163 | color: #cfd8dc; } 164 | md-tabs.md-blue-grey-theme md-tab.active { 165 | color: white; } 166 | md-tabs.md-blue-grey-theme md-tab[disabled] { 167 | color: rgba(0, 0, 0, 0.12); } 168 | md-tabs.md-blue-grey-theme md-tab:focus { 169 | border-color: rgba(0, 0, 0, 0.73); } 170 | md-tabs.md-blue-grey-theme md-tab .md-ripple-container { 171 | color: #ffff85; } 172 | 173 | md-input-group.md-blue-grey-theme input, md-input-group.md-blue-grey-theme textarea { 174 | text-shadow: none; } 175 | md-input-group.md-blue-grey-theme input:-ms-input-placeholder, md-input-group.md-blue-grey-theme textarea:-ms-input-placeholder { 176 | color: rgba(0, 0, 0, 0.26); } 177 | md-input-group.md-blue-grey-theme input::-webkit-input-placeholder, md-input-group.md-blue-grey-theme textarea::-webkit-input-placeholder { 178 | color: rgba(0, 0, 0, 0.26); } 179 | md-input-group.md-blue-grey-theme label { 180 | text-shadow: none; 181 | color: rgba(0, 0, 0, 0.26); } 182 | md-input-group.md-blue-grey-theme input, md-input-group.md-blue-grey-theme textarea { 183 | color: rgba(0, 0, 0, 0.73); 184 | border-color: rgba(0, 0, 0, 0.12); } 185 | md-input-group.md-blue-grey-theme.md-input-focused input, md-input-group.md-blue-grey-theme.md-input-focused textarea { 186 | border-color: #607d8b; } 187 | md-input-group.md-blue-grey-theme.md-input-focused label { 188 | color: #607d8b; } 189 | md-input-group.md-blue-grey-theme.md-input-has-value:not(.md-input-focused) label { 190 | color: rgba(0, 0, 0, 0.372); } 191 | md-input-group.md-blue-grey-theme[disabled] input, md-input-group.md-blue-grey-theme[disabled] textarea { 192 | border-bottom-color: rgba(0, 0, 0, 0.12); 193 | color: rgba(0, 0, 0, 0.26); 194 | background-image: linear-gradient(to right, rgba(0, 0, 0, 0.19) 0%, rgba(0, 0, 0, 0.19) 50%, rgba(0, 0, 0, 0) 0%); } 195 | 196 | md-toast.md-blue-grey-theme { 197 | background-color: #323232; 198 | color: white; } 199 | md-toast.md-blue-grey-theme .md-button { 200 | color: white; } 201 | md-toast.md-blue-grey-theme .md-action { 202 | } 203 | 204 | md-toolbar.md-blue-grey-theme { 205 | background-color: #607d8b; 206 | color: white; } 207 | md-toolbar.md-blue-grey-theme .md-button { 208 | color: white; } 209 | 210 | md-tooltip.md-blue-grey-theme { 211 | color: #ffffff; } 212 | md-tooltip.md-blue-grey-theme .md-background { 213 | background-color: rgba(0, 0, 0, 0.52); } 214 | -------------------------------------------------------------------------------- /src/angular2/rtts-assert.js: -------------------------------------------------------------------------------- 1 | var _global = typeof window === 'object' ? window : global; 2 | 3 | // TODO(vojta): 4 | // - extract into multiple files 5 | // - different error types 6 | // - simplify/humanize error messages 7 | // - throw when invalid input (such as odd number of args into assert.argumentTypes) 8 | 9 | var POSITION_NAME = ['', '1st', '2nd', '3rd']; 10 | function argPositionName(i) { 11 | var position = (i / 2) + 1; 12 | 13 | return POSITION_NAME[position] || (position + 'th'); 14 | } 15 | 16 | var primitives; 17 | var genericType; 18 | 19 | if (typeof $traceurRuntime === 'object') { 20 | primitives = $traceurRuntime.type; 21 | genericType = $traceurRuntime.genericType; 22 | } else { 23 | // Allow to work without traceur runtime as well! 24 | primitives = { 25 | any: {name: 'any'}, 26 | boolean: {name: 'boolean'}, 27 | number: {name: 'number'}, 28 | string: {name: 'string'}, 29 | symbol: {name: 'symbol'}, 30 | void: {name: 'void'} 31 | }; 32 | genericType = function(type, args) { 33 | return { 34 | type: type, 35 | args: args 36 | } 37 | } 38 | } 39 | Object.keys(primitives).forEach(function(name) { 40 | primitives[name].__assertName = name; 41 | }); 42 | 43 | export function proxy(){ 44 | } 45 | 46 | function assertArgumentTypes(...params) { 47 | var actual, type; 48 | var currentArgErrors; 49 | var errors = []; 50 | var msg; 51 | 52 | for (var i = 0, l = params.length; i < l; i = i + 2) { 53 | actual = params[i]; 54 | type = params[i + 1]; 55 | 56 | currentArgErrors = []; 57 | 58 | // currentStack = []; 59 | // 60 | 61 | if (!isType(actual, type, currentArgErrors)) { 62 | 63 | // console.log(JSON.stringify(errors, null, ' ')); 64 | // TODO(vojta): print "an instance of" only if T starts with uppercase. 65 | errors.push(argPositionName(i) + ' argument has to be an instance of ' + prettyPrint(type) + ', got ' + prettyPrint(actual)); 66 | if (currentArgErrors.length) { 67 | errors.push(currentArgErrors); 68 | } 69 | } 70 | } 71 | 72 | if (errors.length) { 73 | throw new Error('Invalid arguments given!\n' + formatErrors(errors)); 74 | } 75 | } 76 | 77 | function prettyPrint(value) { 78 | if (typeof value === 'undefined') { 79 | return 'undefined'; 80 | } 81 | 82 | if (typeof value === 'string') { 83 | return '"' + value + '"'; 84 | } 85 | 86 | if (typeof value === 'boolean') { 87 | return value.toString(); 88 | } 89 | 90 | if (value === null) { 91 | return 'null'; 92 | } 93 | 94 | if (typeof value === 'object') { 95 | if (value.__assertName) { 96 | return value.__assertName; 97 | } 98 | 99 | if (value.map) { 100 | return '[' + value.map(prettyPrint).join(', ') + ']'; 101 | } 102 | 103 | var properties = Object.keys(value); 104 | return '{' + properties.map((p) => p + ': ' + prettyPrint(value[p])).join(', ') + '}'; 105 | } 106 | 107 | return value.__assertName || value.name || value.toString(); 108 | } 109 | 110 | function isType(value, T, errors) { 111 | if (T && T.type) { 112 | // needed for generics. 113 | // TODO(tbosch): read out T.args and do assertions based on them as well! 114 | T = T.type; 115 | } 116 | if (T === primitives.void) { 117 | return typeof value === 'undefined'; 118 | } 119 | 120 | if (_isProxy(value)) { 121 | return true; 122 | } 123 | 124 | if (T === primitives.any || value === null) { 125 | return true; 126 | } 127 | 128 | if (T === primitives.string) { 129 | return typeof value === 'string'; 130 | } 131 | 132 | if (T === primitives.number) { 133 | return typeof value === 'number'; 134 | } 135 | 136 | if (T === primitives.boolean) { 137 | return typeof value === 'boolean'; 138 | } 139 | 140 | // var parentStack = currentStack; 141 | // currentStack = []; 142 | 143 | // shouldnt this create new stack? 144 | if (typeof T.assert === 'function') { 145 | var parentStack = currentStack; 146 | var isValid; 147 | currentStack = errors; 148 | try { 149 | isValid = T.assert(value) ; 150 | } catch (e) { 151 | fail(e.message); 152 | isValid = false; 153 | } 154 | 155 | currentStack = parentStack; 156 | 157 | if (typeof isValid === 'undefined') { 158 | isValid = errors.length === 0; 159 | } 160 | 161 | return isValid; 162 | 163 | // if (!currentStack.length) { 164 | // currentStack = parentStack; 165 | // return []; 166 | // } 167 | // var res = currentStack; 168 | // currentStack = parentStack; 169 | // return ['not instance of ' + prettyPrint(T), res]; 170 | } 171 | 172 | return value instanceof T; 173 | 174 | // if (!(value instanceof T)) { 175 | // fail('not instance of ' + prettyPrint(T)); 176 | // } 177 | 178 | // var res = currentStack; 179 | // currentStack = parentStack; 180 | 181 | // return res; 182 | } 183 | 184 | function _isProxy(obj) { 185 | if (!obj || !obj.constructor || !obj.constructor.annotations) return false; 186 | return obj.constructor.annotations.filter((a) => a instanceof proxy).length > 0; 187 | } 188 | 189 | function formatErrors(errors, indent = ' ') { 190 | return errors.map((e) => { 191 | if (typeof e === 'string') return indent + '- ' + e; 192 | return formatErrors(e, indent + ' '); 193 | }).join('\n'); 194 | } 195 | 196 | 197 | // assert a type of given value and throw if does not pass 198 | function type(actual, T) { 199 | var errors = []; 200 | // currentStack = []; 201 | 202 | if (!isType(actual, T, errors)) { 203 | // console.log(JSON.stringify(errors, null, ' ')); 204 | // TODO(vojta): print "an instance of" only if T starts with uppercase. 205 | var msg = 'Expected an instance of ' + prettyPrint(T) + ', got ' + prettyPrint(actual) + '!'; 206 | if (errors.length) { 207 | msg += '\n' + formatErrors(errors); 208 | } 209 | 210 | throw new Error(msg); 211 | } 212 | return actual; 213 | } 214 | 215 | function returnType(actual, T) { 216 | var errors = []; 217 | // currentStack = []; 218 | 219 | if (!isType(actual, T, errors)) { 220 | // console.log(JSON.stringify(errors, null, ' ')); 221 | // TODO(vojta): print "an instance of" only if T starts with uppercase. 222 | var msg = 'Expected to return an instance of ' + prettyPrint(T) + ', got ' + prettyPrint(actual) + '!'; 223 | if (errors.length) { 224 | msg += '\n' + formatErrors(errors); 225 | } 226 | 227 | throw new Error(msg); 228 | } 229 | 230 | return actual; 231 | } 232 | 233 | // TODO(vojta): define these with DSL? 234 | var string = type.string = define('string', function(value) { 235 | return typeof value === 'string'; 236 | }); 237 | 238 | var boolean = type.boolean = define('boolean', function(value) { 239 | return typeof value === 'boolean'; 240 | }); 241 | 242 | var number = type.number = define('number', function(value) { 243 | return typeof value === 'number'; 244 | }); 245 | 246 | function arrayOf(...types) { 247 | return assert.define('array of ' + types.map(prettyPrint).join('/'), function(value) { 248 | if (assert(value).is(Array)) { 249 | for (var item of value) { 250 | assert(item).is(...types); 251 | } 252 | } 253 | }); 254 | } 255 | 256 | function structure(definition) { 257 | var properties = Object.keys(definition); 258 | return assert.define('object with properties ' + properties.join(', '), function(value) { 259 | if (assert(value).is(Object)) { 260 | for (var property of properties) { 261 | assert(value[property]).is(definition[property]); 262 | } 263 | } 264 | }) 265 | } 266 | 267 | 268 | 269 | // I'm sorry, bad global state... to make the API nice ;-) 270 | var currentStack = []; 271 | 272 | function fail(message) { 273 | currentStack.push(message); 274 | } 275 | 276 | function define(classOrName, check) { 277 | var cls = classOrName; 278 | 279 | if (typeof classOrName === 'string') { 280 | cls = function() {}; 281 | cls.__assertName = classOrName; 282 | } 283 | 284 | cls.assert = function(value) { 285 | // var parentStack = currentStack; 286 | 287 | // currentStack = []; 288 | 289 | return check(value); 290 | 291 | // if (currentStack.length) { 292 | // parentStack.push(currentStack) 293 | // } 294 | // currentStack = parentStack; 295 | }; 296 | 297 | return cls; 298 | } 299 | 300 | 301 | 302 | function assert(value) { 303 | return { 304 | is: function is(...types) { 305 | // var errors = [] 306 | var allErrors = []; 307 | var errors; 308 | 309 | for (var type of types) { 310 | errors = []; 311 | 312 | if (isType(value, type, errors)) { 313 | return true; 314 | } 315 | 316 | // if no errors, merge multiple "is not instance of " into x/y/z ? 317 | allErrors.push(prettyPrint(value) + ' is not instance of ' + prettyPrint(type)) 318 | if (errors.length) { 319 | allErrors.push(errors); 320 | } 321 | } 322 | 323 | // if (types.length > 1) { 324 | // currentStack.push(['has to be ' + types.map(prettyPrint).join(' or '), ...allErrors]); 325 | // } else { 326 | currentStack.push(...allErrors); 327 | // } 328 | return false; 329 | } 330 | }; 331 | } 332 | 333 | 334 | // PUBLIC API 335 | 336 | // asserting API 337 | 338 | // throw if no type provided 339 | assert.type = type; 340 | for (var prop in primitives) { 341 | assert.type[prop] = primitives[prop]; 342 | } 343 | assert.genericType = genericType; 344 | 345 | // throw if odd number of args 346 | assert.argumentTypes = assertArgumentTypes; 347 | assert.returnType = returnType; 348 | 349 | 350 | // define AP; 351 | assert.define = define; 352 | assert.fail = fail; 353 | 354 | // primitive value type; 355 | assert.string = string; 356 | assert.number = number; 357 | assert.boolean = boolean; 358 | 359 | // custom types 360 | assert.arrayOf = arrayOf; 361 | assert.structure = structure; 362 | 363 | 364 | export {assert} 365 | -------------------------------------------------------------------------------- /dist/es6/angular2/rtts-assert.js: -------------------------------------------------------------------------------- 1 | var _global = typeof window === 'object' ? window : global; 2 | 3 | // TODO(vojta): 4 | // - extract into multiple files 5 | // - different error types 6 | // - simplify/humanize error messages 7 | // - throw when invalid input (such as odd number of args into assert.argumentTypes) 8 | 9 | var POSITION_NAME = ['', '1st', '2nd', '3rd']; 10 | function argPositionName(i) { 11 | var position = (i / 2) + 1; 12 | 13 | return POSITION_NAME[position] || (position + 'th'); 14 | } 15 | 16 | var primitives; 17 | var genericType; 18 | 19 | if (typeof $traceurRuntime === 'object') { 20 | primitives = $traceurRuntime.type; 21 | genericType = $traceurRuntime.genericType; 22 | } else { 23 | // Allow to work without traceur runtime as well! 24 | primitives = { 25 | any: {name: 'any'}, 26 | boolean: {name: 'boolean'}, 27 | number: {name: 'number'}, 28 | string: {name: 'string'}, 29 | symbol: {name: 'symbol'}, 30 | void: {name: 'void'} 31 | }; 32 | genericType = function(type, args) { 33 | return { 34 | type: type, 35 | args: args 36 | } 37 | } 38 | } 39 | Object.keys(primitives).forEach(function(name) { 40 | primitives[name].__assertName = name; 41 | }); 42 | 43 | export function proxy(){ 44 | } 45 | 46 | function assertArgumentTypes(...params) { 47 | var actual, type; 48 | var currentArgErrors; 49 | var errors = []; 50 | var msg; 51 | 52 | for (var i = 0, l = params.length; i < l; i = i + 2) { 53 | actual = params[i]; 54 | type = params[i + 1]; 55 | 56 | currentArgErrors = []; 57 | 58 | // currentStack = []; 59 | // 60 | 61 | if (!isType(actual, type, currentArgErrors)) { 62 | 63 | // console.log(JSON.stringify(errors, null, ' ')); 64 | // TODO(vojta): print "an instance of" only if T starts with uppercase. 65 | errors.push(argPositionName(i) + ' argument has to be an instance of ' + prettyPrint(type) + ', got ' + prettyPrint(actual)); 66 | if (currentArgErrors.length) { 67 | errors.push(currentArgErrors); 68 | } 69 | } 70 | } 71 | 72 | if (errors.length) { 73 | throw new Error('Invalid arguments given!\n' + formatErrors(errors)); 74 | } 75 | } 76 | 77 | function prettyPrint(value) { 78 | if (typeof value === 'undefined') { 79 | return 'undefined'; 80 | } 81 | 82 | if (typeof value === 'string') { 83 | return '"' + value + '"'; 84 | } 85 | 86 | if (typeof value === 'boolean') { 87 | return value.toString(); 88 | } 89 | 90 | if (value === null) { 91 | return 'null'; 92 | } 93 | 94 | if (typeof value === 'object') { 95 | if (value.__assertName) { 96 | return value.__assertName; 97 | } 98 | 99 | if (value.map) { 100 | return '[' + value.map(prettyPrint).join(', ') + ']'; 101 | } 102 | 103 | var properties = Object.keys(value); 104 | return '{' + properties.map((p) => p + ': ' + prettyPrint(value[p])).join(', ') + '}'; 105 | } 106 | 107 | return value.__assertName || value.name || value.toString(); 108 | } 109 | 110 | function isType(value, T, errors) { 111 | if (T && T.type) { 112 | // needed for generics. 113 | // TODO(tbosch): read out T.args and do assertions based on them as well! 114 | T = T.type; 115 | } 116 | if (T === primitives.void) { 117 | return typeof value === 'undefined'; 118 | } 119 | 120 | if (_isProxy(value)) { 121 | return true; 122 | } 123 | 124 | if (T === primitives.any || value === null) { 125 | return true; 126 | } 127 | 128 | if (T === primitives.string) { 129 | return typeof value === 'string'; 130 | } 131 | 132 | if (T === primitives.number) { 133 | return typeof value === 'number'; 134 | } 135 | 136 | if (T === primitives.boolean) { 137 | return typeof value === 'boolean'; 138 | } 139 | 140 | // var parentStack = currentStack; 141 | // currentStack = []; 142 | 143 | // shouldnt this create new stack? 144 | if (typeof T.assert === 'function') { 145 | var parentStack = currentStack; 146 | var isValid; 147 | currentStack = errors; 148 | try { 149 | isValid = T.assert(value) ; 150 | } catch (e) { 151 | fail(e.message); 152 | isValid = false; 153 | } 154 | 155 | currentStack = parentStack; 156 | 157 | if (typeof isValid === 'undefined') { 158 | isValid = errors.length === 0; 159 | } 160 | 161 | return isValid; 162 | 163 | // if (!currentStack.length) { 164 | // currentStack = parentStack; 165 | // return []; 166 | // } 167 | // var res = currentStack; 168 | // currentStack = parentStack; 169 | // return ['not instance of ' + prettyPrint(T), res]; 170 | } 171 | 172 | return value instanceof T; 173 | 174 | // if (!(value instanceof T)) { 175 | // fail('not instance of ' + prettyPrint(T)); 176 | // } 177 | 178 | // var res = currentStack; 179 | // currentStack = parentStack; 180 | 181 | // return res; 182 | } 183 | 184 | function _isProxy(obj) { 185 | if (!obj || !obj.constructor || !obj.constructor.annotations) return false; 186 | return obj.constructor.annotations.filter((a) => a instanceof proxy).length > 0; 187 | } 188 | 189 | function formatErrors(errors, indent = ' ') { 190 | return errors.map((e) => { 191 | if (typeof e === 'string') return indent + '- ' + e; 192 | return formatErrors(e, indent + ' '); 193 | }).join('\n'); 194 | } 195 | 196 | 197 | // assert a type of given value and throw if does not pass 198 | function type(actual, T) { 199 | var errors = []; 200 | // currentStack = []; 201 | 202 | if (!isType(actual, T, errors)) { 203 | // console.log(JSON.stringify(errors, null, ' ')); 204 | // TODO(vojta): print "an instance of" only if T starts with uppercase. 205 | var msg = 'Expected an instance of ' + prettyPrint(T) + ', got ' + prettyPrint(actual) + '!'; 206 | if (errors.length) { 207 | msg += '\n' + formatErrors(errors); 208 | } 209 | 210 | throw new Error(msg); 211 | } 212 | return actual; 213 | } 214 | 215 | function returnType(actual, T) { 216 | var errors = []; 217 | // currentStack = []; 218 | 219 | if (!isType(actual, T, errors)) { 220 | // console.log(JSON.stringify(errors, null, ' ')); 221 | // TODO(vojta): print "an instance of" only if T starts with uppercase. 222 | var msg = 'Expected to return an instance of ' + prettyPrint(T) + ', got ' + prettyPrint(actual) + '!'; 223 | if (errors.length) { 224 | msg += '\n' + formatErrors(errors); 225 | } 226 | 227 | throw new Error(msg); 228 | } 229 | 230 | return actual; 231 | } 232 | 233 | // TODO(vojta): define these with DSL? 234 | var string = type.string = define('string', function(value) { 235 | return typeof value === 'string'; 236 | }); 237 | 238 | var boolean = type.boolean = define('boolean', function(value) { 239 | return typeof value === 'boolean'; 240 | }); 241 | 242 | var number = type.number = define('number', function(value) { 243 | return typeof value === 'number'; 244 | }); 245 | 246 | function arrayOf(...types) { 247 | return assert.define('array of ' + types.map(prettyPrint).join('/'), function(value) { 248 | if (assert(value).is(Array)) { 249 | for (var item of value) { 250 | assert(item).is(...types); 251 | } 252 | } 253 | }); 254 | } 255 | 256 | function structure(definition) { 257 | var properties = Object.keys(definition); 258 | return assert.define('object with properties ' + properties.join(', '), function(value) { 259 | if (assert(value).is(Object)) { 260 | for (var property of properties) { 261 | assert(value[property]).is(definition[property]); 262 | } 263 | } 264 | }) 265 | } 266 | 267 | 268 | 269 | // I'm sorry, bad global state... to make the API nice ;-) 270 | var currentStack = []; 271 | 272 | function fail(message) { 273 | currentStack.push(message); 274 | } 275 | 276 | function define(classOrName, check) { 277 | var cls = classOrName; 278 | 279 | if (typeof classOrName === 'string') { 280 | cls = function() {}; 281 | cls.__assertName = classOrName; 282 | } 283 | 284 | cls.assert = function(value) { 285 | // var parentStack = currentStack; 286 | 287 | // currentStack = []; 288 | 289 | return check(value); 290 | 291 | // if (currentStack.length) { 292 | // parentStack.push(currentStack) 293 | // } 294 | // currentStack = parentStack; 295 | }; 296 | 297 | return cls; 298 | } 299 | 300 | 301 | 302 | function assert(value) { 303 | return { 304 | is: function is(...types) { 305 | // var errors = [] 306 | var allErrors = []; 307 | var errors; 308 | 309 | for (var type of types) { 310 | errors = []; 311 | 312 | if (isType(value, type, errors)) { 313 | return true; 314 | } 315 | 316 | // if no errors, merge multiple "is not instance of " into x/y/z ? 317 | allErrors.push(prettyPrint(value) + ' is not instance of ' + prettyPrint(type)) 318 | if (errors.length) { 319 | allErrors.push(errors); 320 | } 321 | } 322 | 323 | // if (types.length > 1) { 324 | // currentStack.push(['has to be ' + types.map(prettyPrint).join(' or '), ...allErrors]); 325 | // } else { 326 | currentStack.push(...allErrors); 327 | // } 328 | return false; 329 | } 330 | }; 331 | } 332 | 333 | 334 | // PUBLIC API 335 | 336 | // asserting API 337 | 338 | // throw if no type provided 339 | assert.type = type; 340 | for (var prop in primitives) { 341 | assert.type[prop] = primitives[prop]; 342 | } 343 | assert.genericType = genericType; 344 | 345 | // throw if odd number of args 346 | assert.argumentTypes = assertArgumentTypes; 347 | assert.returnType = returnType; 348 | 349 | 350 | // define AP; 351 | assert.define = define; 352 | assert.fail = fail; 353 | 354 | // primitive value type; 355 | assert.string = string; 356 | assert.number = number; 357 | assert.boolean = boolean; 358 | 359 | // custom types 360 | assert.arrayOf = arrayOf; 361 | assert.structure = structure; 362 | 363 | 364 | export {assert} 365 | -------------------------------------------------------------------------------- /examples/hello-jspm/jspm_packages/github/robianmcd/angular-next@0.0.3/rtts-assert.js: -------------------------------------------------------------------------------- 1 | /* */ 2 | var _global = typeof window === 'object' ? window : global; 3 | 4 | // TODO(vojta): 5 | // - extract into multiple files 6 | // - different error types 7 | // - simplify/humanize error messages 8 | // - throw when invalid input (such as odd number of args into assert.argumentTypes) 9 | 10 | var POSITION_NAME = ['', '1st', '2nd', '3rd']; 11 | function argPositionName(i) { 12 | var position = (i / 2) + 1; 13 | 14 | return POSITION_NAME[position] || (position + 'th'); 15 | } 16 | 17 | var primitives; 18 | var genericType; 19 | 20 | if (typeof $traceurRuntime === 'object') { 21 | primitives = $traceurRuntime.type; 22 | genericType = $traceurRuntime.genericType; 23 | } else { 24 | // Allow to work without traceur runtime as well! 25 | primitives = { 26 | any: {name: 'any'}, 27 | boolean: {name: 'boolean'}, 28 | number: {name: 'number'}, 29 | string: {name: 'string'}, 30 | symbol: {name: 'symbol'}, 31 | void: {name: 'void'} 32 | }; 33 | genericType = function(type, args) { 34 | return { 35 | type: type, 36 | args: args 37 | } 38 | } 39 | } 40 | Object.keys(primitives).forEach(function(name) { 41 | primitives[name].__assertName = name; 42 | }); 43 | 44 | export function proxy(){ 45 | } 46 | 47 | function assertArgumentTypes(...params) { 48 | var actual, type; 49 | var currentArgErrors; 50 | var errors = []; 51 | var msg; 52 | 53 | for (var i = 0, l = params.length; i < l; i = i + 2) { 54 | actual = params[i]; 55 | type = params[i + 1]; 56 | 57 | currentArgErrors = []; 58 | 59 | // currentStack = []; 60 | // 61 | 62 | if (!isType(actual, type, currentArgErrors)) { 63 | 64 | // console.log(JSON.stringify(errors, null, ' ')); 65 | // TODO(vojta): print "an instance of" only if T starts with uppercase. 66 | errors.push(argPositionName(i) + ' argument has to be an instance of ' + prettyPrint(type) + ', got ' + prettyPrint(actual)); 67 | if (currentArgErrors.length) { 68 | errors.push(currentArgErrors); 69 | } 70 | } 71 | } 72 | 73 | if (errors.length) { 74 | throw new Error('Invalid arguments given!\n' + formatErrors(errors)); 75 | } 76 | } 77 | 78 | function prettyPrint(value) { 79 | if (typeof value === 'undefined') { 80 | return 'undefined'; 81 | } 82 | 83 | if (typeof value === 'string') { 84 | return '"' + value + '"'; 85 | } 86 | 87 | if (typeof value === 'boolean') { 88 | return value.toString(); 89 | } 90 | 91 | if (value === null) { 92 | return 'null'; 93 | } 94 | 95 | if (typeof value === 'object') { 96 | if (value.__assertName) { 97 | return value.__assertName; 98 | } 99 | 100 | if (value.map) { 101 | return '[' + value.map(prettyPrint).join(', ') + ']'; 102 | } 103 | 104 | var properties = Object.keys(value); 105 | return '{' + properties.map((p) => p + ': ' + prettyPrint(value[p])).join(', ') + '}'; 106 | } 107 | 108 | return value.__assertName || value.name || value.toString(); 109 | } 110 | 111 | function isType(value, T, errors) { 112 | if (T && T.type) { 113 | // needed for generics. 114 | // TODO(tbosch): read out T.args and do assertions based on them as well! 115 | T = T.type; 116 | } 117 | if (T === primitives.void) { 118 | return typeof value === 'undefined'; 119 | } 120 | 121 | if (_isProxy(value)) { 122 | return true; 123 | } 124 | 125 | if (T === primitives.any || value === null) { 126 | return true; 127 | } 128 | 129 | if (T === primitives.string) { 130 | return typeof value === 'string'; 131 | } 132 | 133 | if (T === primitives.number) { 134 | return typeof value === 'number'; 135 | } 136 | 137 | if (T === primitives.boolean) { 138 | return typeof value === 'boolean'; 139 | } 140 | 141 | // var parentStack = currentStack; 142 | // currentStack = []; 143 | 144 | // shouldnt this create new stack? 145 | if (typeof T.assert === 'function') { 146 | var parentStack = currentStack; 147 | var isValid; 148 | currentStack = errors; 149 | try { 150 | isValid = T.assert(value) ; 151 | } catch (e) { 152 | fail(e.message); 153 | isValid = false; 154 | } 155 | 156 | currentStack = parentStack; 157 | 158 | if (typeof isValid === 'undefined') { 159 | isValid = errors.length === 0; 160 | } 161 | 162 | return isValid; 163 | 164 | // if (!currentStack.length) { 165 | // currentStack = parentStack; 166 | // return []; 167 | // } 168 | // var res = currentStack; 169 | // currentStack = parentStack; 170 | // return ['not instance of ' + prettyPrint(T), res]; 171 | } 172 | 173 | return value instanceof T; 174 | 175 | // if (!(value instanceof T)) { 176 | // fail('not instance of ' + prettyPrint(T)); 177 | // } 178 | 179 | // var res = currentStack; 180 | // currentStack = parentStack; 181 | 182 | // return res; 183 | } 184 | 185 | function _isProxy(obj) { 186 | if (!obj || !obj.constructor || !obj.constructor.annotations) return false; 187 | return obj.constructor.annotations.filter((a) => a instanceof proxy).length > 0; 188 | } 189 | 190 | function formatErrors(errors, indent = ' ') { 191 | return errors.map((e) => { 192 | if (typeof e === 'string') return indent + '- ' + e; 193 | return formatErrors(e, indent + ' '); 194 | }).join('\n'); 195 | } 196 | 197 | 198 | // assert a type of given value and throw if does not pass 199 | function type(actual, T) { 200 | var errors = []; 201 | // currentStack = []; 202 | 203 | if (!isType(actual, T, errors)) { 204 | // console.log(JSON.stringify(errors, null, ' ')); 205 | // TODO(vojta): print "an instance of" only if T starts with uppercase. 206 | var msg = 'Expected an instance of ' + prettyPrint(T) + ', got ' + prettyPrint(actual) + '!'; 207 | if (errors.length) { 208 | msg += '\n' + formatErrors(errors); 209 | } 210 | 211 | throw new Error(msg); 212 | } 213 | return actual; 214 | } 215 | 216 | function returnType(actual, T) { 217 | var errors = []; 218 | // currentStack = []; 219 | 220 | if (!isType(actual, T, errors)) { 221 | // console.log(JSON.stringify(errors, null, ' ')); 222 | // TODO(vojta): print "an instance of" only if T starts with uppercase. 223 | var msg = 'Expected to return an instance of ' + prettyPrint(T) + ', got ' + prettyPrint(actual) + '!'; 224 | if (errors.length) { 225 | msg += '\n' + formatErrors(errors); 226 | } 227 | 228 | throw new Error(msg); 229 | } 230 | 231 | return actual; 232 | } 233 | 234 | // TODO(vojta): define these with DSL? 235 | var string = type.string = define('string', function(value) { 236 | return typeof value === 'string'; 237 | }); 238 | 239 | var boolean = type.boolean = define('boolean', function(value) { 240 | return typeof value === 'boolean'; 241 | }); 242 | 243 | var number = type.number = define('number', function(value) { 244 | return typeof value === 'number'; 245 | }); 246 | 247 | function arrayOf(...types) { 248 | return assert.define('array of ' + types.map(prettyPrint).join('/'), function(value) { 249 | if (assert(value).is(Array)) { 250 | for (var item of value) { 251 | assert(item).is(...types); 252 | } 253 | } 254 | }); 255 | } 256 | 257 | function structure(definition) { 258 | var properties = Object.keys(definition); 259 | return assert.define('object with properties ' + properties.join(', '), function(value) { 260 | if (assert(value).is(Object)) { 261 | for (var property of properties) { 262 | assert(value[property]).is(definition[property]); 263 | } 264 | } 265 | }) 266 | } 267 | 268 | 269 | 270 | // I'm sorry, bad global state... to make the API nice ;-) 271 | var currentStack = []; 272 | 273 | function fail(message) { 274 | currentStack.push(message); 275 | } 276 | 277 | function define(classOrName, check) { 278 | var cls = classOrName; 279 | 280 | if (typeof classOrName === 'string') { 281 | cls = function() {}; 282 | cls.__assertName = classOrName; 283 | } 284 | 285 | cls.assert = function(value) { 286 | // var parentStack = currentStack; 287 | 288 | // currentStack = []; 289 | 290 | return check(value); 291 | 292 | // if (currentStack.length) { 293 | // parentStack.push(currentStack) 294 | // } 295 | // currentStack = parentStack; 296 | }; 297 | 298 | return cls; 299 | } 300 | 301 | 302 | 303 | function assert(value) { 304 | return { 305 | is: function is(...types) { 306 | // var errors = [] 307 | var allErrors = []; 308 | var errors; 309 | 310 | for (var type of types) { 311 | errors = []; 312 | 313 | if (isType(value, type, errors)) { 314 | return true; 315 | } 316 | 317 | // if no errors, merge multiple "is not instance of " into x/y/z ? 318 | allErrors.push(prettyPrint(value) + ' is not instance of ' + prettyPrint(type)) 319 | if (errors.length) { 320 | allErrors.push(errors); 321 | } 322 | } 323 | 324 | // if (types.length > 1) { 325 | // currentStack.push(['has to be ' + types.map(prettyPrint).join(' or '), ...allErrors]); 326 | // } else { 327 | currentStack.push(...allErrors); 328 | // } 329 | return false; 330 | } 331 | }; 332 | } 333 | 334 | 335 | // PUBLIC API 336 | 337 | // asserting API 338 | 339 | // throw if no type provided 340 | assert.type = type; 341 | for (var prop in primitives) { 342 | assert.type[prop] = primitives[prop]; 343 | } 344 | assert.genericType = genericType; 345 | 346 | // throw if odd number of args 347 | assert.argumentTypes = assertArgumentTypes; 348 | assert.returnType = returnType; 349 | 350 | 351 | // define AP; 352 | assert.define = define; 353 | assert.fail = fail; 354 | 355 | // primitive value type; 356 | assert.string = string; 357 | assert.number = number; 358 | assert.boolean = boolean; 359 | 360 | // custom types 361 | assert.arrayOf = arrayOf; 362 | assert.structure = structure; 363 | 364 | 365 | export {assert} 366 | -------------------------------------------------------------------------------- /examples/hello-jspm/jspm_packages/github/robianmcd/angular-next@0.0.3/ngNext/angular2Adapter.js: -------------------------------------------------------------------------------- 1 | /* */ 2 | import {Directive, DirectiveClass} from '../ng2/directive'; 3 | import {Component, ComponentClass} from '../ng2/component'; 4 | import {Template} from '../ng2/template'; 5 | import {NgElement} from '../ng2/ngElement'; 6 | import {InjectNgOne} from './injectNgOne'; 7 | import polyfillPromise from './polyfillPromise'; 8 | 9 | class Angular2Adapter { 10 | constructor({moduleName, logLevel = 0}) { 11 | this.moduleName = moduleName; 12 | this.app = angular.module(moduleName); 13 | //not currently used 14 | this.logLevel = logLevel; 15 | 16 | this.registeredDirectives = new Set(); 17 | 18 | polyfillPromise(this.app); 19 | } 20 | 21 | bootstrapComponent(rootComponent:ComponentClass) { 22 | var rootComponentAnno:Component; 23 | rootComponentAnno = this.getDirAnno(rootComponent); 24 | 25 | var rootElement = document.querySelector(rootComponentAnno.selector); 26 | 27 | angular.element(rootElement).ready(() => { 28 | this.registerDirectiveTree(rootComponent); 29 | angular.bootstrap(rootElement, [this.moduleName]); 30 | }); 31 | } 32 | 33 | registerDirectiveTree(dir:DirectiveClass) { 34 | if(this.registeredDirectives.has(dir)) { 35 | return; 36 | } else { 37 | this.registeredDirectives.add(dir); 38 | } 39 | 40 | this.registerDirective(dir); 41 | 42 | var templateAnno = this.getTemplateAnno(dir); 43 | if (templateAnno && templateAnno.directives) { 44 | templateAnno.directives.forEach((childDir) => { 45 | this.registerDirectiveTree(childDir); 46 | }); 47 | } 48 | } 49 | 50 | registerDirective(dir:DirectiveClass) { 51 | dir = this.wrapDir(dir); 52 | dir.$inject = this.getInjectArray(dir); 53 | 54 | this.registerComponentServices(dir); 55 | 56 | var dirInfo = this.getNg1DirectiveInfo(dir); 57 | 58 | this.app.directive(dirInfo.name, function () { 59 | return dirInfo.ddo; 60 | }); 61 | } 62 | 63 | registerComponentServices(dir:DirectiveClass) { 64 | var dirAnno = this.getDirAnno(dir); 65 | 66 | //Register component services 67 | if (dirAnno.componentServices) { 68 | dirAnno.componentServices.forEach((serviceType) => { 69 | serviceType.$inject = this.getInjectArray(serviceType); 70 | this.app.service(this.lowerCaseFirstLetter(this.getFunctionName(serviceType)), serviceType); 71 | }); 72 | } 73 | } 74 | 75 | //Returns name and ddo for a directive class 76 | getNg1DirectiveInfo(dir:DirectiveClass) { 77 | var dirAnno = this.getDirAnno(dir); 78 | 79 | var restrict; 80 | var dashesDirectiveName; 81 | 82 | //Try and match an attribute selector. e.g. "[attr]" 83 | //If it matches store the attribute name in match[1] 84 | var match; 85 | if (match = dirAnno.selector.match(/^\[(.*)\]$/)) { 86 | restrict = 'A'; 87 | dashesDirectiveName = match[1]; 88 | 89 | //Try to match a class selector. e.g. ".class" 90 | } else if (match = dirAnno.selector.match(/^\.(.*)$/)) { 91 | restrict = 'C'; 92 | dashesDirectiveName = match[1]; 93 | 94 | } else { 95 | restrict = 'E'; 96 | dashesDirectiveName = dirAnno.selector; 97 | } 98 | 99 | var scope = {}; 100 | 101 | for (var key in dirAnno.bind) { 102 | if (dirAnno.bind.hasOwnProperty(key)) { 103 | scope[key] = '=' + dirAnno.bind[key]; 104 | } 105 | } 106 | 107 | var ddo = { 108 | restrict: restrict, 109 | controller: dir, 110 | controllerAs: dirAnno.controllerAs, 111 | scope: scope, 112 | bindToController: true 113 | }; 114 | 115 | var templateAnno = this.getTemplateAnno(dir); 116 | if(templateAnno) { 117 | if(templateAnno.inline) { 118 | ddo.template = templateAnno.inline; 119 | } else if (templateAnno.url) { 120 | ddo.templateUrl = templateAnno.url; 121 | } 122 | } 123 | 124 | //Convert the directive name from dash separated to camelCase 125 | var name = dashesDirectiveName.replace(/-([a-z])/g, char => char[1].toUpperCase()); 126 | 127 | return {name, ddo}; 128 | } 129 | 130 | //Services that require $element (e.g. NgElement) cannot be injected normally as $element can only be injected 131 | //directly into the controller of a directive. If the directive passed in requires any of these services then it 132 | //will be wrapped (inherited) by a function that injects $element and manually initialized the $element based 133 | //services before passing them in. 134 | wrapDir(dirType:DirectiveClass) { 135 | var adapter = this; 136 | 137 | var dirAnno = this.getDirAnno(dirType); 138 | 139 | var retDirType = dirType; 140 | 141 | if (dirType.parameters) { 142 | var injectableServices = []; 143 | 144 | //e.g. {pos: 3, type: MyDir} 145 | var uninjectableParams = []; 146 | var requiresElement = false; 147 | var requiresScope = false; 148 | 149 | for (var i = 0; i < dirType.parameters.length; i++) { 150 | var curParamType = dirType.parameters[i][0]; 151 | 152 | //TODO: should check if they are already injecting $element or $scope so we don't end up injecting it twice 153 | 154 | if (curParamType === NgElement || this.isDirClass(curParamType)) { 155 | uninjectableParams.push({pos: i, type: curParamType}); 156 | requiresElement = true; 157 | } else { 158 | injectableServices.push(curParamType); 159 | } 160 | } 161 | 162 | if (dirAnno.observe) { 163 | requiresScope = true; 164 | } 165 | 166 | 167 | //If the directive needs to be wrapped 168 | if (uninjectableParams.length || requiresElement || requiresScope) { 169 | 170 | retDirType = function (...args) { 171 | var element, scope; 172 | 173 | if (requiresScope) { 174 | scope = args.pop(); 175 | } 176 | 177 | if (requiresElement) { 178 | element = args.pop(); 179 | } 180 | 181 | var origDirParams = angular.copy(args); 182 | 183 | //Manually create each parameter that could not be injected 184 | uninjectableParams.forEach((param) => { 185 | var model; 186 | if (param.type === NgElement) { 187 | model = new NgElement(element); 188 | } else if (adapter.isDirClass(param.type)) { 189 | var dirName = adapter.lowerCaseFirstLetter(adapter.getFunctionName(param.type)); 190 | model = element.inheritedData(`$${dirName}Controller`); 191 | } 192 | origDirParams.splice(param.pos, 0, model); 193 | }); 194 | 195 | //Setup any watches specified in dirAnno.observe 196 | if (dirAnno.observe) { 197 | for (let key in dirAnno.observe) { 198 | if (dirAnno.observe.hasOwnProperty(key)) { 199 | let functionName = dirAnno.observe[key]; 200 | 201 | scope.$watch(`${dirAnno.controllerAs}.${key}`, (newValue, oldValue) => { 202 | if (this[functionName]) { 203 | this[functionName](newValue, oldValue); 204 | } else { 205 | console.warn(`'${key}' has changed but observe function, '${functionName}' does not exist.`); 206 | } 207 | }); 208 | } 209 | } 210 | } 211 | 212 | //Steal constructor 213 | dirType.apply(this, origDirParams); 214 | }; 215 | 216 | //Inherit prototype 217 | retDirType.prototype = Object.create(dirType.prototype); 218 | retDirType.annotations = dirType.annotations; 219 | retDirType.parameters = injectableServices.map(type => [type]); 220 | 221 | if (requiresElement) { 222 | retDirType.parameters.push([new InjectNgOne('$element')]); 223 | } 224 | if (requiresScope) { 225 | retDirType.parameters.push([new InjectNgOne('$scope')]); 226 | } 227 | } 228 | } 229 | 230 | return retDirType; 231 | } 232 | 233 | getInjectArray(aClass:Function) { 234 | var $inject = []; 235 | 236 | if (aClass.parameters) { 237 | aClass.parameters.forEach((paramAnnotations) => { 238 | $inject.push(this.getInjectStrFromParamAnnotations(paramAnnotations)); 239 | }); 240 | } 241 | 242 | return $inject; 243 | } 244 | 245 | getInjectStrFromParamAnnotations(paramAnnotations) { 246 | for (var i = 0; i < paramAnnotations.length; i++) { 247 | var paramAnno = paramAnnotations[i]; 248 | 249 | if (paramAnno instanceof InjectNgOne) { 250 | return paramAnno.typeStr; 251 | } else if (paramAnno instanceof Function) { 252 | return this.lowerCaseFirstLetter(this.getFunctionName(paramAnno)); 253 | } 254 | } 255 | 256 | if(paramAnnotations.length === 0) { 257 | throw `Could not inject parameter. You must either specify its type or annotate it with @InjectNgOne('...').`; 258 | } else { 259 | throw `Could not determine how to inject parameter with annotations: ${paramAnnotations}`; 260 | } 261 | 262 | } 263 | 264 | getDirAnno(directive:DirectiveClass) { 265 | var dirAnnos = directive.annotations.filter((annotation) => annotation instanceof Directive); 266 | 267 | return dirAnnos.length ? dirAnnos[0] : undefined; 268 | } 269 | 270 | getTemplateAnno(directive:DirectiveClass) { 271 | var dirAnnos = directive.annotations.filter((annotation) => annotation instanceof Template); 272 | 273 | return dirAnnos.length ? dirAnnos[0] : undefined; 274 | } 275 | 276 | lowerCaseFirstLetter(str) { 277 | return str.charAt(0).toLowerCase() + str.slice(1); 278 | } 279 | 280 | getFunctionName(func:Function) { 281 | if (func.name) { 282 | return func.name; 283 | 284 | //IE doesn't support function.name and neither does traceur. 285 | } else { 286 | var ret = func.toString(); 287 | ret = ret.substr('function '.length); 288 | ret = ret.substr(0, ret.indexOf('(')); 289 | return ret; 290 | } 291 | } 292 | 293 | isDirClass(obj) { 294 | return !!(obj.annotations && obj.annotations.filter(anno => anno instanceof Directive).length); 295 | } 296 | 297 | } 298 | 299 | export {Angular2Adapter}; -------------------------------------------------------------------------------- /dist/es6/angular2/ngNext/angular2Adapter.js: -------------------------------------------------------------------------------- 1 | import {Directive, DirectiveClass} from '../ng2/directive'; 2 | import {Component, ComponentClass} from '../ng2/component'; 3 | import {Template} from '../ng2/template'; 4 | import {NgElement} from '../ng2/ngElement'; 5 | import {InjectNgOne} from './injectNgOne'; 6 | import polyfillPromise from './polyfillPromise'; 7 | import registerNg2Directives from './registerNg2Directives'; 8 | 9 | class Angular2Adapter { 10 | constructor({moduleName, logLevel = 0}) { 11 | this.moduleName = moduleName; 12 | this.app = angular.module(moduleName); 13 | //not currently used 14 | this.logLevel = logLevel; 15 | 16 | this.registeredDirectives = new Set(); 17 | 18 | polyfillPromise(this.app); 19 | registerNg2Directives(this.app); 20 | 21 | } 22 | 23 | bootstrapComponent(rootComponent:ComponentClass) { 24 | var rootComponentAnno:Component; 25 | rootComponentAnno = this.getDirAnno(rootComponent); 26 | 27 | var rootElement = document.querySelector(rootComponentAnno.selector); 28 | 29 | angular.element(rootElement).ready(() => { 30 | this.registerDirectiveTree(rootComponent); 31 | angular.bootstrap(rootElement, [this.moduleName]); 32 | }); 33 | } 34 | 35 | registerDirectiveTree(dir:DirectiveClass) { 36 | if(this.registeredDirectives.has(dir)) { 37 | return; 38 | } else { 39 | this.registeredDirectives.add(dir); 40 | } 41 | 42 | this.registerDirective(dir); 43 | 44 | var templateAnno = this.getTemplateAnno(dir); 45 | if (templateAnno && templateAnno.directives) { 46 | templateAnno.directives.forEach((childDir) => { 47 | this.registerDirectiveTree(childDir); 48 | }); 49 | } 50 | } 51 | 52 | registerDirective(dir:DirectiveClass) { 53 | dir = this.wrapDir(dir); 54 | dir.$inject = this.getInjectArray(dir); 55 | 56 | this.registerComponentServices(dir); 57 | 58 | var dirInfo = this.getNg1DirectiveInfo(dir); 59 | 60 | this.app.directive(dirInfo.name, function () { 61 | return dirInfo.ddo; 62 | }); 63 | } 64 | 65 | registerComponentServices(dir:DirectiveClass) { 66 | var dirAnno = this.getDirAnno(dir); 67 | 68 | //Register component services 69 | if (dirAnno.componentServices) { 70 | dirAnno.componentServices.forEach((serviceType) => { 71 | serviceType.$inject = this.getInjectArray(serviceType); 72 | this.app.service(this.lowerCaseFirstLetter(this.getFunctionName(serviceType)), serviceType); 73 | }); 74 | } 75 | } 76 | 77 | //Returns name and ddo for a directive class 78 | getNg1DirectiveInfo(dir:DirectiveClass) { 79 | var dirAnno = this.getDirAnno(dir); 80 | 81 | var restrict; 82 | var dashesDirectiveName; 83 | 84 | //Try and match an attribute selector. e.g. "[attr]" 85 | //If it matches store the attribute name in match[1] 86 | var match; 87 | if (match = dirAnno.selector.match(/^\[(.*)\]$/)) { 88 | restrict = 'A'; 89 | dashesDirectiveName = match[1]; 90 | 91 | //Try to match a class selector. e.g. ".class" 92 | } else if (match = dirAnno.selector.match(/^\.(.*)$/)) { 93 | restrict = 'C'; 94 | dashesDirectiveName = match[1]; 95 | 96 | } else { 97 | restrict = 'E'; 98 | dashesDirectiveName = dirAnno.selector; 99 | } 100 | 101 | var scope = {}; 102 | 103 | for (var key in dirAnno.bind) { 104 | if (dirAnno.bind.hasOwnProperty(key)) { 105 | scope[key] = '=' + dirAnno.bind[key]; 106 | } 107 | } 108 | 109 | var ddo = { 110 | restrict: restrict, 111 | controller: dir, 112 | controllerAs: dirAnno.controllerAs, 113 | scope: scope, 114 | bindToController: true 115 | }; 116 | 117 | var templateAnno = this.getTemplateAnno(dir); 118 | if(templateAnno) { 119 | if(templateAnno.inline) { 120 | ddo.template = templateAnno.inline; 121 | } else if (templateAnno.url) { 122 | ddo.templateUrl = templateAnno.url; 123 | } 124 | } 125 | 126 | //Convert the directive name from dash separated to camelCase 127 | var name = dashesDirectiveName.replace(/-([a-z])/g, char => char[1].toUpperCase()); 128 | 129 | return {name, ddo}; 130 | } 131 | 132 | //Services that require $element (e.g. NgElement) cannot be injected normally as $element can only be injected 133 | //directly into the controller of a directive. If the directive passed in requires any of these services then it 134 | //will be wrapped (inherited) by a function that injects $element and manually initialized the $element based 135 | //services before passing them in. 136 | wrapDir(dirType:DirectiveClass) { 137 | var adapter = this; 138 | 139 | var dirAnno = this.getDirAnno(dirType); 140 | 141 | var retDirType = dirType; 142 | 143 | if (dirType.parameters) { 144 | var injectableServices = []; 145 | 146 | //e.g. {pos: 3, type: MyDir} 147 | var uninjectableParams = []; 148 | var requiresElement = false; 149 | var requiresScope = false; 150 | 151 | for (var i = 0; i < dirType.parameters.length; i++) { 152 | var curParamType = dirType.parameters[i][0]; 153 | 154 | //TODO: should check if they are already injecting $element or $scope so we don't end up injecting it twice 155 | 156 | if (curParamType === NgElement || this.isDirClass(curParamType)) { 157 | uninjectableParams.push({pos: i, type: curParamType}); 158 | requiresElement = true; 159 | } else { 160 | injectableServices.push(curParamType); 161 | } 162 | } 163 | 164 | if (dirAnno.observe) { 165 | requiresScope = true; 166 | } 167 | 168 | 169 | //If the directive needs to be wrapped 170 | if (uninjectableParams.length || requiresElement || requiresScope) { 171 | 172 | retDirType = function (...args) { 173 | var element, scope; 174 | 175 | if (requiresScope) { 176 | scope = args.pop(); 177 | } 178 | 179 | if (requiresElement) { 180 | element = args.pop(); 181 | } 182 | 183 | var origDirParams = angular.copy(args); 184 | 185 | //Manually create each parameter that could not be injected 186 | uninjectableParams.forEach((param) => { 187 | var model; 188 | if (param.type === NgElement) { 189 | model = new NgElement(element); 190 | } else if (adapter.isDirClass(param.type)) { 191 | var dirName = adapter.lowerCaseFirstLetter(adapter.getFunctionName(param.type)); 192 | model = element.inheritedData(`$${dirName}Controller`); 193 | } 194 | origDirParams.splice(param.pos, 0, model); 195 | }); 196 | 197 | //Setup any watches specified in dirAnno.observe 198 | if (dirAnno.observe) { 199 | for (let key in dirAnno.observe) { 200 | if (dirAnno.observe.hasOwnProperty(key)) { 201 | let functionName = dirAnno.observe[key]; 202 | 203 | scope.$watch(`${dirAnno.controllerAs}.${key}`, (newValue, oldValue) => { 204 | if (this[functionName]) { 205 | this[functionName](newValue, oldValue); 206 | } else { 207 | console.warn(`'${key}' has changed but observe function, '${functionName}' does not exist.`); 208 | } 209 | }); 210 | } 211 | } 212 | } 213 | 214 | //Steal constructor 215 | dirType.apply(this, origDirParams); 216 | }; 217 | 218 | //Inherit prototype 219 | retDirType.prototype = Object.create(dirType.prototype); 220 | retDirType.annotations = dirType.annotations; 221 | retDirType.parameters = injectableServices.map(type => [type]); 222 | 223 | if (requiresElement) { 224 | retDirType.parameters.push([new InjectNgOne('$element')]); 225 | } 226 | if (requiresScope) { 227 | retDirType.parameters.push([new InjectNgOne('$scope')]); 228 | } 229 | } 230 | } 231 | 232 | return retDirType; 233 | } 234 | 235 | getInjectArray(aClass:Function) { 236 | var $inject = []; 237 | 238 | if (aClass.parameters) { 239 | aClass.parameters.forEach((paramAnnotations) => { 240 | $inject.push(this.getInjectStrFromParamAnnotations(paramAnnotations)); 241 | }); 242 | } 243 | 244 | return $inject; 245 | } 246 | 247 | getInjectStrFromParamAnnotations(paramAnnotations) { 248 | for (var i = 0; i < paramAnnotations.length; i++) { 249 | var paramAnno = paramAnnotations[i]; 250 | 251 | if (paramAnno instanceof InjectNgOne) { 252 | return paramAnno.typeStr; 253 | } else if (paramAnno instanceof Function) { 254 | return this.lowerCaseFirstLetter(this.getFunctionName(paramAnno)); 255 | } 256 | } 257 | 258 | if(paramAnnotations.length === 0) { 259 | throw `Could not inject parameter. You must either specify its type or annotate it with @InjectNgOne('...').`; 260 | } else { 261 | throw `Could not determine how to inject parameter with annotations: ${paramAnnotations}`; 262 | } 263 | 264 | } 265 | 266 | getDirAnno(directive:DirectiveClass) { 267 | var dirAnnos = directive.annotations.filter((annotation) => annotation instanceof Directive); 268 | 269 | return dirAnnos.length ? dirAnnos[0] : undefined; 270 | } 271 | 272 | getTemplateAnno(directive:DirectiveClass) { 273 | var dirAnnos = directive.annotations.filter((annotation) => annotation instanceof Template); 274 | 275 | return dirAnnos.length ? dirAnnos[0] : undefined; 276 | } 277 | 278 | lowerCaseFirstLetter(str) { 279 | return str.charAt(0).toLowerCase() + str.slice(1); 280 | } 281 | 282 | getFunctionName(func:Function) { 283 | if (func.name) { 284 | return func.name; 285 | 286 | //IE doesn't support function.name and neither does traceur. 287 | } else { 288 | var ret = func.toString(); 289 | ret = ret.substr('function '.length); 290 | ret = ret.substr(0, ret.indexOf('(')); 291 | return ret; 292 | } 293 | } 294 | 295 | isDirClass(obj) { 296 | return !!(obj.annotations && obj.annotations.filter(anno => anno instanceof Directive).length); 297 | } 298 | 299 | } 300 | 301 | export {Angular2Adapter}; -------------------------------------------------------------------------------- /src/angular2/ngNext/angular2Adapter.js: -------------------------------------------------------------------------------- 1 | import {Directive, DirectiveClass} from '../ng2/directive.js'; 2 | import {Component, ComponentClass} from '../ng2/component.js'; 3 | import {Template} from '../ng2/template.js'; 4 | import {NgElement} from '../ng2/ngElement.js'; 5 | import {InjectNgOne} from './injectNgOne.js'; 6 | import polyfillPromise from './polyfillPromise.js'; 7 | import registerNg2Directives from './registerNg2Directives.js'; 8 | 9 | class Angular2Adapter { 10 | constructor({moduleName, logLevel = 0}) { 11 | this.moduleName = moduleName; 12 | this.app = angular.module(moduleName); 13 | //not currently used 14 | this.logLevel = logLevel; 15 | 16 | this.registeredDirectives = new Set(); 17 | 18 | polyfillPromise(this.app); 19 | registerNg2Directives(this.app); 20 | 21 | } 22 | 23 | bootstrapComponent(rootComponent:ComponentClass) { 24 | var rootComponentAnno:Component; 25 | rootComponentAnno = this.getDirAnno(rootComponent); 26 | 27 | var rootElement = document.querySelector(rootComponentAnno.selector); 28 | 29 | angular.element(rootElement).ready(() => { 30 | this.registerDirectiveTree(rootComponent); 31 | angular.bootstrap(rootElement, [this.moduleName]); 32 | }); 33 | } 34 | 35 | registerDirectiveTree(dir:DirectiveClass) { 36 | if(this.registeredDirectives.has(dir)) { 37 | return; 38 | } else { 39 | this.registeredDirectives.add(dir); 40 | } 41 | 42 | this.registerDirective(dir); 43 | 44 | var templateAnno = this.getTemplateAnno(dir); 45 | if (templateAnno && templateAnno.directives) { 46 | templateAnno.directives.forEach((childDir) => { 47 | this.registerDirectiveTree(childDir); 48 | }); 49 | } 50 | } 51 | 52 | registerDirective(dir:DirectiveClass) { 53 | dir = this.wrapDir(dir); 54 | dir.$inject = this.getInjectArray(dir); 55 | 56 | this.registerComponentServices(dir); 57 | 58 | var dirInfo = this.getNg1DirectiveInfo(dir); 59 | 60 | this.app.directive(dirInfo.name, function () { 61 | return dirInfo.ddo; 62 | }); 63 | } 64 | 65 | registerComponentServices(dir:DirectiveClass) { 66 | var dirAnno = this.getDirAnno(dir); 67 | 68 | //Register component services 69 | if (dirAnno.componentServices) { 70 | dirAnno.componentServices.forEach((serviceType) => { 71 | serviceType.$inject = this.getInjectArray(serviceType); 72 | this.app.service(this.lowerCaseFirstLetter(this.getFunctionName(serviceType)), serviceType); 73 | }); 74 | } 75 | } 76 | 77 | //Returns name and ddo for a directive class 78 | getNg1DirectiveInfo(dir:DirectiveClass) { 79 | var dirAnno = this.getDirAnno(dir); 80 | 81 | var restrict; 82 | var dashesDirectiveName; 83 | 84 | //Try and match an attribute selector. e.g. "[attr]" 85 | //If it matches store the attribute name in match[1] 86 | var match; 87 | if (match = dirAnno.selector.match(/^\[(.*)\]$/)) { 88 | restrict = 'A'; 89 | dashesDirectiveName = match[1]; 90 | 91 | //Try to match a class selector. e.g. ".class" 92 | } else if (match = dirAnno.selector.match(/^\.(.*)$/)) { 93 | restrict = 'C'; 94 | dashesDirectiveName = match[1]; 95 | 96 | } else { 97 | restrict = 'E'; 98 | dashesDirectiveName = dirAnno.selector; 99 | } 100 | 101 | var scope = {}; 102 | 103 | for (var key in dirAnno.bind) { 104 | if (dirAnno.bind.hasOwnProperty(key)) { 105 | scope[key] = '=' + dirAnno.bind[key]; 106 | } 107 | } 108 | 109 | var ddo = { 110 | restrict: restrict, 111 | controller: dir, 112 | controllerAs: dirAnno.controllerAs, 113 | scope: scope, 114 | bindToController: true 115 | }; 116 | 117 | var templateAnno = this.getTemplateAnno(dir); 118 | if(templateAnno) { 119 | if(templateAnno.inline) { 120 | ddo.template = templateAnno.inline; 121 | } else if (templateAnno.url) { 122 | ddo.templateUrl = templateAnno.url; 123 | } 124 | } 125 | 126 | //Convert the directive name from dash separated to camelCase 127 | var name = dashesDirectiveName.replace(/-([a-z])/g, char => char[1].toUpperCase()); 128 | 129 | return {name, ddo}; 130 | } 131 | 132 | //Services that require $element (e.g. NgElement) cannot be injected normally as $element can only be injected 133 | //directly into the controller of a directive. If the directive passed in requires any of these services then it 134 | //will be wrapped (inherited) by a function that injects $element and manually initialized the $element based 135 | //services before passing them in. 136 | wrapDir(dirType:DirectiveClass) { 137 | var adapter = this; 138 | 139 | var dirAnno = this.getDirAnno(dirType); 140 | 141 | var retDirType = dirType; 142 | 143 | if (dirType.parameters) { 144 | var injectableServices = []; 145 | 146 | //e.g. {pos: 3, type: MyDir} 147 | var uninjectableParams = []; 148 | var requiresElement = false; 149 | var requiresScope = false; 150 | 151 | for (var i = 0; i < dirType.parameters.length; i++) { 152 | var curParamType = dirType.parameters[i][0]; 153 | 154 | //TODO: should check if they are already injecting $element or $scope so we don't end up injecting it twice 155 | 156 | if (curParamType === NgElement || this.isDirClass(curParamType)) { 157 | uninjectableParams.push({pos: i, type: curParamType}); 158 | requiresElement = true; 159 | } else { 160 | injectableServices.push(curParamType); 161 | } 162 | } 163 | 164 | if (dirAnno.observe) { 165 | requiresScope = true; 166 | } 167 | 168 | 169 | //If the directive needs to be wrapped 170 | if (uninjectableParams.length || requiresElement || requiresScope) { 171 | 172 | retDirType = function (...args) { 173 | var element, scope; 174 | 175 | if (requiresScope) { 176 | scope = args.pop(); 177 | } 178 | 179 | if (requiresElement) { 180 | element = args.pop(); 181 | } 182 | 183 | var origDirParams = angular.copy(args); 184 | 185 | //Manually create each parameter that could not be injected 186 | uninjectableParams.forEach((param) => { 187 | var model; 188 | if (param.type === NgElement) { 189 | model = new NgElement(element); 190 | } else if (adapter.isDirClass(param.type)) { 191 | var dirName = adapter.lowerCaseFirstLetter(adapter.getFunctionName(param.type)); 192 | model = element.inheritedData(`$${dirName}Controller`); 193 | } 194 | origDirParams.splice(param.pos, 0, model); 195 | }); 196 | 197 | //Setup any watches specified in dirAnno.observe 198 | if (dirAnno.observe) { 199 | for (let key in dirAnno.observe) { 200 | if (dirAnno.observe.hasOwnProperty(key)) { 201 | let functionName = dirAnno.observe[key]; 202 | 203 | scope.$watch(`${dirAnno.controllerAs}.${key}`, (newValue, oldValue) => { 204 | if (this[functionName]) { 205 | this[functionName](newValue, oldValue); 206 | } else { 207 | console.warn(`'${key}' has changed but observe function, '${functionName}' does not exist.`); 208 | } 209 | }); 210 | } 211 | } 212 | } 213 | 214 | //Steal constructor 215 | dirType.apply(this, origDirParams); 216 | }; 217 | 218 | //Inherit prototype 219 | retDirType.prototype = Object.create(dirType.prototype); 220 | retDirType.annotations = dirType.annotations; 221 | retDirType.parameters = injectableServices.map(type => [type]); 222 | 223 | if (requiresElement) { 224 | retDirType.parameters.push([new InjectNgOne('$element')]); 225 | } 226 | if (requiresScope) { 227 | retDirType.parameters.push([new InjectNgOne('$scope')]); 228 | } 229 | } 230 | } 231 | 232 | return retDirType; 233 | } 234 | 235 | getInjectArray(aClass:Function) { 236 | var $inject = []; 237 | 238 | if (aClass.parameters) { 239 | aClass.parameters.forEach((paramAnnotations) => { 240 | $inject.push(this.getInjectStrFromParamAnnotations(paramAnnotations)); 241 | }); 242 | } 243 | 244 | return $inject; 245 | } 246 | 247 | getInjectStrFromParamAnnotations(paramAnnotations) { 248 | for (var i = 0; i < paramAnnotations.length; i++) { 249 | var paramAnno = paramAnnotations[i]; 250 | 251 | if (paramAnno instanceof InjectNgOne) { 252 | return paramAnno.typeStr; 253 | } else if (paramAnno instanceof Function) { 254 | return this.lowerCaseFirstLetter(this.getFunctionName(paramAnno)); 255 | } 256 | } 257 | 258 | if(paramAnnotations.length === 0) { 259 | throw `Could not inject parameter. You must either specify its type or annotate it with @InjectNgOne('...').`; 260 | } else { 261 | throw `Could not determine how to inject parameter with annotations: ${paramAnnotations}`; 262 | } 263 | 264 | } 265 | 266 | getDirAnno(directive:DirectiveClass) { 267 | var dirAnnos = directive.annotations.filter((annotation) => annotation instanceof Directive); 268 | 269 | return dirAnnos.length ? dirAnnos[0] : undefined; 270 | } 271 | 272 | getTemplateAnno(directive:DirectiveClass) { 273 | var dirAnnos = directive.annotations.filter((annotation) => annotation instanceof Template); 274 | 275 | return dirAnnos.length ? dirAnnos[0] : undefined; 276 | } 277 | 278 | lowerCaseFirstLetter(str) { 279 | return str.charAt(0).toLowerCase() + str.slice(1); 280 | } 281 | 282 | getFunctionName(func:Function) { 283 | if (func.name) { 284 | return func.name; 285 | 286 | //IE doesn't support function.name and neither does traceur. 287 | } else { 288 | var ret = func.toString(); 289 | ret = ret.substr('function '.length); 290 | ret = ret.substr(0, ret.indexOf('(')); 291 | return ret; 292 | } 293 | } 294 | 295 | isDirClass(obj) { 296 | return !!(obj.annotations && obj.annotations.filter(anno => anno instanceof Directive).length); 297 | } 298 | 299 | } 300 | 301 | export {Angular2Adapter}; -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | 203 | -------------------------------------------------------------------------------- /examples/color-slider/build/vendor/angular-aria.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license AngularJS v1.3.8 3 | * (c) 2010-2014 Google, Inc. http://angularjs.org 4 | * License: MIT 5 | */ 6 | (function(window, angular, undefined) {'use strict'; 7 | 8 | /** 9 | * @ngdoc module 10 | * @name ngAria 11 | * @description 12 | * 13 | * The `ngAria` module provides support for common 14 | * [ARIA](http://www.w3.org/TR/wai-aria/) 15 | * attributes that convey state or semantic information about the application for users 16 | * of assistive technologies, such as screen readers. 17 | * 18 | *
19 | * 20 | * ## Usage 21 | * 22 | * For ngAria to do its magic, simply include the module as a dependency. The directives supported 23 | * by ngAria are: 24 | * `ngModel`, `ngDisabled`, `ngShow`, `ngHide`, `ngClick`, `ngDblClick`, and `ngMessages`. 25 | * 26 | * Below is a more detailed breakdown of the attributes handled by ngAria: 27 | * 28 | * | Directive | Supported Attributes | 29 | * |---------------------------------------------|----------------------------------------------------------------------------------------| 30 | * | {@link ng.directive:ngModel ngModel} | aria-checked, aria-valuemin, aria-valuemax, aria-valuenow, aria-invalid, aria-required | 31 | * | {@link ng.directive:ngDisabled ngDisabled} | aria-disabled | 32 | * | {@link ng.directive:ngShow ngShow} | aria-hidden | 33 | * | {@link ng.directive:ngHide ngHide} | aria-hidden | 34 | * | {@link ng.directive:ngClick ngClick} | tabindex, keypress event | 35 | * | {@link ng.directive:ngDblclick ngDblclick} | tabindex | 36 | * | {@link module:ngMessages ngMessages} | aria-live | 37 | * 38 | * Find out more information about each directive by reading the 39 | * {@link guide/accessibility ngAria Developer Guide}. 40 | * 41 | * ##Example 42 | * Using ngDisabled with ngAria: 43 | * ```html 44 | * 45 | * ``` 46 | * Becomes: 47 | * ```html 48 | * 49 | * ``` 50 | * 51 | * ##Disabling Attributes 52 | * It's possible to disable individual attributes added by ngAria with the 53 | * {@link ngAria.$ariaProvider#config config} method. For more details, see the 54 | * {@link guide/accessibility Developer Guide}. 55 | */ 56 | /* global -ngAriaModule */ 57 | var ngAriaModule = angular.module('ngAria', ['ng']). 58 | provider('$aria', $AriaProvider); 59 | 60 | /** 61 | * @ngdoc provider 62 | * @name $ariaProvider 63 | * 64 | * @description 65 | * 66 | * Used for configuring the ARIA attributes injected and managed by ngAria. 67 | * 68 | * ```js 69 | * angular.module('myApp', ['ngAria'], function config($ariaProvider) { 70 | * $ariaProvider.config({ 71 | * ariaValue: true, 72 | * tabindex: false 73 | * }); 74 | * }); 75 | *``` 76 | * 77 | * ## Dependencies 78 | * Requires the {@link ngAria} module to be installed. 79 | * 80 | */ 81 | function $AriaProvider() { 82 | var config = { 83 | ariaHidden: true, 84 | ariaChecked: true, 85 | ariaDisabled: true, 86 | ariaRequired: true, 87 | ariaInvalid: true, 88 | ariaMultiline: true, 89 | ariaValue: true, 90 | tabindex: true, 91 | bindKeypress: true 92 | }; 93 | 94 | /** 95 | * @ngdoc method 96 | * @name $ariaProvider#config 97 | * 98 | * @param {object} config object to enable/disable specific ARIA attributes 99 | * 100 | * - **ariaHidden** – `{boolean}` – Enables/disables aria-hidden tags 101 | * - **ariaChecked** – `{boolean}` – Enables/disables aria-checked tags 102 | * - **ariaDisabled** – `{boolean}` – Enables/disables aria-disabled tags 103 | * - **ariaRequired** – `{boolean}` – Enables/disables aria-required tags 104 | * - **ariaInvalid** – `{boolean}` – Enables/disables aria-invalid tags 105 | * - **ariaMultiline** – `{boolean}` – Enables/disables aria-multiline tags 106 | * - **ariaValue** – `{boolean}` – Enables/disables aria-valuemin, aria-valuemax and aria-valuenow tags 107 | * - **tabindex** – `{boolean}` – Enables/disables tabindex tags 108 | * - **bindKeypress** – `{boolean}` – Enables/disables keypress event binding on ng-click 109 | * 110 | * @description 111 | * Enables/disables various ARIA attributes 112 | */ 113 | this.config = function(newConfig) { 114 | config = angular.extend(config, newConfig); 115 | }; 116 | 117 | function watchExpr(attrName, ariaAttr, negate) { 118 | return function(scope, elem, attr) { 119 | var ariaCamelName = attr.$normalize(ariaAttr); 120 | if (config[ariaCamelName] && !attr[ariaCamelName]) { 121 | scope.$watch(attr[attrName], function(boolVal) { 122 | if (negate) { 123 | boolVal = !boolVal; 124 | } 125 | elem.attr(ariaAttr, boolVal); 126 | }); 127 | } 128 | }; 129 | } 130 | 131 | /** 132 | * @ngdoc service 133 | * @name $aria 134 | * 135 | * @description 136 | * 137 | * The $aria service contains helper methods for applying common 138 | * [ARIA](http://www.w3.org/TR/wai-aria/) attributes to HTML directives. 139 | * 140 | * ngAria injects common accessibility attributes that tell assistive technologies when HTML 141 | * elements are enabled, selected, hidden, and more. To see how this is performed with ngAria, 142 | * let's review a code snippet from ngAria itself: 143 | * 144 | *```js 145 | * ngAriaModule.directive('ngDisabled', ['$aria', function($aria) { 146 | * return $aria.$$watchExpr('ngDisabled', 'aria-disabled'); 147 | * }]) 148 | *``` 149 | * Shown above, the ngAria module creates a directive with the same signature as the 150 | * traditional `ng-disabled` directive. But this ngAria version is dedicated to 151 | * solely managing accessibility attributes. The internal `$aria` service is used to watch the 152 | * boolean attribute `ngDisabled`. If it has not been explicitly set by the developer, 153 | * `aria-disabled` is injected as an attribute with its value synchronized to the value in 154 | * `ngDisabled`. 155 | * 156 | * Because ngAria hooks into the `ng-disabled` directive, developers do not have to do 157 | * anything to enable this feature. The `aria-disabled` attribute is automatically managed 158 | * simply as a silent side-effect of using `ng-disabled` with the ngAria module. 159 | * 160 | * The full list of directives that interface with ngAria: 161 | * * **ngModel** 162 | * * **ngShow** 163 | * * **ngHide** 164 | * * **ngClick** 165 | * * **ngDblclick** 166 | * * **ngMessages** 167 | * * **ngDisabled** 168 | * 169 | * Read the {@link guide/accessibility ngAria Developer Guide} for a thorough explanation of each 170 | * directive. 171 | * 172 | * 173 | * ## Dependencies 174 | * Requires the {@link ngAria} module to be installed. 175 | */ 176 | this.$get = function() { 177 | return { 178 | config: function(key) { 179 | return config[key]; 180 | }, 181 | $$watchExpr: watchExpr 182 | }; 183 | }; 184 | } 185 | 186 | 187 | ngAriaModule.directive('ngShow', ['$aria', function($aria) { 188 | return $aria.$$watchExpr('ngShow', 'aria-hidden', true); 189 | }]) 190 | .directive('ngHide', ['$aria', function($aria) { 191 | return $aria.$$watchExpr('ngHide', 'aria-hidden', false); 192 | }]) 193 | .directive('ngModel', ['$aria', function($aria) { 194 | 195 | function shouldAttachAttr(attr, normalizedAttr, elem) { 196 | return $aria.config(normalizedAttr) && !elem.attr(attr); 197 | } 198 | 199 | function getShape(attr, elem) { 200 | var type = attr.type, 201 | role = attr.role; 202 | 203 | return ((type || role) === 'checkbox' || role === 'menuitemcheckbox') ? 'checkbox' : 204 | ((type || role) === 'radio' || role === 'menuitemradio') ? 'radio' : 205 | (type === 'range' || role === 'progressbar' || role === 'slider') ? 'range' : 206 | (type || role) === 'textbox' || elem[0].nodeName === 'TEXTAREA' ? 'multiline' : ''; 207 | } 208 | 209 | return { 210 | restrict: 'A', 211 | require: '?ngModel', 212 | link: function(scope, elem, attr, ngModel) { 213 | var shape = getShape(attr, elem); 214 | var needsTabIndex = shouldAttachAttr('tabindex', 'tabindex', elem); 215 | 216 | function ngAriaWatchModelValue() { 217 | return ngModel.$modelValue; 218 | } 219 | 220 | function getRadioReaction() { 221 | if (needsTabIndex) { 222 | needsTabIndex = false; 223 | return function ngAriaRadioReaction(newVal) { 224 | var boolVal = newVal === attr.value; 225 | elem.attr('aria-checked', boolVal); 226 | elem.attr('tabindex', 0 - !boolVal); 227 | }; 228 | } else { 229 | return function ngAriaRadioReaction(newVal) { 230 | elem.attr('aria-checked', newVal === attr.value); 231 | }; 232 | } 233 | } 234 | 235 | function ngAriaCheckboxReaction(newVal) { 236 | elem.attr('aria-checked', !!newVal); 237 | } 238 | 239 | switch (shape) { 240 | case 'radio': 241 | case 'checkbox': 242 | if (shouldAttachAttr('aria-checked', 'ariaChecked', elem)) { 243 | scope.$watch(ngAriaWatchModelValue, shape === 'radio' ? 244 | getRadioReaction() : ngAriaCheckboxReaction); 245 | } 246 | break; 247 | case 'range': 248 | if ($aria.config('ariaValue')) { 249 | if (attr.min && !elem.attr('aria-valuemin')) { 250 | elem.attr('aria-valuemin', attr.min); 251 | } 252 | if (attr.max && !elem.attr('aria-valuemax')) { 253 | elem.attr('aria-valuemax', attr.max); 254 | } 255 | if (!elem.attr('aria-valuenow')) { 256 | scope.$watch(ngAriaWatchModelValue, function ngAriaValueNowReaction(newVal) { 257 | elem.attr('aria-valuenow', newVal); 258 | }); 259 | } 260 | } 261 | break; 262 | case 'multiline': 263 | if (shouldAttachAttr('aria-multiline', 'ariaMultiline', elem)) { 264 | elem.attr('aria-multiline', true); 265 | } 266 | break; 267 | } 268 | 269 | if (needsTabIndex) { 270 | elem.attr('tabindex', 0); 271 | } 272 | 273 | if (ngModel.$validators.required && shouldAttachAttr('aria-required', 'ariaRequired', elem)) { 274 | scope.$watch(function ngAriaRequiredWatch() { 275 | return ngModel.$error.required; 276 | }, function ngAriaRequiredReaction(newVal) { 277 | elem.attr('aria-required', !!newVal); 278 | }); 279 | } 280 | 281 | if (shouldAttachAttr('aria-invalid', 'ariaInvalid', elem)) { 282 | scope.$watch(function ngAriaInvalidWatch() { 283 | return ngModel.$invalid; 284 | }, function ngAriaInvalidReaction(newVal) { 285 | elem.attr('aria-invalid', !!newVal); 286 | }); 287 | } 288 | } 289 | }; 290 | }]) 291 | .directive('ngDisabled', ['$aria', function($aria) { 292 | return $aria.$$watchExpr('ngDisabled', 'aria-disabled'); 293 | }]) 294 | .directive('ngMessages', function() { 295 | return { 296 | restrict: 'A', 297 | require: '?ngMessages', 298 | link: function(scope, elem, attr, ngMessages) { 299 | if (!elem.attr('aria-live')) { 300 | elem.attr('aria-live', 'assertive'); 301 | } 302 | } 303 | }; 304 | }) 305 | .directive('ngClick',['$aria', '$parse', function($aria, $parse) { 306 | return { 307 | restrict: 'A', 308 | compile: function(elem, attr) { 309 | var fn = $parse(attr.ngClick, /* interceptorFn */ null, /* expensiveChecks */ true); 310 | return function(scope, elem, attr) { 311 | if ($aria.config('tabindex') && !elem.attr('tabindex')) { 312 | elem.attr('tabindex', 0); 313 | } 314 | 315 | if ($aria.config('bindKeypress') && !attr.ngKeypress) { 316 | elem.on('keypress', function(event) { 317 | if (event.keyCode === 32 || event.keyCode === 13) { 318 | scope.$apply(callback); 319 | } 320 | 321 | function callback() { 322 | fn(scope, { $event: event }); 323 | } 324 | }); 325 | } 326 | }; 327 | } 328 | }; 329 | }]) 330 | .directive('ngDblclick', ['$aria', function($aria) { 331 | return function(scope, elem, attr) { 332 | if ($aria.config('tabindex') && !elem.attr('tabindex')) { 333 | elem.attr('tabindex', 0); 334 | } 335 | }; 336 | }]); 337 | 338 | 339 | })(window, window.angular); 340 | --------------------------------------------------------------------------------