Resumé

JsRender per il Templating in javascript

Cristian Merighi () 0,00

Sviluppo di un client per Twitter totalmente ...client! Utilizzando JsRender assieme a "qualche" altro componente javascript.
Questo articolo è da considerarsi obsoleto. Alcune funzionalità potrebbero non essere più disponibili e non è possibile aggiungere commenti.

Mi adeguo al marasma presente sulla scena dei componenti javascript e provo a presentare una soluzione riveduta e rivedibile di come assemblare un parser per Twitter purely-client.

Introduco preventivamente i componenti coinvolti nel seguente blocco di codice e nella demo allegata:

  • Microsoft Ajax 4 (String.format, Date.parseInvariant, Array.insert...)
  • jQuery (Async calls, DOM manipulation, Utilities...)
  • JsRender (Templating, Data formatting...)
  • Altri plugin (jQuery) di utilità ristretta...

Obiettivo: utilizzare i servizi REST di Twitter per recuperare contenuti e mostrarli in una modalità quanto più completa possibile (mostrando avatars, hashtags, mentions e collegamenti). Il tutto esclusivamente via DHTML (scusate il termine riesumato dal 20° secolo).

Sezioniamo il codice, innanzitutto la dichiarazione del template per JsRender:

JsRender Template
  1. <ul id="tweets" class="Tweets">
  2. <li><div class="Loader"></div></li>
  3. </ul>
  4. <script id="twitTmpl" type="text/x-jsrender">
  5.     <li><img src="{{:user.profile_image_url_https}}" />{{:~renderTweet(#view)}}<span class="Date">{{:~timeago(created_at)}}</span></li>
  6. </script>

Ho evidenziato i punti in cui sono riportati richiami all'entità che va a popolare ogni singola istanza del template: user e created_at sono "proprietà" dell'oggetto json che rappresenta un singolo tweet, #view rappresenta un wrapper per l'intero oggetto (una sorta di DataItem per chi è abituato alla logica del mondo WebForms di ASP.Net).
Sintassi JsRender: {{:[_property_].[_subproperty_]}} (mi raccomando, niente spazi tra parentesi graffe e due-punti!) per il rendering "diretto" del valore della property.
{{:~foofunc([_propertypath_or_view_])}} per modellare l'output con un po' di logica custom (presente nel metodo helper "foofunc") prima del rendering.

Dove posizionare questi metodi helper (nell'esempio seguente renderTweet e timeago):

View Helper Methods
  1. // "sort-of" converters
  2. $.views.helpers({
  3.     // accepts the whole (wrapped) dataItem (aka "#view")
  4.     renderTweet: function (view) {
  5.         var tweet = view.data;
  6.         var txt = tweet.text;
  7.         var rettxt = '';
  8.         var entities = tweet.entities;
  9.         var trunks = [];
  10.         if (entities) {
  11.             // sorting the various entity trunks
  12.             $.each(entities.hashtags, function (i, hash) {
  13.                 pushTrunk(trunks, { start: hash.indices[0], end: hash.indices[1], text: hash.text, type: 'hash' });
  14.             });
  15.             $.each(entities.urls, function (i, url) {
  16.                 pushTrunk(trunks, { start: url.indices[0], end: url.indices[1], text: url.url, type: 'url' });
  17.             });
  18.             $.each(entities.user_mentions, function (i, usr) {
  19.                 pushTrunk(trunks, { start: usr.indices[0], end: usr.indices[1], text: usr.screen_name, type: 'user' });
  20.             });
  21.             // assembling the final html string (rettxt)
  22.             var lastIndex = 0;
  23.             $.each(trunks, function (i, trunk) {
  24.                 switch (trunk.type) {
  25.                     case "hash":
  26.                         rettxt += txt.substring(lastIndex, trunk.start) + "<a target=\"_blank\" href=\"https://twitter.com/search/%23" + trunk.text + "\">#" + trunk.text + "</a>";
  27.                         break;
  28.                     case "url":
  29.                         rettxt += txt.substring(lastIndex, trunk.start) + "<a target=\"_blank\" href=\"" + trunk.text + "\">" + trunk.text + "</a>";
  30.                         break;
  31.                     case "user":
  32.                         rettxt += txt.substring(lastIndex, trunk.start) + "<a target=\"_blank\" href=\"https://twitter.com/" + trunk.text + "\">@" + trunk.text + "</a>";
  33.                         break;
  34.                 }
  35.                 lastIndex = trunk.end;
  36.             });
  37.             rettxt += txt.substring(lastIndex);
  38.         } else rettxt = txt;
  39.         return rettxt ;
  40.     },
  41.     timeago: function (createdAt) {
  42.         // using timeago plugin (issues with UTC date and L10N)
  43.         // Date.parseInvariant is exposed by Ajax 4
  44.         return $.timeago(Date.parseInvariant(createdAt, 'ddd MMM dd HH:mm:ss +0000 yyyy'));
  45.     }
  46. });

Nei commenti al codice, prego di notare i richiami ai vari frameworks javascript utilizzati.

il collante tra declarative-template e il codice sopra è rappresentato dalla seguente function javascript (fate attenzione alle istruzioni evidenziate ed al rispettivo significato riportato nei commenti che le precedono):

Glue Code
  1. function loadTweets() {
  2.     // obey to cross-site-scripting issues
  3.     $.support.cors = true;
  4.     // format url using Ajax 4 String.format
  5.     var rest_url = String.format("https://api.twitter.com/1/statuses/user_timeline.json?include_entities=true&include_rts=true&screen_name={0}&count={1}", 'cmerighi', 3);
  6.     // jQuery ajax (fluent version)
  7.     $.ajax({
  8.         // be sure to specify dataType jsonp
  9.         dataType: "jsonp",
  10.         url: rest_url
  11.     }).success(function (tweets) {
  12.         // build up
  13.         // FIRST jsrender template...
  14.         $.templates({ twit: '#twitTmpl' });
  15.         // ...THEN the DOM
  16.         $('#tweets').empty().append($.render.twit(tweets));
  17.     }).error(function (e) {
  18.         alert(e.statusText);
  19.     }).always(function(){ /* runs anyway */ });
  20. }

Ho approntato una DEMO funzionante per consentire di visualizzare anche la porzione di codice omesso e sperando di far cosa gradita... ;)

Take care. Bye.

feedback
 

Syndicate

Autore

Cristian Merighi facebook twitter google+ youtube

Ultimi articoli

Top rated

Archivio

Dove sono?

Autore

Cristian Merighi facebook twitter google+ youtube

Le mie letture

Feeds