Clubic pour iPhone

Partager sur Facebook

28/04/2010 : Article mis à jour suite à la refonte graphique du site Clubic.

Le site Clubic ne prévoit pas d'affichage optimisé pour l'iPhone. Avec un peu de CSS, de PHP et de JQuery, j'ai réussi à faire, sans trop de mal, un petit bidule qui affiche les derniers articles parus sur le site, et qui permet de les consulter. Tout ça en s'adaptant à la résolution du téléphone.

Principe

Le principe est de créer des classes PHP permettant de se connecter au site de Clubic, de récupérer la liste des derniers articles et de les mettre en forme sur une page avec un peu de CSS.

Heureusement Apple a bien documenté la création d'applications web pour l'iPhone ici. Des CSS toutes prêtes sont ainsi disponibles dans les exemples d'applications ainsi que des fichiers JavaScript permettant de gérer le passage en mode paysage par exemple. Pour cette application, je suis parti de la CSS de l'exemple Simple Browser ainsi que du fichier browser.js de ce même exemple.

Scripts PHP

PHP

Il nous faut commencer par récupérer la liste des articles de la page d'accueil de Clubic. Evidemment nous n'avons pas accès à la base de données de Clubic, il va donc falloir ruser.

La page d'accueil affiche un petit bouton "Afficher le flux d'actu condensé" qui affiche la liste des dernières actualités, avec un système de pagination. En surveillant les flux HTTP qui circulent lorsque l'on clique sur les numéros de la pagination, on voit à chaque fois un appel à la page : http://www.clubic.com/ajax/news-light.php. Des paramètres lui sont passés en POST :

  • action = display
  • page = numéro de page

Nous allons exploiter cette page pour créer notre version iPhone.

Nous allons créer trois classes PHP :

  • la classe Article : elle représente un article Clubic. Elle possède 3 attributs (titre de l'article, la date de publication, le lien vers l'article). Niveau méthodes, cette classe possède juste un constructeur et des accesseurs.
  • la classe ArticlesParser : cette classe va parser différentes pages. Elle possède deux méthodes statiques :
    • la méthode getArticlesList : elle prend en paramètre l'URL de la page news-light.php. Elle va parser le code source de cette page pour en extraire les différents articles. Elle retourne un tableau d'objets Article
    • la méthode getArticleContent : elle prend en paramètre l'URL d'un article. Elle va parser le code source de cette page pour en extraire le contenu de l'article sans tout ce qui l'entoure (structure du site, commentaires, ...). Elle retourne une chaîne de caractères qui correspond au contenu de l'article.
  • la classe URL : cette classe va permettre d'ouvrir une connexion à la page news-light.php et de lui passer les paramètres POST. Elle contient une seule méthode statique. Cette méthode est reprise telle qu'elle d'un commentaire de la fonction file_get_contents de la doc PHP. Pour cette raison, cette classe ne sera pas détaillée.

Ces trois classes suffisent à créer notre application. La page d'accueil de l'application fera appel à la méthode ArticlesParser::getArticlesList pour récupérer la liste des articles. A nous ensuite d'afficher cette liste sur la page. Lorsque nous cliquerons sur un article, nous ferons appel à la méthode ArticlesParser::getArticleContent pour afficher le contenu de cet article.

Voici donc le contenu du fichier article.class.php :

<?php

require_once('misc.class.php');

// Constants
define('CLUBIC_URL', 'http://www.clubic.com');
define('ARTICLES_LIST', '/ajax/news-light.php?action=display&page=1');

class Article
{
    private $title;
    private $date;
    private $link;

    public function __construct($title, $date, $link)
    {
        $this->title = $title;
        $this->date = $date;
        $this->link = $link;
    }

    public function __set($attribute, $value) {
        $this->$attribute = $value;
    }

    public function __get($attribute){
        return $this->$attribute;
    }
}

