<!DOCTYPE html>
<html>

  <head>
    <title>Angular 2 Wikipedia Demo</title>
    <script src="https://code.angularjs.org/tools/system.js"></script>
    <script src="https://code.angularjs.org/tools/typescript.js"></script>
    <script src="config.js"></script>
    <script src="https://code.angularjs.org/2.0.0-beta.6/Rx.min.js"></script>
    <script src="https://code.angularjs.org/2.0.0-beta.6/angular2-polyfills.min.js"></script>
    <script src="https://code.angularjs.org/2.0.0-beta.6/angular2.js"></script>
    <script src="https://code.angularjs.org/2.0.0-beta.6/http.min.js"></script>
    <script src="https://code.angularjs.org/2.0.0-beta.6/testing.dev.js"></script>
    
    <script src="https://cdnjs.cloudflare.com/ajax/libs/ng2-bootstrap/1.0.3/ng2-bootstrap.min.js"></script>
    <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet">
    <link href="style.css" rel="stylesheet" />
    
    <script>
      System
        .import('app')
        .catch(console.error.bind(console));
    </script>
  </head>

  <body>
    <my-app>
      <div id="container">
        <div class="box">Loading...</div>
        <div class="box">
          <img src="https://media.giphy.com/media/sIIhZliB2McAo/giphy.gif" />
        </div>
      </div>
    </my-app>
  </body>

</html>
System.config({
  //use typescript for compilation
  transpiler: 'typescript',
  //typescript compiler options
  typescriptOptions: {
    emitDecoratorMetadata: true
  },
  //map tells the System loader where to look for things
  map: {
    app: "./src"
  },
  //packages defines our app package
  packages: {
    app: {
      main: './main.ts',
      defaultExtension: 'ts'
    }
  }
});
import {Component} from 'angular2/core';
import {Control} from 'angular2/common';
import {URLSearchParams, Jsonp, JSONP_PROVIDERS} from 'angular2/http';

//import all
import 'rxjs/Rx';
/*
//cherry pick
import {Observable} from 'rxjs/Observable';
import 'rxjs/add/operator/filter';
import 'rxjs/add/operator/debounceTime';
import 'rxjs/add/operator/distinctUntilChanged';
import 'rxjs/add/operator/mergeMap';
import 'rxjs/add/operator/switchMap';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/retryWhen';
import 'rxjs/add/operator/delay';
*/

@Component({
  selector: 'my-app'
  template: `
    <div>
      <h1>Wikipedia Search</h1>
      <input class="form-control" type="text" [ngFormControl]="search">
      <div class="list" [style.display]="hasResults?'block':'none'"> 
        <ul>
          <li *ngFor="#result of results | async" class="result" (click)="open(result.url)">
            {{result.title}}
          </li>
        </ul>
      <div>
    </div>`,
    providers: [JSONP_PROVIDERS]
})
export class App {
  private WIKIPEDIA_URL = 'http://en.wikipedia.org/w/api.php?callback=JSONP_CALLBACK';
  private search = new Control();
  private hasResults = false;
  
  constructor(jsonp: Jsonp) {
    //slow down calls          .debounceTime(2000)
    //avoid same requests      .distinctUntilChanged()
    //cancel pending requests  .switchMap
    //retry if fails           .retryWhen(errors => errors.delay(5000))

    this.results = this.search.valueChanges
      .debounceTime(200)
      .distinctUntilChanged()
      .switchMap(term => { 
                                                                                      console.log(`Querying [${term}]...`);
        return jsonp
          .get(this.WIKIPEDIA_URL, searchParams(term))
          .retryWhen( errors => errors.delay(3000) )
          .map(response => {
            var results = formatResults(response);
                                                                                      this.hasResults = results.length>0;
                                                                                      console.log(`> Results for [${term}]: ${results.length}`);
            return results;
          });
      });
      
      function searchParams(term) {
        var params = new URLSearchParams();
        params.append('action', 'opensearch');
        params.append('search', encodeURI(term));
        params.append('format', 'json');
        return {
          search: params
        };
      }
      
      function formatResults(response){
        var results = response.json();
        return results[1].map( (value, index) => 
            ({ 
              title: value,
              url: results[3][index]
            })
          );
      }
  }
  
  private open(url){
    window.open(url, '_blank');
  }
}
//main entry point
import {bootstrap} from 'angular2/platform/browser';
import {enableProdMode} from "angular2/core";
import {App} from './app';

enableProdMode();

setTimeout(function() {
  bootstrap(App, [])
    .catch(err => console.error(err));
}, 1000);
@import url(https://fonts.googleapis.com/css?family=Ubuntu:500);
@import url(https://fonts.googleapis.com/css?family=Ubuntu+Mono);

body {
  margin: 15px;
  font-family: "Ubuntu";
}

a:link,
a:visited {
  border: none;
  color: rgb(255, 0, 100);
  text-decoration: none;
}

#container {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
}

.box {
  width: 300px;
  margin: 5px;
  text-align: center;
}

ul {
  list-style-type: none;
  padding: 0;
}

.list {
  max-height: 150px;
  width: 100%;
  overflow-y: auto;
  background-color: #fff;
  border: 1px solid #eee;
}

.result {
  padding: 10px;
  cursor: pointer;
}

.result:hover,
.result:hover a {
  background-color: rgb(255, 0, 100);
  color: #fff;
  text-decoration: none;
}