keemor.com - Surfin' JavaScript Wave

Twitter API: Strumień wpisów po słowie kluczowym w PHP, JSON i Prototype

W serwisie Twitter.com pojawia się bardzo dużo wpisów na wiele różnych tematów. Pokażę dzisiaj jak przy pomocy API Twittera, PHP, JSON’a i PrototypeJS zrobić prosty gadżet, który będzie co jakiś czas odpytywać się o nowe wpisy na dany temat i automatycznie je wyświetlać.

ZOBACZ DEMO »

Twitter API: Strumień wpisów po słowie kluczowym w PHP, JSON i Prototype

Na początek tworzymy plik search.php, w którym użyjemy biblioteki JSON-PHP.


<?php
header('Content-type: application/json'); 
require_once "lib/twitterapi.php";
require_once "lib/JSON.php";

if($_POST['twitterq']){
	$twitter_query= $_POST['twitterq'];
	$twitts_limit = $_POST['twitts_limit'];
	$search = new TwitterSearch($twitter_query);
	//ustawiamy pobieranie tylko wpisów po angielsku
	$search->lang('en');
	$results = $search->results(); 	
	//zwracamy tylko najnowsze n wpisów dla zadanej frazy
	$results =  array_slice($results,0,$twitts_limit);
	foreach($results as $result){
		$result->text=toLink($result->text);			
	}	
	$json = new Services_JSON();
	echo $json->encode($results);
 }
?>

Jeżeli nie znasz sposobu działania metody bind, zapoznaj się z Tu Haczyk IStnieje – ‘this’ cz. I i Tu Haczyk IStnieje – this cz. II.

Kod JavaScript gadżetu:


