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:
- Reperire i tweet.
- Formattare i tweet convertendo gli URL testuali in link e modificando le date.
- Mettere in cache i tweet.
- 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:
username
: il vostro username di Twitterlimit
: il numero di tweet da reperirecache
: 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();
});