jQuery: creare un plugin per Twitter con cache

jQuery: creare un plugin per Twitter con cache

Twitter mette a disposizione degli sviluppatori due tipi di API: un'API priva di autenticazione e a sola lettura ed un'API con autenticazione in lettura e scrittura. JavaScript riesce ad interagire con il primo tipo di API tramite il formato JSONP (JSON with Padding). Dato che jQuery dispone del metodo $.getJSON() è possibile creare un plugin che reperisca i nostri tweet da Twitter.

Il nostro plugin dovrà svolgere i seguenti compiti:

  1. Reperire i tweet.
  2. Formattare i tweet convertendo gli URL testuali in link e modificando le date.
  3. Mettere in cache i tweet.
  4. Visualizzare i tweet.

La parte più complessa è la cache. Esistono varie opzioni in tal senso:

  • Cookie
  • Local storage
  • Session storage
  • Web database

A livello di retrocompatibilità con i browser obsoleti l'unica via percorribile è quella dei cookie, quindi come prima cosa dobbiamo creare una funzione di utility per questo scopo:


(function(factory) {
	if (typeof define === 'function' && define.amd && define.amd.jQuery) {
		define(['jquery'], factory);
	} else {
		factory(jQuery);
	}
}(function($) {
	var pluses = /\+/g;

	function raw(s) {
		return s;
	}

	function decoded(s) {
		return decodeURIComponent(s.replace(pluses, ' '));
	}

	function converted(s) {
		if (s.indexOf('"') === 0) {
			s = s.slice(1, -1).replace(/\\"/g, '"').replace(/\\\\/g, '\\');
		}
		try {
			return config.json ? JSON.parse(s) : s;
		} catch (er) {}
	}
	var config = $.cookie = function(key, value, options) {
			if (value !== undefined) {
				options = $.extend({}, config.defaults, options);
				if (typeof options.expires === 'number') {
					var days = options.expires,
						t = options.expires = new Date();
					t.setHours(t.getHours() + days);
				}
				value = config.json ? JSON.stringify(value) : String(value);
				return (document.cookie = [encodeURIComponent(key), '=', config.raw ? value : encodeURIComponent(value), options.expires ? '; expires=' + options.expires.toUTCString() : '', options.path ? '; path=' + options.path : '', options.domain ? '; domain=' + options.domain : '', options.secure ? '; secure' : ''].join(''));
			}
			var decode = config.raw ? raw : decoded;
			var cookies = document.cookie.split('; ');
			var result = key ? undefined : {};
			for (var i = 0, l = cookies.length; i < l; i++) {
				var parts = cookies[i].split('=');
				var name = decode(parts.shift());
				var cookie = decode(parts.join('='));
				if (key && key === name) {
					result = converted(cookie);
					break;
				}
				if (!key) {
					result[name] = converted(cookie);
				}
			}
			return result;
		};
	config.defaults = {};
	$.removeCookie = function(key, options) {
		if ($.cookie(key) !== undefined) {
			$.cookie(key, '', $.extend(options, {
				expires: -1
			}));
			return true;
		}
		return false;
	};
}));

La nostra funzione crea un cookie la cui durata è calcolata in ore. Il suo uso è il seguente:


$.cookie('test', 'true', {expires: 1});

Il codice di cui sopra crea il cookie test il cui valore è true e che ha un tempo di scadenza di un'ora. Ovviamente è possibile modificare il codice della funzione per calcolare il tempo in minuti.

A questo punto possiamo cominciare a creare il plugin:


(function($) {
	$.fn.twitterFeed = function(options) {
		var that = this;
		var settings = {
			username: 'gabromanato',
			limit: 5,
			cache: false
		};
		options = $.extend(settings, options);

		// continua
	};
})(jQuery);

Il nostro plugin accetta tre opzioni:

  1. username: il vostro username di Twitter
  2. limit: il numero di tweet da reperire
  3. cache: un valore booleano che indica se i tweet debbano essere messi in cache o meno.

La logica del plugin sarà delegata ad un oggetto:


var TwitterFeed = new function() {
    // continua
}();

Per prima cosa definiamo l'URL della richiesta:


var url = 'http://api.twitter.com/1/statuses/user_timeline.json?screen_name=' + options.username + '&count=' + options.limit + '&callback=?';
// continua

Quindi creiamo un metodo privato per la formattazione delle date:


// continua
var relativeTime = function(time_value) {
	var values = time_value.split(" ");
	time_value = values[1] + " " + values[2] + ", " + values[5] + " " + values[3];
	var parsed_date = Date.parse(time_value);
	var relative_to = (arguments.length > 1) ? arguments[1] : new Date();
	var delta = parseInt((relative_to.getTime() - parsed_date) / 1000);
	delta = delta + (relative_to.getTimezoneOffset() * 60);
	if (delta < 60) {
		return 'less than a minute ago';
	} else if (delta < 120) {
		return 'about a minute ago';
	} else if (delta < (60 * 60)) {
		return (parseInt(delta / 60)).toString() + ' minutes ago';
	} else if (delta < (120 * 60)) {
		return 'about an hour ago';
	} else if (delta < (24 * 60 * 60)) {
		return 'about ' + (parseInt(delta / 3600)).toString() + ' hours ago';
	} else if (delta < (48 * 60 * 60)) {
		return '1 day ago';
	} else {
		return (parseInt(delta / 86400)).toString() + ' days ago';
	}
};
// continua

Ora creiamo altri due metodi privati per leggere e scrivere il cookie:


// continua
var createCookie = function(value) {
	$.cookie('tweet', value, {
		expires: 1
	});
};
var getCookie = function() {
	var cookie = $.cookie('tweet');
	return cookie;
};
// continua

Poi passiamo alla formattazione degli URL testuali:


// continua
var replaceURLs = function(text) {
	var replaced = text.replace(/(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig, '<a href="$&">$&</a> ');
	return replaced;
};
// continua

Infine creiamo il metodo pubblico principale che andrà a reperire, formattare e memorizzare i nostri tweet:


// continua
this.fetch = function() {
	if (!options.cache) {
		$.getJSON(url, function(data) {
			var html = '<div id="tweets-wrapper">';
			$.each(data, function(i, item) {
				var tweet = replaceURLs(item.text);
				var time = relativeTime(item.created_at);
				html += '<div class="tweet">';
				html += tweet;
				html += '<small>' + time + '</small>';
				html += '</div>';
			});
			html += '</div>';
			that.html(html);
		});
	} else {
		var tweet = getCookie();
		if (tweet !== undefined) {
			that.html(tweet);
		} else {
			$.getJSON(url, function(data) {
				var html = '<div id="tweets-wrapper">';
			$.each(data, function(i, item) {
				var tweet = replaceURLs(item.text);
				var time = relativeTime(item.created_at);
				html += '<div class="tweet">';
				html += tweet;
				html += '<small>' + time + '</small>';
				html += '</div>';
			});
				html += '</div>';
				createCookie(html);
				that.html(getCookie());
			});
		}
	}
};
// chiusura dell'oggetto

Quindi utilizziamo il nostro oggetto:


return that.each(function() {
	TwitterFeed.fetch();
});

Torna su