<!DOCTYPE html>
<html>
<head>
<base href="." />
<title>angular2 playground</title>
<link rel="stylesheet" href="style.css" />
<script src="https://unpkg.com/zone.js/dist/zone.js"></script>
<script src="https://unpkg.com/zone.js/dist/long-stack-trace-zone.js"></script>
<script src="https://unpkg.com/reflect-metadata@0.1.3/Reflect.js"></script>
<script src="https://unpkg.com/systemjs@0.19.31/dist/system.js"></script>
<script src="config.js"></script>
<script>
System.import('app')
.catch(console.error.bind(console));
</script>
</head>
<body>
<my-app>
loading...
</my-app>
</body>
</html>
/* Styles go here */
### Angular Starter Plunker - Typescript
System.config({
//use typescript for compilation
transpiler: 'typescript',
//typescript compiler options
typescriptOptions: {
emitDecoratorMetadata: true
},
paths: {
'npm:': 'https://unpkg.com/'
},
//map tells the System loader where to look for things
map: {
'app': './src',
'@angular/core': 'npm:@angular/core/bundles/core.umd.js',
'@angular/common': 'npm:@angular/common/bundles/common.umd.js',
'@angular/compiler': 'npm:@angular/compiler/bundles/compiler.umd.js',
'@angular/platform-browser': 'npm:@angular/platform-browser/bundles/platform-browser.umd.js',
'@angular/platform-browser-dynamic': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js',
'@angular/http': 'npm:@angular/http/bundles/http.umd.js',
'@angular/router': 'npm:@angular/router/bundles/router.umd.js',
'@angular/forms': 'npm:@angular/forms/bundles/forms.umd.js',
'@angular/core/testing': 'npm:@angular/core/bundles/core-testing.umd.js',
'@angular/common/testing': 'npm:@angular/common/bundles/common-testing.umd.js',
'@angular/compiler/testing': 'npm:@angular/compiler/bundles/compiler-testing.umd.js',
'@angular/platform-browser/testing': 'npm:@angular/platform-browser/bundles/platform-browser-testing.umd.js',
'@angular/platform-browser-dynamic/testing': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic-testing.umd.js',
'@angular/http/testing': 'npm:@angular/http/bundles/http-testing.umd.js',
'@angular/router/testing': 'npm:@angular/router/bundles/router-testing.umd.js',
'rxjs': 'npm:rxjs',
'typescript': 'npm:typescript@2.0.2/lib/typescript.js'
},
//packages defines our app package
packages: {
app: {
main: './main.ts',
defaultExtension: 'ts'
},
rxjs: {
defaultExtension: 'js'
}
}
});
//main entry point
import {platformBrowserDynamic} from '@angular/platform-browser-dynamic';
import {AppModule} from './app';
platformBrowserDynamic().bootstrapModule(AppModule)
//our root app component
import { Component, NgModule } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { RouterModule } from '@angular/router';
import { StopWatchModule } from './stopwatch/stopwatch'
@Component({
selector: 'my-app',
template: `
<div>
<a href="" [routerLink]="['']">Page 1</a>
<a href="" [routerLink]="['page2']">Page 2</a>
<router-outlet></router-outlet>
</div>
`,
})
export class App {
name:string;
constructor() {
this.name = 'Angular2'
}
}
@Component({
selector: 'page-one',
template: `
<div>
<h1>Page 1</h1>
<stopwatch></stopwatch>
</div>
`,
})
export class AppPageOne {
}
@Component({
selector: 'page-two',
template: `
<div>
<h1>Page 2</h1>
<stopwatch></stopwatch>
</div>
`,
})
export class AppPageTwo {
}
@NgModule({
imports: [
RouterModule.forRoot([
{ path: '', component: AppPageOne },
{ path: 'page2', component: AppPageTwo },
])
],
exports: [
RouterModule
]
})
export class AppRoutingModule {}
@NgModule({
imports: [
BrowserModule,
RouterModule,
AppRoutingModule,
StopWatchModule.forRoot()
],
declarations: [ App, AppPageOne, AppPageTwo ],
bootstrap: [ App ]
})
export class AppModule {}
import {Injectable} from '@angular/core';
@Injectable()
export class StopWatchService {
public laps: Lap[];
private startAt: number;
private lapTime: number;
constructor() {
this.reset();
}
lap() {
let timeMs = this.startAt
? this.lapTime + this.now() - this.startAt
: this.lapTime;
this.laps[this.laps.length - 1].stop(timeMs);
this.laps.push(new Lap(timeMs));
}
now() {
return _now();
}
reset() {
this.startAt = 0;
this.lapTime = 0;
this.laps = new Array<Lap>();
this.laps.push(new Lap(0));
}
start() {
this.startAt = this.startAt
? this.startAt
: this.now();
}
stop() {
let timeMs = this.startAt
? this.lapTime + this.now() - this.startAt
: this.lapTime;
this.lapTime = timeMs;
this.laps[this.laps.length - 1].stop(timeMs);
this.startAt = 0;
}
time() {
return this.lapTime
+ (this.startAt ? this.now() - this.startAt : 0);
}
}
export class Lap {
public startMs: number;
public endMs: number;
constructor(startMs: number) {
this.startMs = startMs;
this.endMs = 0;
}
stop(timeMs: number) {
this.endMs = timeMs;
}
}
function _now() {
return (new Date()).getTime();
}
import { Component, NgModule, Input } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { StopWatchService } from './stopwatch.service';
@Component({
selector: 'stopwatch',
template:
`
<div class="container">
<h1>{{ formatTime(time) }}</h1>
<div class="btn-group">
<button (click)="toggle()">
<span *ngIf="!started">Start</span>
<span *ngIf="started">Pause</span>
</button>
<button (click)="reset()">Reset</button>
<button (click)="lap()">Split</button>
</div>
<div class="laps"
*ngIf="stopwatchService.laps.length > 1">
<div class="lap"
*ngFor="let lap of stopwatchService.laps; let i = index; let last = last;">
<div>Round {{ i }}</div>
<div>{{ formatTime(lap.startMs) }}</div>
<div *ngIf="last">{{ formatTime(time) }}</div>
<div *ngIf="!last">{{ formatTime(lap.endMs) }}</div>
</div>
</div>
</div>
`,
styleUrls: ['./src/stopwatch/stopwatch.css']
})
export class StopWatchComponent {
public started: boolean;
//public stopwatchService: StopWatchService;
public time: number;
public autoStart: boolean = true;
private timer: any;
constructor(public stopwatchService: StopWatchService) {
this.stopwatchService = stopwatchService;
this.time = 0;
this.started = false;
if (this.autoStart) {
this.start();
}
}
formatTime(timeMs: number) {
let minutes: string,
seconds: string;
minutes = Math.floor(timeMs / 60000).toString();
seconds = ((timeMs % 60000) / 1000).toFixed(3);
return minutes + ':' + (+seconds < 10 ? '0' : '') + seconds;
}
getUpdate() {
let self = this;
return () => {
self.time = this.stopwatchService.time();
};
}
lap() {
this.update();
if (this.time) {
this.stopwatchService.lap();
}
}
reset() {
this.stopwatchService.reset();
this.started = false;
this.update();
}
start() {
this.timer = setInterval(this.getUpdate(), 1);
this.stopwatchService.start();
}
stop() {
clearInterval(this.timer);
this.stopwatchService.stop();
}
toggle() {
if (this.started) {
this.stop();
} else {
this.start();
}
this.started = !this.started;
}
update() {
this.time = this.stopwatchService.time();
}
onClick() {
console.log(this.stopwatchService);
}
}
@NgModule({
imports: [BrowserModule],
exports: [StopWatchComponent],
declarations: [StopWatchComponent]
})
export class StopWatchModule {
static forRoot(): ModuleWithProviders {
return {
ngModule: StopWatchModule,
providers: [StopWatchService],
};
}
}
.container {
background-color: #ecf0f1;
font-family: 'Roboto', sans-serif;
margin: 1em auto 1em auto;
-webkit-border-radius: 8px;
-moz-border-radius: 8px;
-ms-border-radius: 8px;
-o-border-radius: 8px;
border-radius: 8px;
padding-top: 1.5em;
-webkit-box-shadow: #bdc3c7 0 5px 5px;
-moz-box-shadow: #bdc3c7 0 5px 5px;
box-shadow: #bdc3c7 0 5px 5px;
}
.container h1 {
text-align: center;
font-weight: 500;
font-size: 80px;
}
@media (min-width: 768px) {
.container {
width: 750px;
}
.container h1 {
font-size: 150px;
}
}
@media (min-width: 992px) {
.container {
width: 970px;
}
.container h1 {
font-size: 200px;
}
}
@media (min-width: 1200px) {
.container {
width: 1170px;
}
}
.btn-group {
font-size: 0;
line-height: 1;
white-space: nowrap;
display: inline;
}
.btn-group button {
width: 33%;
text-decoration: none;
text-transform: uppercase;
font-family: 'Roboto', sans-serif;
font-weight: 400;
font-size: 40px;
background: #34495e;
color: #fff;
border: 1px solid #bdc3c7;
border-left-width: 0;
display: inline-block;
padding: 0.25em 1.25em;
outline: 0;
}
.btn-group button:last-child {
border-right-width: 0;
width: 34%;
}
.btn-group button:first-child {
border-radius: 0 0 0 8px;
}
.btn-group button:last-child {
border-radius: 0 0 8px 0;
}
.btn-group button:active {
background: transparent;
color: #4d4d4d;
}
.laps {
padding: 10px;
}
.lap {
padding: 10px;
display: flex;
justify-content: space-around;
}