Transformez un simple menu en tableau de bord dynamique
Posé ici le jeudi 03 décembre 2009 à 14:19 par
Je crois que ce que j'aime le plus dans mon métier, c'est de modifier radicalement, grâce à Css et Javascript, l'aspect et les fonctionnalités d'un élément d'une page web à priori sans intérêt. Aujourd'hui je m'amuse à booster un menu en liste non-ordonnée tout ce qu'il y a de plus bête en un tableau de bord dynamique.
Ce que je veux
Dans mon application, j'ai un menu qui mène à divers parties stratégiques et très souvent en mouvement, comme par exemple une gestion de commentaires ou de messages privés.
<ul id="menu">
<li class="comments"><a href="/comments">Commentaires</a></li>
<li class="messages"><a href="/messages">Messages</a></li>
<li class="favorites"><a href="/favorites">Favoris</a></li>
<li class="files"><a href="/files">Fichiers</a></li>
<li class="trash"><a href="/trash">Corbeille</a></li>
</ul>
L'utilisateur doit constamment cliquer sur l'un des liens accessibles pour savoir si un nouveau message est arrivé, un commentaire posté, etc.... L'idéal serait d'avoir en permanence un compteur d'éléments, toujours à jour, à côté de chaque lien. Ainsi, l'utilisateur est informé en tant réel des nouveaux éléments dans son application. Pour parfaire l'idée, on travaillera également le look and feel pour le rendre le menu un peu plus sexy et en adéquation avec sa nouvelle fonction de tableau de bord.
Mise en forme initiale
Internet regorge de librairies d'icônes libre d'utilisation (Veillez à bien lire et respecter les licences). Mon choix s'est arrêté sur ces icônes réalisés par Jonas Rask.
Armé de ces jolis icônes, on peut maintenant attaquer la feuille de style :
#menu li {
float:left;
list-style:none;
margin:10px;
position:relative;
}
#menu a {
display:block;
text-indent:-9999px;
width:32px; height:32px;
}
#menu .comments {
background:url(images/comments.png);
}
#menu .messages {
background:url(images/messages.png);
}
#menu .favorites {
background:url(images/favorites.png);
}
#menu .files {
background:url(images/files.png);
}
#menu .trash {
background:url(images/trash.png);
}
On place les éléments de la liste côte à côte (float:left) et on supprime la puce par défaut (list-style:none). Chaque lien est remplacé par une image. Rien de bien nouveau, ces techniques ont déjà été abordées plus en détail dans un article précédent. On en arrive au résultat suivant :
La Logique
Attaquons-nous maintenant à la logique. En pratique, l'idée est d'interroger les nouveaux résultats formaté Json sur le serveur par une requête Ajax lancée toutes les X secondes. Les résultats renvoyés par le serveur auront cette forme :
{ comments: 4,
messages: 5,
favorites: 0,
trash: 25,
files: 4
}
Côté serveur
Je ne vais pas m'étendre sur l'aspect serveur car il est à votre convenance. Dans mon exemple j'utilise Php. Créez donc un fichier data.php et à vous de jouer pour extraire les résultats de votre base de données.
<?php
// Ajoutez ici votre connexion à votre base de données ainsi que votre logique
// de comptage des éléments selon les besoins de votre application.
?>
{ comments: <?php echo $counter['comments'] ?>,
messages: <?php echo $counter['messages'] ?>,
favorites: <?php echo $counter['favorites'] ?>,
trash: <?php echo $counter['trash'] ?>,
files: <?php echo $counter['files'] ?>,
}
Côté client
Côté client, un script jQuery va appeler le fichier data.php et en récupérer les données. Les lignes de notre menu/liste seront itérées, on y ajoute un span contenant le nombre d'éléments qui nous est donné par le fichier Json précédemment généré en Php. Chaque entrée sera retrouvée grâce au nom de sa classe. Ainsi li avec la classe messages se verra attribuer la valeur Json messages:5, et ainsi de suite.
Concrètement la fonction de base donne ceci :
$(function() {
function dashboard() {
$.getJSON('data.php', function(data) {
// Itère toutes les lignes du menu #dashboard
$('#menuli').each(function() {
var li = $(this),
value = data[ li.attr('class') ],
span = $('<span>'+ value +'</span>');
li.find('span')
.remove()
.end()
.append(span);
});
});
setTimeout(dashboard, 10000); // rappel toutes les 10 secondes
}
dashboard();
});
Vous remarquerez que, comme la fonction est appelée en boucle toutes les 10 secondes, les éventuels span déjà présents dans le li sont supprimés avant d'en ajouter de nouveaux. Sinon on se retrouverait avec autant de compteur par ligne qu'il y a eu d'appel.
Pour que l'effet soit sympa, stylons maintenant les span nouvellement insérés.
#menu span {
border-radius:10em;
-moz-border-radius:10em;
-webkit-border-radius:10em;
border:1px solid #999;
background:#EFEFEF;
padding:2px 5px 2px 6px;
font:bold 9px Verdana, sans-serif;
color:#222;
position:absolute;
bottom:0;
right:0;
margin:-7px;
}
Le résultat finale devrait s'approcher de celui-ci.
Et enfin un plugin
Pour finir, tirons partie de la puissance de jQuery et de son système de plugin. Pour plus d'informations sur la réalisation de plugin jQuery, référez-vous à cet article.
Je profite du passage à l'état de plugin pour enrichir un peu le concept : Les compteurs apparaitrons avec une effet de fondu et les résultats qui changent du tour précédent seront indiqués plus clairement. Bien évidemment, j'ajoute les paramètres de configuration d'usage qui rendront le plugin flexible.
/**
* Tableau de bord
* par Jay Salvat - http://blog.jaysalvat.com/
*/
(function($) {
$.fn.dashboard = function(path, settings) {
var options = {
delay: 10000
};
$.extend(options, settings);
return this.each(function(){
var $$ = $(this);
pull();
function pull() {
$.getJSON(path, function(data) {
$('li', $$).each(function() {
var li = $(this),
span = $('span', li),
value = span.text(),
newValue = data[ li.attr('class') ],
newSpan = $('<span>'+ newValue +'</span>');
span.remove();
if (newValue) {
if (newValue != value) {
newSpan.addClass('new');
}
li.append(newSpan.fadeIn('slow'));
}
});
});
setTimeout(pull, options.delay);
}
});
};
})(jQuery);
Puis la feuille de style complète.
#menu li {
float:left;
list-style:none;
margin:10px;
position:relative;
}
#menu a {
display:block;
text-indent:-9999px;
width:32px; height:32px;
}
#menu .comments {
background:url(images/comments.png);
}
#menu .messages {
background:url(images/messages.png);
}
#menu .favorites {
background:url(images/favorites.png);
}
#menu .files {
background:url(images/files.png);
}
#menu .trash {
background:url(images/trash.png);
}
#menu span {
border-radius:10em;
-moz-border-radius:10em;
-webkit-border-radius:10em;
border:1px solid #999;
background:#EFEFEF;
padding:2px 5px 2px 6px;
font:bold 9px Verdana, sans-serif;
color:#222;
position:absolute; bottom:0; right:0;
margin:-7px;
}
#menu .new {
border:1px solid #F00;
background:#F00;
color:#FFF;
}
Usage
Comme d'habitude, il faut inclure jQuery et appliquer le plugin à votre liste (ici avec l'id #menu).
$(function() {
$('#menu').dashboard('data.php', { delay:10000 });
});
Ce contenu est mis à disposition selon les termes de la licence Creative Commons 2.0 France : Paternité, Pas d'Utilisation Commerciale, Partage des Conditions Initiales à l'Identique.
Context
Thématiques :
Trackbacks
0 trackback



