Contactez-nous
Kitpages
17 rue de la Frise
38000 Grenoble
tel : 04 58 00 33 81
Y.App et progressive enhancement (YUI Application framework)
Introduction et vocabulaire
Dans ce tutoriel, nous allons créer un mini site de quelques pages
- Single page website : Un site dont les changements de contenus ne se font qu'en ajax. Concrêtement dans le navigateur on ne change jamais de page.
- Progressive enhancement : Le principe consiste à créer un site qui fonctionne sans javascript et à ajouter des comportements javascripts pour améliorer l'expérience utilisateur, mais sans dégrader le service sans javascript.
Vous pouvez trouver l'exemple complet sur github
Ici on a un site avec plusieurs pages dont les transitions se font en Ajax si Javascript est actif et en HTML simple si Javascript est désactivé.
Je précise ici qu'on ne parle pas d'une application web déconnectée. Les problématiques sont un peu différentes.
Présentation de l'exemple
Cet exemple présente un site de 4 pages (home, about, liste d'objets, détail des objets).
Si javascript est désactivé, c'est un site on ne peut plus classique.
Si javascript est activé, on reste toujours sur la même page. La transition entre les contenus de pages se fait avec un fadeIn/fadeOut pour des pages "principales". Entre la liste d'objets et les détails d'objets, la transition se fait par un slide horizontal.
Pour visualiser un peu mieux le mode de fonctionnement de l'exemple, nous affichons le contenu sur un fond jaune quand l'affichage est en web classique et en vert quand Javascript est activé et que les changements de pages se font en Ajax.
Notez que dans la version javascript, l'adresse de la page dans la barre d'adresse est modifiée comme si on était dans un site web classique, et le bouton "back" fonctionne normalement.
Organisation des répertoires
Voilà l'organisation générale des répertoires. Le fichier vraiment important là dedans est le index.php.
Les autres sont plus "cosmétiques".
.htaccess
Ce fichier ne sert qu'à réorienter toutes les requêtes vers le index.php
RewriteEngine On RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^(.*)$ index.php [QSA,L]
index.php
index.php commence par un petit système de routage très simple qui permet de récupérer le fichier /page/list.php à partir d'une URL du type "http://example.com/page-list".
Le contenu du fichier /page/xxx.php est ensuite enregistré dans une variable $result.
<?php // extract page name and rootUrl $path = parse_url($_SERVER["REQUEST_URI"], PHP_URL_PATH); $pathTab = explode('/', $path); $path = array_pop($pathTab); $rootUrl = implode('/', $pathTab); $path = str_replace('\\', '', $path); $fileName = dirname(__FILE__).'/page/'.substr($path, 5).'.php'; // little routing system $result = null; if ( (strpos($path, 'page-')===0) && is_file($fileName) ) { ob_start(); include ($fileName); $result = ob_get_clean(); } ?>
On cherche ensuite à savoir si c'est une requête Ajax ou une requête classique (sachant que Y.App ajoute un header "X-PJAX" aux requêtes ajax).
<?php $displayTemplate = true; $headers = apache_request_headers(); if (isset($headers["X-PJAX"])) { $displayTemplate = false; }
Si ça n'est pas une requête ajax, on renvoie l'ensemble de la page avec tous les <html><head><body>...
<?php if ($displayTemplate) { // Display entire page, if not a pjax request ?> <html> <head> <title>Tuto Y.App</title> <script src="http://yui.yahooapis.com/3.8.0pr2/build/yui/yui-min.js"></script> </head> <body> <h1>Tuto Y.App</h1> <h2>navigation</h2> <ul> <li><a href="index.php">Home</a></li> <li><a href="page-about">About</a></li> <li><a href="page-list">List</a></li> </ul> <h2>Contenu à changer</h2> <div id="content" style="border: 1px solid #DDD; padding: 5px;background-color: #F8F8F8;"> <?php } ?>
On affiche ensuite le contenu de la page qu'on avait trouvé dans /page/xxx.php
(si on est en ajax, on n'affche que ça, sinon on affiche toute la structure html autour).
Ce contenu est affiché sur un fond vert quand on est en Ajax et sur un fond jaune quand on navigue sans javascript (juste pour faciliter la compréhension du mécanisme).
<div style="background-color: <?php echo $displayTemplate ? "#FFFF80": "#80FF80"?>; padding: 2px;margin: 5px;"> <pre style="font-size: 0.8em;color: #999;"> <?php echo "path=$path, file=$fileName"; ?> </pre> <?php if ($result) { echo $result; } else { ?> Page d'accueil <?php } ?> </div>
Le code Javascript à la fin de index.php
Ce code JS contient les étapes suivante :
- Définition de l'instance de Y.App
- Liste des routes avec le liens de parenté entre les routes
- transition: true indique qu'on veut des transitions sympa (fadein/out pour des pages indépendantes, slide left/right pour des pages parents/enfants
- viewContainer : div dans laquelle on insère le contenu chargé
- attribut root : indique le root_url de l'application. Il est utilisé par le routeur de Y.App pour retrouver ses petits
- app.route('*', 'loadContent', function(req, res, next) {...});
- Dit au router d'intercepter tous les changements d'URL ("*")
- le "loadContent" dit qu'il faut charger le contenu correspondant à l'URL demandée en Ajax
- le callback crée la vue Y.View et l'affiche dans le DOM
- app.render().dispatch() : lance l'instance de Y.App
YUI().use('app', 'node', function (Y) { var app = new Y.App({ views: { '/index.php': {}, '/page-about': {}, '/page-list': {}, '/page-detail': {parent:"/page-list"} }, transitions: true, viewContainer: '#content' }); app.set("root", "<?php echo $rootUrl; ?>"); app.route('*', 'loadContent', function(req, res, next) { this.showContent(res.content.node, {view: req.path}); }); app.render().dispatch(); });
Liens et conclusion
Voilà quelques liens liés à cet article :
On trouve peu d'exemples fonctionnels avec Y.App. Ici on présente un exemple de site classique avec des transitions javascript sympas.
Dans un futur tutoriel, je présenterai une application web déconnectée avec Y.App. Nous verrons que la problématique est en fait assez différente.
N'hésitez pas à envoyez vos remarques, corrections, félicitations,... dans les commentaires.
Commentaires
Note : on ne peut plus ajouter de commentaire sur ce site