Last active
October 30, 2018 12:23
-
-
Save johnlindquist/3682134ab53c08b809fd789dcb319df9 to your computer and use it in GitHub Desktop.
Angular 2 Wikipedia Image Search
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
SystemJS.config({ | |
transpiler: "typescript", | |
typescriptOptions: { | |
"experimentalDecorators": true, | |
"emitDecoratorMetadata": true | |
}, | |
map: { | |
"rxjs": "https://npmcdn.com/[email protected]", | |
"angular2": "https://npmcdn.com/[email protected]", | |
"typescript": "https://npmcdn.com/[email protected]/lib/typescript.js" | |
}, | |
packages: { | |
"rxjs": { "defaultExtension": "js" }, | |
"angular2": { "defaultExtension": "js" }, | |
"@ngrx/store":{ | |
"main":"dist/index.js" | |
}, | |
"src": { "defaultExtension": "ts" }, | |
"build": { "defaultExtension": "ts" } | |
} | |
}); | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<title>Angular 2 App</title> | |
<script src="https://npmcdn.com/angular2/bundles/angular2-polyfills.js"></script> | |
<script src="https://npmcdn.com/systemjs/dist/system.js"></script> | |
<link rel="stylesheet" type="text/css" href="style.css"> | |
</head> | |
<body> | |
<app></app> | |
<script src="config.js"></script> | |
<script>System.import('src/main');</script> | |
</body> | |
</html> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import {Component} from 'angular2/core'; | |
import 'rxjs/add/operator/map'; | |
import 'rxjs/add/operator/do'; | |
import 'rxjs/add/operator/concatAll'; | |
import 'rxjs/add/operator/mergeMap'; | |
import 'rxjs/add/operator/scan'; | |
import 'rxjs/add/operator/filter'; | |
import 'rxjs/add/operator/debounceTime'; | |
import 'rxjs/add/operator/reduce'; | |
import 'rxjs/add/operator/startWith'; | |
import 'rxjs/add/operator/share'; | |
import 'rxjs/add/operator/distinctUntilChanged'; | |
import 'rxjs/add/operator/combineLatest'; | |
import 'rxjs/add/operator/withLatestFrom'; | |
import 'rxjs/add/operator/switchMap'; | |
import 'rxjs/add/operator/concat'; | |
import 'rxjs/add/operator/takeUntil'; | |
import 'rxjs/add/operator/race'; | |
import 'rxjs/add/operator/mapTo'; | |
import 'rxjs/add/observable/bindCallback'; | |
import 'rxjs/add/observable/merge'; | |
import {JSONP_PROVIDERS, HTTP_PROVIDERS, Http, Jsonp} from 'angular2/http'; | |
import {Subject} from 'rxjs/Subject'; | |
import {BehaviorSubject} from 'rxjs/BehaviorSubject'; | |
import {WikipediaService} from './services/wikipedia.service'; | |
import {Observable} from 'rxjs/Observable'; | |
@Component({ | |
selector: 'app', | |
providers: [HTTP_PROVIDERS, JSONP_PROVIDERS, WikipediaService] | |
template: ` | |
<style> | |
.container{ | |
width: 350px; | |
} | |
img{ | |
width: 90px; | |
border: 5px solid black; | |
} | |
img:hover { | |
width: 90px; | |
border: 5px solid gray; | |
} | |
</style> | |
<div> | |
<h2>Search: {{(searchTerm$ | async)}}</h2> | |
<input type="text" (input)="input$.next($event)"> | |
<h3>{{imageCount$ | async}} results</h3> | |
<div class="container"> | |
<a *ngFor="#image of images$ | async" [href]="image.descriptionurl"> | |
<img [src]="image.url" alt=""> | |
</a> | |
</div> | |
</div> | |
` | |
}) | |
export class App { | |
input$ = new Subject().map(event => event.target.value); | |
searchTerm$; | |
images$; | |
imageCount$; | |
constructor(wikipediaService:WikipediaService) { | |
this.searchTerm$ = this.input$ | |
.distinctUntilChanged() | |
.debounceTime(500) | |
.filter(term => term.length > 0) | |
.share(); | |
this.images$ = this.searchTerm$ | |
.switchMap(term=> wikipediaService.searchAllImages(term) | |
.map(wikipediaService.mapAllImagesToTitles) | |
.concatAll() | |
.mergeMap(wikipediaService.getImageInfoFromTitle) | |
.map(wikipediaService.mapImageInfoToUrls) | |
.scan((acc, curr)=> [...acc, ...curr]) | |
) | |
.startWith([]) | |
.share() | |
this.imageCount$ = this.images$ | |
.map(results => results.length) | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import {enableProdMode} from 'angular2/core'; | |
import {bootstrap} from 'angular2/platform/browser'; | |
import {App} from './app'; | |
enableProdMode(); | |
bootstrap(App) | |
.catch(console.log.bind(console)); | |
console.clear(); | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import {Injectable} from 'angular2/core'; | |
import {Jsonp} from 'angular2/http'; | |
const CALLBACK = 'callback=JSONP_CALLBACK'; | |
const WIKIPEDIA = 'https://en.wikipedia.org/w/api.php'; | |
const QUERY = 'action=query'; | |
const JSON = 'format=json'; | |
const ALLIMAGES = 'list=allimages'; | |
const IMAGEINFO = 'prop=imageinfo'; | |
const API = `${WIKIPEDIA}?${QUERY}&${JSON}&${CALLBACK}&${ALLIMAGES}`; | |
const PROP_URL = 'iiprop=url'; | |
@Injectable() | |
export class WikipediaService{ | |
constructor(private _jsonp:Jsonp){} | |
searchAllImages = term => this._jsonp.get(`${API}&${ALLIMAGES}&aifrom=${term}`) | |
.map(res => res.json()); | |
mapAllImagesToTitles = allImages => allImages.query.allimages.map(({title}) => title); | |
getImageInfoFromTitle= title => this._jsonp.get(`${API}&${IMAGEINFO}&${PROP_URL}&titles=${title}`) | |
.map(res => res.json()); | |
mapImageInfoToUrls = body => Object.keys(body.query.pages) | |
.filter(page => page > 0) //page -1 means no images | |
.map(page =>{ | |
return body.query.pages[page].imageinfo[0]; | |
}); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* Styles go here */ | |
body{ | |
font-family: sans-serif; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment