├── .gitignore ├── .vscode └── settings.json ├── README.md ├── index.html ├── package.json ├── screenshot.png ├── src ├── all-the-things.css ├── app │ ├── app.component.html │ ├── app.component.ts │ ├── subscription.component.html │ └── subscription.component.ts ├── img │ ├── pusher-logo.png │ ├── pusher.png │ └── twitter.png └── style.css ├── tsconfig.json └── typings.json /.gitignore: -------------------------------------------------------------------------------- 1 | src/app/*.js 2 | src/app/*.js.map 3 | node_modules 4 | typings 5 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | // Place your settings in this file to overwrite default and user settings. 2 | { 3 | "files.exclude": { 4 | "**/.git": true, 5 | "**/.svn": true, 6 | "**/.DS_Store": true, 7 | "**/*.js": true 8 | } 9 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Angular 2 and Pusher 2 | 3 | A client of the [Pusher Datasource API](https://github.com/pusher-community/pusher-datasource-api) that lets you search for tweets and view the results in realtime. 4 | 5 | ![](./screenshot.png) 6 | 7 | ## Running 8 | 9 | ``` 10 | $ npm install 11 | ``` 12 | 13 | You need to run two processes separately. The first will compile your TypeScript: 14 | 15 | ``` 16 | $ npm run tsc 17 | ``` 18 | 19 | To run the app locally with live reload enabled, use `npm start`: 20 | 21 | ``` 22 | $ npm start 23 | ``` 24 | 25 | This will run the app on port 8080 and open a new browser tab. 26 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Angular 2 QuickStart 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 55 | 56 | 57 | 76 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angular-pusher-datasource", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "tsc": "tsc", 8 | "start": "npm run tsc && live-server --open=/", 9 | "postinstall": "typings install" 10 | }, 11 | "keywords": [], 12 | "author": "", 13 | "license": "ISC", 14 | "dependencies": { 15 | "@angular/common": "2.0.0-rc.1", 16 | "@angular/compiler": "2.0.0-rc.1", 17 | "@angular/core": "2.0.0-rc.1", 18 | "@angular/http": "2.0.0-rc.1", 19 | "@angular/platform-browser": "2.0.0-rc.1", 20 | "@angular/platform-browser-dynamic": "2.0.0-rc.1", 21 | "@angular/router": "2.0.0-rc.1", 22 | "es6-shim": "0.35.0", 23 | "reflect-metadata": "0.1.2", 24 | "rxjs": "5.0.0-beta.6", 25 | "systemjs": "0.19.26", 26 | "zone.js": "^0.6.12" 27 | }, 28 | "devDependencies": { 29 | "live-server": "^0.8.2", 30 | "typescript": "^1.6.2", 31 | "typings": "^0.8.1" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pusher-community/realtime-twitter-search-angular2/330b7e07e171a07517ca98d7938095b48983e79c/screenshot.png -------------------------------------------------------------------------------- /src/app/app.component.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |

5 | Pusher Angular Realtime Demo 6 |

7 | 8 |

9 | Displaying live tweets using Pusher and Angular 2. 10 |

11 | 12 |
13 |
14 | 15 | 16 |
17 |
18 |
19 |
20 | 21 |
22 |
23 |
24 |
25 |

26 | 27 | Tweets for {{ channel.term }} 28 |

29 |
30 | 33 | 36 |
37 | 38 |
39 |
40 |
41 |
42 | 43 | 44 |
45 | -------------------------------------------------------------------------------- /src/app/app.component.ts: -------------------------------------------------------------------------------- 1 | declare var Pusher: any; 2 | 3 | import {bootstrap} from '@angular/platform-browser-dynamic'; 4 | import {Component} from '@angular/core'; 5 | 6 | import SubscriptionComponent from './subscription.component'; 7 | 8 | @Component({ 9 | moduleId: module.id, 10 | selector: 'my-app', 11 | templateUrl: 'app.component.html', 12 | directives: [SubscriptionComponent], 13 | }) 14 | class AppComponent { 15 | private newSearchTerm: string; 16 | private pusher; 17 | private channels: any[]; 18 | 19 | constructor() { 20 | this.pusher = new Pusher('9fd1b33fcb36d968145f'); 21 | this.channels = []; 22 | } 23 | 24 | public newSubscription() { 25 | this.channels.push({term: this.newSearchTerm, active: true}); 26 | this.newSearchTerm = ''; 27 | } 28 | 29 | public clearSearch(channel) { 30 | this.channels = this.channels.filter((ch) => { 31 | if (ch.term === channel.term) { 32 | this.toggleSearch(channel); 33 | } 34 | return ch.term !== channel.term; 35 | }); 36 | } 37 | public toggleSearch(channel) { 38 | for (let ch of this.channels) { 39 | if (ch.term === channel.term) { 40 | ch.active = !ch.active; 41 | break; 42 | } 43 | } 44 | } 45 | } 46 | 47 | bootstrap(AppComponent); 48 | -------------------------------------------------------------------------------- /src/app/subscription.component.html: -------------------------------------------------------------------------------- 1 | 6 | -------------------------------------------------------------------------------- /src/app/subscription.component.ts: -------------------------------------------------------------------------------- 1 | import { 2 | Component, 3 | Input, 4 | AfterViewChecked, 5 | OnInit, 6 | OnChanges, 7 | OnDestroy 8 | } from '@angular/core'; 9 | 10 | @Component({ 11 | moduleId: module.id, 12 | selector: 'subscription', 13 | templateUrl: 'subscription.component.html' 14 | }) 15 | export default class SubscriptionComponent implements OnInit, OnChanges, OnDestroy, AfterViewChecked { 16 | @Input() search: any; 17 | @Input() pusher; 18 | public tweets : Object[]; 19 | private channel; 20 | private subscribed: boolean = false; 21 | private className: String; 22 | 23 | public ngOnInit() { 24 | this.subscribeToChannel(); 25 | this.tweets = []; 26 | this.className = this.search.term.replace(' ', '-'); 27 | } 28 | 29 | private subscribeToChannel() { 30 | this.channel = this.pusher.subscribe(btoa(this.search.term)); 31 | this.channel.bind('new_tweet', (data) => { 32 | this.newTweet(data); 33 | }); 34 | this.subscribed = true; 35 | } 36 | 37 | private newTweet(data: Object) { 38 | this.tweets.push(data); 39 | } 40 | 41 | public ngOnChanges() { 42 | console.log(this.search); 43 | if (!this.search.active && this.subscribed) { 44 | this.ngOnDestroy(); 45 | } else if (this.search.active && !this.subscribed) { 46 | this.subscribeToChannel(); 47 | } 48 | } 49 | 50 | public ngOnDestroy() { 51 | this.pusher.unsubscribe(btoa(this.search.term)); 52 | this.channel && this.channel.unbind(); 53 | this.subscribed = false; 54 | } 55 | 56 | public ngAfterViewChecked() { 57 | var listItem = document.querySelector(".channel-" + this.className); 58 | if (listItem) { 59 | listItem.scrollTop = listItem.scrollHeight; 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/img/pusher-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pusher-community/realtime-twitter-search-angular2/330b7e07e171a07517ca98d7938095b48983e79c/src/img/pusher-logo.png -------------------------------------------------------------------------------- /src/img/pusher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pusher-community/realtime-twitter-search-angular2/330b7e07e171a07517ca98d7938095b48983e79c/src/img/pusher.png -------------------------------------------------------------------------------- /src/img/twitter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pusher-community/realtime-twitter-search-angular2/330b7e07e171a07517ca98d7938095b48983e79c/src/img/twitter.png -------------------------------------------------------------------------------- /src/style.css: -------------------------------------------------------------------------------- 1 | #search-form { 2 | margin-top: 30px; 3 | } 4 | 5 | .channel { 6 | margin-bottom: 50px; 7 | } 8 | 9 | .channel-results { 10 | list-style: none; 11 | padding: 0; 12 | } 13 | 14 | #subscription-controls { 15 | margin-top: 20px; 16 | margin-bottom: 20px; 17 | } 18 | 19 | #subscription-controls button { 20 | padding: 10px 15px; 21 | } 22 | 23 | .twitter-icon { 24 | vertical-align: top; 25 | } 26 | 27 | .tweets-container { 28 | width: 800px; 29 | } 30 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES5", 4 | "module": "commonjs", 5 | "sourceMap": true, 6 | "emitDecoratorMetadata": true, 7 | "experimentalDecorators": true, 8 | "removeComments": false, 9 | "noImplicitAny": false 10 | }, 11 | "exclude": [ 12 | "node_modules", 13 | "typings/browser.d.ts", 14 | "typings/browser" 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /typings.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "xhr2": "github:gdi2290/typed-xhr2#69f2b8d40d0cd407c1b2a2f2f41fecc6852cabbb" 4 | }, 5 | "devDependencies": {}, 6 | "ambientDependencies": { 7 | "async": "github:DefinitelyTyped/DefinitelyTyped/async/async.d.ts#5c3e47967affa3c4128a3875d1664ba206ae1b0f", 8 | "es6-shim": "github:DefinitelyTyped/DefinitelyTyped/es6-shim/es6-shim.d.ts#6697d6f7dadbf5773cb40ecda35a76027e0783b2", 9 | "jasmine": "github:DefinitelyTyped/DefinitelyTyped/jasmine/jasmine.d.ts#26c98c8a9530c44f8c801ccc3b2057e2101187ee", 10 | "ng2": "github:gdi2290/typings-ng2/ng2.d.ts#32998ff5584c0eab0cd9dc7704abb1c5c450701c", 11 | "node": "github:DefinitelyTyped/DefinitelyTyped/node/node.d.ts#138ad74b9e8e6c08af7633964962835add4c91e2", 12 | "systemjs": "github:DefinitelyTyped/DefinitelyTyped/systemjs/systemjs.d.ts#5c3e47967affa3c4128a3875d1664ba206ae1b0f", 13 | "zone.js": "github:DefinitelyTyped/DefinitelyTyped/zone.js/zone.js.d.ts#b923a5aaf013ac84c566f27ba6b5843211981c7a" 14 | } 15 | } 16 | --------------------------------------------------------------------------------