Return false

Un blog IT de plus le blog de Hubebert.

Articles taggés avec ‘js’

“Tiens, je me suis fait 0.50€ pendant que j’étais aux toilettes, et déjà 1,54€ depuis mon premier café!”

Regis essayant myTwoCents

Écran de détail d'un compteur

Écran de détail d'un compteur

Après deux ans d’étude et d’inactivité bloguistique je retrouve le courage d’écrire quelque chose.

J’ai découvert récemment le framework jQueryMobile qui m’a paru franchement sympa et m’a donné envie de (re) jouer un peu avec le web mobile. J’ai donc réalisé une petite “webapp” pour l’occasion.

J’ai décidé réécrire un truc que j’adore: le module iGlande sur faineant.com: Une petite appli flash qui remplace le comptage de mouches par le comptage de brouzoufs quand on fout rien au boulot. Le but étant de se réjouir toute la journée en comptant combien on gagne chaque seconde.

Comme c’est du flash, et que mon téléphone n’aime pas ça, c’était l’occasion.

Pour ceux qui veulent essayer et s’amuser 5 minutes c’est par ici, pour les apprentis magiciens qui veulent des détails sur la réalisation, bonne lecture.

Je présente ici la partie stockage des données et calcul des compteurs. Pour plus de lisibilité la partie purement jQueryMobile fera l’objet d’un autre article.



TL;DR: scanne ça pour tester.

TL;DR: scanne ça pour tester.

Cahier des charges

Je veux :

  • savoir combien je gagne en temps réel
  • garder en mémoire les paramètres (compteurs, options…)
  • que mon salaire soit compté même quand je ne suis pas sur le site
  • pouvoir suivre plusieurs compteurs en parallèle (celui de ma femme, de ma dernière sieste et de mon dernier café)

Je ne veux pas:

  • de base de donnée (pas envie de me casser les pieds)
  • que les utilisateur puissent voir les compteurs des autres
  • de login  / mdp

Petite nuance par rapport au module iGlande: je ne compte pas le salaire au 35H, mais en heures réelles, afin que le compteur puisse continuer a tourner la nuit. Ça fait à peu près du 720H/Mois.

Au final, on code que dans 2 fichiers, le reste, c'est des frameworks et des plugins

Au final, on code que dans 2 fichiers, le reste, c'est le framework et les plugins

Les outils

Pour réaliser l’appli je vais utiliser:

  • du jQueryMobile (c’était le but après tout)
  • un plugin jQuery pour gérer les cookies
  • du jQuery tout court
  • un bon IDE et du café

Le stockage des données

Pour ne pas avoir à gérer de base de données et de login/mdp j’ai décidé de stocker les données côté client, dans son navigateur. En me réunissant avec moi même j’ai pensé a deux solutions:

les cookies

Les cookies sont ces sales petits trucs qui se stockent dans votre navigateur lorsque vous visitez des sites. Ça sert aussi bien a cibler la publicité qu’a connaître vos habitudes de surf nocturnes. Typiquement la case “se rappeller de moi” quand vous vous loguez sur un site,  utilise un cookie.

Les plus:

  • Tous les navigateurs les prennent en charge

Les moins:

Tous les navigateurs s’en méfient. Le stockage d’un cookie est effectué pour une durée donnée. Le problème c’est que l’abus de beaucoup de sites a conduit les navigateurs à êtres drastiques avec les cookies. Aucun moyen de savoir si la durée de stockage sera respectée, ou même si le navigateur acceptera de garder les cookies ne serais-ce que 20 secondes après la fermeture de la page.

le localStorage

Le localStorage c’est l’évolution logique du cookie, qui est apparu avec la norme HTML5. C’est encore peu utilisé et peu pris en charge, c’est à la fois un avantage et un inconvénient, les navigateurs et autres logiciels “nettoyeurs de trace” ont moins tendance a supprimer sauvagement le localStorage que les cookies.

Plus:

  • Plus rapide que les cookies
  • Pas de limitation de durée

Moins:

  • Pas géré par tous les navigateurs (notamment mobiles)

Écran principal

L'écran d'accueil

Comme souvent quand il faut choisir, j’ai décidé de prendre les deux solutions. Mon site devra donc regarder si le local Storage est disponible, et si ce n’est pas le cas, utiliser les cookies. Pour cela c’est très simple, le test suivant va nous dire pour le navigateur courant, si le localStorage est utilisable:

if (localStorage) {
debug("J'ai le localStorage");
}else{
debug("Je vais devoir utiliser les cookies...");
}

Maintenant la question des compteurs: comment faire compter un compteur côté client, lorsque que le client n’est pas sur la page?

C’est très simple: on ne peut pas.

On va donc fonctionner différemment. On stocke l’heure de démarrage du compteur, lorsqu’on voudra connaître l’argent gagné depuis, on fera la différence avec l’heure actuelle. En pratique ça donne ça:

On déclare des variables globales en tête de fichier

/**
* Global vars
*/
var debugConsole    =   true;//TODO: affiche les infos dans la console quand vrai, passer a false en prod
//Paramètres
var CURRENCY        =   "€";
var LOCAL_STORAGE   =   false;
var TICK            =   false;
var DISPLAY_BUTTON  =   false;
var NOTIF           =   false;
var NOTIF_CAPABLE   =   false;
var TIMERLAP        =   10;
//Données compteurs
var counterNames    =   Array();
var counterDates    =   Array();
var counterIncomes  =   Array();

Puis on les attribue en fonction de la détection du navigateur:

La dernière ligne de chaque bloc, écrit un texte dans l’écran de config afin d’informer l’utilisateur de la technique de stockage utilisée.

if (localStorage) {
LOCAL_STORAGE   =   true;
CURRENCY        =   localStorage.getItem("CURRENCY")==="true"       ?true:CURRENCY;
TICK            =   localStorage.getItem("TICK")==="true"           ?true:TICK;
DISPLAY_BUTTON  =   localStorage.getItem("DISPLAY_BUTTON")==="true" ?true:DISPLAY_BUTTON;
NOTIF           =   localStorage.getItem("NOTIF")==="true"          ?true:NOTIF;
$("#localStorageStatus").html("Great! Your browser can use localStorage. You maybe won't see the difference, but I will!");
debug(TIMERLAP);
} else {
LOCAL_STORAGE   =   false;
CURRENCY        =   $.cookie("CURRENCY")==="true"       ?true:CURRENCY;
TICK            =   $.cookie("TICK")==="true"           ?true:TICK;
DISPLAY_BUTTON  =   $.cookie("DISPLAY_BUTTON")==="true" ?true:DISPLAY_BUTTON;
NOTIF           =   $.cookie("NOTIF")==="true"          ?true:NOTIF;
$("#localStorageStatus").html("Your browser doens't have a localStorage. Data will be stored in cookies. If they get erased, you'll loose your data");

Du coup, chaque ajout de compteur prendra simplement la forme :

//Lecture des données
var name = $("#counterName").val();
var income = $("#monthIncome").val();
var startDate = new Date().getTime();
//Reset des champs de saisie
$("#counterName").val("");
$("#monthIncome").val("");

//Intégration dans les tableaux de compteurs
counterNames.push(name);
counterDates.push(startDate);
counterIncomes.push(income);
saveCounterValue();

La fonction saveCounterValue() se chargeant simplement de sauvegarder les tableaux au bon endroit selon la valeur de la variable LOCAL_STORAGE vue plus haut.

Ajout d'un compteur

Ajout d'un compteur

Le Calcul

Pour calculer combien d’argent on a gagné on boucle sur chaque compteur. On va alors déterminer la différence entre la date de départ de celui-ci et la date actuelle.

//Calcul de la différence entre maintenant et le début
delta = new Date().getTime() - counterDates[i];
//Conversion du revenu mensuel en revenu milliseconduel

Puis on va réduire un salaire mensuel, à un salaire par milliseconde. On commence par se demander combien vous gagnez par an (pour pouvoir gérer un revenu moyen indépendamment du fait que l’année soit bissextile ou non), pour le diviser ensuite par le nombre de milliseconde d’une année.

function monthlyToMillisecIncome(income){
var DAYS_PER_YEAR       =   365.25;
var MONTH_PER_YEAR      =   12;
var HOURS_PER_DAY       =   24;
var MINUTES_PER_HOUR    =   60;
var SEC_PER_MINUTE      =   60;
var MILLISEC_PER_MINUTE =   1000;
return income * MONTH_PER_YEAR / DAYS_PER_YEAR / HOURS_PER_DAY / MINUTES_PER_HOUR / SEC_PER_MINUTE / MILLISEC_PER_MINUTE;
}

On n’a plus qu’a appeler la fonction et à formater la chaîne à afficher…

millisecIncome = monthlyToMillisecIncome(thatIncome);
sofar = delta * millisecIncome;
sofar = Math.round(sofar * 100) / 100;//Arrondi a 2 décimales

//Formattage pour l'affichage du temps écoulé
tmpDate = new Date(delta);
elapsed = tmpDate.getUTCHours() +":"+tmpDate.getUTCMinutes()+ ":"+tmpDate.getUTCSeconds();

Voilà pour la partie backoffice de l’application. C’est loin d’être parfait, mais c’est fonctionnel et testable en ligne. Je compte encore passer quelques jours dessus si je trouve des choses intéressantes à y faire.

La partie jQueryMobile fera l’objet d’un prochain article.

Fun fact: j’ai gagné 1,87€ en rédigeant ce post.

TODOLIST:

  • Des notifications compatibles avec les  mobiles?
  • Une animation de l’icône lors d’une notification?
  • Une version multilingue?
  • Des supers idées proposées par les nofragés?