class ArticlesParser
{
    public static function getArticlesList($url)
    {
        // Article table
        $a_array = array();
        // Get source code
        $source = URL::file_post_contents($url);

        // Parse list
        if (preg_match_all('!<div class="news-item[^>]+>(.*)</div>!sUi', $source, $matches))
        {
            $div = $matches[1];
            foreach($div as $d)
            {
                // Article title
                preg_match("!>([^<]+)</a>!i", $d, $regs);
                $title = trim($regs[1]);
                // Article date
                preg_match("!>([^<]+)</span>!si", $d, $regs);
                $date = trim($regs[1]);
                // Article link
                preg_match("!href="([^']+)"!si", $d, $regs);
                $link = trim($regs[1]);
                $link = substr($link, 0, 7) == 'http://' ? $link : CLUBIC_URL . $link;

                $a_array[] = new Article($title, $date, $link);
            }
        }
        return $a_array;
    }

    public static function getArticleContent($url)
    {
        // Article content
        $articleContent = '';
        // Open web page
        $handle = fopen($url, 'rb');
        // Get source code
        $source = stream_get_contents($handle);

        // Parse article content
        if (preg_match("!<div class="editorial">(.*)</div>s*<!-- Base de connaissance -->!sUi", $source, $matches))
        {
            $articleContent = str_replace("href='/", "href='". CLUBIC_URL ."/", $matches[1]);
        }
        return $articleContent;
    }
}

?>

Quelques petites explications :

  • L'instruction URL::file_post_contents($url) récupère la liste des actualités Clubic.
  • L'instruction $handle = fopen($url, 'rb'); permet d'ouvrir un fichier situé sur un serveur distant. Pour que cela fonctionne, il faut que l'option soit activée dans le fichier php.ini (allow_url_fopen = On)
  • Chaque article est situé entre les balises : <div class="news-item*> </div> d'où l'expression régulière. De même, chaque contenu d'article est situé entre les balises <div class='editorial'> </div>
  • On complète les URLs relatives avec http://www.clubic.com

Page d'accueil

La page d'accueil est assez simple. On inclue le fichier article.class.php afin d'utiliser les classes définies précédemment.

Comme expliqué sur la page Configuring the viewport, il faut ajouter la ligne suivante dans le head :

<meta name="viewport" content="width=device-width, minimum-scale=1.0, maximum-scale=1.0">

Cela permet d'adapter le contenu de la page à la résolution de l'iphone.

Voilà à quoi ressemble notre page index.php :

<?php
require_once('article.class.php');
?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<meta name="viewport" content="width=device-width, minimum-scale=1.0, maximum-scale=1.0">
<title>iClubic</title>
<link href="styles.css" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="browser.js" charset="utf-8"></script>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="scripts.js"></script>
</head>

<body>
    <div id="main">
        <div id="banner"></div>
        <div id="content">
            <div id="articleContent">
                <div id="return">Retour</div>
                <h1></h1>
                <div id="realContent"></div>
            </div>
            <ul>
            <?php
                $a_list = ArticlesParser::getArticlesList(CLUBIC_URL . ARTICLES_LIST);
                foreach($a_list as $article)
                {
                    echo '<li class="group">';
                    echo $article->date .' ';
                    echo '<a href="'. $article->link .'">'. $article->title .'</a>';
                    echo '</li>';
                }
            ?>
            </ul>
        </div>
    </div>
</body>
</html>

Le fichier scripts.js inclus permettra de gérer les actions relatives aux clics sur les titres des articles. La div dont l'id est articleContent est masquée dans la CSS. Cette div contiendra le contenu de l'article.

Le code PHP récupère la liste des articles Clubic et les affiches dans une liste de type ul.

Code Javascript

J'utilise la librairie JQuery qui simplifie quand même sacrément le code Javascript. Le fichier script.js commence par supprimer l'évènement click des liens. En effet, lorsqu'on clique sur un lien, on ne veut pas afficher la page de l'article, mais récupérer le contenu de l'article et le placer dans la div dont l'id est articleContent. On ajoute donc un écouteur sur l'évènement click aux éléments de liste li. Ce qui se passe lorsqu'on clique sur un li :

  • récupération de l'URL et du titre de l'article sur lequel on vient de cliquer
  • écriture du titre de l'article dans l'élément h1 de la div articleContent
  • on masque la liste ul et on affiche la div articleContent
  • appel AJAX vers un script PHP (getArticleContent.php) auquel on passe l'URL de l'article. Ce script se contente d'appeler la méthode ArticlesParser::getArticleContent pour récupérer le contenu de l'article
  • affichage du contenu de l'article récupéré dans la div realContent

Le code simple du script getArticleContent.php :

<?php
header('Content-Type: text/html; charset=iso-8859-1');
require_once('article.class.php');
echo ArticlesParser::getArticleContent($_POST['articleURL']);
?>

Et le code du fichier script.js :

$(document).ready(function(){
    // Disable links
    $('li[class="group"] a').click(function(event) {
        event.preventDefault();
    });
   
    // Click on <li>
    $('li[class="group"]').click(function(event) {
        // Get article URL
        var articleURL = $(this).children('a').attr('href');
       
        // Get article title
        var articlTitle = $(this).children('a').html();
       
        // Hide articles list and display article content
        $('#realContent').empty();
        $('#articleContent > h1').html(articlTitle);
        $('#content > ul').css('display', 'none');
        $('#articleContent').css('display', 'block');
       
        $.ajax({
            type: "POST",
            url: "getArticleContent.php",
            data: "articleURL="+ escape(articleURL),
            success: function(content){
                // Display content
                $('#realContent').html(content);
            },
            error: function() {
                alert('Erreur de connexion');
            }
        });
    });
   
    // Click on return
    $('#return').click(function(event) {
        $('#articleContent').css('display', 'none');
        $('#content > ul').css('display', 'block');
    });
});

Conclusion

Et voilà ! Evidemment cette application est très simple, mais c'était juste pour essayer. On pourrait y ajouter les commentaires, l'authentification sur le site, l'accès aux anciens articles, supprimer les vidéos flash (qui ne marchent pas sur iPhone) dans les articles, ...

Commentaires

kalvados

- 28/04/2010 à 11:20:00 - # 1

Salut dbanon,

J'étais tombé sur ton billet en cherchant une version de Clubic adaptée à la navigation depuis l'iPhone.
A ce moment, la version hébergée et les sources ne fonctionnaient plus à cause d'un changement dans le code des pages Clubic (simple quote au lieu de double quote ou l'inverse...) mais j'avais réussi à corriger la regex correspondante et je suis très vite devenu accro !
Au point d'avoir ajouté la possibilité de naviguer sur les différentes pages de news et d'avoir fait une version "desktop" pour l'utiliser sur ordi de bureau ou portable...
Seulement voila, le Clubic nouveau est arrivé... et iClubic s'en est allé.
Je suis incapable de me ré-habituer à la lecture des news depuis le site et me voila avec près de quinze jours de retard sur l'actualité ^^.
Je ferais très volontiers l'adaptation mais je maitrise très mal les Regex.
Si tu avais le temps et la patience de t'en occuper, je me ferais un plaisir de faire le reste et de donner les sources. Sinon ça va me prendre un moment et je ne suis pas sur d'y arriver.
Beau boulot de départ en tout cas, même si j'aurais du te le dire bien plus tôt !

Daniel

- 28/04/2010 à 14:22:49 - # 2

Salut Kalvados,

Je viens de mettre à jour l'application. Le principal problème venait du fait que la page "homeajax.php" n'existe plus. Elle est remplacée par la page "news-light.php" un peu plus compliquée à exploiter parce qu'elle demande des paramètres passés en POST.
A noter qu'on pourrait beaucoup plus simplement exploiter le flux RSS de Clubic, mais dans ce cas on serait limiter à un certain nombre d'articles.
A priori ça refonctionne, sauf sur certains types d'actu (je viens de m'en rendre compte) qui renvoie vers une page de téléchargement de logiciel. Bref, il faudrait quelques petites adaptations.
En tout cas, content de constater que quelqu'un se servait de cet article :D

Kalvados

- 29/04/2010 à 11:04:25 - # 3

Salut Daniel,

Quand je te disais que j'avais quinze jours de retard... je viens à l'instant de lire la news de Clubic où ils proposent la ré-intégration du flux condensé (16 avril) et par la même occasion de voir qu'il est déjà en place, ce qui m'aurait fait gagner du temps (ou prendre moins de retard) si je m'en était rendu compte plus tôt.

De plus, il me semble qu'il est bien plus facile à exploiter pour ton appli que la nouvelle Une du site (paramètres POST en plus certes, mais Regex plus simples et proches des anciennes ?).

Pour ce qui est des cas particuliers (dossier, test, fiche logiciel), j'avais déjà dû faire des adaptations sur l'ancien iClubic pour permettre une lecture de news ininterrompue.

Je vais mettre mon code à jour et t'en ferai profiter ;)

Ha et puis je voulais aussi te dire : le nom de ton blog est fabuleux !

Daniel

- 29/04/2010 à 11:22:34 - # 4

Je n'avais pas vu le flux condensé avant hier ! Et effectivement ça aide du coup puisque ça ressemble  beaucoup à l'ancienne version. En tout cas je serais ravi d'intégrer tes ajustements pour les actus particulières. En fait y aurait plein d'évol à faire, comme la navigation dans les anciennes actu, l'affichage des commentaires, ... mais parions que Clubic finira par sortir une version mobile bien mieux fichue que celle-là !

Kalvados

- 29/04/2010 à 12:16:10 - # 5

D'un côté on peut effectivement d'attendre à une "vraie" version mobile, mais il faut aussi s'attendre à ce qu'elle intègre un paquet de bandeaux publicitaires ou de pub qui s'affiche en surimpression comme sur la version normale...
C'est peut-être même ça qui freine l'arrivée d'une version mobile.
ça ne doit pas être évident de concilier l'affichage restreint à l'essentiel d'une version mobile et les contrats publicitaires qu'il faut honorer...

Pour ce qui de mes adaptations, ça ne va pas chercher bien loin, je me contente de mettre un lien vers la page Clubic. Par contre j'avais rajouté la navigation sur les différentes pages de news.

D'ailleurs, c'est normal que tu récupères la page 2 plutôt que la première dans ton code et sur la démo ?

J'ai des trucs à faire cet après-midi, mais je vais essayer de mettre à jour mon bazar vite fait...

Daniel

- 30/04/2010 à 14:55:55 - # 6

Oups, effectivement c'était pas normal que je récupère la page 2, c'est une erreur. Merci, je viens de corriger du coup.
J'aime bien les versions mobile en général, parce que justement, à cause de la petite taille des écrans, ils sont obligés de ne mettre que l'essentiel. Il suffit de voir l'appli voyages-sncf pour iPhone et le site internet pour s'en convaincre...
Maintenant je sais pas si c'est prévu côté Clubic.
Ce qu'il faudrait juste faire pour les actu de type téléchargement, dossier et compagnie, c'est ajouter une condition : si la regex de base n'est pas trouvée, alors on cherche une autre regex (correspondant à une page de téléchargement), si on trouve pas, on cherche une autre, ... le problème c'est d'être exhaustif !

Kalvados

- 29/04/2010 à 16:41:23 - # 7

Mouais mais bon en général, quand je navigue depuis mon iPhone c'est uniquement pour lire les news dans les transports en commun ou une file d'attente, donc déjà les "fiches télécharger" ça n'a pas d'intérêt...
Et puis si un dossier m'intéresse je peux toujours ouvrir le lien dans un nouvel onglet et garder mon flux de news dans l'onglet actuel.
Surtout que les dossiers sont sur plusieurs pages ce qui ajoute une difficulté supplémentaire si on veut les intégrer...

D'ailleurs tu as probablement remarqué que depuis plusieurs mois sur Clubic, si on tombe sur une news "dossier" on sort du flux et plus moyen d'aller à la news suivante, et ce n'est pas corrigé sur la nouvelle maquette... en fait mon adapation n'a fait que ré-implémenter l'ancien système (news avec lien vers dossier ou fiche...), l'intro en moins...

Daniel

- 29/04/2010 à 16:43:42 - # 8

C'est vrai qu'à la base j'avais créé ce truc juste pour lire les news dans le bus, la version normale n'étant vraiment pas adaptée. Bon maintenant j'avoue, je traine un peu plus sur PCInpact, qui a une version mobile donc bon... cette version est suffisante finalement pour ce que j'en fais !

Kalvados

- 12/12/2010 à 22:39:06 - # 9

Salut Daniel,

Bon ça fait un bail... mais j'ai vraiment été très occupé depuis un moment !

Enfin, ce week-end j'ai quand même pu passer un peu de temps sur iClubic qui était de nouveau inutilisable depuis quelques mois, et avec l'aide précieuse d'un ami spécialiste en php et regex, j'ai réussi à obtenir quelque chose de fonctionnel.

Ca ne se base plus sur le flux condensé, compliqué à exploiter à cause de l'Ajax, mais sur le flux standard de Clubic.

Il y a la navigation entre les pages, et la navigation rapide d'une news à l'autre sur une même page.

De plus il y a une détection des iPhone/iPod par le UserAgent pour lier selon le cas ta css d'origine ou une autre permettant la consultation sur un ordinateur (Clubic sans les pubs :)
Et en mode "desktop", on peut naviguer entre le news au clavier avec les flèches haut et bas.

Et voila les liens pour tester et récupérer le bidule.

http://www.colin-online.fr/Clubic
http://www.colin-online.fr/Clubic.rar

Cordialement,

Colin

Daniel

- 15/01/2011 à 20:36:02 - # 10

Salut !

Bon désolé pour le retard, j'avoue que je m'occupe plus trop de ce site (dès que j'en fais un en fait, je m'en occupe pendant 6 mois et après...).
Bref, je savais pas que iClubic marchait plus, et en tout cas ta version a l'air top !
Félicitations pour cette version. Je me demande quand même si une version mobile et/ou application n'est pas prévue par Clubic.

Bref, à une prochaine Colin !

TheBigSchtroumpf

- 09/05/2011 à 23:29:38 - # 11

Bravo à tous les 2!
Et c'est étonant que cluclu n'ai pas de version mobile.

Maciej

- 07/06/2011 à 10:52:50 - # 12

Pour info, Clubic a désormais une application Iphone et Android : http://www.clubic.com/application/index.html

Daniel

- 27/06/2011 à 21:58:08 - # 13

Oui j'ai vu ça, très bonne appli en plus. La version (foireuse) présentée sur ce site n'a donc plus aucun intérêt ;)

Nouveau commentaire

Clubic adapté à l'iPhone
iClubic
Catégories
Liens