var Stream = {
	init: function(opt){
		//sekundy pomiedzy kolejnymi szukaniami
		this.searchInterval = opt.updateEvery || 30;
		//szukana fraza           		
		this.twitterq = opt.searchQuery || 'kitesurfing';
		//limit pokazywanych wpisow
		this.twittsLimit = opt.twittsLimit || 5;
		//czas do kolejnego szukania, maleje od this.searchInterval 
		this.time2search = this.searchInterval;
		//pokazanie szukanej frazy
		$('twitterq').update(this.twitterq);
		//lista wpisow
		this.twitterResults = $('twitter-results');
		//element zawierajacy czas do nastepnego szukania
		this.time2searchInfo = $('time2search'); 
		//lista id wyswietlonych wpisow
		this.twittIds = [];
		//lista obiektow wpisu do pokazania po szukaniu
		this.twitts2display = [];										
		//metoda pokazujaca wpis
		this.displayTwitt = this.displayTwitt.bind(this);
		//id intervalu wywolania metody displayTwitt
		this.intervalId = null;
		//metoda sprawdzajaca czy juz pokazalismy wpis
		this.setTwitt = this.setTwitt.bind(this);
		//metoda szukajaca wpisow
		this.xhrSearch = this.xhrSearch.bind(this);
		//metoda zarzadzajaca opoznieniem pomiedzy szukaniem
		this._clearInterval = this._clearInterval.bind(this);
		//metoda aktualizujaca czas do nastepnego szukania
		this.setTime2search = this.setTime2search.bind(this);
		//wywolanie metody szukajacej
		this.xhrSearch();
	},
	//szablon pojedynczego wpisu
	template: new Template('<div class="twitter_status" style="display: none">' +
	'<img src="#{profile_image_url}" class="twitter_image">#{text}' +
	'<span class="twitter_small">' +
	'<strong>From:</strong> <a href="http://www.twitter.com/#{from_user}">#{from_user}</a>: ' +
	'<strong>at:</strong> #{created_at}' +
	'<input type="hidden" value="#{id}"></input>' +
	'</span></div>'),
	/*
	 * metoda wywoluje ajaxa z parametrami: twitts_limit i twitterq  
	 * w przypadku sukcesu jest wywolana metoda this.xhrSearchSuccess 
	 */ 
	xhrSearch: function(){										
		var xhr = new Ajax.Request("search.php", {
			parameters: {
				twitts_limit: this.twittsLimit,
				twitterq: this.twitterq
			},
			onSuccess: this.xhrSearchSuccess.bind(this)
		});
	},				
	xhrSearchSuccess: function(transport){
		//zatrzymanie zmiejszania czasu do kolejnego szukania
		clearInterval(this.time2searchId);					 
		//aktualizacja elementu this.time2searchInfo            		
		this.time2searchInfo.update('updating ...');            		
		//pobranie listy wpisow z ajax w postaci JSONA
		this.data = transport.responseJSON;
		//wyczyszczenie listy obiektow wpisu do wyswietlenia
		this.twitts2display = [];
		//wywolanie metody this.setTwitt dla kazdego wpisu
		this.data.each(this.setTwitt);
		//rozmiar tablicy z wpisami do wyswietlenia
		this.limit = this.twitts2display.length;
		//iterator po liscie this.twitts2display
		this.i = this.limit - 1;
		
		//zabiepieczenie przed nieskonczona dlugoscia tablicy wyswietlonych wpisow
		if (this.twittIds.length > 50) {
			this.twittIds = this.twittIds.slice(-10);
		}
		//jesli nie ma wpisow do wyswietlenia czekamy do nastepnego szukania
		if (this.limit === 0) {
			window.setTimeout(this._clearInterval);
		} else {
		//w przeciwnym wypadku wyswietlamy jeden wpis na sekunde	
			this.intervalId = window.setInterval(this.displayTwitt, 1000);
		}
	},
	//metoda sprawdzajaca czy juz pokazalismy wpis
	setTwitt: function(twitt){
		//jesli id wpisu nie ma w juz wyswietlonych 
		if (this.twittIds.indexOf(twitt.id) === -1) {
			//dodajemy do wyswietlonych id wpisow
			this.twittIds.push(twitt.id);
			//dodajemy obiekt do tablicy do wyswietlenia
			this.twitts2display.push(twitt);
		}
	},
	//metoda pokazujaca wpis
	displayTwitt: function(){
		//obiekt wpisu do wyswietlenia
		var twitt = this.twitts2display[this.i];
		//wstawienie ukrytego wpisu przy pomocy szablonu na poczatek listy wpisow
		this.twitterResults.insert({
			top: this.template.evaluate(twitt)
		});
		//pobranie lista wpisow
		var twitterElements = this.twitterResults.childElements();
		//pokazanie najnowszego wpisu 
		twitterElements[0].appear({
			duration: 0.5
		});
		//usuniecie ostatniego jesli jest wiecej niz zalozony limit wpisow
		if (twitterElements.length > this.twittsLimit) {
			twitterElements.last().remove();
		}
		//jesli pokazany zostal ostatni wpis czekamy do nastepnego szukania
		if (this.i === 0) {
			window.setTimeout(this._clearInterval);
		}
		//zmiejszenie iteratora po this.twitts2display 
		this.i--;
	},
	//metoda zarzadzajaca opoznieniem pomiedzy szukaniem
	_clearInterval: function(){
		//poczatkowa wartosc sekund do nastepnego szukania pomniejszona o 1
		this.time2search = this.searchInterval-1;
		//zatrzymanie cyklicznego wywolania metody this.displayTwitt
		clearInterval(this.intervalId);
		//opoznienie wywolania metody szukajacej frazy  
		this.xhrSearch.delay(this.searchInterval);
		//ustawienie cyklicznego wywolania metody setTime2search 
		this.time2searchId = window.setInterval(this.setTime2search, 1000);
	},
	//metoda aktualizujaca czas do nastepnego szukania
	setTime2search: function(){
		this.time2searchInfo.update(this.time2search--)
	}
}
document.observe('dom:loaded', Stream.init.bind(Stream, {
	twittsLimit: 6,
	updateEvery: 15,
	searchQuery: 'google'
}));

I to wszystko. Dzięki za czytanie. Mam nadzieję, że znalazłaś(eś) rozwiązanie swojego problemu.