chore: rename modules/examples to modules/playground
The directory contains code authored in a style that makes it transpilable to dart. As such, these are not idiomatic examples of Angular 2 usage. The main purpose of this directory is to enable experimentation with Angular within the angular/angular repository. Closes #4342 Closes #4639
This commit is contained in:

committed by
Flavio Corpa Ríos

parent
c3ab20cc87
commit
e4e74ae65c
14
modules/playground/src/animate/animate-app.ts
Normal file
14
modules/playground/src/animate/animate-app.ts
Normal file
@ -0,0 +1,14 @@
|
||||
import {Component, View, NgIf} from 'angular2/angular2';
|
||||
|
||||
@Component({selector: 'animate-app'})
|
||||
@View({
|
||||
directives: [NgIf],
|
||||
template: `
|
||||
<h1>The box is {{visible ? 'visible' : 'hidden'}}</h1>
|
||||
<div class="ng-animate box" *ng-if="visible"></div>
|
||||
<button (click)="visible = !visible">Animate</button>
|
||||
`
|
||||
})
|
||||
export class AnimateApp {
|
||||
visible: boolean = false;
|
||||
}
|
25
modules/playground/src/animate/css/app.css
Normal file
25
modules/playground/src/animate/css/app.css
Normal file
@ -0,0 +1,25 @@
|
||||
body {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.box {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
background-color: red;
|
||||
transition: all 0.35s ease-in-out;
|
||||
}
|
||||
.box.blue {
|
||||
background-color: blue;
|
||||
}
|
||||
.box.ng-enter {
|
||||
opacity: 0;
|
||||
height: 0;
|
||||
}
|
||||
.box.ng-enter-active {
|
||||
opacity: 1;
|
||||
height: 100px;
|
||||
}
|
||||
.box.ng-leave-active {
|
||||
opacity: 0;
|
||||
height: 0;
|
||||
}
|
10
modules/playground/src/animate/index.html
Normal file
10
modules/playground/src/animate/index.html
Normal file
@ -0,0 +1,10 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<title>Animation Example</title>
|
||||
<link rel="stylesheet" type="text/css" href="./css/app.css" />
|
||||
<base href="/playground/src/animate/">
|
||||
<body>
|
||||
<animate-app>Loading...</animate-app>
|
||||
$SCRIPTS$
|
||||
</body>
|
||||
</html>
|
6
modules/playground/src/animate/index.ts
Normal file
6
modules/playground/src/animate/index.ts
Normal file
@ -0,0 +1,6 @@
|
||||
import {AnimateApp} from './animate-app';
|
||||
import {bootstrap} from 'angular2/bootstrap';
|
||||
|
||||
export function main() {
|
||||
bootstrap(AnimateApp);
|
||||
}
|
14
modules/playground/src/async/index.html
Normal file
14
modules/playground/src/async/index.html
Normal file
@ -0,0 +1,14 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Async</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<async-app>
|
||||
Loading...
|
||||
</async-app>
|
||||
|
||||
$SCRIPTS$
|
||||
</body>
|
||||
</html>
|
96
modules/playground/src/async/index.ts
Normal file
96
modules/playground/src/async/index.ts
Normal file
@ -0,0 +1,96 @@
|
||||
import {bootstrap} from 'angular2/bootstrap';
|
||||
import {NgIf, Component, View} from 'angular2/core';
|
||||
import {TimerWrapper} from 'angular2/src/core/facade/async';
|
||||
|
||||
@Component({selector: 'async-app'})
|
||||
@View({
|
||||
template: `
|
||||
<div id='increment'>
|
||||
<span class='val'>{{val1}}</span>
|
||||
<button class='action' (click)="increment()">Increment</button>
|
||||
</div>
|
||||
<div id='delayedIncrement'>
|
||||
<span class='val'>{{val2}}</span>
|
||||
<button class='action' (click)="delayedIncrement()">Delayed Increment</button>
|
||||
<button class='cancel' *ng-if="timeoutId != null" (click)="cancelDelayedIncrement()">Cancel</button>
|
||||
</div>
|
||||
<div id='multiDelayedIncrements'>
|
||||
<span class='val'>{{val3}}</span>
|
||||
<button class='action' (click)="multiDelayedIncrements(10)">10 Delayed Increments</button>
|
||||
<button class='cancel' *ng-if="multiTimeoutId != null" (click)="cancelMultiDelayedIncrements()">Cancel</button>
|
||||
</div>
|
||||
<div id='periodicIncrement'>
|
||||
<span class='val'>{{val4}}</span>
|
||||
<button class='action' (click)="periodicIncrement()">Periodic Increment</button>
|
||||
<button class='cancel' *ng-if="intervalId != null" (click)="cancelPeriodicIncrement()">Cancel</button>
|
||||
</div>
|
||||
`,
|
||||
directives: [NgIf]
|
||||
})
|
||||
class AsyncApplication {
|
||||
val1: number = 0;
|
||||
val2: number = 0;
|
||||
val3: number = 0;
|
||||
val4: number = 0;
|
||||
timeoutId = null;
|
||||
multiTimeoutId = null;
|
||||
intervalId = null;
|
||||
|
||||
increment(): void { this.val1++; };
|
||||
|
||||
delayedIncrement(): void {
|
||||
this.cancelDelayedIncrement();
|
||||
this.timeoutId = TimerWrapper.setTimeout(() => {
|
||||
this.val2++;
|
||||
this.timeoutId = null;
|
||||
}, 2000);
|
||||
};
|
||||
|
||||
multiDelayedIncrements(i: number): void {
|
||||
this.cancelMultiDelayedIncrements();
|
||||
|
||||
var self = this;
|
||||
function helper(_i) {
|
||||
if (_i <= 0) {
|
||||
self.multiTimeoutId = null;
|
||||
return;
|
||||
}
|
||||
|
||||
self.multiTimeoutId = TimerWrapper.setTimeout(() => {
|
||||
self.val3++;
|
||||
helper(_i - 1);
|
||||
}, 500);
|
||||
}
|
||||
helper(i);
|
||||
};
|
||||
|
||||
periodicIncrement(): void {
|
||||
this.cancelPeriodicIncrement();
|
||||
this.intervalId = TimerWrapper.setInterval(() => { this.val4++; }, 2000)
|
||||
};
|
||||
|
||||
cancelDelayedIncrement(): void {
|
||||
if (this.timeoutId != null) {
|
||||
TimerWrapper.clearTimeout(this.timeoutId);
|
||||
this.timeoutId = null;
|
||||
}
|
||||
};
|
||||
|
||||
cancelMultiDelayedIncrements(): void {
|
||||
if (this.multiTimeoutId != null) {
|
||||
TimerWrapper.clearTimeout(this.multiTimeoutId);
|
||||
this.multiTimeoutId = null;
|
||||
}
|
||||
};
|
||||
|
||||
cancelPeriodicIncrement(): void {
|
||||
if (this.intervalId != null) {
|
||||
TimerWrapper.clearInterval(this.intervalId);
|
||||
this.intervalId = null;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export function main() {
|
||||
bootstrap(AsyncApplication);
|
||||
}
|
16
modules/playground/src/benchpress/index.html
Normal file
16
modules/playground/src/benchpress/index.html
Normal file
@ -0,0 +1,16 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Benchpress test</title>
|
||||
</head>
|
||||
<body>
|
||||
<button onclick="pleaseLog()">Click me</button>
|
||||
<div id="log"></div>
|
||||
|
||||
<script type="text/javascript">
|
||||
function pleaseLog() {
|
||||
document.getElementById("log").innerHTML = "hi";
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
32
modules/playground/src/gestures/index.html
Normal file
32
modules/playground/src/gestures/index.html
Normal file
File diff suppressed because one or more lines are too long
20
modules/playground/src/gestures/index.ts
Normal file
20
modules/playground/src/gestures/index.ts
Normal file
@ -0,0 +1,20 @@
|
||||
import {bootstrap} from 'angular2/bootstrap';
|
||||
import {Component, View} from 'angular2/core';
|
||||
|
||||
@Component({selector: 'gestures-app'})
|
||||
@View({templateUrl: 'template.html'})
|
||||
class GesturesCmp {
|
||||
swipeDirection: string = '-';
|
||||
pinchScale: number = 1;
|
||||
rotateAngle: number = 0;
|
||||
|
||||
onSwipe(event): void { this.swipeDirection = event.deltaX > 0 ? 'right' : 'left'; }
|
||||
|
||||
onPinch(event): void { this.pinchScale = event.scale; }
|
||||
|
||||
onRotate(event): void { this.rotateAngle = event.rotation; }
|
||||
}
|
||||
|
||||
export function main() {
|
||||
bootstrap(GesturesCmp);
|
||||
}
|
15
modules/playground/src/gestures/template.html
Normal file
15
modules/playground/src/gestures/template.html
Normal file
@ -0,0 +1,15 @@
|
||||
<style type="text/css">
|
||||
.row {
|
||||
height: 33%;
|
||||
text-align: center;
|
||||
border-bottom: 1px solid black;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
-webkit-user-select: none;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="row" (swipe)="onSwipe($event)">Swipe (direction = {{swipeDirection}})</div>
|
||||
<div class="row" (pinch)="onPinch($event)">pinch (scale = {{pinchScale}})</div>
|
||||
<div class="row" (rotate)="onRotate($event)">Rotate (angle = {{rotateAngle}})</div>
|
||||
<div class="row"></div>
|
11
modules/playground/src/hello_world/index.html
Normal file
11
modules/playground/src/hello_world/index.html
Normal file
@ -0,0 +1,11 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<title>Hello Angular 2.0</title>
|
||||
<body>
|
||||
<hello-app>
|
||||
Loading...
|
||||
</hello-app>
|
||||
|
||||
$SCRIPTS$
|
||||
</body>
|
||||
</html>
|
62
modules/playground/src/hello_world/index.ts
Normal file
62
modules/playground/src/hello_world/index.ts
Normal file
@ -0,0 +1,62 @@
|
||||
import {bootstrap} from 'angular2/bootstrap';
|
||||
import {ElementRef, Component, Directive, Injectable} from 'angular2/core';
|
||||
import {Renderer} from 'angular2/render';
|
||||
|
||||
export function main() {
|
||||
// Bootstrapping only requires specifying a root component.
|
||||
// The boundary between the Angular application and the rest of the page is
|
||||
// the shadowDom of this root component.
|
||||
// The selector of the component passed in is used to find where to insert the
|
||||
// application.
|
||||
// You can use the light dom of the <hello-app> tag as temporary content (for
|
||||
// example 'Loading...') before the application is ready.
|
||||
bootstrap(HelloCmp);
|
||||
}
|
||||
|
||||
// A service available to the Injector, used by the HelloCmp component.
|
||||
@Injectable()
|
||||
class GreetingService {
|
||||
greeting: string = 'hello';
|
||||
}
|
||||
|
||||
// Directives are light-weight. They don't allow new
|
||||
// expression contexts (use @Component for those needs).
|
||||
@Directive({selector: '[red]'})
|
||||
class RedDec {
|
||||
// ElementRef is always injectable and it wraps the element on which the
|
||||
// directive was found by the compiler.
|
||||
constructor(el: ElementRef, renderer: Renderer) { renderer.setElementStyle(el, 'color', 'red'); }
|
||||
}
|
||||
|
||||
// Angular 2.0 supports 2 basic types of directives:
|
||||
// - Component - the basic building blocks of Angular 2.0 apps. Backed by
|
||||
// ShadowDom.(http://www.html5rocks.com/en/tutorials/webcomponents/shadowdom/)
|
||||
// - Directive - add behavior to existing elements.
|
||||
|
||||
// @Component is AtScript syntax to annotate the HelloCmp class as an Angular
|
||||
// 2.0 component.
|
||||
@Component({
|
||||
// The Selector prop tells Angular on which elements to instantiate this
|
||||
// class. The syntax supported is a basic subset of CSS selectors, for example
|
||||
// 'element', '[attr]', [attr=foo]', etc.
|
||||
selector: 'hello-app',
|
||||
// These are services that would be created if a class in the component's
|
||||
// template tries to inject them.
|
||||
viewProviders: [GreetingService],
|
||||
// Expressions in the template (like {{greeting}}) are evaluated in the
|
||||
// context of the HelloCmp class below.
|
||||
template: `<div class="greeting">{{greeting}} <span red>world</span>!</div>
|
||||
<button class="changeButton" (click)="changeGreeting()">change greeting</button>`,
|
||||
// All directives used in the template need to be specified. This allows for
|
||||
// modularity (RedDec can only be used in this template)
|
||||
// and better tooling (the template can be invalidated if the attribute is
|
||||
// misspelled).
|
||||
directives: [RedDec]
|
||||
})
|
||||
export class HelloCmp {
|
||||
greeting: string;
|
||||
|
||||
constructor(service: GreetingService) { this.greeting = service.greeting; }
|
||||
|
||||
changeGreeting(): void { this.greeting = 'howdy'; }
|
||||
}
|
21
modules/playground/src/http/http_comp.ts
Normal file
21
modules/playground/src/http/http_comp.ts
Normal file
@ -0,0 +1,21 @@
|
||||
import {Component, View, NgFor} from 'angular2/angular2';
|
||||
import {Http} from 'angular2/http';
|
||||
|
||||
@Component({selector: 'http-app'})
|
||||
@View({
|
||||
directives: [NgFor],
|
||||
template: `
|
||||
<h1>people</h1>
|
||||
<ul class="people">
|
||||
<li *ng-for="#person of people">
|
||||
hello, {{person['name']}}
|
||||
</li>
|
||||
</ul>
|
||||
`
|
||||
})
|
||||
export class HttpCmp {
|
||||
people: Object;
|
||||
constructor(http: Http) {
|
||||
http.get('./people.json').map(res => res.json()).subscribe(res => this.people = res);
|
||||
}
|
||||
}
|
11
modules/playground/src/http/index.html
Normal file
11
modules/playground/src/http/index.html
Normal file
@ -0,0 +1,11 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<title>Hello Http</title>
|
||||
<body>
|
||||
<http-app>
|
||||
Loading...
|
||||
</http-app>
|
||||
|
||||
$SCRIPTS$
|
||||
</body>
|
||||
</html>
|
7
modules/playground/src/http/index.ts
Normal file
7
modules/playground/src/http/index.ts
Normal file
@ -0,0 +1,7 @@
|
||||
import {bootstrap} from 'angular2/bootstrap';
|
||||
import {HTTP_PROVIDERS} from 'angular2/http';
|
||||
import {HttpCmp} from './http_comp';
|
||||
|
||||
export function main() {
|
||||
bootstrap(HttpCmp, [HTTP_PROVIDERS]);
|
||||
}
|
1
modules/playground/src/http/people.json
Normal file
1
modules/playground/src/http/people.json
Normal file
@ -0,0 +1 @@
|
||||
[{"name":"Jeff"}]
|
11
modules/playground/src/jsonp/index.html
Normal file
11
modules/playground/src/jsonp/index.html
Normal file
@ -0,0 +1,11 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<title>Hello Jsonp</title>
|
||||
<body>
|
||||
<jsonp-app>
|
||||
Loading...
|
||||
</jsonp-app>
|
||||
|
||||
$SCRIPTS$
|
||||
</body>
|
||||
</html>
|
7
modules/playground/src/jsonp/index.ts
Normal file
7
modules/playground/src/jsonp/index.ts
Normal file
@ -0,0 +1,7 @@
|
||||
import {bootstrap} from 'angular2/bootstrap';
|
||||
import {JSONP_PROVIDERS} from 'angular2/http';
|
||||
import {JsonpCmp} from './jsonp_comp';
|
||||
|
||||
export function main() {
|
||||
bootstrap(JsonpCmp, [JSONP_PROVIDERS]);
|
||||
}
|
22
modules/playground/src/jsonp/jsonp_comp.ts
Normal file
22
modules/playground/src/jsonp/jsonp_comp.ts
Normal file
@ -0,0 +1,22 @@
|
||||
import {Component, View, NgFor} from 'angular2/angular2';
|
||||
import {Jsonp, Response} from 'angular2/http';
|
||||
import {ObservableWrapper} from 'angular2/src/core/facade/async';
|
||||
|
||||
@Component({selector: 'jsonp-app'})
|
||||
@View({
|
||||
directives: [NgFor],
|
||||
template: `
|
||||
<h1>people</h1>
|
||||
<ul class="people">
|
||||
<li *ng-for="#person of people">
|
||||
hello, {{person['name']}}
|
||||
</li>
|
||||
</ul>
|
||||
`
|
||||
})
|
||||
export class JsonpCmp {
|
||||
people: Object;
|
||||
constructor(jsonp: Jsonp) {
|
||||
jsonp.get('./people.json?callback=JSONP_CALLBACK').subscribe(res => this.people = res.json());
|
||||
}
|
||||
}
|
2
modules/playground/src/jsonp/people.json
Normal file
2
modules/playground/src/jsonp/people.json
Normal file
@ -0,0 +1,2 @@
|
||||
// This can only be requested once due to constant method name :(
|
||||
__ng_jsonp__.__req0.finished([{"name":"caitp"}])
|
26
modules/playground/src/key_events/index.html
Normal file
26
modules/playground/src/key_events/index.html
Normal file
@ -0,0 +1,26 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<title>Key events</title>
|
||||
<style>
|
||||
.sample-area {
|
||||
text-align: center;
|
||||
margin: 5px;
|
||||
height: 50px;
|
||||
line-height: 50px;
|
||||
border-radius: 5px;
|
||||
border: 1px solid #d0d0d0;
|
||||
}
|
||||
.sample-area:focus {
|
||||
border: 1px solid blue;
|
||||
color: blue;
|
||||
font-weight: bold;
|
||||
}
|
||||
</style>
|
||||
<body>
|
||||
<key-events-app>
|
||||
Loading...
|
||||
</key-events-app>
|
||||
|
||||
$SCRIPTS$
|
||||
</body>
|
||||
</html>
|
36
modules/playground/src/key_events/index.ts
Normal file
36
modules/playground/src/key_events/index.ts
Normal file
@ -0,0 +1,36 @@
|
||||
import {bootstrap} from 'angular2/bootstrap';
|
||||
import {Component, View} from 'angular2/core';
|
||||
import {KeyEventsPlugin} from 'angular2/src/core/render/dom/events/key_events';
|
||||
|
||||
@Component({selector: 'key-events-app'})
|
||||
@View({
|
||||
template: `Click in the following area and press a key to display its name:<br>
|
||||
<div (keydown)="onKeyDown($event)" class="sample-area" tabindex="0">{{lastKey}}</div><br>
|
||||
Click in the following area and press shift.enter:<br>
|
||||
<div
|
||||
(keydown.shift.enter)="onShiftEnter($event)"
|
||||
(click)="resetShiftEnter()"
|
||||
class="sample-area"
|
||||
tabindex="0"
|
||||
>{{shiftEnter ? 'You pressed shift.enter!' : ''}}</div>`
|
||||
})
|
||||
class KeyEventsApp {
|
||||
lastKey: string = '(none)';
|
||||
shiftEnter: boolean = false;
|
||||
|
||||
onKeyDown(event): void {
|
||||
this.lastKey = KeyEventsPlugin.getEventFullKey(event);
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
onShiftEnter(event): void {
|
||||
this.shiftEnter = true;
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
resetShiftEnter(): void { this.shiftEnter = false; }
|
||||
}
|
||||
|
||||
export function main() {
|
||||
bootstrap(KeyEventsApp);
|
||||
}
|
12
modules/playground/src/material/.clang-format
Normal file
12
modules/playground/src/material/.clang-format
Normal file
@ -0,0 +1,12 @@
|
||||
Language: JavaScript
|
||||
BasedOnStyle: Google
|
||||
ColumnLimit: 100
|
||||
|
||||
TabWidth: 2
|
||||
ContinuationIndentWidth: 4
|
||||
MaxEmptyLinesToKeep : 2
|
||||
|
||||
AllowShortBlocksOnASingleLine: false
|
||||
AllowShortIfStatementsOnASingleLine: false
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
AllowShortFunctionsOnASingleLine: Empty
|
88
modules/playground/src/material/button/demo_app.html
Normal file
88
modules/playground/src/material/button/demo_app.html
Normal file
@ -0,0 +1,88 @@
|
||||
<style>
|
||||
section {
|
||||
background: #f7f7f7;
|
||||
border-radius: 3px;
|
||||
text-align: center;
|
||||
margin: 1em;
|
||||
position: relative !important;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
.label {
|
||||
position: absolute;
|
||||
bottom: 5px;
|
||||
left: 7px;
|
||||
color: #ccc;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.custom {
|
||||
background-color: #ae0001;
|
||||
color: #eeba30;
|
||||
}
|
||||
|
||||
.custom:hover, .custom.md-button-focus {
|
||||
background-color: #740001;
|
||||
color: #d3a625;
|
||||
}
|
||||
</style>
|
||||
|
||||
<h1>Button demo</h1>
|
||||
|
||||
<p>
|
||||
You just clicked: <span>{{previousClick}}</span>
|
||||
</p>
|
||||
|
||||
<section>
|
||||
<form (submit)="submit('form submit')">
|
||||
<button md-button>SUBMIT</button>
|
||||
<button>Native button</button>
|
||||
</form>
|
||||
|
||||
<span class="label">form submit</span>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<span class="label">Regular button</span>
|
||||
|
||||
<button md-button (click)="click('button')">BUTTON</button>
|
||||
|
||||
<button md-button class="md-primary" (click)="click('primary')">PRIMARY</button>
|
||||
<button md-button disabled="disabled" (click)="click('disabled')">DISABLED</button>
|
||||
<button md-button class="md-accent" (click)="click('accent')">ACCENT</button>
|
||||
<button md-button class="md-warn" (click)="click('warn')">WARN</button>
|
||||
<button md-button class="custom" (click)="click('custom')">CUSTOM</button>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<span class="label">Raised button</span>
|
||||
<button md-raised-button (click)="click('raised')">BUTTON</button>
|
||||
<button md-raised-button class="md-primary" (click)="click('raised primary')">PRIMARY</button>
|
||||
<button md-raised-button disabled="disabled" (click)="click('raised disabled')">DISABLED</button>
|
||||
<button md-raised-button class="md-accent" (click)="click('raised accent')">ACCENT</button>
|
||||
<button md-raised-button class="md-warn" (click)="click('raised warn')">WARN</button>
|
||||
<button md-raised-button class="custom" (click)="click('custom raised')">CUSTOM</button>
|
||||
</section>
|
||||
<section>
|
||||
<span class="label">Fab button</span>
|
||||
<button md-fab (click)="click('fab')">BTN</button>
|
||||
<button md-fab class="md-primary" (click)="click('fab primary')">PRMY</button>
|
||||
<button md-fab disabled="disabled" (click)="click('fab disabled')">DIS</button>
|
||||
<button md-fab class="md-accent" (click)="click('fab accent')">ACC</button>
|
||||
<button md-fab class="md-warn" (click)="click('fab warn')">WRN</button>
|
||||
<button md-fab class="custom" (click)="click('custom fab')">CSTM</button>
|
||||
</section>
|
||||
<section>
|
||||
<span class="label">Anchor / hyperlink</span>
|
||||
<a md-button href="http://google.com" target="_blank">HREF</a>
|
||||
<a md-button href="http://google.com" disabled>DISABLED HREF</a>
|
||||
<a md-raised-button target="_blank" href="http://google.com">RAISED HREF</a>
|
||||
</section>
|
||||
|
||||
<section dir="rtl">
|
||||
<span class="label" dir="ltr">Right-to-left</span>
|
||||
<button md-button (click)="click('Hebrew button')">לחצן</button>
|
||||
<button md-raised-button (click)="click('Hebrew raised button')">העלה</button>
|
||||
<a md-button href="http://translate.google.com">עוגן</a>
|
||||
</section>
|
||||
|
13
modules/playground/src/material/button/index.html
Normal file
13
modules/playground/src/material/button/index.html
Normal file
@ -0,0 +1,13 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head lang="en">
|
||||
<meta charset="UTF-8">
|
||||
<title>ng-material button demo</title>
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=RobotoDraft:400,500,700,400italic">
|
||||
<style> * { font-family: RobotoDraft, Roboto, 'Helvetica Neue', sans-serif; } </style>
|
||||
</head>
|
||||
<body>
|
||||
<demo-app>Loading...</demo-app>
|
||||
$SCRIPTS$
|
||||
</body>
|
||||
</html>
|
44
modules/playground/src/material/button/index.ts
Normal file
44
modules/playground/src/material/button/index.ts
Normal file
@ -0,0 +1,44 @@
|
||||
import {bootstrap} from 'angular2/bootstrap';
|
||||
import {bind, provide, Component, NgFor, UrlResolver, View, ViewEncapsulation} from 'angular2/core';
|
||||
import {MdButton, MdAnchor} from 'angular2_material/src/components/button/button';
|
||||
import {commonDemoSetup, DemoUrlResolver} from '../demo_common';
|
||||
|
||||
@Component({
|
||||
selector: 'demo-app',
|
||||
})
|
||||
@View({
|
||||
templateUrl: './demo_app.html',
|
||||
directives: [MdButton, MdAnchor, NgFor],
|
||||
encapsulation: ViewEncapsulation.None
|
||||
})
|
||||
class DemoApp {
|
||||
previousClick: string;
|
||||
action: string;
|
||||
clickCount: number;
|
||||
items: number[];
|
||||
|
||||
constructor() {
|
||||
this.previousClick = 'Nothing';
|
||||
this.action = "ACTIVATE";
|
||||
this.clickCount = 0;
|
||||
this.items = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0];
|
||||
}
|
||||
|
||||
click(msg: string) {
|
||||
this.previousClick = msg;
|
||||
}
|
||||
|
||||
submit(msg: string, event) {
|
||||
event.preventDefault();
|
||||
this.previousClick = msg;
|
||||
}
|
||||
|
||||
increment() {
|
||||
this.clickCount++;
|
||||
}
|
||||
}
|
||||
|
||||
export function main() {
|
||||
commonDemoSetup();
|
||||
bootstrap(DemoApp, [provide(UrlResolver, {useValue: new DemoUrlResolver()})]);
|
||||
}
|
9
modules/playground/src/material/checkbox/demo_app.html
Normal file
9
modules/playground/src/material/checkbox/demo_app.html
Normal file
@ -0,0 +1,9 @@
|
||||
<div md-theme="default">
|
||||
<h2>Checkbox demo</h2>
|
||||
|
||||
<md-checkbox (click)="increment()">Normal checkbox</md-checkbox>
|
||||
<md-checkbox class="md-primary" (click)="increment()">Primary checkbox</md-checkbox>
|
||||
<md-checkbox disabled (click)="increment()">Disabled checkbox</md-checkbox>
|
||||
|
||||
<p>Toggle count: {{toggleCount}}</p>
|
||||
</div>
|
13
modules/playground/src/material/checkbox/index.html
Normal file
13
modules/playground/src/material/checkbox/index.html
Normal file
@ -0,0 +1,13 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head lang="en">
|
||||
<meta charset="UTF-8">
|
||||
<title>ng-material checkbox demo</title>
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=RobotoDraft:400,500,700,400italic">
|
||||
<style> * { font-family: RobotoDraft, Roboto; } </style>
|
||||
</head>
|
||||
<body>
|
||||
<demo-app>Loading...</demo-app>
|
||||
$SCRIPTS$
|
||||
</body>
|
||||
</html>
|
38
modules/playground/src/material/checkbox/index.ts
Normal file
38
modules/playground/src/material/checkbox/index.ts
Normal file
@ -0,0 +1,38 @@
|
||||
import {bootstrap} from 'angular2/bootstrap';
|
||||
import {
|
||||
bind,
|
||||
provide,
|
||||
Component,
|
||||
Directive,
|
||||
UrlResolver,
|
||||
View,
|
||||
ViewEncapsulation
|
||||
} from 'angular2/core';
|
||||
import {MdCheckbox} from 'angular2_material/src/components/checkbox/checkbox';
|
||||
import {commonDemoSetup, DemoUrlResolver} from '../demo_common';
|
||||
|
||||
|
||||
@Component({
|
||||
selector: 'demo-app',
|
||||
})
|
||||
@View({
|
||||
templateUrl: './demo_app.html',
|
||||
directives: [MdCheckbox],
|
||||
encapsulation: ViewEncapsulation.None
|
||||
})
|
||||
class DemoApp {
|
||||
toggleCount: number;
|
||||
|
||||
constructor() {
|
||||
this.toggleCount = 0;
|
||||
}
|
||||
|
||||
increment() {
|
||||
this.toggleCount++;
|
||||
}
|
||||
}
|
||||
|
||||
export function main() {
|
||||
commonDemoSetup();
|
||||
bootstrap(DemoApp, [provide(UrlResolver, {useValue: new DemoUrlResolver()})]);
|
||||
}
|
23
modules/playground/src/material/demo_common.dart
Normal file
23
modules/playground/src/material/demo_common.dart
Normal file
@ -0,0 +1,23 @@
|
||||
library angular2_examples.material.demo_common;
|
||||
|
||||
import 'package:angular2/src/core/dom/browser_adapter.dart';
|
||||
import 'package:angular2/src/core/compiler/url_resolver.dart';
|
||||
|
||||
void commonDemoSetup() {
|
||||
BrowserDomAdapter.makeCurrent();
|
||||
}
|
||||
|
||||
class DemoUrlResolver extends UrlResolver {
|
||||
@override
|
||||
String resolve(String baseUrl, String url) {
|
||||
const MATERIAL_PKG = 'package:angular2_material/';
|
||||
|
||||
// We run a proxy server in front of pub serve that prepends "example" to
|
||||
// paths
|
||||
if (url.startsWith(MATERIAL_PKG)) {
|
||||
return '/examples/packages/angular2_material/' +
|
||||
url.substring(MATERIAL_PKG.length);
|
||||
}
|
||||
return super.resolve(baseUrl, url);
|
||||
}
|
||||
}
|
27
modules/playground/src/material/demo_common.ts
Normal file
27
modules/playground/src/material/demo_common.ts
Normal file
@ -0,0 +1,27 @@
|
||||
import {print} from 'angular2/src/core/facade/lang';
|
||||
import {UrlResolver} from 'angular2/src/core/compiler/url_resolver';
|
||||
import {isPresent, isBlank, RegExpWrapper, StringWrapper} from 'angular2/src/core/facade/lang';
|
||||
import {DOM} from 'angular2/src/core/dom/dom_adapter';
|
||||
import {Injectable} from 'angular2/core';
|
||||
import {BrowserDomAdapter} from 'angular2/src/core/dom/browser_adapter';
|
||||
|
||||
|
||||
export function commonDemoSetup(): void {
|
||||
BrowserDomAdapter.makeCurrent();
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class DemoUrlResolver extends UrlResolver {
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
|
||||
resolve(baseUrl: string, url: string): string {
|
||||
// The standard UrlResolver looks for "package:" templateUrls in
|
||||
// node_modules, however in our repo we host material widgets at the root.
|
||||
if (url.startsWith('package:angular2_material/')) {
|
||||
return '/' + url.substring(8);
|
||||
}
|
||||
return super.resolve(baseUrl, url);
|
||||
}
|
||||
}
|
32
modules/playground/src/material/dialog/demo_app.html
Normal file
32
modules/playground/src/material/dialog/demo_app.html
Normal file
@ -0,0 +1,32 @@
|
||||
<div>
|
||||
<h2>Dialog demo</h2>
|
||||
|
||||
<button id="open" type="button" (click)="open()" [disabled]="!!dialogRef">
|
||||
Open a dialog
|
||||
</button>
|
||||
|
||||
<button type="button" (click)="close()" [disabled]="!dialogRef">
|
||||
Close the dialog
|
||||
</button>
|
||||
|
||||
<p>
|
||||
Last result: {{lastResult}}
|
||||
</p>
|
||||
|
||||
<hr>
|
||||
|
||||
<p> Here are some paragaphs to make the page scrollable</p>
|
||||
<p> Here are some paragaphs to make the page scrollable</p>
|
||||
<p> Here are some paragaphs to make the page scrollable</p>
|
||||
<p> Here are some paragaphs to make the page scrollable</p>
|
||||
<p> Here are some paragaphs to make the page scrollable</p>
|
||||
<p> Here are some paragaphs to make the page scrollable</p>
|
||||
<p> Here are some paragaphs to make the page scrollable</p>
|
||||
<p> Here are some paragaphs to make the page scrollable</p>
|
||||
<p> Here are some paragaphs to make the page scrollable</p>
|
||||
<p> Here are some paragaphs to make the page scrollable</p>
|
||||
<p> Here are some paragaphs to make the page scrollable</p>
|
||||
<p> Here are some paragaphs to make the page scrollable</p>
|
||||
<p> Here are some paragaphs to make the page scrollable</p>
|
||||
|
||||
</div>
|
13
modules/playground/src/material/dialog/index.html
Normal file
13
modules/playground/src/material/dialog/index.html
Normal file
@ -0,0 +1,13 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head lang="en">
|
||||
<meta charset="UTF-8">
|
||||
<title>ng-material dialog demo</title>
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=RobotoDraft:400,500,700,400italic">
|
||||
<style> * { font-family: RobotoDraft, Roboto; } </style>
|
||||
</head>
|
||||
<body class="dialog-demo">
|
||||
<demo-app>Loading...</demo-app>
|
||||
$SCRIPTS$
|
||||
</body>
|
||||
</html>
|
106
modules/playground/src/material/dialog/index.ts
Normal file
106
modules/playground/src/material/dialog/index.ts
Normal file
@ -0,0 +1,106 @@
|
||||
import {bootstrap} from 'angular2/bootstrap';
|
||||
import {
|
||||
bind,
|
||||
provide,
|
||||
ElementRef,
|
||||
ComponentRef,
|
||||
Component,
|
||||
UrlResolver,
|
||||
View,
|
||||
ViewEncapsulation
|
||||
} from 'angular2/core';
|
||||
import {
|
||||
MdDialog,
|
||||
MdDialogRef,
|
||||
MdDialogConfig
|
||||
} from 'angular2_material/src/components/dialog/dialog';
|
||||
import {commonDemoSetup, DemoUrlResolver} from '../demo_common';
|
||||
import {isPresent} from 'angular2/src/core/facade/lang';
|
||||
|
||||
|
||||
@Component({
|
||||
selector: 'demo-app',
|
||||
viewProviders: [MdDialog],
|
||||
})
|
||||
@View({
|
||||
templateUrl: './demo_app.html',
|
||||
directives: [],
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
})
|
||||
class DemoApp {
|
||||
dialog: MdDialog;
|
||||
elementRef: ElementRef;
|
||||
dialogRef: MdDialogRef;
|
||||
dialogConfig: MdDialogConfig;
|
||||
lastResult: string;
|
||||
|
||||
constructor(mdDialog: MdDialog, elementRef: ElementRef) {
|
||||
this.dialog = mdDialog;
|
||||
this.elementRef = elementRef;
|
||||
this.dialogConfig = new MdDialogConfig();
|
||||
|
||||
this.dialogConfig.width = '60%';
|
||||
this.dialogConfig.height = '60%';
|
||||
this.lastResult = '';
|
||||
}
|
||||
|
||||
open() {
|
||||
if (isPresent(this.dialogRef)) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.dialog.open(SimpleDialogComponent, this.elementRef, this.dialogConfig)
|
||||
.then(ref => {
|
||||
this.dialogRef = ref;
|
||||
ref.instance.numCoconuts = 777;
|
||||
|
||||
ref.whenClosed.then(result => {
|
||||
this.dialogRef = null;
|
||||
this.lastResult = result;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
close() {
|
||||
this.dialogRef.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'simple-dialog',
|
||||
inputs: ['numCoconuts'],
|
||||
})
|
||||
@View({
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
template: `
|
||||
<h2>This is the dialog content</h2>
|
||||
<p>There are {{numCoconuts}} coconuts.</p>
|
||||
<p>Return: <input (input)="updateValue($event)"></p>
|
||||
<button type="button" (click)="done()">Done</button>
|
||||
`
|
||||
})
|
||||
class SimpleDialogComponent {
|
||||
numCoconuts: number;
|
||||
dialogRef: MdDialogRef;
|
||||
toReturn: string;
|
||||
|
||||
constructor(dialogRef: MdDialogRef) {
|
||||
this.numCoconuts = 0;
|
||||
this.dialogRef = dialogRef;
|
||||
this.toReturn = '';
|
||||
}
|
||||
|
||||
updateValue(event) {
|
||||
this.toReturn = event.target.value;
|
||||
}
|
||||
|
||||
done() {
|
||||
this.dialogRef.close(this.toReturn);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export function main() {
|
||||
commonDemoSetup();
|
||||
bootstrap(DemoApp, [provide(UrlResolver, {useValue: new DemoUrlResolver()})]);
|
||||
}
|
41
modules/playground/src/material/grid_list/demo_app.html
Normal file
41
modules/playground/src/material/grid_list/demo_app.html
Normal file
@ -0,0 +1,41 @@
|
||||
<style>
|
||||
md-grid-tile {
|
||||
background-color: lightblue;
|
||||
}
|
||||
|
||||
md-grid-list {
|
||||
min-height: 400px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div>
|
||||
|
||||
<h2>grid-list demo</h2>
|
||||
|
||||
<md-grid-list cols="4" row-height="50px" gutter-size="2em" id="complex">
|
||||
|
||||
<md-grid-tile rowspan="1" colspan="2"> Tile #1 </md-grid-tile>
|
||||
<md-grid-tile rowspan="1" colspan="1"> Tile #2 </md-grid-tile>
|
||||
<md-grid-tile rowspan="3" colspan="1"> Tile #3 </md-grid-tile>
|
||||
<md-grid-tile rowspan="2" colspan="2"> Tile #4 </md-grid-tile>
|
||||
<md-grid-tile rowspan="1" colspan="3"> Tile #5 </md-grid-tile>
|
||||
|
||||
</md-grid-list>
|
||||
|
||||
<hr>
|
||||
|
||||
|
||||
|
||||
<md-grid-list cols="4" row-height="50px" gutter-size="2em" id="simple">
|
||||
|
||||
<md-grid-tile rowspan="1" colspan="1"> Tile #1 </md-grid-tile>
|
||||
<md-grid-tile rowspan="1" colspan="1"> Tile #2 </md-grid-tile>
|
||||
<md-grid-tile rowspan="1" colspan="1"> Tile #3 </md-grid-tile>
|
||||
<md-grid-tile rowspan="1" colspan="1"> Tile #4 </md-grid-tile>
|
||||
<md-grid-tile rowspan="1" colspan="1"> Tile #5 </md-grid-tile>
|
||||
<md-grid-tile rowspan="1" colspan="1"> Tile #6 </md-grid-tile>
|
||||
<md-grid-tile rowspan="1" colspan="1"> Tile #7 </md-grid-tile>
|
||||
|
||||
</md-grid-list>
|
||||
|
||||
</div>
|
13
modules/playground/src/material/grid_list/index.html
Normal file
13
modules/playground/src/material/grid_list/index.html
Normal file
@ -0,0 +1,13 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head lang="en">
|
||||
<meta charset="UTF-8">
|
||||
<title>ng-material grid-list demo</title>
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=RobotoDraft:400,500,700,400italic">
|
||||
<style> * { font-family: RobotoDraft, Roboto; } </style>
|
||||
</head>
|
||||
<body>
|
||||
<demo-app>Loading...</demo-app>
|
||||
$SCRIPTS$
|
||||
</body>
|
||||
</html>
|
28
modules/playground/src/material/grid_list/index.ts
Normal file
28
modules/playground/src/material/grid_list/index.ts
Normal file
@ -0,0 +1,28 @@
|
||||
import {bootstrap} from 'angular2/bootstrap';
|
||||
import {bind, provide, Component, UrlResolver, View, ViewEncapsulation} from 'angular2/core';
|
||||
import {MdGridList, MdGridTile} from 'angular2_material/src/components/grid_list/grid_list';
|
||||
import {commonDemoSetup, DemoUrlResolver} from '../demo_common';
|
||||
|
||||
|
||||
@Component({
|
||||
selector: 'demo-app',
|
||||
})
|
||||
@View({
|
||||
templateUrl: './demo_app.html',
|
||||
directives: [MdGridList, MdGridTile],
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
})
|
||||
class DemoApp {
|
||||
tile3RowSpan: number;
|
||||
tile3ColSpan: number;
|
||||
|
||||
constructor() {
|
||||
this.tile3RowSpan = 3;
|
||||
this.tile3ColSpan = 3;
|
||||
}
|
||||
}
|
||||
|
||||
export function main() {
|
||||
commonDemoSetup();
|
||||
bootstrap(DemoApp, [provide(UrlResolver, {useValue: new DemoUrlResolver()})]);
|
||||
}
|
43
modules/playground/src/material/input/demo_app.html
Normal file
43
modules/playground/src/material/input/demo_app.html
Normal file
@ -0,0 +1,43 @@
|
||||
<style>@import "package:angular2_material/src/components/input/input.css";</style>
|
||||
|
||||
<style>
|
||||
body {
|
||||
max-width: 500px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div>
|
||||
<h2>input demo</h2>
|
||||
|
||||
|
||||
<h3>Normal input</h3>
|
||||
<md-input-container>
|
||||
<label>Name</label>
|
||||
<input md-input>
|
||||
</md-input-container>
|
||||
|
||||
<h3>Pre-filled value</h3>
|
||||
<md-input-container>
|
||||
<label>Favorite Framework</label>
|
||||
<input value="Angular">
|
||||
</md-input-container>
|
||||
|
||||
<h3>Disabled input</h3>
|
||||
<md-input-container>
|
||||
<label>ID Number</label>
|
||||
<input disabled>
|
||||
</md-input-container>
|
||||
|
||||
<h3>Disabled, pre-filled input</h3>
|
||||
<md-input-container>
|
||||
<label>Best TV show</label>
|
||||
<input disabled value="Firefly">
|
||||
</md-input-container>
|
||||
|
||||
<!--<h3>textarea</h3>
|
||||
<md-input-container>
|
||||
<label>What I did on my summer vaccation</label>
|
||||
<textarea></textarea>
|
||||
</md-input-container>-->
|
||||
|
||||
</div>
|
14
modules/playground/src/material/input/index.html
Normal file
14
modules/playground/src/material/input/index.html
Normal file
@ -0,0 +1,14 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head lang="en">
|
||||
<meta charset="UTF-8">
|
||||
<title>ng-material input demo</title>
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=RobotoDraft:400,500,700,400italic">
|
||||
<style> * { font-family: RobotoDraft, Roboto; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<demo-app>Loading...</demo-app>
|
||||
$SCRIPTS$
|
||||
</body>
|
||||
</html>
|
19
modules/playground/src/material/input/index.ts
Normal file
19
modules/playground/src/material/input/index.ts
Normal file
@ -0,0 +1,19 @@
|
||||
import {bootstrap} from 'angular2/bootstrap';
|
||||
import {bind, provide, Component, UrlResolver, View, ViewEncapsulation} from 'angular2/core';
|
||||
import {MdInputContainer, MdInput} from 'angular2_material/src/components/input/input';
|
||||
import {commonDemoSetup, DemoUrlResolver} from '../demo_common';
|
||||
|
||||
@Component({selector: 'demo-app'})
|
||||
@View({
|
||||
templateUrl: './demo_app.html',
|
||||
directives: [MdInputContainer, MdInput],
|
||||
encapsulation: ViewEncapsulation.None
|
||||
})
|
||||
class DemoApp {
|
||||
constructor() {}
|
||||
}
|
||||
|
||||
export function main() {
|
||||
commonDemoSetup();
|
||||
bootstrap(DemoApp, [provide(UrlResolver, {useValue: new DemoUrlResolver()})]);
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
<div style="width: 500px;">
|
||||
<h2>Progress-linear demo</h2>
|
||||
|
||||
<p>
|
||||
Determinate: primary
|
||||
<md-progress-linear mode="determinate" [value]="progress" class="md-accent">
|
||||
</md-progress-linear>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Determinate: accent
|
||||
<md-progress-linear mode="determinate" [value]="progress" class="md-primary">
|
||||
</md-progress-linear>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Buffer
|
||||
<md-progress-linear mode="buffer"
|
||||
[value]="progress" [buffer-value]="progress + (200 / progress)" class="md-warn">
|
||||
</md-progress-linear>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Indeterminate
|
||||
<md-progress-linear mode="indeterminate" class="md-primary">
|
||||
</md-progress-linear>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Query
|
||||
<md-progress-linear mode="query" class="md-accent">
|
||||
</md-progress-linear>
|
||||
</p>
|
||||
|
||||
<!--<md-progress-linear></md-progress-linear>-->
|
||||
|
||||
<p>Progress: {{progress}}</p>
|
||||
<button type="button" (click)="step(10)" id="increment">Increment</button>
|
||||
<button type="button" (click)="step(-10)" id="decrement">Decrement</button>
|
||||
</div>
|
15
modules/playground/src/material/progress-linear/index.html
Normal file
15
modules/playground/src/material/progress-linear/index.html
Normal file
@ -0,0 +1,15 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head lang="en">
|
||||
<meta charset="UTF-8">
|
||||
<title>ng-material progress-linear demo</title>
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=RobotoDraft:400,500,700,400italic">
|
||||
<style> * { font-family: RobotoDraft, Roboto; } </style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<demo-app>Loading...</demo-app>
|
||||
|
||||
$SCRIPTS$
|
||||
</body>
|
||||
</html>
|
30
modules/playground/src/material/progress-linear/index.ts
Normal file
30
modules/playground/src/material/progress-linear/index.ts
Normal file
@ -0,0 +1,30 @@
|
||||
import {bootstrap} from 'angular2/bootstrap';
|
||||
import {bind, provide, Component, View, ViewEncapsulation} from 'angular2/core';
|
||||
import {MdProgressLinear} from 'angular2_material/src/components/progress-linear/progress_linear';
|
||||
import {UrlResolver} from 'angular2/src/core/compiler/url_resolver';
|
||||
import {commonDemoSetup, DemoUrlResolver} from '../demo_common';
|
||||
|
||||
@Component({
|
||||
selector: 'demo-app',
|
||||
})
|
||||
@View({
|
||||
templateUrl: './demo_app.html',
|
||||
directives: [MdProgressLinear],
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
})
|
||||
class DemoApp {
|
||||
progress: number;
|
||||
|
||||
constructor() {
|
||||
this.progress = 40;
|
||||
}
|
||||
|
||||
step(s: number) {
|
||||
this.progress += s;
|
||||
}
|
||||
}
|
||||
|
||||
export function main() {
|
||||
commonDemoSetup();
|
||||
bootstrap(DemoApp, [provide(UrlResolver, {useValue: new DemoUrlResolver()})]);
|
||||
}
|
41
modules/playground/src/material/radio/demo_app.html
Normal file
41
modules/playground/src/material/radio/demo_app.html
Normal file
@ -0,0 +1,41 @@
|
||||
<style>
|
||||
md-radio-button {
|
||||
max-width: 200px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div>
|
||||
<h2>Radio buttons</h2>
|
||||
<h3>Inside of a radiogroup</h3>
|
||||
|
||||
<md-radio-group #scifi (change)="onGroupChange()" id="scifi-group">
|
||||
<md-radio-button value="star-wars">Star Wars</md-radio-button>
|
||||
<md-radio-button value="star-trek" id="special-radio">Star Trek</md-radio-button>
|
||||
<md-radio-button value="bsg" disabled>Battlestar Galactica</md-radio-button>
|
||||
<md-radio-button [value]="thirdValue">Dr. Who</md-radio-button>
|
||||
</md-radio-group>
|
||||
|
||||
<p>Your selection: {{scifi.value}}</p>
|
||||
<p>radio group value change count: {{groupValueChangeCount}}</p>
|
||||
|
||||
<hr>
|
||||
<h3>Standalone</h3>
|
||||
|
||||
<md-radio-button name="element" (click)="onIndividualClick()">Earth</md-radio-button>
|
||||
<md-radio-button name="element" (click)="onIndividualClick()">Fire</md-radio-button>
|
||||
<md-radio-button name="element" (click)="onIndividualClick()" disabled>Wind (disabled)</md-radio-button>
|
||||
<md-radio-button name="element" (click)="onIndividualClick()">Heart</md-radio-button>
|
||||
|
||||
<p>individual radio value change count: {{individualValueChanges}}</p>
|
||||
|
||||
<hr>
|
||||
<h3>Disabled radio group</h3>
|
||||
<p>Chosen: {{pokemon}}</p>
|
||||
<md-radio-group disabled [value]="pokemon">
|
||||
<md-radio-button value="fire">Charmander</md-radio-button>
|
||||
<md-radio-button value="leaf">Bulbasaur</md-radio-button>
|
||||
<md-radio-button value="water">Squirtle</md-radio-button>
|
||||
</md-radio-group>
|
||||
|
||||
<button type="button" (click)="chooseCharmander()">Choose Charmander</button>
|
||||
</div>
|
15
modules/playground/src/material/radio/index.html
Normal file
15
modules/playground/src/material/radio/index.html
Normal file
@ -0,0 +1,15 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head lang="en">
|
||||
<meta charset="UTF-8">
|
||||
<title>ng-material radio demo</title>
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=RobotoDraft:400,500,700,400italic">
|
||||
<style> * { font-family: RobotoDraft, Roboto; } </style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<demo-app>Loading...</demo-app>
|
||||
|
||||
$SCRIPTS$
|
||||
</body>
|
||||
</html>
|
47
modules/playground/src/material/radio/index.ts
Normal file
47
modules/playground/src/material/radio/index.ts
Normal file
@ -0,0 +1,47 @@
|
||||
import {bootstrap} from 'angular2/bootstrap';
|
||||
import {bind, provide, Component, UrlResolver, View, ViewEncapsulation} from 'angular2/core';
|
||||
import {MdRadioButton, MdRadioGroup} from 'angular2_material/src/components/radio/radio_button';
|
||||
import {MdRadioDispatcher} from 'angular2_material/src/components/radio/radio_dispatcher';
|
||||
import {commonDemoSetup, DemoUrlResolver} from '../demo_common';
|
||||
|
||||
@Component({
|
||||
selector: 'demo-app',
|
||||
viewProviders: [MdRadioDispatcher],
|
||||
})
|
||||
@View({
|
||||
templateUrl: './demo_app.html',
|
||||
directives: [MdRadioGroup, MdRadioButton],
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
})
|
||||
class DemoApp {
|
||||
thirdValue;
|
||||
groupValueChangeCount;
|
||||
individualValueChanges;
|
||||
pokemon;
|
||||
someTabindex;
|
||||
|
||||
constructor() {
|
||||
this.thirdValue = 'dr-who';
|
||||
this.groupValueChangeCount = 0;
|
||||
this.individualValueChanges = 0;
|
||||
this.pokemon = '';
|
||||
this.someTabindex = 888;
|
||||
}
|
||||
|
||||
chooseCharmander() {
|
||||
this.pokemon = 'fire';
|
||||
}
|
||||
|
||||
onGroupChange() {
|
||||
this.groupValueChangeCount++;
|
||||
}
|
||||
|
||||
onIndividualClick() {
|
||||
this.individualValueChanges++;
|
||||
}
|
||||
}
|
||||
|
||||
export function main() {
|
||||
commonDemoSetup();
|
||||
bootstrap(DemoApp, [provide(UrlResolver, {useValue: new DemoUrlResolver()})]);
|
||||
}
|
9
modules/playground/src/material/switcher/demo_app.html
Normal file
9
modules/playground/src/material/switcher/demo_app.html
Normal file
@ -0,0 +1,9 @@
|
||||
<div md-theme="default">
|
||||
<h2>NgSwitch demo</h2>
|
||||
|
||||
<md-switch (click)="increment()">Normal switch</md-switch>
|
||||
<md-switch class="md-primary" (click)="increment()">Primary switch</md-switch>
|
||||
<md-switch disabled (click)="increment()">Disabled switch</md-switch>
|
||||
|
||||
<p>Toggle count: {{toggleCount}}</p>
|
||||
</div>
|
19
modules/playground/src/material/switcher/index.html
Normal file
19
modules/playground/src/material/switcher/index.html
Normal file
@ -0,0 +1,19 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head lang="en">
|
||||
<meta charset="UTF-8">
|
||||
<title>ng-material switch demo</title>
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=RobotoDraft:400,500,700,400italic">
|
||||
<style>
|
||||
* {
|
||||
font-family: RobotoDraft, Roboto;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<demo-app>Loading...</demo-app>
|
||||
|
||||
$SCRIPTS$
|
||||
</body>
|
||||
</html>
|
30
modules/playground/src/material/switcher/index.ts
Normal file
30
modules/playground/src/material/switcher/index.ts
Normal file
@ -0,0 +1,30 @@
|
||||
import {bootstrap} from 'angular2/bootstrap';
|
||||
import {bind, provide, Component, View, ViewEncapsulation} from 'angular2/core';
|
||||
import {MdSwitch} from 'angular2_material/src/components/switcher/switch';
|
||||
import {UrlResolver} from 'angular2/src/core/compiler/url_resolver';
|
||||
import {commonDemoSetup, DemoUrlResolver} from '../demo_common';
|
||||
|
||||
@Component({
|
||||
selector: 'demo-app',
|
||||
})
|
||||
@View({
|
||||
templateUrl: './demo_app.html',
|
||||
directives: [MdSwitch],
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
})
|
||||
class DemoApp {
|
||||
toggleCount: number;
|
||||
|
||||
constructor() {
|
||||
this.toggleCount = 0;
|
||||
}
|
||||
|
||||
increment() {
|
||||
this.toggleCount++;
|
||||
}
|
||||
}
|
||||
|
||||
export function main() {
|
||||
commonDemoSetup();
|
||||
bootstrap(DemoApp, [provide(UrlResolver, {useValue: new DemoUrlResolver()})]);
|
||||
}
|
19
modules/playground/src/model_driven_forms/index.html
Normal file
19
modules/playground/src/model_driven_forms/index.html
Normal file
@ -0,0 +1,19 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Model Driven Forms</title>
|
||||
<style>
|
||||
.ng-touched.ng-invalid {
|
||||
border-color: red;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<model-driven-forms>
|
||||
Loading...
|
||||
</model-driven-forms>
|
||||
|
||||
$SCRIPTS$
|
||||
</body>
|
||||
</html>
|
161
modules/playground/src/model_driven_forms/index.ts
Normal file
161
modules/playground/src/model_driven_forms/index.ts
Normal file
@ -0,0 +1,161 @@
|
||||
import {bootstrap} from 'angular2/bootstrap';
|
||||
import {
|
||||
FORM_DIRECTIVES,
|
||||
NgControl,
|
||||
Validators,
|
||||
NgFormModel,
|
||||
FormBuilder,
|
||||
NgIf,
|
||||
NgFor,
|
||||
Component,
|
||||
Directive,
|
||||
View,
|
||||
Host
|
||||
} from 'angular2/core';
|
||||
|
||||
import {RegExpWrapper, print, isPresent} from 'angular2/src/core/facade/lang';
|
||||
|
||||
/**
|
||||
* Custom validator.
|
||||
*/
|
||||
function creditCardValidator(c): {[key: string]: boolean} {
|
||||
if (isPresent(c.value) && RegExpWrapper.test(/^\d{16}$/g, c.value)) {
|
||||
return null;
|
||||
} else {
|
||||
return {"invalidCreditCard": true};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a component that displays an error message.
|
||||
*
|
||||
* For instance,
|
||||
*
|
||||
* <show-error control="creditCard" [errors]="['required', 'invalidCreditCard']"></show-error>
|
||||
*
|
||||
* Will display the "is required" error if the control is empty, and "invalid credit card" if the
|
||||
* control is not empty
|
||||
* but not valid.
|
||||
*
|
||||
* In a real application, this component would receive a service that would map an error code to an
|
||||
* actual error message.
|
||||
* To make it simple, we are using a simple map here.
|
||||
*/
|
||||
@Component({selector: 'show-error', inputs: ['controlPath: control', 'errorTypes: errors']})
|
||||
@View({
|
||||
template: `
|
||||
<span *ng-if="errorMessage !== null">{{errorMessage}}</span>
|
||||
`,
|
||||
directives: [NgIf]
|
||||
})
|
||||
class ShowError {
|
||||
formDir;
|
||||
controlPath: string;
|
||||
errorTypes: string[];
|
||||
|
||||
constructor(@Host() formDir: NgFormModel) { this.formDir = formDir; }
|
||||
|
||||
get errorMessage(): string {
|
||||
var control = this.formDir.form.find(this.controlPath);
|
||||
if (isPresent(control) && control.touched) {
|
||||
for (var i = 0; i < this.errorTypes.length; ++i) {
|
||||
if (control.hasError(this.errorTypes[i])) {
|
||||
return this._errorMessage(this.errorTypes[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
_errorMessage(code: string): string {
|
||||
var config = {'required': 'is required', 'invalidCreditCard': 'is invalid credit card number'};
|
||||
return config[code];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Component({selector: 'model-driven-forms', viewProviders: [FormBuilder]})
|
||||
@View({
|
||||
template: `
|
||||
<h1>Checkout Form (Model Driven)</h1>
|
||||
|
||||
<form (ng-submit)="onSubmit()" [ng-form-model]="form" #f="form">
|
||||
<p>
|
||||
<label for="firstName">First Name</label>
|
||||
<input type="text" id="firstName" ng-control="firstName">
|
||||
<show-error control="firstName" [errors]="['required']"></show-error>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<label for="middleName">Middle Name</label>
|
||||
<input type="text" id="middleName" ng-control="middleName">
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<label for="lastName">Last Name</label>
|
||||
<input type="text" id="lastName" ng-control="lastName">
|
||||
<show-error control="lastName" [errors]="['required']"></show-error>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<label for="country">Country</label>
|
||||
<select id="country" ng-control="country">
|
||||
<option *ng-for="#c of countries" [value]="c">{{c}}</option>
|
||||
</select>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<label for="creditCard">Credit Card</label>
|
||||
<input type="text" id="creditCard" ng-control="creditCard">
|
||||
<show-error control="creditCard" [errors]="['required', 'invalidCreditCard']"></show-error>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<label for="amount">Amount</label>
|
||||
<input type="number" id="amount" ng-control="amount">
|
||||
<show-error control="amount" [errors]="['required']"></show-error>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<label for="email">Email</label>
|
||||
<input type="email" id="email" ng-control="email">
|
||||
<show-error control="email" [errors]="['required']"></show-error>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<label for="comments">Comments</label>
|
||||
<textarea id="comments" ng-control="comments">
|
||||
</textarea>
|
||||
</p>
|
||||
|
||||
<button type="submit" [disabled]="!f.form.valid">Submit</button>
|
||||
</form>
|
||||
`,
|
||||
directives: [FORM_DIRECTIVES, NgFor, ShowError]
|
||||
})
|
||||
class ModelDrivenForms {
|
||||
form;
|
||||
countries = ['US', 'Canada'];
|
||||
|
||||
constructor(fb: FormBuilder) {
|
||||
this.form = fb.group({
|
||||
"firstName": ["", Validators.required],
|
||||
"middleName": [""],
|
||||
"lastName": ["", Validators.required],
|
||||
"country": ["Canada", Validators.required],
|
||||
"creditCard": ["", Validators.compose([Validators.required, creditCardValidator])],
|
||||
"amount": [0, Validators.required],
|
||||
"email": ["", Validators.required],
|
||||
"comments": [""]
|
||||
});
|
||||
}
|
||||
|
||||
onSubmit(): void {
|
||||
print("Submitting:");
|
||||
print(this.form.value);
|
||||
}
|
||||
}
|
||||
|
||||
export function main() {
|
||||
bootstrap(ModelDrivenForms);
|
||||
}
|
39
modules/playground/src/observable_models/app.dart
Normal file
39
modules/playground/src/observable_models/app.dart
Normal file
@ -0,0 +1,39 @@
|
||||
library benchmarks.src.naive_infinite_scroll.app;
|
||||
|
||||
import "package:angular2/src/core/facade/collection.dart" show List, ListWrapper;
|
||||
import "scroll_area.dart" show ScrollAreaComponent;
|
||||
import "package:angular2/angular2.dart" show Component, Directive, View, IterableDiffers, SkipSelf, Binding;
|
||||
import "package:angular2/core.dart" show ObservableListDiffFactory, NgIf, NgFor;
|
||||
import 'package:observe/observe.dart' show ObservableList;
|
||||
|
||||
createDiffers(IterableDiffers parent) {
|
||||
return IterableDiffers.create([const ObservableListDiffFactory()], parent);
|
||||
}
|
||||
|
||||
const binding = const Binding(IterableDiffers,
|
||||
toFactory: createDiffers, deps: const [ const[IterableDiffers, const SkipSelf()]]);
|
||||
|
||||
@Component(
|
||||
selector: "scroll-app",
|
||||
bindings: const [binding]
|
||||
)
|
||||
@View(directives: const [ScrollAreaComponent, NgIf, NgFor], template: '''
|
||||
<div>
|
||||
<div style="display: flex">
|
||||
<scroll-area id="testArea"></scroll-area>
|
||||
</div>
|
||||
<div template="ng-if scrollAreas.length > 0">
|
||||
<p>Following tables are only here to add weight to the UI:</p>
|
||||
<scroll-area template="ng-for #scrollArea of scrollAreas"></scroll-area>
|
||||
</div>
|
||||
</div>''')
|
||||
class App {
|
||||
List<int> scrollAreas;
|
||||
App() {
|
||||
var scrollAreas = [];
|
||||
for (var i = 0; i < 300; i++) {
|
||||
scrollAreas.add(i);
|
||||
}
|
||||
this.scrollAreas = new ObservableList.from(scrollAreas);
|
||||
}
|
||||
}
|
135
modules/playground/src/observable_models/cells.dart
Normal file
135
modules/playground/src/observable_models/cells.dart
Normal file
@ -0,0 +1,135 @@
|
||||
library benchmarks.src.naive_infinite_scroll.cells;
|
||||
|
||||
import "package:angular2/src/core/facade/collection.dart"
|
||||
show List, ListWrapper, Map;
|
||||
import "common.dart"
|
||||
show Company, Opportunity, Offering, Account, CustomDate, STATUS_LIST;
|
||||
import "package:angular2/core.dart" show NgFor;
|
||||
import "package:angular2/angular2.dart" show Component, Directive, View, ChangeDetectionStrategy;
|
||||
|
||||
class HasStyle {
|
||||
int cellWidth;
|
||||
HasStyle() {}
|
||||
set width(int w) {
|
||||
this.cellWidth = w;
|
||||
}
|
||||
}
|
||||
@Component(
|
||||
selector: "company-name",
|
||||
inputs: const ["width: cell-width", "company"],
|
||||
changeDetection: ChangeDetectionStrategy.OnPushObserve
|
||||
)
|
||||
@View(
|
||||
directives: const [],
|
||||
template: '''<div [style.width.px]="cellWidth">{{company.name}}</div>'''
|
||||
)
|
||||
class CompanyNameComponent extends HasStyle {
|
||||
Company company;
|
||||
}
|
||||
@Component(
|
||||
selector: "opportunity-name",
|
||||
inputs: const ["width: cell-width", "opportunity"],
|
||||
changeDetection: ChangeDetectionStrategy.OnPushObserve
|
||||
)
|
||||
@View(
|
||||
directives: const [],
|
||||
template: '''<div [style.width.px]="cellWidth">{{opportunity.name}}</div>'''
|
||||
)
|
||||
class OpportunityNameComponent extends HasStyle {
|
||||
Opportunity opportunity;
|
||||
}
|
||||
@Component(
|
||||
selector: "offering-name",
|
||||
inputs: const ["width: cell-width", "offering"],
|
||||
changeDetection: ChangeDetectionStrategy.OnPushObserve
|
||||
)
|
||||
@View(
|
||||
directives: const [],
|
||||
template: '''<div [style.width.px]="cellWidth">{{offering.name}}</div>'''
|
||||
)
|
||||
class OfferingNameComponent extends HasStyle {
|
||||
Offering offering;
|
||||
}
|
||||
class Stage {
|
||||
String name;
|
||||
bool isDisabled;
|
||||
String backgroundColor;
|
||||
Function apply;
|
||||
}
|
||||
@Component(
|
||||
selector: "stage-buttons",
|
||||
inputs: const ["width: cell-width", "offering"],
|
||||
changeDetection: ChangeDetectionStrategy.OnPushObserve
|
||||
)
|
||||
@View(directives: const [NgFor], template: '''
|
||||
<div [style.width.px]="cellWidth">
|
||||
<button template="ng-for #stage of stages"
|
||||
[disabled]="stage.isDisabled"
|
||||
[style.background-color]="stage.backgroundColor"
|
||||
on-click="setStage(stage)">
|
||||
{{stage.name}}
|
||||
</button>
|
||||
</div>''')
|
||||
class StageButtonsComponent extends HasStyle {
|
||||
Offering _offering;
|
||||
List<Stage> stages;
|
||||
Offering get offering {
|
||||
return this._offering;
|
||||
}
|
||||
set offering(Offering offering) {
|
||||
this._offering = offering;
|
||||
this._computeStageButtons();
|
||||
}
|
||||
setStage(Stage stage) {
|
||||
this._offering.status = stage.name;
|
||||
this._offering.name = this._offering.name + "!";
|
||||
this._computeStageButtons();
|
||||
}
|
||||
_computeStageButtons() {
|
||||
var disabled = true;
|
||||
this.stages = ListWrapper.clone(STATUS_LIST.map((status) {
|
||||
var isCurrent = this._offering.status == status;
|
||||
var stage = new Stage();
|
||||
stage.name = status;
|
||||
stage.isDisabled = disabled;
|
||||
stage.backgroundColor = disabled ? "#DDD" : isCurrent ? "#DDF" : "#FDD";
|
||||
if (isCurrent) {
|
||||
disabled = false;
|
||||
}
|
||||
return stage;
|
||||
}).toList());
|
||||
}
|
||||
}
|
||||
@Component(
|
||||
selector: "account-cell",
|
||||
inputs: const ["width: cell-width", "account"],
|
||||
changeDetection: ChangeDetectionStrategy.OnPushObserve
|
||||
)
|
||||
@View(directives: const [], template: '''
|
||||
<div [style.width.px]="cellWidth">
|
||||
<a href="/account/{{account.accountId}}">
|
||||
{{account.accountId}}
|
||||
</a>
|
||||
</div>''')
|
||||
class AccountCellComponent extends HasStyle {
|
||||
Account account;
|
||||
}
|
||||
@Component(
|
||||
selector: "formatted-cell",
|
||||
inputs: const ["width: cell-width", "value"],
|
||||
changeDetection: ChangeDetectionStrategy.OnPushObserve
|
||||
)
|
||||
@View(
|
||||
directives: const [],
|
||||
template: '''<div [style.width.px]="cellWidth">{{formattedValue}}</div>''')
|
||||
class FormattedCellComponent extends HasStyle {
|
||||
String formattedValue;
|
||||
set value(value) {
|
||||
if (value is CustomDate) {
|
||||
this.formattedValue =
|
||||
'''${ value . month}/${ value . day}/${ value . year}''';
|
||||
} else {
|
||||
this.formattedValue = value.toString();
|
||||
}
|
||||
}
|
||||
}
|
241
modules/playground/src/observable_models/common.dart
Normal file
241
modules/playground/src/observable_models/common.dart
Normal file
@ -0,0 +1,241 @@
|
||||
library benchmarks.src.naive_infinite_scroll.common;
|
||||
|
||||
import "package:angular2/src/core/facade/math.dart" show Math;
|
||||
import "package:angular2/src/core/facade/collection.dart";
|
||||
import 'package:observe/observe.dart';
|
||||
import 'dart:collection';
|
||||
import 'dart:async';
|
||||
|
||||
var ITEMS = 1000;
|
||||
var ITEM_HEIGHT = 40;
|
||||
var VISIBLE_ITEMS = 17;
|
||||
var HEIGHT = ITEMS * ITEM_HEIGHT;
|
||||
var VIEW_PORT_HEIGHT = ITEM_HEIGHT * VISIBLE_ITEMS;
|
||||
var COMPANY_NAME_WIDTH = 100;
|
||||
var OPPORTUNITY_NAME_WIDTH = 100;
|
||||
var OFFERING_NAME_WIDTH = 100;
|
||||
var ACCOUNT_CELL_WIDTH = 50;
|
||||
var BASE_POINTS_WIDTH = 50;
|
||||
var KICKER_POINTS_WIDTH = 50;
|
||||
var STAGE_BUTTONS_WIDTH = 220;
|
||||
var BUNDLES_WIDTH = 120;
|
||||
var DUE_DATE_WIDTH = 100;
|
||||
var END_DATE_WIDTH = 100;
|
||||
var AAT_STATUS_WIDTH = 100;
|
||||
var ROW_WIDTH = COMPANY_NAME_WIDTH +
|
||||
OPPORTUNITY_NAME_WIDTH +
|
||||
OFFERING_NAME_WIDTH +
|
||||
ACCOUNT_CELL_WIDTH +
|
||||
BASE_POINTS_WIDTH +
|
||||
KICKER_POINTS_WIDTH +
|
||||
STAGE_BUTTONS_WIDTH +
|
||||
BUNDLES_WIDTH +
|
||||
DUE_DATE_WIDTH +
|
||||
END_DATE_WIDTH +
|
||||
AAT_STATUS_WIDTH;
|
||||
var STATUS_LIST = ["Planned", "Pitched", "Won", "Lost"];
|
||||
var AAT_STATUS_LIST = ["Active", "Passive", "Abandoned"];
|
||||
// Imitate Streamy entities.
|
||||
|
||||
// Just a non-trivial object. Nothing fancy or correct.
|
||||
class CustomDate {
|
||||
num year;
|
||||
num month;
|
||||
num day;
|
||||
CustomDate(num y, num m, num d) {
|
||||
this.year = y;
|
||||
this.month = m;
|
||||
this.day = d;
|
||||
}
|
||||
CustomDate addDays(num days) {
|
||||
var newDay = this.day + days;
|
||||
var newMonth = this.month + Math.floor(newDay / 30);
|
||||
newDay = newDay % 30;
|
||||
var newYear = this.year + Math.floor(newMonth / 12);
|
||||
return new CustomDate(newYear, newMonth, newDay);
|
||||
}
|
||||
static CustomDate now() {
|
||||
return new CustomDate(2014, 1, 28);
|
||||
}
|
||||
}
|
||||
class RawEntity extends Object
|
||||
with MapMixin<String, dynamic>
|
||||
implements ObservableMap<String, dynamic> {
|
||||
ObservableMap _data = new ObservableMap();
|
||||
|
||||
@override
|
||||
Iterable<String> get keys => _data.keys;
|
||||
|
||||
@override
|
||||
void clear() {
|
||||
_data.clear();
|
||||
}
|
||||
|
||||
@override
|
||||
operator [](String key) {
|
||||
if (!key.contains('.')) {
|
||||
return _data[key];
|
||||
}
|
||||
var pieces = key.split('.');
|
||||
var last = pieces.removeLast();
|
||||
var target = _resolve(pieces, this);
|
||||
if (target == null) {
|
||||
return null;
|
||||
}
|
||||
return target[last];
|
||||
}
|
||||
|
||||
@override
|
||||
operator []=(String key, value) {
|
||||
if (!key.contains('.')) {
|
||||
_data[key] = value;
|
||||
return;
|
||||
}
|
||||
var pieces = key.split('.');
|
||||
var last = pieces.removeLast();
|
||||
var target = _resolve(pieces, this);
|
||||
target[last] = value;
|
||||
}
|
||||
|
||||
dynamic get(String name) { return this[name]; }
|
||||
|
||||
set(String name, dynamic value) { this[name] = value; }
|
||||
|
||||
@override
|
||||
remove(String key) {
|
||||
if (!key.contains('.')) {
|
||||
return _data.remove(key);
|
||||
}
|
||||
var pieces = key.split('.');
|
||||
var last = pieces.removeLast();
|
||||
var target = _resolve(pieces, this);
|
||||
return target.remove(last);
|
||||
}
|
||||
|
||||
_resolve(List<String> pieces, start) {
|
||||
var cur = start;
|
||||
for (var i = 0; i < pieces.length; i++) {
|
||||
cur = cur[pieces[i]];
|
||||
if (cur == null) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return cur;
|
||||
}
|
||||
|
||||
@override
|
||||
Stream<List<ChangeRecord>> get changes => _data.changes;
|
||||
@override
|
||||
bool get hasObservers => _data.hasObservers;
|
||||
@override
|
||||
bool deliverChanges() => _data.deliverChanges();
|
||||
@override
|
||||
notifyPropertyChange(Symbol field, Object oldValue, Object newValue) =>
|
||||
_data.notifyPropertyChange(field, oldValue, newValue);
|
||||
@override
|
||||
void notifyChange(ChangeRecord record) {
|
||||
_data.notifyChange(record);
|
||||
}
|
||||
|
||||
@override
|
||||
void observed() {
|
||||
_data.observed();
|
||||
}
|
||||
|
||||
@override
|
||||
void unobserved() {
|
||||
_data.observed();
|
||||
}
|
||||
}
|
||||
class Company extends RawEntity {
|
||||
String get name {
|
||||
return this.get("name");
|
||||
}
|
||||
set name(String val) {
|
||||
this.set("name", val);
|
||||
}
|
||||
}
|
||||
class Offering extends RawEntity {
|
||||
String get name {
|
||||
return this.get("name");
|
||||
}
|
||||
set name(String val) {
|
||||
this.set("name", val);
|
||||
}
|
||||
Company get company {
|
||||
return this.get("company");
|
||||
}
|
||||
set company(Company val) {
|
||||
this.set("company", val);
|
||||
}
|
||||
Opportunity get opportunity {
|
||||
return this.get("opportunity");
|
||||
}
|
||||
set opportunity(Opportunity val) {
|
||||
this.set("opportunity", val);
|
||||
}
|
||||
Account get account {
|
||||
return this.get("account");
|
||||
}
|
||||
set account(Account val) {
|
||||
this.set("account", val);
|
||||
}
|
||||
num get basePoints {
|
||||
return this.get("basePoints");
|
||||
}
|
||||
set basePoints(num val) {
|
||||
this.set("basePoints", val);
|
||||
}
|
||||
num get kickerPoints {
|
||||
return this.get("kickerPoints");
|
||||
}
|
||||
set kickerPoints(num val) {
|
||||
this.set("kickerPoints", val);
|
||||
}
|
||||
String get status {
|
||||
return this.get("status");
|
||||
}
|
||||
set status(String val) {
|
||||
this.set("status", val);
|
||||
}
|
||||
String get bundles {
|
||||
return this.get("bundles");
|
||||
}
|
||||
set bundles(String val) {
|
||||
this.set("bundles", val);
|
||||
}
|
||||
CustomDate get dueDate {
|
||||
return this.get("dueDate");
|
||||
}
|
||||
set dueDate(CustomDate val) {
|
||||
this.set("dueDate", val);
|
||||
}
|
||||
CustomDate get endDate {
|
||||
return this.get("endDate");
|
||||
}
|
||||
set endDate(CustomDate val) {
|
||||
this.set("endDate", val);
|
||||
}
|
||||
String get aatStatus {
|
||||
return this.get("aatStatus");
|
||||
}
|
||||
set aatStatus(String val) {
|
||||
this.set("aatStatus", val);
|
||||
}
|
||||
}
|
||||
class Opportunity extends RawEntity {
|
||||
String get name {
|
||||
return this.get("name");
|
||||
}
|
||||
set name(String val) {
|
||||
this.set("name", val);
|
||||
}
|
||||
}
|
||||
class Account extends RawEntity {
|
||||
num get accountId {
|
||||
return this.get("accountId");
|
||||
}
|
||||
set accountId(num val) {
|
||||
this.set("accountId", val);
|
||||
}
|
||||
}
|
14
modules/playground/src/observable_models/index.dart
Normal file
14
modules/playground/src/observable_models/index.dart
Normal file
@ -0,0 +1,14 @@
|
||||
library benchmarks.src.naive_infinite_scroll.index;
|
||||
|
||||
import "package:angular2/bootstrap.dart" show bootstrap;
|
||||
import "app.dart" show App;
|
||||
import "package:angular2/src/core/linker/view_pool.dart"
|
||||
show APP_VIEW_POOL_CAPACITY;
|
||||
import "package:angular2/core.dart" show bind;
|
||||
|
||||
main() {
|
||||
bootstrap(App, createBindings());
|
||||
}
|
||||
List<dynamic> createBindings() {
|
||||
return [bind(APP_VIEW_POOL_CAPACITY).toValue(100000)];
|
||||
}
|
13
modules/playground/src/observable_models/index.html
Normal file
13
modules/playground/src/observable_models/index.html
Normal file
@ -0,0 +1,13 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>AngularDart Scrolling Benchmark</title>
|
||||
</head>
|
||||
<body>
|
||||
<scroll-app></scroll-app>
|
||||
|
||||
<script src="url_params_to_form.js" type="text/javascript"></script>
|
||||
<script src="index.dart" type="application/dart"></script>
|
||||
<script src="naive_infinite_scroll/packages/browser/dart.js" type="text/javascript"></script>
|
||||
</body>
|
||||
</html>
|
86
modules/playground/src/observable_models/random_data.dart
Normal file
86
modules/playground/src/observable_models/random_data.dart
Normal file
@ -0,0 +1,86 @@
|
||||
library benchmarks.src.naive_infinite_scroll.random_data;
|
||||
|
||||
import "package:angular2/src/core/facade/lang.dart" show StringWrapper;
|
||||
import "package:angular2/src/core/facade/collection.dart" show List, ListWrapper;
|
||||
import "common.dart"
|
||||
show
|
||||
CustomDate,
|
||||
Offering,
|
||||
Company,
|
||||
Opportunity,
|
||||
Account,
|
||||
STATUS_LIST,
|
||||
AAT_STATUS_LIST;
|
||||
|
||||
List<Offering> generateOfferings(int count) {
|
||||
var res = [];
|
||||
for (var i = 0; i < count; i++) {
|
||||
res.add(generateOffering(i));
|
||||
}
|
||||
return res;
|
||||
}
|
||||
Offering generateOffering(int seed) {
|
||||
var res = new Offering();
|
||||
res.name = generateName(seed++);
|
||||
res.company = generateCompany(seed++);
|
||||
res.opportunity = generateOpportunity(seed++);
|
||||
res.account = generateAccount(seed++);
|
||||
res.basePoints = seed % 10;
|
||||
res.kickerPoints = seed % 4;
|
||||
res.status = STATUS_LIST[seed % STATUS_LIST.length];
|
||||
res.bundles = randomString(seed++);
|
||||
res.dueDate = randomDate(seed++);
|
||||
res.endDate = randomDate(seed++, res.dueDate);
|
||||
res.aatStatus = AAT_STATUS_LIST[seed % AAT_STATUS_LIST.length];
|
||||
return res;
|
||||
}
|
||||
Company generateCompany(int seed) {
|
||||
var res = new Company();
|
||||
res.name = generateName(seed);
|
||||
return res;
|
||||
}
|
||||
Opportunity generateOpportunity(int seed) {
|
||||
var res = new Opportunity();
|
||||
res.name = generateName(seed);
|
||||
return res;
|
||||
}
|
||||
Account generateAccount(int seed) {
|
||||
var res = new Account();
|
||||
res.accountId = seed;
|
||||
return res;
|
||||
}
|
||||
var names = [
|
||||
"Foo",
|
||||
"Bar",
|
||||
"Baz",
|
||||
"Qux",
|
||||
"Quux",
|
||||
"Garply",
|
||||
"Waldo",
|
||||
"Fred",
|
||||
"Plugh",
|
||||
"Xyzzy",
|
||||
"Thud",
|
||||
"Cruft",
|
||||
"Stuff"
|
||||
];
|
||||
String generateName(int seed) {
|
||||
return names[seed % names.length];
|
||||
}
|
||||
var offsets = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
|
||||
CustomDate randomDate(int seed, [CustomDate minDate = null]) {
|
||||
if (minDate == null) {
|
||||
minDate = CustomDate.now();
|
||||
}
|
||||
return minDate.addDays(offsets[seed % offsets.length]);
|
||||
}
|
||||
var stringLengths = [5, 7, 9, 11, 13];
|
||||
var charCodeOffsets = [0, 1, 2, 3, 4, 5, 6, 7, 8];
|
||||
String randomString(int seed) {
|
||||
var len = stringLengths[seed % 5];
|
||||
var str = "";
|
||||
for (var i = 0; i < len; i++) {
|
||||
str += StringWrapper.fromCharCode(97 + charCodeOffsets[seed % 9] + i);
|
||||
}
|
||||
return str;
|
||||
}
|
71
modules/playground/src/observable_models/scroll_area.dart
Normal file
71
modules/playground/src/observable_models/scroll_area.dart
Normal file
@ -0,0 +1,71 @@
|
||||
library benchmarks.src.naive_infinite_scroll.scroll_area;
|
||||
|
||||
import "package:angular2/src/core/facade/collection.dart" show ListWrapper;
|
||||
import "package:angular2/src/core/facade/math.dart" show Math;
|
||||
import "package:angular2/angular2.dart" show Component, Directive, View, ChangeDetectionStrategy;
|
||||
import "common.dart"
|
||||
show
|
||||
Offering,
|
||||
ITEMS,
|
||||
ITEM_HEIGHT,
|
||||
VISIBLE_ITEMS,
|
||||
VIEW_PORT_HEIGHT,
|
||||
ROW_WIDTH,
|
||||
HEIGHT;
|
||||
import "random_data.dart" show generateOfferings;
|
||||
import "scroll_item.dart" show ScrollItemComponent;
|
||||
import "package:angular2/core.dart" show NgFor;
|
||||
|
||||
@Component(selector: "scroll-area", changeDetection: ChangeDetectionStrategy.OnPushObserve)
|
||||
@View(directives: const [ScrollItemComponent, NgFor], template: '''
|
||||
<div>
|
||||
<div id="scrollDiv"
|
||||
[style.height.px]="viewPortHeight"
|
||||
style="width: 1000px; border: 1px solid #000; overflow: scroll"
|
||||
on-scroll="onScroll(\$event)">
|
||||
<div id="padding"></div>
|
||||
<div id="inner">
|
||||
<scroll-item
|
||||
template="ng-for #item of visibleItems"
|
||||
[offering]="item">
|
||||
</scroll-item>
|
||||
</div>
|
||||
</div>
|
||||
</div>''')
|
||||
class ScrollAreaComponent {
|
||||
List<Offering> _fullList;
|
||||
List<Offering> visibleItems;
|
||||
num viewPortHeight;
|
||||
var paddingDiv;
|
||||
var innerDiv;
|
||||
ScrollAreaComponent() {
|
||||
this._fullList = generateOfferings(ITEMS);
|
||||
this.visibleItems = [];
|
||||
this.viewPortHeight = VIEW_PORT_HEIGHT;
|
||||
this.onScroll(null);
|
||||
}
|
||||
onScroll(evt) {
|
||||
var scrollTop = 0;
|
||||
if (evt != null) {
|
||||
var scrollDiv = evt.target;
|
||||
if (this.paddingDiv == null) {
|
||||
this.paddingDiv = scrollDiv.querySelector("#padding");
|
||||
}
|
||||
if (this.innerDiv == null) {
|
||||
this.innerDiv = scrollDiv.querySelector("#inner");
|
||||
this.innerDiv.style.setProperty("width", '''${ ROW_WIDTH}px''');
|
||||
}
|
||||
scrollTop = scrollDiv.scrollTop;
|
||||
}
|
||||
var iStart = Math.floor(scrollTop / ITEM_HEIGHT);
|
||||
var iEnd = Math.min(iStart + VISIBLE_ITEMS + 1, this._fullList.length);
|
||||
var padding = iStart * ITEM_HEIGHT;
|
||||
if (this.innerDiv != null) {
|
||||
this.innerDiv.style.setProperty("height", '''${ HEIGHT - padding}px''');
|
||||
}
|
||||
if (this.paddingDiv != null) {
|
||||
this.paddingDiv.style.setProperty("height", '''${ padding}px''');
|
||||
}
|
||||
this.visibleItems = ListWrapper.slice(this._fullList, iStart, iEnd);
|
||||
}
|
||||
}
|
117
modules/playground/src/observable_models/scroll_item.dart
Normal file
117
modules/playground/src/observable_models/scroll_item.dart
Normal file
@ -0,0 +1,117 @@
|
||||
library benchmarks.src.naive_infinite_scroll.scroll_item;
|
||||
|
||||
import "cells.dart"
|
||||
show
|
||||
CompanyNameComponent,
|
||||
OpportunityNameComponent,
|
||||
OfferingNameComponent,
|
||||
StageButtonsComponent,
|
||||
AccountCellComponent,
|
||||
FormattedCellComponent;
|
||||
import "package:angular2/angular2.dart" show Component, Directive, View, ChangeDetectionStrategy;
|
||||
import "common.dart"
|
||||
show
|
||||
Offering,
|
||||
ITEM_HEIGHT,
|
||||
COMPANY_NAME_WIDTH,
|
||||
OPPORTUNITY_NAME_WIDTH,
|
||||
OFFERING_NAME_WIDTH,
|
||||
ACCOUNT_CELL_WIDTH,
|
||||
BASE_POINTS_WIDTH,
|
||||
KICKER_POINTS_WIDTH,
|
||||
STAGE_BUTTONS_WIDTH,
|
||||
BUNDLES_WIDTH,
|
||||
DUE_DATE_WIDTH,
|
||||
END_DATE_WIDTH,
|
||||
AAT_STATUS_WIDTH;
|
||||
|
||||
@Component(selector: "scroll-item", inputs: const ["offering"],
|
||||
changeDetection: ChangeDetectionStrategy.OnPushObserve)
|
||||
@View(
|
||||
directives: const [
|
||||
CompanyNameComponent,
|
||||
OpportunityNameComponent,
|
||||
OfferingNameComponent,
|
||||
StageButtonsComponent,
|
||||
AccountCellComponent,
|
||||
FormattedCellComponent
|
||||
],
|
||||
template: '''
|
||||
<div class="row"
|
||||
[style.height.px]="itemHeight"
|
||||
[style.line-height.px]="itemHeight"
|
||||
style="font-size: 18px; display: flex; justify-content: space-between;">
|
||||
<company-name [company]="offering.company"
|
||||
[cell-width]="companyNameWidth">
|
||||
</company-name>
|
||||
<opportunity-name [opportunity]="offering.opportunity"
|
||||
[cell-width]="opportunityNameWidth">
|
||||
</opportunity-name>
|
||||
<offering-name [offering]="offering"
|
||||
[cell-width]="offeringNameWidth">
|
||||
</offering-name>
|
||||
<account-cell [account]="offering.account"
|
||||
[cell-width]="accountCellWidth">
|
||||
</account-cell>
|
||||
<formatted-cell [value]="offering.basePoints"
|
||||
[cell-width]="basePointsWidth">
|
||||
</formatted-cell>
|
||||
<formatted-cell [value]="offering.kickerPoints"
|
||||
[cell-width]="kickerPointsWidth">
|
||||
</formatted-cell>
|
||||
<stage-buttons [offering]="offering"
|
||||
[cell-width]="stageButtonsWidth">
|
||||
</stage-buttons>
|
||||
<formatted-cell [value]="offering.bundles"
|
||||
[cell-width]="bundlesWidth">
|
||||
</formatted-cell>
|
||||
<formatted-cell [value]="offering.dueDate"
|
||||
[cell-width]="dueDateWidth">
|
||||
</formatted-cell>
|
||||
<formatted-cell [value]="offering.endDate"
|
||||
[cell-width]="endDateWidth">
|
||||
</formatted-cell>
|
||||
<formatted-cell [value]="offering.aatStatus"
|
||||
[cell-width]="aatStatusWidth">
|
||||
</formatted-cell>
|
||||
</div>''')
|
||||
class ScrollItemComponent {
|
||||
Offering offering;
|
||||
num itemHeight;
|
||||
ScrollItemComponent() {
|
||||
this.itemHeight = ITEM_HEIGHT;
|
||||
}
|
||||
get companyNameWidth {
|
||||
return COMPANY_NAME_WIDTH;
|
||||
}
|
||||
get opportunityNameWidth {
|
||||
return OPPORTUNITY_NAME_WIDTH;
|
||||
}
|
||||
get offeringNameWidth {
|
||||
return OFFERING_NAME_WIDTH;
|
||||
}
|
||||
get accountCellWidth {
|
||||
return ACCOUNT_CELL_WIDTH;
|
||||
}
|
||||
get basePointsWidth {
|
||||
return BASE_POINTS_WIDTH;
|
||||
}
|
||||
get kickerPointsWidth {
|
||||
return KICKER_POINTS_WIDTH;
|
||||
}
|
||||
get stageButtonsWidth {
|
||||
return STAGE_BUTTONS_WIDTH;
|
||||
}
|
||||
get bundlesWidth {
|
||||
return BUNDLES_WIDTH;
|
||||
}
|
||||
get dueDateWidth {
|
||||
return DUE_DATE_WIDTH;
|
||||
}
|
||||
get endDateWidth {
|
||||
return END_DATE_WIDTH;
|
||||
}
|
||||
get aatStatusWidth {
|
||||
return AAT_STATUS_WIDTH;
|
||||
}
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
// helper script that will read out the url parameters
|
||||
// and store them in appropriate form fields on the page
|
||||
(function() {
|
||||
var regex = /(\w+)=(\w+)/g;
|
||||
var search = decodeURIComponent(location.search);
|
||||
while (match = regex.exec(search)) {
|
||||
var name = match[1];
|
||||
var value = match[2];
|
||||
var els = document.querySelectorAll('input[name="'+name+'"]');
|
||||
var el;
|
||||
for (var i=0; i<els.length; i++) {
|
||||
el = els[i];
|
||||
if (el.type === 'radio' || el.type === 'checkbox') {
|
||||
el.checked = el.value === value;
|
||||
} else {
|
||||
el.value = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
})();
|
19
modules/playground/src/order_management/index.html
Normal file
19
modules/playground/src/order_management/index.html
Normal file
@ -0,0 +1,19 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Order Management</title>
|
||||
<style>
|
||||
.warning {
|
||||
background-color: yellow;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<order-management-app>
|
||||
Loading...
|
||||
</order-management-app>
|
||||
|
||||
$SCRIPTS$
|
||||
</body>
|
||||
</html>
|
205
modules/playground/src/order_management/index.ts
Normal file
205
modules/playground/src/order_management/index.ts
Normal file
@ -0,0 +1,205 @@
|
||||
import {bootstrap} from 'angular2/bootstrap';
|
||||
import {
|
||||
NgIf,
|
||||
NgFor,
|
||||
Component,
|
||||
Directive,
|
||||
View,
|
||||
Host,
|
||||
forwardRef,
|
||||
Provider,
|
||||
EventEmitter,
|
||||
FORM_DIRECTIVES,
|
||||
Injectable
|
||||
} from 'angular2/core';
|
||||
|
||||
import {ListWrapper} from 'angular2/src/core/facade/collection';
|
||||
|
||||
/**
|
||||
* You can find the Angular 1 implementation of this example here:
|
||||
* https://github.com/wardbell/ng1DataBinding
|
||||
*/
|
||||
|
||||
// ---- model
|
||||
|
||||
class OrderItem {
|
||||
constructor(public orderItemId: number, public orderId: number, public productName: string,
|
||||
public qty: number, public unitPrice: number) {}
|
||||
|
||||
get total(): number { return this.qty * this.unitPrice; }
|
||||
}
|
||||
|
||||
class Order {
|
||||
constructor(public orderId: number, public customerName: string, public limit: number,
|
||||
private _dataService: DataService) {}
|
||||
|
||||
get items(): OrderItem[] { return this._dataService.itemsFor(this); }
|
||||
get total(): number { return this.items.map(i => i.total).reduce((a, b) => a + b); }
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ---- services
|
||||
|
||||
var _nextId = 1000;
|
||||
@Injectable()
|
||||
class DataService {
|
||||
orderItems: OrderItem[];
|
||||
orders: Order[];
|
||||
currentOrder: Order = null;
|
||||
|
||||
constructor() {
|
||||
this.orders = [
|
||||
new Order(_nextId++, "J. Coltrane", 100, this),
|
||||
new Order(_nextId++, "B. Evans", 200, this)
|
||||
];
|
||||
|
||||
this.orderItems = [
|
||||
new OrderItem(_nextId++, this.orders[0].orderId, "Bread", 5, 1),
|
||||
new OrderItem(_nextId++, this.orders[0].orderId, "Brie", 5, 2),
|
||||
new OrderItem(_nextId++, this.orders[0].orderId, "IPA", 5, 3),
|
||||
|
||||
new OrderItem(_nextId++, this.orders[1].orderId, "Mozzarella", 5, 2),
|
||||
new OrderItem(_nextId++, this.orders[1].orderId, "Wine", 5, 3)
|
||||
];
|
||||
}
|
||||
|
||||
itemsFor(order: Order): OrderItem[] {
|
||||
return ListWrapper.filter(this.orderItems, i => i.orderId === order.orderId);
|
||||
}
|
||||
|
||||
addItemForOrder(order: Order): void {
|
||||
this.orderItems.push(new OrderItem(_nextId++, order.orderId, "", 0, 0));
|
||||
}
|
||||
|
||||
deleteItem(item: OrderItem): void { ListWrapper.remove(this.orderItems, item); }
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ---- components
|
||||
|
||||
@Component({selector: 'order-list-cmp'})
|
||||
@View({
|
||||
template: `
|
||||
<h1>Orders</h1>
|
||||
<div *ng-for="#order of orders" [class.warning]="order.total > order.limit">
|
||||
<div>
|
||||
<label>Customer name:</label>
|
||||
{{order.customerName}}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label>Limit: <input [(ng-model)]="order.limit" type="number" placeholder="Limit"></label>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label>Number of items:</label>
|
||||
{{order.items.length}}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label>Order total:</label>
|
||||
{{order.total}}
|
||||
</div>
|
||||
|
||||
<button (click)="select(order)">Select</button>
|
||||
</div>
|
||||
`,
|
||||
directives: [FORM_DIRECTIVES, NgFor]
|
||||
})
|
||||
class OrderListComponent {
|
||||
orders: Order[];
|
||||
|
||||
constructor(private _service: DataService) { this.orders = _service.orders; }
|
||||
select(order: Order): void { this._service.currentOrder = order; }
|
||||
}
|
||||
|
||||
|
||||
@Component({selector: 'order-item-cmp', inputs: ['item'], outputs: ['delete']})
|
||||
@View({
|
||||
template: `
|
||||
<div>
|
||||
<div>
|
||||
<label>Product name: <input [(ng-model)]="item.productName" type="text" placeholder="Product name"></label>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label>Quantity: <input [(ng-model)]="item.qty" type="number" placeholder="Quantity"></label>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label>Unit Price: <input [(ng-model)]="item.unitPrice" type="number" placeholder="Unit price"></label>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label>Total:</label>
|
||||
{{item.total}}
|
||||
</div>
|
||||
|
||||
<button (click)="onDelete()">Delete</button>
|
||||
</div>
|
||||
`,
|
||||
directives: [FORM_DIRECTIVES]
|
||||
})
|
||||
class OrderItemComponent {
|
||||
item: OrderItem;
|
||||
delete = new EventEmitter();
|
||||
|
||||
onDelete(): void { this.delete.next(this.item); }
|
||||
}
|
||||
|
||||
@Component({selector: 'order-details-cmp'})
|
||||
@View({
|
||||
template: `
|
||||
<div *ng-if="order !== null">
|
||||
<h1>Selected Order</h1>
|
||||
<div>
|
||||
<label>Customer name: <input [(ng-model)]="order.customerName" type="text" placeholder="Customer name"></label>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label>Limit: <input [(ng-model)]="order.limit" type="number" placeholder="Limit"></label>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label>Number of items:</label>
|
||||
{{order.items.length}}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label>Order total:</label>
|
||||
{{order.total}}
|
||||
</div>
|
||||
|
||||
<h2>Items</h2>
|
||||
<button (click)="addItem()">Add Item</button>
|
||||
<order-item-cmp *ng-for="#item of order.items" [item]="item" (delete)="deleteItem(item)"></order-item-cmp>
|
||||
</div>
|
||||
`,
|
||||
directives: [FORM_DIRECTIVES, OrderItemComponent, NgFor, NgIf]
|
||||
})
|
||||
class OrderDetailsComponent {
|
||||
constructor(private _service: DataService) {}
|
||||
|
||||
get order(): Order { return this._service.currentOrder; }
|
||||
|
||||
deleteItem(item: OrderItem): void { this._service.deleteItem(item); }
|
||||
|
||||
addItem(): void { this._service.addItemForOrder(this.order); }
|
||||
}
|
||||
|
||||
@Component({selector: 'order-management-app', bindings: [DataService]})
|
||||
@View({
|
||||
template: `
|
||||
<order-list-cmp></order-list-cmp>
|
||||
<order-details-cmp></order-details-cmp>
|
||||
`,
|
||||
directives: [OrderListComponent, OrderDetailsComponent]
|
||||
})
|
||||
class OrderManagementApplication {
|
||||
}
|
||||
|
||||
export function main() {
|
||||
bootstrap(OrderManagementApplication);
|
||||
}
|
19
modules/playground/src/person_management/index.html
Normal file
19
modules/playground/src/person_management/index.html
Normal file
@ -0,0 +1,19 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Person Management</title>
|
||||
<style>
|
||||
.ng-touched.ng-invalid {
|
||||
border-color: red;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<person-management-app>
|
||||
Loading...
|
||||
</person-management-app>
|
||||
|
||||
$SCRIPTS$
|
||||
</body>
|
||||
</html>
|
213
modules/playground/src/person_management/index.ts
Normal file
213
modules/playground/src/person_management/index.ts
Normal file
@ -0,0 +1,213 @@
|
||||
import {bootstrap} from 'angular2/bootstrap';
|
||||
import {
|
||||
NgIf,
|
||||
NgFor,
|
||||
Component,
|
||||
Directive,
|
||||
View,
|
||||
Host,
|
||||
forwardRef,
|
||||
Provider,
|
||||
FORM_DIRECTIVES,
|
||||
Injectable
|
||||
} from 'angular2/core';
|
||||
|
||||
import {CONST_EXPR} from 'angular2/src/core/facade/lang';
|
||||
|
||||
|
||||
/**
|
||||
* You can find the Angular 1 implementation of this example here:
|
||||
* https://github.com/wardbell/ng1DataBinding
|
||||
*/
|
||||
|
||||
// ---- model
|
||||
|
||||
var _nextId = 1;
|
||||
class Person {
|
||||
personId: number;
|
||||
mom: Person;
|
||||
dad: Person;
|
||||
friends: Person[];
|
||||
|
||||
constructor(public firstName: string, public lastName: string, public yearOfBirth: number) {
|
||||
this.personId = _nextId++;
|
||||
this.firstName = firstName;
|
||||
this.lastName = lastName;
|
||||
this.mom = null;
|
||||
this.dad = null;
|
||||
this.friends = [];
|
||||
this.personId = _nextId++;
|
||||
}
|
||||
|
||||
get age(): number { return 2015 - this.yearOfBirth; }
|
||||
get fullName(): string { return `${this.firstName} ${this.lastName}`; }
|
||||
get friendNames(): string { return this.friends.map(f => f.fullName).join(', '); }
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ---- services
|
||||
|
||||
@Injectable()
|
||||
class DataService {
|
||||
currentPerson: Person;
|
||||
persons: Person[];
|
||||
|
||||
constructor() {
|
||||
this.persons = [
|
||||
new Person('Victor', 'Savkin', 1930),
|
||||
new Person('Igor', 'Minar', 1920),
|
||||
new Person('John', 'Papa', 1910),
|
||||
new Person('Nancy', 'Duarte', 1910),
|
||||
new Person('Jack', 'Papa', 1910),
|
||||
new Person('Jill', 'Papa', 1910),
|
||||
new Person('Ward', 'Bell', 1910),
|
||||
new Person('Robert', 'Bell', 1910),
|
||||
new Person('Tracy', 'Ward', 1910),
|
||||
new Person('Dan', 'Wahlin', 1910)
|
||||
];
|
||||
|
||||
this.persons[0].friends = [0, 1, 2, 6, 9].map(_ => this.persons[_]);
|
||||
this.persons[1].friends = [0, 2, 6, 9].map(_ => this.persons[_]);
|
||||
this.persons[2].friends = [0, 1, 6, 9].map(_ => this.persons[_]);
|
||||
this.persons[6].friends = [0, 1, 2, 9].map(_ => this.persons[_]);
|
||||
this.persons[9].friends = [0, 1, 2, 6].map(_ => this.persons[_]);
|
||||
|
||||
this.persons[2].mom = this.persons[5];
|
||||
this.persons[2].dad = this.persons[4];
|
||||
this.persons[6].mom = this.persons[8];
|
||||
this.persons[6].dad = this.persons[7];
|
||||
|
||||
this.currentPerson = this.persons[0];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ---- components
|
||||
|
||||
@Component({selector: 'full-name-cmp'})
|
||||
@View({
|
||||
template: `
|
||||
<h1>Edit Full Name</h1>
|
||||
<div>
|
||||
<form>
|
||||
<div>
|
||||
<label>
|
||||
First: <input [(ng-model)]="person.firstName" type="text" placeholder="First name">
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label>
|
||||
Last: <input [(ng-model)]="person.lastName" type="text" placeholder="Last name">
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label>{{person.fullName}}</label>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
`,
|
||||
directives: [FORM_DIRECTIVES]
|
||||
})
|
||||
class FullNameComponent {
|
||||
constructor(private _service: DataService) {}
|
||||
get person(): Person { return this._service.currentPerson; }
|
||||
}
|
||||
|
||||
@Component({selector: 'person-detail-cmp'})
|
||||
@View({
|
||||
template: `
|
||||
<h2>{{person.fullName}}</h2>
|
||||
|
||||
<div>
|
||||
<form>
|
||||
<div>
|
||||
<label>First: <input [(ng-model)]="person.firstName" type="text" placeholder="First name"></label>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label>Last: <input [(ng-model)]="person.lastName" type="text" placeholder="Last name"></label>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label>Year of birth: <input [(ng-model)]="person.yearOfBirth" type="number" placeholder="Year of birth"></label>
|
||||
Age: {{person.age}}
|
||||
</div>\
|
||||
|
||||
<div *ng-if="person.mom != null">
|
||||
<label>Mom:</label>
|
||||
<input [(ng-model)]="person.mom.firstName" type="text" placeholder="Mom's first name">
|
||||
<input [(ng-model)]="person.mom.lastName" type="text" placeholder="Mom's last name">
|
||||
{{person.mom.fullName}}
|
||||
</div>
|
||||
|
||||
<div *ng-if="person.dad != null">
|
||||
<label>Dad:</label>
|
||||
<input [(ng-model)]="person.dad.firstName" type="text" placeholder="Dad's first name">
|
||||
<input [(ng-model)]="person.dad.lastName" type="text" placeholder="Dad's last name">
|
||||
{{person.dad.fullName}}
|
||||
</div>
|
||||
|
||||
<div *ng-if="person.friends.length > 0">
|
||||
<label>Friends:</label>
|
||||
{{person.friendNames}}
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
`,
|
||||
directives: [FORM_DIRECTIVES, NgIf]
|
||||
})
|
||||
class PersonsDetailComponent {
|
||||
constructor(private _service: DataService) {}
|
||||
get person(): Person { return this._service.currentPerson; }
|
||||
}
|
||||
|
||||
@Component({selector: 'persons-cmp'})
|
||||
@View({
|
||||
template: `
|
||||
<h1>FullName Demo</h1>
|
||||
<div>
|
||||
<ul>
|
||||
<li *ng-for="#person of persons">
|
||||
<label (click)="select(person)">{{person.fullName}}</label>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<person-detail-cmp></person-detail-cmp>
|
||||
</div>
|
||||
`,
|
||||
directives: [FORM_DIRECTIVES, PersonsDetailComponent, NgFor]
|
||||
})
|
||||
class PersonsComponent {
|
||||
persons: Person[];
|
||||
|
||||
constructor(private _service: DataService) { this.persons = _service.persons; }
|
||||
|
||||
select(person: Person): void { this._service.currentPerson = person; }
|
||||
}
|
||||
|
||||
|
||||
@Component({selector: 'person-management-app', viewBindings: [DataService]})
|
||||
@View({
|
||||
template: `
|
||||
<button (click)="switchToEditName()">Edit Full Name</button>
|
||||
<button (click)="switchToPersonList()">Person Array</button>
|
||||
|
||||
<full-name-cmp *ng-if="mode == 'editName'"></full-name-cmp>
|
||||
<persons-cmp *ng-if="mode == 'personList'"></persons-cmp>
|
||||
`,
|
||||
directives: [FullNameComponent, PersonsComponent, NgIf]
|
||||
})
|
||||
class PersonManagementApplication {
|
||||
mode: string;
|
||||
|
||||
switchToEditName(): void { this.mode = 'editName'; }
|
||||
switchToPersonList(): void { this.mode = 'personList'; }
|
||||
}
|
||||
|
||||
export function main() {
|
||||
bootstrap(PersonManagementApplication);
|
||||
}
|
57
modules/playground/src/routing/css/app.css
Normal file
57
modules/playground/src/routing/css/app.css
Normal file
@ -0,0 +1,57 @@
|
||||
body {
|
||||
background:#eee;
|
||||
color:black;
|
||||
}
|
||||
|
||||
.inbox-list,
|
||||
.inbox-list li {
|
||||
list-style:none;
|
||||
padding:0;
|
||||
margin:0;
|
||||
}
|
||||
|
||||
.inbox-list a {
|
||||
padding:5px;
|
||||
display:block;
|
||||
}
|
||||
|
||||
inbox, drafts, inbox-side-menu {
|
||||
display:block;
|
||||
}
|
||||
|
||||
inbox-side-menu .link {
|
||||
display:block;
|
||||
text-align:center;
|
||||
padding:1em;
|
||||
}
|
||||
|
||||
inbox-side-menu .link.active {
|
||||
background:white;
|
||||
}
|
||||
|
||||
inbox-side-menu .link:hover {
|
||||
background:#eee;
|
||||
}
|
||||
|
||||
inbox-side-menu {
|
||||
position:fixed;
|
||||
left:0;
|
||||
top:0;
|
||||
bottom:0;
|
||||
width:200px;
|
||||
background:#ddd;
|
||||
}
|
||||
|
||||
inbox-side-menu a {
|
||||
display: block;
|
||||
}
|
||||
|
||||
inbox, drafts, inbox-detail {
|
||||
padding:1em;
|
||||
margin-left:200px;
|
||||
}
|
||||
|
||||
inbox-detail {
|
||||
display:block;
|
||||
margin-left:200px;
|
||||
}
|
2116
modules/playground/src/routing/data.ts
Normal file
2116
modules/playground/src/routing/data.ts
Normal file
File diff suppressed because it is too large
Load Diff
11
modules/playground/src/routing/drafts.html
Normal file
11
modules/playground/src/routing/drafts.html
Normal file
@ -0,0 +1,11 @@
|
||||
<div ng-if="ready">
|
||||
<h2 class="page-title">Drafts</h2>
|
||||
|
||||
<ol class="inbox-list">
|
||||
<li *ng-for="#item of items" class="inbox-item-record">
|
||||
<a id="item-{{ item.id }}"
|
||||
[router-link]="['/DetailPage', {'id':item.id}]">
|
||||
{{ item.subject }}</a>
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
5
modules/playground/src/routing/inbox-app.html
Normal file
5
modules/playground/src/routing/inbox-app.html
Normal file
@ -0,0 +1,5 @@
|
||||
<inbox-side-menu class="inbox-aside">
|
||||
<a [router-link]="['/Inbox']" class="link" [class.active]="inboxPageActive()">Inbox</a>
|
||||
<a [router-link]="['/Drafts']" class="link" [class.active]="draftsPageActive()">Drafts</a>
|
||||
</inbox-side-menu>
|
||||
<router-outlet></router-outlet>
|
161
modules/playground/src/routing/inbox-app.ts
Normal file
161
modules/playground/src/routing/inbox-app.ts
Normal file
@ -0,0 +1,161 @@
|
||||
import {NgIf, NgFor, EventEmitter, Component, View, Inject, Injectable} from 'angular2/angular2';
|
||||
import {
|
||||
RouterLink,
|
||||
RouteConfig,
|
||||
Router,
|
||||
Route,
|
||||
RouterOutlet,
|
||||
Location,
|
||||
RouteParams
|
||||
} from 'angular2/router';
|
||||
import * as db from './data';
|
||||
import {ObservableWrapper, PromiseWrapper, Promise} from 'angular2/src/core/facade/async';
|
||||
import {ListWrapper} from 'angular2/src/core/facade/collection';
|
||||
import {isPresent, DateWrapper} from 'angular2/src/core/facade/lang';
|
||||
|
||||
class InboxRecord {
|
||||
id: string = '';
|
||||
subject: string = '';
|
||||
content: string = '';
|
||||
email: string = '';
|
||||
firstName: string = '';
|
||||
lastName: string = '';
|
||||
date: string;
|
||||
draft: boolean = false;
|
||||
|
||||
constructor(data: {
|
||||
id: string,
|
||||
subject: string,
|
||||
content: string,
|
||||
email: string,
|
||||
firstName: string,
|
||||
lastName: string,
|
||||
date: string, draft?: boolean
|
||||
} = null) {
|
||||
if (isPresent(data)) {
|
||||
this.setData(data);
|
||||
}
|
||||
}
|
||||
|
||||
setData(record: {
|
||||
id: string,
|
||||
subject: string,
|
||||
content: string,
|
||||
email: string,
|
||||
firstName: string,
|
||||
lastName: string,
|
||||
date: string, draft?: boolean
|
||||
}) {
|
||||
this.id = record['id'];
|
||||
this.subject = record['subject'];
|
||||
this.content = record['content'];
|
||||
this.email = record['email'];
|
||||
this.firstName = record['first-name'];
|
||||
this.lastName = record['last-name'];
|
||||
this.date = record['date'];
|
||||
this.draft = record['draft'] == true;
|
||||
}
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
class DbService {
|
||||
getData(): Promise<any[]> {
|
||||
var p = PromiseWrapper.completer();
|
||||
p.resolve(db.data);
|
||||
return p.promise;
|
||||
}
|
||||
|
||||
drafts(): Promise<any[]> {
|
||||
return PromiseWrapper.then(this.getData(), (data) => {
|
||||
return ListWrapper.filter(data,
|
||||
(record => isPresent(record['draft']) && record['draft'] == true));
|
||||
});
|
||||
}
|
||||
|
||||
emails(): Promise<any[]> {
|
||||
return PromiseWrapper.then(this.getData(), (data) => {
|
||||
return ListWrapper.filter(data, (record => !isPresent(record['draft'])));
|
||||
});
|
||||
}
|
||||
|
||||
email(id): Promise<any> {
|
||||
return PromiseWrapper.then(this.getData(), (data) => {
|
||||
for (var i = 0; i < data.length; i++) {
|
||||
var entry = data[i];
|
||||
if (entry['id'] == id) {
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Component({selector: 'inbox-detail'})
|
||||
@View({templateUrl: "inbox-detail.html", directives: [NgFor, RouterLink]})
|
||||
class InboxDetailCmp {
|
||||
record: InboxRecord = new InboxRecord();
|
||||
ready: boolean = false;
|
||||
|
||||
constructor(db: DbService, params: RouteParams) {
|
||||
var id = params.get('id');
|
||||
PromiseWrapper.then(db.email(id), (data) => { this.record.setData(data); });
|
||||
}
|
||||
}
|
||||
|
||||
@Component({selector: 'inbox'})
|
||||
@View({templateUrl: "inbox.html", directives: [NgFor, RouterLink]})
|
||||
class InboxCmp {
|
||||
items: InboxRecord[] = [];
|
||||
ready: boolean = false;
|
||||
|
||||
constructor(public router: Router, db: DbService, params: RouteParams) {
|
||||
var sortType = params.get('sort');
|
||||
var sortEmailsByDate = isPresent(sortType) && sortType == "date";
|
||||
|
||||
PromiseWrapper.then(db.emails(), emails => {
|
||||
this.ready = true;
|
||||
this.items = emails.map(data => new InboxRecord(data));
|
||||
|
||||
if (sortEmailsByDate) {
|
||||
ListWrapper.sort(this.items,
|
||||
(a, b) => DateWrapper.toMillis(DateWrapper.fromISOString(a.date)) <
|
||||
DateWrapper.toMillis(DateWrapper.fromISOString(b.date)) ?
|
||||
-1 :
|
||||
1);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Component({selector: 'drafts'})
|
||||
@View({templateUrl: "drafts.html", directives: [NgFor, RouterLink]})
|
||||
class DraftsCmp {
|
||||
items: InboxRecord[] = [];
|
||||
ready: boolean = false;
|
||||
|
||||
constructor(public router: Router, db: DbService) {
|
||||
PromiseWrapper.then(db.drafts(), (drafts) => {
|
||||
this.ready = true;
|
||||
this.items = drafts.map(data => new InboxRecord(data));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Component({selector: 'inbox-app', viewProviders: [DbService]})
|
||||
@View({templateUrl: "inbox-app.html", directives: [RouterOutlet, RouterLink]})
|
||||
@RouteConfig([
|
||||
new Route({path: '/', component: InboxCmp, as: 'Inbox'}),
|
||||
new Route({path: '/drafts', component: DraftsCmp, as: 'Drafts'}),
|
||||
new Route({path: '/detail/:id', component: InboxDetailCmp, as: 'DetailPage'})
|
||||
])
|
||||
export class InboxApp {
|
||||
router: Router;
|
||||
location: Location;
|
||||
constructor(router: Router, location: Location) {
|
||||
this.router = router;
|
||||
this.location = location;
|
||||
}
|
||||
inboxPageActive() { return this.location.path() == ''; }
|
||||
draftsPageActive() { return this.location.path() == '/drafts'; }
|
||||
}
|
24
modules/playground/src/routing/inbox-detail.html
Normal file
24
modules/playground/src/routing/inbox-detail.html
Normal file
@ -0,0 +1,24 @@
|
||||
<div ng-if="ready">
|
||||
<h2 class="page-title">{{ record.subject }}</h2>
|
||||
|
||||
<ul>
|
||||
<li id="record-id">ID: {{ record.id }}</li>
|
||||
<li id="record-name">Name: {{ record.firstName }} {{ record.lastName }}</li>
|
||||
<li id="record-email">Email: {{ record.email }}</li>
|
||||
<li id="record-date">Date: {{ record.date }}</li>
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
{{ record.content }}
|
||||
</p>
|
||||
|
||||
<span class="btn medium primary">
|
||||
<a [router-link]="record.draft ? ['../Drafts'] : ['../Inbox']" class="back-button">Back</a>
|
||||
</span>
|
||||
|
||||
<hr />
|
||||
|
||||
<a [router-link]="['../Inbox', { sort: 'date'} ]" class="sort-button">
|
||||
View Latest Messages
|
||||
</a>
|
||||
</div>
|
10
modules/playground/src/routing/inbox.html
Normal file
10
modules/playground/src/routing/inbox.html
Normal file
@ -0,0 +1,10 @@
|
||||
<div ng-if="ready">
|
||||
<h2 class="page-title">Inbox</h2>
|
||||
|
||||
<ol class="inbox-list">
|
||||
<li *ng-for="#item of items" class="inbox-item-record">
|
||||
<a id="item-{{ item.id }}"
|
||||
[router-link]="['/DetailPage', {'id':item.id}]">{{ item.subject }}</a>
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
14
modules/playground/src/routing/index.html
Normal file
14
modules/playground/src/routing/index.html
Normal file
@ -0,0 +1,14 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<title>Routing Example</title>
|
||||
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/gumby/2.6.0/css/gumby.css" />
|
||||
<link rel="stylesheet" type="text/css" href="./css/app.css" />
|
||||
<base href="/playground/src/routing/">
|
||||
<body>
|
||||
<inbox-app>
|
||||
Loading...
|
||||
</inbox-app>
|
||||
|
||||
$SCRIPTS$
|
||||
</body>
|
||||
</html>
|
13
modules/playground/src/routing/index.ts
Normal file
13
modules/playground/src/routing/index.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import {InboxApp} from './inbox-app';
|
||||
import {bind, provide} from 'angular2/angular2';
|
||||
import {bootstrap} from 'angular2/bootstrap';
|
||||
import {ROUTER_PROVIDERS, HashLocationStrategy, LocationStrategy} from 'angular2/router';
|
||||
|
||||
import {reflector} from 'angular2/src/core/reflection/reflection';
|
||||
import {ReflectionCapabilities} from 'angular2/src/core/reflection/reflection_capabilities';
|
||||
|
||||
export function main() {
|
||||
reflector.reflectionCapabilities = new ReflectionCapabilities();
|
||||
bootstrap(InboxApp,
|
||||
[ROUTER_PROVIDERS, provide(LocationStrategy, {useClass: HashLocationStrategy})]);
|
||||
}
|
16
modules/playground/src/sourcemap/index.html
Normal file
16
modules/playground/src/sourcemap/index.html
Normal file
@ -0,0 +1,16 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<title>Sourcemaps</title>
|
||||
<body>
|
||||
<error-app>
|
||||
Loading...
|
||||
</error-app>
|
||||
|
||||
<p>
|
||||
Please look into the console and check whether the stack trace is mapped
|
||||
via source maps!
|
||||
</p>
|
||||
|
||||
$SCRIPTS$
|
||||
</body>
|
||||
</html>
|
18
modules/playground/src/sourcemap/index.ts
Normal file
18
modules/playground/src/sourcemap/index.ts
Normal file
@ -0,0 +1,18 @@
|
||||
import {BaseException, WrappedException} from 'angular2/src/core/facade/exceptions';
|
||||
import {bootstrap} from 'angular2/bootstrap';
|
||||
import {Component, View} from 'angular2/core';
|
||||
|
||||
@Component({
|
||||
selector: 'error-app',
|
||||
})
|
||||
@View({
|
||||
template: `
|
||||
<button class="errorButton" (click)="createError()">create error</button>`
|
||||
})
|
||||
export class ErrorComponent {
|
||||
createError(): void { throw new BaseException('Sourcemap test'); }
|
||||
}
|
||||
|
||||
export function main() {
|
||||
bootstrap(ErrorComponent);
|
||||
}
|
19
modules/playground/src/template_driven_forms/index.html
Normal file
19
modules/playground/src/template_driven_forms/index.html
Normal file
@ -0,0 +1,19 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Template Driven Forms</title>
|
||||
<style>
|
||||
.ng-touched.ng-invalid {
|
||||
border-color: red;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<template-driven-forms>
|
||||
Loading...
|
||||
</template-driven-forms>
|
||||
|
||||
$SCRIPTS$
|
||||
</body>
|
||||
</html>
|
172
modules/playground/src/template_driven_forms/index.ts
Normal file
172
modules/playground/src/template_driven_forms/index.ts
Normal file
@ -0,0 +1,172 @@
|
||||
import {bootstrap} from 'angular2/bootstrap';
|
||||
import {
|
||||
NgIf,
|
||||
NgFor,
|
||||
Component,
|
||||
Directive,
|
||||
View,
|
||||
Host,
|
||||
NG_VALIDATORS,
|
||||
forwardRef,
|
||||
Provider,
|
||||
FORM_DIRECTIVES,
|
||||
NgControl,
|
||||
Validators,
|
||||
NgForm
|
||||
} from 'angular2/core';
|
||||
|
||||
import {RegExpWrapper, print, isPresent, CONST_EXPR} from 'angular2/src/core/facade/lang';
|
||||
|
||||
/**
|
||||
* A domain model we are binding the form controls to.
|
||||
*/
|
||||
class CheckoutModel {
|
||||
firstName: string;
|
||||
middleName: string;
|
||||
lastName: string;
|
||||
country: string = "Canada";
|
||||
|
||||
creditCard: string;
|
||||
amount: number;
|
||||
email: string;
|
||||
comments: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom validator.
|
||||
*/
|
||||
function creditCardValidator(c): {[key: string]: boolean} {
|
||||
if (isPresent(c.value) && RegExpWrapper.test(/^\d{16}$/g, c.value)) {
|
||||
return null;
|
||||
} else {
|
||||
return {"invalidCreditCard": true};
|
||||
}
|
||||
}
|
||||
|
||||
const creditCardValidatorBinding =
|
||||
CONST_EXPR(new Provider(NG_VALIDATORS, {useValue: creditCardValidator, multi: true}));
|
||||
|
||||
@Directive({selector: '[credit-card]', bindings: [creditCardValidatorBinding]})
|
||||
class CreditCardValidator {
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a component that displays an error message.
|
||||
*
|
||||
* For instance,
|
||||
*
|
||||
* <show-error control="creditCard" [errors]="['required', 'invalidCreditCard']"></show-error>
|
||||
*
|
||||
* Will display the "is required" error if the control is empty, and "invalid credit card" if the
|
||||
* control is not empty
|
||||
* but not valid.
|
||||
*
|
||||
* In a real application, this component would receive a service that would map an error code to an
|
||||
* actual error message.
|
||||
* To make it simple, we are using a simple map here.
|
||||
*/
|
||||
@Component({selector: 'show-error', inputs: ['controlPath: control', 'errorTypes: errors']})
|
||||
@View({
|
||||
template: `
|
||||
<span *ng-if="errorMessage !== null">{{errorMessage}}</span>
|
||||
`,
|
||||
directives: [NgIf]
|
||||
})
|
||||
class ShowError {
|
||||
formDir;
|
||||
controlPath: string;
|
||||
errorTypes: string[];
|
||||
|
||||
constructor(@Host() formDir: NgForm) { this.formDir = formDir; }
|
||||
|
||||
get errorMessage(): string {
|
||||
var control = this.formDir.form.find(this.controlPath);
|
||||
if (isPresent(control) && control.touched) {
|
||||
for (var i = 0; i < this.errorTypes.length; ++i) {
|
||||
if (control.hasError(this.errorTypes[i])) {
|
||||
return this._errorMessage(this.errorTypes[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
_errorMessage(code: string): string {
|
||||
var config = {'required': 'is required', 'invalidCreditCard': 'is invalid credit card number'};
|
||||
return config[code];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Component({selector: 'template-driven-forms'})
|
||||
@View({
|
||||
template: `
|
||||
<h1>Checkout Form</h1>
|
||||
|
||||
<form (ng-submit)="onSubmit()" #f="form">
|
||||
<p>
|
||||
<label for="firstName">First Name</label>
|
||||
<input type="text" id="firstName" ng-control="firstName" [(ng-model)]="model.firstName" required>
|
||||
<show-error control="firstName" [errors]="['required']"></show-error>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<label for="middleName">Middle Name</label>
|
||||
<input type="text" id="middleName" ng-control="middleName" [(ng-model)]="model.middleName">
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<label for="lastName">Last Name</label>
|
||||
<input type="text" id="lastName" ng-control="lastName" [(ng-model)]="model.lastName" required>
|
||||
<show-error control="lastName" [errors]="['required']"></show-error>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<label for="country">Country</label>
|
||||
<select id="country" ng-control="country" [(ng-model)]="model.country">
|
||||
<option *ng-for="#c of countries" [value]="c">{{c}}</option>
|
||||
</select>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<label for="creditCard">Credit Card</label>
|
||||
<input type="text" id="creditCard" ng-control="creditCard" [(ng-model)]="model.creditCard" required credit-card>
|
||||
<show-error control="creditCard" [errors]="['required', 'invalidCreditCard']"></show-error>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<label for="amount">Amount</label>
|
||||
<input type="number" id="amount" ng-control="amount" [(ng-model)]="model.amount" required>
|
||||
<show-error control="amount" [errors]="['required']"></show-error>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<label for="email">Email</label>
|
||||
<input type="email" id="email" ng-control="email" [(ng-model)]="model.email" required>
|
||||
<show-error control="email" [errors]="['required']"></show-error>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<label for="comments">Comments</label>
|
||||
<textarea id="comments" ng-control="comments" [(ng-model)]="model.comments">
|
||||
</textarea>
|
||||
</p>
|
||||
|
||||
<button type="submit" [disabled]="!f.form.valid">Submit</button>
|
||||
</form>
|
||||
`,
|
||||
directives: [FORM_DIRECTIVES, NgFor, CreditCardValidator, ShowError]
|
||||
})
|
||||
class TemplateDrivenForms {
|
||||
model = new CheckoutModel();
|
||||
countries = ['US', 'Canada'];
|
||||
|
||||
onSubmit(): void {
|
||||
print("Submitting:");
|
||||
print(this.model);
|
||||
}
|
||||
}
|
||||
|
||||
export function main() {
|
||||
bootstrap(TemplateDrivenForms);
|
||||
}
|
379
modules/playground/src/todo/css/base.css
Normal file
379
modules/playground/src/todo/css/base.css
Normal file
@ -0,0 +1,379 @@
|
||||
@charset "utf-8";
|
||||
|
||||
button {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
background: none;
|
||||
font-size: 100%;
|
||||
vertical-align: baseline;
|
||||
font-family: inherit;
|
||||
font-weight: inherit;
|
||||
color: inherit;
|
||||
-webkit-appearance: none;
|
||||
-ms-appearance: none;
|
||||
appearance: none;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-font-smoothing: antialiased;
|
||||
-ms-font-smoothing: antialiased;
|
||||
font-smoothing: antialiased;
|
||||
}
|
||||
|
||||
button,
|
||||
input[type="checkbox"] {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.visible {
|
||||
display: block !important;
|
||||
}
|
||||
|
||||
#todoapp {
|
||||
background: #fff;
|
||||
margin: 130px 0 40px 0;
|
||||
position: relative;
|
||||
box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2),
|
||||
0 25px 50px 0 rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
#todoapp input::-webkit-input-placeholder {
|
||||
font-style: italic;
|
||||
font-weight: 300;
|
||||
color: #e6e6e6;
|
||||
}
|
||||
|
||||
#todoapp input::-moz-placeholder {
|
||||
font-style: italic;
|
||||
font-weight: 300;
|
||||
color: #e6e6e6;
|
||||
}
|
||||
|
||||
#todoapp input::input-placeholder {
|
||||
font-style: italic;
|
||||
font-weight: 300;
|
||||
color: #e6e6e6;
|
||||
}
|
||||
|
||||
#todoapp h1 {
|
||||
position: absolute;
|
||||
top: -155px;
|
||||
width: 100%;
|
||||
font-size: 100px;
|
||||
font-weight: 100;
|
||||
text-align: center;
|
||||
color: rgba(175, 47, 47, 0.15);
|
||||
-webkit-text-rendering: optimizeLegibility;
|
||||
-moz-text-rendering: optimizeLegibility;
|
||||
-ms-text-rendering: optimizeLegibility;
|
||||
text-rendering: optimizeLegibility;
|
||||
}
|
||||
|
||||
#new-todo,
|
||||
.edit {
|
||||
position: relative;
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
font-size: 24px;
|
||||
font-family: inherit;
|
||||
font-weight: inherit;
|
||||
line-height: 1.4em;
|
||||
border: 0;
|
||||
outline: none;
|
||||
color: inherit;
|
||||
padding: 6px;
|
||||
border: 1px solid #999;
|
||||
box-shadow: inset 0 -1px 5px 0 rgba(0, 0, 0, 0.2);
|
||||
-ms-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-font-smoothing: antialiased;
|
||||
-ms-font-smoothing: antialiased;
|
||||
font-smoothing: antialiased;
|
||||
}
|
||||
|
||||
#new-todo {
|
||||
padding: 16px 16px 16px 60px;
|
||||
border: none;
|
||||
background: rgba(0, 0, 0, 0.003);
|
||||
box-shadow: inset 0 -2px 1px rgba(0,0,0,0.03);
|
||||
}
|
||||
|
||||
#main {
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
border-top: 1px solid #e6e6e6;
|
||||
}
|
||||
|
||||
label[for='toggle-all'] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#toggle-all {
|
||||
position: absolute;
|
||||
top: -55px;
|
||||
left: -12px;
|
||||
width: 60px;
|
||||
height: 34px;
|
||||
text-align: center;
|
||||
border: none; /* Mobile Safari */
|
||||
}
|
||||
|
||||
#toggle-all:before {
|
||||
content: '❯';
|
||||
font-size: 22px;
|
||||
color: #e6e6e6;
|
||||
padding: 10px 27px 10px 27px;
|
||||
}
|
||||
|
||||
#toggle-all:checked:before {
|
||||
color: #737373;
|
||||
}
|
||||
|
||||
#todo-list {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
#todo-list li {
|
||||
position: relative;
|
||||
font-size: 24px;
|
||||
border-bottom: 1px solid #ededed;
|
||||
}
|
||||
|
||||
#todo-list li:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
#todo-list li.editing {
|
||||
border-bottom: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
#todo-list li.editing .edit {
|
||||
display: block;
|
||||
width: 506px;
|
||||
padding: 13px 17px 12px 17px;
|
||||
margin: 0 0 0 43px;
|
||||
}
|
||||
|
||||
#todo-list li.editing .view {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#todo-list li .toggle {
|
||||
text-align: center;
|
||||
width: 40px;
|
||||
/* auto, since non-WebKit browsers doesn't support input styling */
|
||||
height: auto;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
margin: auto 0;
|
||||
border: none; /* Mobile Safari */
|
||||
-webkit-appearance: none;
|
||||
-ms-appearance: none;
|
||||
appearance: none;
|
||||
}
|
||||
|
||||
#todo-list li .toggle:after {
|
||||
content: url('data:image/svg+xml;charset=utf8,<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="-10 -18 100 135"><circle cx="50" cy="50" r="50" fill="none" stroke="#ededed" stroke-width="3"/></svg>');
|
||||
}
|
||||
|
||||
#todo-list li .toggle:checked:after {
|
||||
content: url('data:image/svg+xml;charset=utf8,<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="-10 -18 100 135"><circle cx="50" cy="50" r="50" fill="none" stroke="#bddad5" stroke-width="3"/><path fill="#5dc2af" d="M72 25L42 71 27 56l-4 4 20 20 34-52z"/></svg>');
|
||||
}
|
||||
|
||||
#todo-list li label {
|
||||
white-space: pre;
|
||||
word-break: break-word;
|
||||
padding: 15px 60px 15px 15px;
|
||||
margin-left: 45px;
|
||||
display: block;
|
||||
line-height: 1.2;
|
||||
transition: color 0.4s;
|
||||
}
|
||||
|
||||
#todo-list li.completed label {
|
||||
color: #d9d9d9;
|
||||
text-decoration: line-through;
|
||||
}
|
||||
|
||||
#todo-list li .destroy {
|
||||
display: none;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 10px;
|
||||
bottom: 0;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
margin: auto 0;
|
||||
font-size: 30px;
|
||||
color: #cc9a9a;
|
||||
margin-bottom: 11px;
|
||||
transition: color 0.2s ease-out;
|
||||
}
|
||||
|
||||
#todo-list li .destroy:hover {
|
||||
color: #af5b5e;
|
||||
}
|
||||
|
||||
#todo-list li .destroy:after {
|
||||
content: '×';
|
||||
}
|
||||
|
||||
#todo-list li:hover .destroy {
|
||||
display: block;
|
||||
}
|
||||
|
||||
#todo-list li .edit {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#todo-list li.editing:last-child {
|
||||
margin-bottom: -1px;
|
||||
}
|
||||
|
||||
#footer {
|
||||
color: #777;
|
||||
padding: 10px 15px;
|
||||
height: 20px;
|
||||
text-align: center;
|
||||
border-top: 1px solid #e6e6e6;
|
||||
}
|
||||
|
||||
#footer:before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
height: 50px;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2),
|
||||
0 8px 0 -3px #f6f6f6,
|
||||
0 9px 1px -3px rgba(0, 0, 0, 0.2),
|
||||
0 16px 0 -6px #f6f6f6,
|
||||
0 17px 2px -6px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
#todo-count {
|
||||
float: left;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
#todo-count strong {
|
||||
font-weight: 300;
|
||||
}
|
||||
|
||||
#filters {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
#filters li {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
#filters li a {
|
||||
color: inherit;
|
||||
margin: 3px;
|
||||
padding: 3px 7px;
|
||||
text-decoration: none;
|
||||
border: 1px solid transparent;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
#filters li a.selected,
|
||||
#filters li a:hover {
|
||||
border-color: rgba(175, 47, 47, 0.1);
|
||||
}
|
||||
|
||||
#filters li a.selected {
|
||||
border-color: rgba(175, 47, 47, 0.2);
|
||||
}
|
||||
|
||||
#clear-completed,
|
||||
html #clear-completed:active {
|
||||
float: right;
|
||||
position: relative;
|
||||
line-height: 20px;
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
visibility: hidden;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#clear-completed::after {
|
||||
visibility: visible;
|
||||
content: 'Clear completed';
|
||||
position: absolute;
|
||||
right: 0;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
#clear-completed:hover::after {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
#info {
|
||||
margin: 65px auto 0;
|
||||
color: #bfbfbf;
|
||||
font-size: 10px;
|
||||
text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#info p {
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
#info a {
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
#info a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
/*
|
||||
Hack to remove background from Mobile Safari.
|
||||
Can't use it globally since it destroys checkboxes in Firefox
|
||||
*/
|
||||
@media screen and (-webkit-min-device-pixel-ratio:0) {
|
||||
#toggle-all,
|
||||
#todo-list li .toggle {
|
||||
background: none;
|
||||
}
|
||||
|
||||
#todo-list li .toggle {
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
#toggle-all {
|
||||
-webkit-transform: rotate(90deg);
|
||||
transform: rotate(90deg);
|
||||
-webkit-appearance: none;
|
||||
appearance: none;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 430px) {
|
||||
#footer {
|
||||
height: 50px;
|
||||
}
|
||||
|
||||
#filters {
|
||||
bottom: 10px;
|
||||
}
|
||||
}
|
BIN
modules/playground/src/todo/css/bg.png
Normal file
BIN
modules/playground/src/todo/css/bg.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.1 KiB |
19
modules/playground/src/todo/css/main.css
Normal file
19
modules/playground/src/todo/css/main.css
Normal file
@ -0,0 +1,19 @@
|
||||
html,
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
body {
|
||||
font: 14px 'Helvetica Neue', Helvetica, Arial, sans-serif;
|
||||
line-height: 1.4em;
|
||||
background: #eaeaea;
|
||||
color: #4d4d4d;
|
||||
width: 550px;
|
||||
margin: 0 auto;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-font-smoothing: antialiased;
|
||||
-ms-font-smoothing: antialiased;
|
||||
-o-font-smoothing: antialiased;
|
||||
font-smoothing: antialiased;
|
||||
}
|
13
modules/playground/src/todo/index.html
Normal file
13
modules/playground/src/todo/index.html
Normal file
@ -0,0 +1,13 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<title>Todo Angular 2</title>
|
||||
<link rel="stylesheet" href="css/main.css" media="screen" title="no title" charset="utf-8">
|
||||
<body>
|
||||
<todo-app>
|
||||
Loading...
|
||||
</todo-app>
|
||||
|
||||
|
||||
$SCRIPTS$
|
||||
</body>
|
||||
</html>
|
47
modules/playground/src/todo/index.ts
Normal file
47
modules/playground/src/todo/index.ts
Normal file
@ -0,0 +1,47 @@
|
||||
import {bootstrap} from 'angular2/bootstrap';
|
||||
import {NgFor, Component, View} from 'angular2/core';
|
||||
import {Store, Todo, TodoFactory} from './services/TodoStore';
|
||||
|
||||
@Component({selector: 'todo-app', viewProviders: [Store, TodoFactory]})
|
||||
@View({templateUrl: 'todo.html', directives: [NgFor]})
|
||||
class TodoApp {
|
||||
todoEdit: Todo = null;
|
||||
|
||||
constructor(public todoStore: Store, public factory: TodoFactory) {}
|
||||
|
||||
enterTodo(inputElement): void {
|
||||
this.addTodo(inputElement.value);
|
||||
inputElement.value = '';
|
||||
}
|
||||
|
||||
editTodo(todo: Todo): void { this.todoEdit = todo; }
|
||||
|
||||
doneEditing($event, todo: Todo): void {
|
||||
var which = $event.which;
|
||||
var target = $event.target;
|
||||
if (which === 13) {
|
||||
todo.title = target.value;
|
||||
this.todoEdit = null;
|
||||
} else if (which === 27) {
|
||||
this.todoEdit = null;
|
||||
target.value = todo.title;
|
||||
}
|
||||
}
|
||||
|
||||
addTodo(newTitle: string): void { this.todoStore.add(this.factory.create(newTitle, false)); }
|
||||
|
||||
completeMe(todo: Todo): void { todo.completed = !todo.completed; }
|
||||
|
||||
deleteMe(todo: Todo): void { this.todoStore.remove(todo); }
|
||||
|
||||
toggleAll($event): void {
|
||||
var isComplete = $event.target.checked;
|
||||
this.todoStore.list.forEach((todo: Todo) => { todo.completed = isComplete; });
|
||||
}
|
||||
|
||||
clearCompleted(): void { this.todoStore.removeBy((todo: Todo) => todo.completed); }
|
||||
}
|
||||
|
||||
export function main() {
|
||||
bootstrap(TodoApp);
|
||||
}
|
47
modules/playground/src/todo/services/TodoStore.ts
Normal file
47
modules/playground/src/todo/services/TodoStore.ts
Normal file
@ -0,0 +1,47 @@
|
||||
import {Injectable} from 'angular2/angular2';
|
||||
import {ListWrapper, Predicate} from 'angular2/src/core/facade/collection';
|
||||
|
||||
// base model for RecordStore
|
||||
export class KeyModel {
|
||||
constructor(public key: number) {}
|
||||
}
|
||||
|
||||
export class Todo extends KeyModel {
|
||||
constructor(key: number, public title: string, public completed: boolean) { super(key); }
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class TodoFactory {
|
||||
_uid: number = 0;
|
||||
|
||||
nextUid(): number { return ++this._uid; }
|
||||
|
||||
create(title: string, isCompleted: boolean): Todo {
|
||||
return new Todo(this.nextUid(), title, isCompleted);
|
||||
}
|
||||
}
|
||||
|
||||
// Store manages any generic item that inherits from KeyModel
|
||||
@Injectable()
|
||||
export class Store {
|
||||
list: KeyModel[] = [];
|
||||
|
||||
add(record: KeyModel): void { this.list.push(record); }
|
||||
|
||||
remove(record: KeyModel): void { this._spliceOut(record); }
|
||||
|
||||
removeBy(callback: Predicate<KeyModel>): void {
|
||||
var records = ListWrapper.filter(this.list, callback);
|
||||
ListWrapper.removeAll(this.list, records);
|
||||
}
|
||||
|
||||
private _spliceOut(record: KeyModel) {
|
||||
var i = this._indexFor(record);
|
||||
if (i > -1) {
|
||||
return ListWrapper.splice(this.list, i, 1)[0];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private _indexFor(record: KeyModel) { return this.list.indexOf(record); }
|
||||
}
|
71
modules/playground/src/todo/todo.html
Normal file
71
modules/playground/src/todo/todo.html
Normal file
@ -0,0 +1,71 @@
|
||||
<style>@import "css/base.css";</style>
|
||||
|
||||
<section id="todoapp">
|
||||
|
||||
<header id="header">
|
||||
<h1>todos</h1>
|
||||
<input
|
||||
id="new-todo"
|
||||
placeholder="What needs to be done?"
|
||||
autofocus
|
||||
#newtodo
|
||||
(keyup.enter)="enterTodo(newtodo)">
|
||||
</header>
|
||||
|
||||
<section id="main">
|
||||
<input id="toggle-all" type="checkbox" (click)="toggleAll($event)">
|
||||
<label for="toggle-all">Mark all as complete</label>
|
||||
|
||||
<ul id="todo-list">
|
||||
|
||||
<li *ng-for="#todo of todoStore.list">
|
||||
|
||||
<div class="view"
|
||||
[class.hidden]="todoEdit == todo">
|
||||
|
||||
<input class="toggle" type="checkbox"
|
||||
(click)="completeMe(todo)"
|
||||
[checked]="todo.completed">
|
||||
|
||||
<label (dblclick)="editTodo(todo)">{{todo.title}}</label>
|
||||
<button class="destroy" (click)="deleteMe(todo)"></button>
|
||||
|
||||
</div>
|
||||
|
||||
<div>
|
||||
|
||||
<input class="edit"
|
||||
[class.visible]="todoEdit == todo"
|
||||
[value]="todo.title"
|
||||
(keyup)="doneEditing($event, todo)">
|
||||
|
||||
</div>
|
||||
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
</section>
|
||||
|
||||
<footer id="footer">
|
||||
<span id="todo-count"></span>
|
||||
<div [class.hidden]="true"></div>
|
||||
<ul id="filters">
|
||||
<li>
|
||||
<a href="#/" class="selected">All</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#/active">Active</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#/completed">Completed</a>
|
||||
</li>
|
||||
</ul>
|
||||
<button id="clear-completed" (click)="clearCompleted()">Clear completed</button>
|
||||
</footer>
|
||||
|
||||
</section>
|
||||
|
||||
<footer id="info">
|
||||
<p>Double-click to edit a todo</p>
|
||||
<p>Created by <a href="http://twitter.com/angularjs">The Angular Team</a></p>
|
||||
</footer>
|
4
modules/playground/src/web_workers/images/b64.d.ts
vendored
Normal file
4
modules/playground/src/web_workers/images/b64.d.ts
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
declare module "B64" {
|
||||
export function fromByteArray(arr: Uint8Array): string;
|
||||
export function toByteArray(str: string): Uint8Array;
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
library playground.src.web_workers.images.background_index;
|
||||
|
||||
import "index_common.dart" show ImageDemo;
|
||||
import "dart:isolate";
|
||||
import "package:angular2/src/web_workers/worker/application.dart"
|
||||
show bootstrapWebWorker;
|
||||
import "package:angular2/src/core/reflection/reflection_capabilities.dart";
|
||||
import "package:angular2/src/core/reflection/reflection.dart";
|
||||
|
||||
main(List<String> args, SendPort replyTo) {
|
||||
reflector.reflectionCapabilities = new ReflectionCapabilities();
|
||||
bootstrapWebWorker(replyTo, ImageDemo).catchError((error) => throw error);
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
import {bootstrapWebWorker} from "angular2/src/web_workers/worker/application";
|
||||
import {ImageDemo} from "./index_common";
|
||||
|
||||
export function main() {
|
||||
bootstrapWebWorker(ImageDemo);
|
||||
}
|
8
modules/playground/src/web_workers/images/bitmap.d.ts
vendored
Normal file
8
modules/playground/src/web_workers/images/bitmap.d.ts
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
declare class Bitmap {
|
||||
constructor(width: number, height: number);
|
||||
|
||||
subsample(n: number): void;
|
||||
dataURL(): string;
|
||||
|
||||
pixel:[any];
|
||||
}
|
127
modules/playground/src/web_workers/images/bitmap.js
Normal file
127
modules/playground/src/web_workers/images/bitmap.js
Normal file
@ -0,0 +1,127 @@
|
||||
/*
|
||||
Copyright 2011 Andrey Zholos
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included
|
||||
in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
function Bitmap(width, height) {
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
this.pixel = new Array(width);
|
||||
for (var x = 0; x < width; x++) {
|
||||
this.pixel[x] = new Array(height);
|
||||
for (var y = 0; y < height; y++) this.pixel[x][y] = [0, 0, 0, 0];
|
||||
}
|
||||
}
|
||||
|
||||
Bitmap.prototype.subsample =
|
||||
function(n) {
|
||||
var width = ~~(this.width / n);
|
||||
var height = ~~(this.height / n);
|
||||
var pixel = new Array(width);
|
||||
for (var x = 0; x < width; x++) {
|
||||
pixel[x] = new Array(height);
|
||||
for (var y = 0; y < height; y++) {
|
||||
var q = [0, 0, 0, 0];
|
||||
for (var i = 0; i < n; i++)
|
||||
for (var j = 0; j < n; j++) {
|
||||
var r = this.pixel[x * n + i][y * n + j];
|
||||
q[0] += r[3] * r[0];
|
||||
q[1] += r[3] * r[1];
|
||||
q[2] += r[3] * r[2];
|
||||
q[3] += r[3];
|
||||
}
|
||||
if (q[3]) {
|
||||
q[0] /= q[3];
|
||||
q[1] /= q[3];
|
||||
q[2] /= q[3];
|
||||
q[3] /= n * n;
|
||||
}
|
||||
pixel[x][y] = q;
|
||||
}
|
||||
}
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
this.pixel = pixel;
|
||||
}
|
||||
|
||||
Bitmap.prototype.dataURL = function() {
|
||||
function sample(v) { return ~~(Math.max(0, Math.min(1, v)) * 255); }
|
||||
|
||||
function gamma(v) { return sample(Math.pow(v, .45455)); }
|
||||
|
||||
function row(pixel, width, y) {
|
||||
var data = "\0";
|
||||
for (var x = 0; x < width; x++) {
|
||||
var r = pixel[x][y];
|
||||
data += String.fromCharCode(gamma(r[0]), gamma(r[1]), gamma(r[2]), sample(r[3]));
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
function rows(pixel, width, height) {
|
||||
var data = "";
|
||||
for (var y = 0; y < height; y++) data += row(pixel, width, y);
|
||||
return data;
|
||||
}
|
||||
|
||||
function adler(data) {
|
||||
var s1 = 1, s2 = 0;
|
||||
for (var i = 0; i < data.length; i++) {
|
||||
s1 = (s1 + data.charCodeAt(i)) % 65521;
|
||||
s2 = (s2 + s1) % 65521;
|
||||
}
|
||||
return s2 << 16 | s1;
|
||||
}
|
||||
|
||||
function hton(i) { return String.fromCharCode(i >>> 24, i >>> 16 & 255, i >>> 8 & 255, i & 255); }
|
||||
|
||||
function deflate(data) {
|
||||
var len = data.length;
|
||||
return "\170\1\1" + String.fromCharCode(len & 255, len >>> 8, ~len & 255, (~len >>> 8) & 255) +
|
||||
data + hton(adler(data));
|
||||
}
|
||||
|
||||
function crc32(data) {
|
||||
var c = ~0;
|
||||
for (var i = 0; i < data.length; i++)
|
||||
for (var b = data.charCodeAt(i) | 0x100; b != 1; b >>>= 1)
|
||||
c = (c >>> 1) ^ ((c ^ b) & 1 ? 0xedb88320 : 0);
|
||||
return ~c;
|
||||
}
|
||||
|
||||
function chunk(type, data) { return hton(data.length) + type + data + hton(crc32(type + data)); }
|
||||
|
||||
function base64(data) {
|
||||
enc = "";
|
||||
for (var i = 5, n = data.length * 8 + 5; i < n; i += 6)
|
||||
enc += "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
|
||||
[(data.charCodeAt(~~(i / 8) - 1) << 8 | data.charCodeAt(~~(i / 8))) >> 7 - i % 8 & 63];
|
||||
for (; enc.length % 4; enc += "=")
|
||||
;
|
||||
return enc;
|
||||
}
|
||||
|
||||
var png = "\211PNG\r\n\32\n" +
|
||||
chunk("IHDR", hton(this.width) + hton(this.height) + "\10\6\0\0\0") +
|
||||
chunk("IDAT", deflate(rows(this.pixel, this.width, this.height))) + chunk("IEND", "");
|
||||
|
||||
return "data:image/png;base64," + base64(png);
|
||||
}
|
9
modules/playground/src/web_workers/images/file_api.dart
Normal file
9
modules/playground/src/web_workers/images/file_api.dart
Normal file
@ -0,0 +1,9 @@
|
||||
export 'dart:html' show FileReader;
|
||||
|
||||
import 'dart:typed_data';
|
||||
|
||||
class Uint8ArrayWrapper {
|
||||
static Uint8ClampedList create(ByteBuffer buffer) {
|
||||
return new Uint8ClampedList.view(buffer);
|
||||
}
|
||||
}
|
6
modules/playground/src/web_workers/images/file_api.ts
Normal file
6
modules/playground/src/web_workers/images/file_api.ts
Normal file
@ -0,0 +1,6 @@
|
||||
var _FileReader = FileReader;
|
||||
export {_FileReader as FileReader};
|
||||
|
||||
export class Uint8ArrayWrapper {
|
||||
static create(buffer: ArrayBuffer) { return new Uint8Array(buffer); }
|
||||
}
|
30
modules/playground/src/web_workers/images/image_demo.css
Normal file
30
modules/playground/src/web_workers/images/image_demo.css
Normal file
@ -0,0 +1,30 @@
|
||||
.hidden{
|
||||
display: none !important;
|
||||
}
|
||||
#images {
|
||||
width: 600px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
ul li {
|
||||
list-style-type: none;
|
||||
float: left;
|
||||
margin-left: 20px;
|
||||
width: 200px;
|
||||
}
|
||||
#main ul {
|
||||
width: 700px;
|
||||
}
|
||||
.card-image .image-loader{
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.card-image img.grey {
|
||||
opacity: 0.4;
|
||||
}
|
||||
|
||||
.fixed-action-btn.bottom {
|
||||
bottom: 45px;
|
||||
right: 24px;
|
||||
}
|
33
modules/playground/src/web_workers/images/image_demo.html
Normal file
33
modules/playground/src/web_workers/images/image_demo.html
Normal file
@ -0,0 +1,33 @@
|
||||
<nav class="blue">
|
||||
<div class="container">
|
||||
<div class="nav-wrapper">
|
||||
<a class="brand-logo">Angular 2 Image Demo</a>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
<section id="main" class="container">
|
||||
<div class="row">
|
||||
<div *ng-for="#image of images" class="col s12 m2">
|
||||
<div class="card">
|
||||
<div class="card-image">
|
||||
<img [src]="image.src" [class.grey]="image.filtering"/>
|
||||
<div class="image-loader progress" [class.hidden]="!image.filtering">
|
||||
<div class="indeterminate"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="fixed-action-btn bottom" (click)="applyFilters()">
|
||||
<a class="btn-floating btn-large blue darken-4" (click)="applyFilters()">
|
||||
<i class="large material-icons" (click)="applyFilters()">invert_colors</i>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="file-field">
|
||||
<div class="btn blue darken-2">
|
||||
<span>Select Images</span>
|
||||
<input type="file" accept="image/bmp" multiple (change)="uploadFiles($event.target.files)" />
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
10
modules/playground/src/web_workers/images/index.dart
Normal file
10
modules/playground/src/web_workers/images/index.dart
Normal file
@ -0,0 +1,10 @@
|
||||
library angular2.examples.web_workers.images.index;
|
||||
|
||||
import "package:angular2/src/web_workers/ui/application.dart" show bootstrap;
|
||||
import "package:angular2/src/core/reflection/reflection_capabilities.dart";
|
||||
import "package:angular2/src/core/reflection/reflection.dart";
|
||||
|
||||
main() {
|
||||
reflector.reflectionCapabilities = new ReflectionCapabilities();
|
||||
bootstrap("background_index.dart");
|
||||
}
|
18
modules/playground/src/web_workers/images/index.html
Normal file
18
modules/playground/src/web_workers/images/index.html
Normal file
@ -0,0 +1,18 @@
|
||||
<html>
|
||||
<head>
|
||||
<link rel="stylesheet" href="image_demo.css" />
|
||||
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
|
||||
</head>
|
||||
<body>
|
||||
<image-demo>
|
||||
</image-demo>
|
||||
|
||||
$SCRIPTS$
|
||||
<!-- Compiled and minified CSS -->
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.97.0/css/materialize.min.css">
|
||||
|
||||
<!-- Compiled and minified JavaScript -->
|
||||
<script type="text/javascript" src="https://code.jquery.com/jquery-2.1.1.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.97.0/js/materialize.min.js"></script>
|
||||
</body>
|
||||
</html>
|
2
modules/playground/src/web_workers/images/index.ts
Normal file
2
modules/playground/src/web_workers/images/index.ts
Normal file
@ -0,0 +1,2 @@
|
||||
import {bootstrap} from "angular2/src/web_workers/ui/application";
|
||||
bootstrap("loader.js");
|
50
modules/playground/src/web_workers/images/index_common.ts
Normal file
50
modules/playground/src/web_workers/images/index_common.ts
Normal file
@ -0,0 +1,50 @@
|
||||
import {NgZone, NgFor, Component, View, NgIf, FORM_DIRECTIVES} from 'angular2/angular2';
|
||||
import {BitmapService} from './services/bitmap';
|
||||
import {EventListener} from 'angular2/src/core/facade/browser';
|
||||
import {FileReader, Uint8ArrayWrapper} from './file_api';
|
||||
import {TimerWrapper} from 'angular2/src/core/facade/async';
|
||||
|
||||
@Component({selector: 'image-demo', viewProviders: [BitmapService]})
|
||||
@View({templateUrl: 'image_demo.html', directives: [NgFor, NgIf, FORM_DIRECTIVES]})
|
||||
export class ImageDemo {
|
||||
images = [];
|
||||
fileInput: String;
|
||||
|
||||
constructor(private _bitmapService: BitmapService) {}
|
||||
|
||||
uploadFiles(files) {
|
||||
for (var i = 0; i < files.length; i++) {
|
||||
var reader = new FileReader();
|
||||
reader.addEventListener("load", this.handleReaderLoad(reader));
|
||||
reader.readAsArrayBuffer(files[i]);
|
||||
}
|
||||
}
|
||||
|
||||
handleReaderLoad(reader: FileReader): EventListener {
|
||||
return (e) => {
|
||||
var buffer = reader.result;
|
||||
this.images.push({
|
||||
src: this._bitmapService.arrayBufferToDataUri(Uint8ArrayWrapper.create(reader.result)),
|
||||
buffer: buffer,
|
||||
filtering: false
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
applyFilters() {
|
||||
for (var i = 0; i < this.images.length; i++) {
|
||||
this.images[i].filtering = true;
|
||||
|
||||
TimerWrapper.setTimeout(this._filter(i), 0);
|
||||
}
|
||||
}
|
||||
|
||||
private _filter(i: number): (...args: any[]) => void {
|
||||
return () => {
|
||||
var imageData = this._bitmapService.convertToImageData(this.images[i].buffer);
|
||||
imageData = this._bitmapService.applySepia(imageData);
|
||||
this.images[i].src = this._bitmapService.toDataUri(imageData);
|
||||
this.images[i].filtering = false;
|
||||
};
|
||||
}
|
||||
}
|
71
modules/playground/src/web_workers/images/loader.css
Normal file
71
modules/playground/src/web_workers/images/loader.css
Normal file
@ -0,0 +1,71 @@
|
||||
body {
|
||||
background: #eaecfa;
|
||||
}
|
||||
|
||||
.loader {
|
||||
width: 250px;
|
||||
height: 50px;
|
||||
line-height: 50px;
|
||||
text-align: center;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
-webkit-transform: translate(-50%, -50%);
|
||||
-ms-transform: translate(-50%, -50%);
|
||||
transform: translate(-50%, -50%);
|
||||
font-family: helvetica, arial, sans-serif;
|
||||
text-transform: uppercase;
|
||||
font-weight: 900;
|
||||
color: #ce4233;
|
||||
letter-spacing: 0.2em;
|
||||
}
|
||||
.loader::before, .loader::after {
|
||||
content: "";
|
||||
display: block;
|
||||
width: 15px;
|
||||
height: 15px;
|
||||
background: #ce4233;
|
||||
position: absolute;
|
||||
-webkit-animation: load .7s infinite alternate ease-in-out;
|
||||
animation: load .7s infinite alternate ease-in-out;
|
||||
}
|
||||
.loader::before {
|
||||
top: 0;
|
||||
}
|
||||
.loader::after {
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
@-webkit-keyframes load {
|
||||
0% {
|
||||
left: 0;
|
||||
height: 30px;
|
||||
width: 15px;
|
||||
}
|
||||
50% {
|
||||
height: 8px;
|
||||
width: 40px;
|
||||
}
|
||||
100% {
|
||||
left: 235px;
|
||||
height: 30px;
|
||||
width: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes load {
|
||||
0% {
|
||||
left: 0;
|
||||
height: 30px;
|
||||
width: 15px;
|
||||
}
|
||||
50% {
|
||||
height: 8px;
|
||||
width: 40px;
|
||||
}
|
||||
100% {
|
||||
left: 235px;
|
||||
height: 30px;
|
||||
width: 15px;
|
||||
}
|
||||
}
|
20
modules/playground/src/web_workers/images/loader.js
Normal file
20
modules/playground/src/web_workers/images/loader.js
Normal file
@ -0,0 +1,20 @@
|
||||
$SCRIPTS$
|
||||
importScripts("b64.js");
|
||||
|
||||
|
||||
System.config({
|
||||
baseURL: '/',
|
||||
defaultJSExtensions: true
|
||||
});
|
||||
|
||||
System.import("playground/src/web_workers/images/background_index")
|
||||
.then(
|
||||
function(m) {
|
||||
console.log("running main");
|
||||
try {
|
||||
m.main();
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
},
|
||||
function(error) { console.error("error loading background", error); });
|
@ -0,0 +1,23 @@
|
||||
library angular2.examples.web_workers.images.bitmap_service;
|
||||
|
||||
import 'dart:html';
|
||||
import 'dart:typed_data';
|
||||
|
||||
// TODO(jteplitz602) Implement this class #3493
|
||||
class BitmapService {
|
||||
ImageData applySepia(ImageData imageData) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String arrayBufferToDataUri(Uint8ClampedList data) {
|
||||
return null;
|
||||
}
|
||||
|
||||
ImageData convertToImageData(ByteBuffer buffer) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String toDataUri(ImageData imageData) {
|
||||
return null;
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user