I Haz A Bug

le blog de jye.

TV Shows : Mon module Netvibes - Release!

Précédemment sur ce blog:

Le widget est donc prêt en beta : rendez-vous à cette adresse pour le tester en standalone. Vous pouvez aussi directement l’ajouter à vos Netvibes/iGoogle respectif via les boutons en dessous du widget. Pour tester le tout sous Windows Live/Vista/Mac/ et iPhone/iPod Touch il faudra attendre un peu. N’hésitez pas à me soumettre vos idées ! La prochaine fois je détaillerai le code javascript UWA du widget en lui-même et ça sera probablement le dernier billet pour ce widget qui devrait être terminé.

Comme promis, mais avec un peu de retard voici la dernière partie. Actuellement le widget fonctionne correctement sous Netvibes mais je n’ai pas encore testé ailleurs. Je vais ci-dessous détaillé le fonctionnement Javascript du widget :

Petit rappel pour avoir un widget Netvibes, il faut inclure ces deux lignes :

<script type="text/javascript" src="http://www.netvibes.com/js/UWA/load.js.php?env=Standalone"></script>
<link rel="stylesheet" type="text/css" href="http://www.netvibes.com/themes/uwa/style.css" />

Pour que votre widget dispose d’icône, à la fois pour le web et les OS, intégrer ces deux lignes :

/* Web Icon */
<link rel="icon" href="http://jeremyselier.com/netvibes/tvshows.png" type="image/x-icon" />
/* Rich Icon */
<link rel="rich-icon" type="image/png"  href="http://jeremyselier.com/netvibes/richicon-tvshows.png"/>

Regardons tout d’abord la partie "préférences" :

<widget:preferences>
    <preference name="period" type="list" label="Période" defaultValue="7" onchange="refresh">
        <option value="7" label="Les 7 prochains jours" />
        <option value="15" label="Les 15 prochains jours" />
        <option value="-7" label="Les 7 derniers et prochains jours" />
        <option value="-15" label="Les 15 derniers et prochains jours" />
        <option value="x" label="Les X prochains jours" />
        <option value="-x" label="Les X derniers et prochains jours" />
    </preference>
    <preference name="x" type="range" label="Nombre de jours (si choisit dans période)" onchange="refresh" defaultValue="1" step="1" min="1" max="100" />
    <preference name="number" type="range" label="Nombre d'épisodes par page" onchange="refresh" defaultValue="10" step="1" min="1" max="30" />
    <preference name="query" type="text" label="Recherche ($QUERY$ représente les mots clefs) " defaultValue="http://www.google.com/search?q=$QUERY$" />
    <preference name="shows" type="hidden" defaultValue="" />
    <preference name="showsTxt" type="hidden" defaultValue="" />

<!--
    <preference name="hideSeen" type="boolean" label="Caché quand marqué comme Vu?" onchange="refresh" defaultValue="true" />
    <preference name="seens" type="hidden" defaultValue="" />
-->

</widget:preferences>

Je définie dans cette partie toutes les options que je souhaite afficher dans ma partie "édition" de mon widget. J’ajoute aussi deux champs Hidden qui vont me permettre de stocker les séries sélectionnés par le user, une version affichable et l’autre destiné à mon API de récupération des données. En commentaire vous pouvez voir deux champs non-implémenté pour le moment qui me permettront d’ajouter la feature Vu/Non vu auquel je réfléchis encore.

Au niveau du code HTML, vous pouvez constater qu’il n’y a rien :

<body>
    <p>Loading...</p>
</body>

En effet tout doit être gérer dans le code Javascript.

On passe donc au gros morceau, le code UWA de mon widget. Je vais détailler seulement les fonctions importantes, je passerais sur les fonctions qui me permettent de cacher/afficher du contenu. Tout d’abord le "main" qui est exécuté à la fin du chargement de la page :

