<!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;
}