Commentaires
12 commentaires
Sympathique pour qui veut développer un CMS par exemple ou un intranet :) On pourrait même imaginer ce système pour afficher en temps réel les nouvelles sur un site en fonction de cookie ou compte utilisateur loggé. j'avoue ne pas avoir vu l'utilité de la chose étant bloqué sur l'aspect très "bureau OS" de l'exemple, masi en fouillant bien c'est très interessant :P je note l'existence de ce nouveau plugin :)
1. Par 10-nice le jeudi 03 décembre 2009 à 15:12
Je me régale toujours autant à te lire... juste le regret de n'avoir point le temps de mettre en place la multitude de fonctionnalités que je découvre ici et ailleurs !
2. Par Emmanuel le jeudi 03 décembre 2009 à 20:24
text-indent:-9999px;
je me demande si cette technique est accessible!?
Si on désactive les images, on a plus rien!
3. Par Hubert le dimanche 06 décembre 2009 à 01:35
Bonsoir Hubert,
Non cette technique n'est toujours pas accessible (la même que dans le précédent article). Une fois encore, si ton soucis est l'accessibilité totale, les fantaisies graphiques de ce type sont à proscrire.
Ci-dessous un excellent article (en anglais) sur les différentes techniques de remplacement et leur niveau d'accessibilité.
Css-tricks.com/…age-replacement
A toi d'utiliser celle qui te convient le mieux, voire aucune pour une accessibilité totale.
4. Par Jay Salvat le dimanche 06 décembre 2009 à 17:32
Bonjour,
Je suis tombé seulement aujourd'hui sur votre blog et je n'ai pas résisté a y passé des heures !
néanmoins je me suis essayer à réaliser ce tuto, et je suis bloqué.
Concernant la partie "client" je ne sais pas comment faire appel au script...
Mes fichiers sont:
index.php (où je définit ma liste)
style.css
data.php(j'ai rentré les valeurs en dur pour le moment)
count.js (j'y ai collé le plugin (juste au dessus de la feuille css complète))
voila mon problème: quand je met <script type="text/javascript" src="count.js"></script> dans la balise <head> ça ne change absolument rien et si je fait appel a une fonction via
$(function() {
$('#menu').dashboard('data.php', { delay:10000 });
});
ça plante avec ce message d'erreur:
parse error, expecting `T_VARIABLE' or `'$'' in C:\wamp\www\bar\index.php on line 18
je sais que c'est pas le meilleur endroit pour demandé de l'aide mais on ne sais jamais ...
sur ce, à bientôt ;)
5. Par Geoffrey le vendredi 12 février 2010 à 17:49
Bonsoir Geoffrey,
Ce script marche avec jQuery, as-tu inclus la librairie jQuery ?
Pour l'erreur PHP à la ligne 18, je ne peux pas te dire grand chose d'ici, je ne sais pas ce qui se trouve à ta ligne 18 :)
6. Par Jay Salvat le dimanche 14 février 2010 à 23:23
encore moi :D
Bon je me suis rendu compte qu'il ne suffisait pas simplement de copier collé le code bêtement, et que pour saisir les opportunités offertes pas Jquery il allait falloir, mettre les mains dans le cambui ^^
Je me suis donc penché sur le Javascript et après avoir fait plusieurs essaies positifs me revoilà sur ce tuto ^^
Donc pour répondre à ta question, oui j'inclus la librairie jquery
<script type="text/javascript" src="jquery.js"></script> (dans la balise <head>) Bon en fait mon erreur php venait du fait que je plaçais ce code dans "index.php":
$(function() {
$('#menu').dashboard('data.php', { delay:10000 });
});
en fait indépendamment je comprend comment marche ces fonction (a peut pres ^^) mais je ne perçois pas très bien comment les organiser... quels code mettre dans quels fichiers...
Pour info voici mon architecture pour l'instant:
index.php
style.css
data.php
count.php
jquery.js
dashboard.js
plugin.js
je n'ai pas d'erreurs, le tableau s'affiche correctement mais je n'ai pas les chiffre devant les items :(
Dsl de vous embêter encore une fois mais ce tuto correspond exactement à ce que je voudrais faire pour mon site :D
7. Par Geoffrey le jeudi 18 février 2010 à 13:39
Bonjour Geoffrey,
Rien de si compliqué. Il te faut :
- Un fichier index.html (ou php) qui inclus jQuery et qui contient ta liste html, tes styles CSS et le code du plugin.
- Un fichier data.php qui contient tes valeurs.
Et c'est tout. Je t'invite à regarder comment est fait la démo :
Blog.jaysalvat.…/demo/dashboard
Après à toi de séparer les différentes portions de code dans des fichiers séparés selon ta logique : styles.css, plugin.js etc...
8. Par Jay Salvat le jeudi 18 février 2010 à 14:06
Je ne pensais pas avoir accès aux script en faisant un banal Ctrl+u sur la démo !!
c'est vrai que avec ces infos ça devient beaucoup plus clair.
Le code marche super, j'ai plus qu'a séparer ça en plusieurs fichiers :D
Merci pour le tuto ET le support ;)
9. Par Geoffrey le jeudi 18 février 2010 à 15:01
Bonjours,
Comment faire lorsqu'on veut changer les fichiers "data" et "jquery" de place ? si je les met à la racine du site ça marche sinon non .
Décidément il m'aura donné du mal celui là ! :s
merci :)
10. Par Geoffrey le samedi 20 février 2010 à 11:39
j'ai toujours pas compris comment marchai le positionnement, les lien doivent être relatif à jquery ...
quoi qu'il en soit, après ces quelques heures d'acharnement j'ai trouvé une solution convenable :)
11. Par Geoffrey le samedi 20 février 2010 à 17:07
Superbe script très bien écris, chapeau bas Mr ;)
12. Par The_Death_Raw le mercredi 18 août 2010 à 00:48