widget.onLoad = function() {

            var body = 'Code HTML comprenant un petit gif qui simule un loader [...]';
            /* Permet d'insérer entre les balises <body> le contenu de la variable body */
            widget.setBody(body);

            /*Logger - Affiche dans Firebug (Firefox seulement) si <meta name="debugMode" content="true" /> est spécifié*/
            widget.log('Updating shows list...');
            /*Récupération d'un fichier XML contenant la liste des séries existantes via mon API PHP qui sera en fourni à la fonction ShowsReader.display pour insertion au sein du widget*/
            UWA.Data.getXml("http://jeremyselier.com/apis/getShows.php", ShowsReader.display);           

            widget.log('Getting users shows and preferences...');
            /*Récupération des séries  ainsi que de différentes options de l'utilisateur*/
            var shows = widget.getValue('shows');
            var period = widget.getValue('period');
            var x = widget.getValue('x');
            var number = widget.getValue('number');

            /*Logging*/
            widget.log('Shows : '+shows);
            widget.log('Period : '+period);
            widget.log('X : '+x);
            widget.log('Number : '+number);

            /*Traitement avant appel du webservice qui récupérera le code HTML à afficher*/
            if(period == "x" || period == "-x") {
                period = period + "&x=" + x;
            }

            /*Demande via l'API de récupérer sous forme de texte (code html) le contenu du widget en fonction de ses préférences d'affichage et de sa liste de séries suivies.*/
            var url = "http://jeremyselier.com/apis/getEpisodeList.php?shows="+shows+"&period="+period+"&number="+number;
            widget.log('Get episodes list... '+url);
            /* Appel de l'url, le résultat sera fournis à Episodes.display qui se chargera d'injecter dans mon widget la réponse de l'url.*/
            UWA.Data.getText(url, Episodes.display);   

            /*Fonction permettant de remplir le panneau qui permet de supprimer des séries de sa liste*/
            widget.log('Get selected show list...');
            fillSelectedShows();
}

/* Petite indication pour préciser de faire le même comportement qu'au chargement lors d'un refresh du widget*/
widget.onRefresh = widget.onLoad;

Le plus important dans cette partie est l’utilisation des fonction UWA.Data qui sont des fonctions Ajax permettant d’interroger une URL et dans récupérer le contenu. Il y a plus d’infos ici. La fonction getXML permettra de récupérer un contenu formaté en XML alors que getText récupérera un contenu basic. Cela permet de fournir de l’html qui sera interprété lors de l’injection dans le widget. Sachez qu’il existe aussi la fonction getFeed permettant de récupérer un flux RSS et de parser très facilement son contenu par la suite.

La fonction ShowsReader.display ci-dessous, se contente de parcourir mon flux XML reçu en paramètre et de l’injecter dans ma liste déroulante.

var ShowsReader = {}

ShowsReader.display = function(xml) {

    widget.log('ShowsReader.display : getting shows list');
    /* On récupère l'élément HTML  et on le cache pour la durée du traitement. */
    showlist = widget.body.getElementsByClassName("showlist")[0];
    showlist.style.display = 'none';

    /* On récupère la liste des séries dans le fichier XML. */
    var shows = xml.documentElement.getElementsByTagName("show");

    /* On spécifie la taille du select. Puis on parcourt la liste des séries afin de les insérer dans le select.*/
    showlist.options.length = shows.length;
    for (var i = 0; i < shows.length; i++) {
        showlist.options[i].text = shows[i].getElementsByTagName('title')[0].firstChild.nodeValue;
        showlist.options[i].value = shows[i].getElementsByTagName('description')[0].firstChild.nodeValue;
    }

    /* Fin du traitement, on re-affiche le select.*/
    showlist.style.display = 'block';

    widget.log('end ShowsReader.display');
}

La fonction Episodes.display injecte dans mon DIV principal le code HTML renvoyé par mon webservice. En effet mon webservice renvoi un code HTML adapté à mon widget :

var Episodes = {}

Episodes.display = function(content) {

    widget.log('Episodes.display');
    widget.body.getElementById('tv_tbl').innerHTML = content;
    widget.log('end Episodes.display');
}

Enfin la dernière fonction que je vais vous détaillé n’est pas non plus très complexe. Je récupère les séries de l’utilisateur et construit le panneau qui lui permettra d’afficher toutes les séries qu’il suit et de les supprimer s’il le souhaite.

function fillSelectedShows() {
    widget.log('fillSelectedShows');

    /* Récupération des préférences utilisateurs (shows : Liste des séries au format de l'API; showsTxt : Liste des séries au format affichable) */
    var shows = widget.getValue('shows');
    var showsTxt = widget.getValue('showsTxt');

    /* Construction des tableaux contenant les séries. */
    var shows_array = {};
    var showsTxt_array = {};

    if(shows != null) {
        var shows_array = shows.split("-");
        var showsTxt_array = showsTxt.split("-");
    }

    /* Début d'implémentation de l'affichage du panneau suppression */
    var str_tab = "Code HTML [...]";

    /* Parcours du tableau et construction de l'affichage */
    var found = false;
    for(i = 0; i < shows_array.length; i++){
        if(shows_array[i] != "") {
            found = true;
            str_tab = str_tab + "Code HTML [...]";
        }
    }

    /* Si on est pas passé dans le tableau, l'utilisateur ne suit donc aucune série */
    if(found == false) {
        str_tab = str_tab + "Vous ne suivez pas de séries.";
    }

    /* Fin de construction de l'affichage et insertion dans le widget */
    str_tab = str_tab + "Code HTML [...]";
    widget.body.getElementsByClassName("tab_del")[0].innerHTML = str_tab;

    widget.log('end fillSelectedShows');
}

