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