Je n’ai pas tout détaillé, en regardant la source vous verrez d’autres fonctions qui me permettent d’ajouter une série/supprimer une série (en gros le fonctionnement consiste juste à insérer la série choisie dans mon champ Hidden de préférence user et recharger le widget; idem pour la suppression), afficher/masquer des informations comme le résumé de l’épisode, les panneaux d’ajouts et de suppressions de séries, le petit bloc qui permet d’accéder à la fiche TV/Recherche, et enfin la pagination.

Voilà pour les explications de mon widget. Si vous avez des questions n’hésitez pas et si vous voulez voir la totalité du code UWA, il suffit de jeter un oeil à la source de cette page. Je le considère comme terminé. Je reviendrais dessus pour rajouter la fonction Vu/Non vu, ainsi que l’internationalisation du widget mais l’essentiel est là. Par rapport aux versions précédentes, celle-ci permet de lire le résumé en anglais en cliquant sur le titre de l’épisode. On obtient aussi la chaîne ainsi que l’heure US (que je dois retravailler). Le widget fonctionne parfaitement en mode StandAlone, sur iGoogle et Netvibes. N’ayant plus Vista je ne peux garantir son fonctionnement, de même pour OS X. Si des gens peuvent tester sur ces OS et me faire un retour, ça serait niquel! Je testerais/débuggerais bientôt sous Opera qui de mémoire fout en l’air l’interface.

Autre info, dans le cadre de cette série de billets et de mes widgets; j’ai été interviewé sur le blog des developpeur de Netvibes (cliquez sur le lien pour la lire). Désolé pour la longueur du billet (comme d’hab) et merci à DjMerguez pour le tip CSS pour faire une simili balise .

12 commentaires pour “TV Shows : Mon module Netvibes - Release!”

  1. evanspro dit :

    "Autre info, dans le cadre de cette série de billets et de mes widgets; j’ai été interviewé sur le blog des developpeur de Netvibes (cliquez sur le lien pour la lire)."

    … pff, poseur.

  2. mouito dit :

    je susi tout naze mais ca fonctionne sous firefox

  3. bibiwan14 dit :

    je vais tester dès que possible sous macos j’te redis ca ;)

  4. bibiwan14 dit :

    feedback pour macos (désolé du retard) : impossible d’ajouter une série… :(

  5. jye dit :

    Oui merci pour le retour, j’ai le même problème sous Opera en widget. Un clic sur Ajouter/Supprimer une série n’ouvre pas le panel. Mon code n’est pas assez bien optimisé j’ai bien l’impression.

  6. channie dit :

    "Connect failed: Too many connections"

    J’ai cette erreur depuis ce matin, vers 10h30.

  7. jye dit :

    Il semblerait que Netvibes soit dans les choux aujourd’hui. Si tu testes en standalone, tout à l’air de bien fonctionner. Merci pour ton retour en tout cas.

  8. Anonyme dit :

    Je n’arrive pas à obtenir les jours de diffusion de cette excellente série avec TV Shows.
    Le module TV Series de Ben y arrive sans soucis.

    Crois-tu pouvoir le débugger ?
    Docg.

  9. jye dit :

    Désolé pour la réponse tardive mais il faut définitivement que je bricole un truc pour remonter automatiquement les commentaires non publiés. D’une façon ou d’une autre.

    J’ai corrigé le parsing qui effectivement ne fonctionnait pas.

  10. Local dit :

    Je viens d’essayer ce widget sous Netvibes, il fonctionne parfaitement.

    Merci

  11. Hubert dit :

    Bonjour

    Je suis également en train de tenter de développer des widgets UWA. J’ai un petit souci, peut-être pourrais-tu m’aider? Mes préférences apparaissent bien en standelone mais quand je l’ajoute dans Netvibes. Tu saurais pourquoi?

  12. jye dit :

    Salut,

    Désolé, mais je n’ai pas retouché à l’UWA depuis un moment et il y a eu pas mal de mises à jour qui ont notamment rendu mon widget incompatible sur iGoogle. Je ne pourrais pas vraiment t’aider pour le coup, mais je te conseille le forum de développement, qui est assez réactif dans mon souvenir.

Laisser un commentaire

Si vous avez un compte sur WeFrag, connectez-vous pour publier un commentaire.

Vous pouvez, entre autres, utiliser les tags XHTML suivant :
<a href="" title="">...</a>,<b>...</b>,<blockquote cite="">...</blockquote>,<code>...</code>,<i>...</i>