[Code] Déterminer les prochaines dates palindromes

Standard

Calendrier
Aujourd’hui, 21/02/2012, est une date palindrome, c’est-à-dire que l’ordre des lettres reste le même qu’on le lise de gauche à droite ou de droite à gauche comme le mot “kayak” (par exemple et pris au hasard !). Je ne sais pas si vous êtes superstitieux, mais en tout cas les dates palindromes sont très rares ! La prochaine sera en effet le 02/02/2020, dans 8 ans.

J’ai eu l’idée de créer un algorithme inutile (donc indispensable) pour trouver les prochaines dates palindromes dans les X prochaines années. Je partage avec vous ce bout de code, qui ne sera surement pas très utile dans la pratique mais a au moins un intérêt théorique. Et puis comme ça vous pourrez déjà noter dans votre calendrier ces dates si exceptionnelles (ou presque !).

Code de test des dates palindromes

Cet algorithme est écrit en PHP. Pour un test sur les 20 prochaines années, on obtient le résultat suivant :
Test dates palindromes

Voici le code source :

Je pense avoir suffisamment détaillé le code source pour qu’il soit facilement compréhensible. Si jamais vous ne compreniez pas un passage, n’hésitez pas à me demander !

Sur ce, je vous laisse, je retourne fêter la fin de ce jour palindrome comme il se doit !

[CODE] Créer de beaux diagrammes avec l’API Google

Standard

Pie chartL’API de Google permet de générer de beaux graphiques dynamiques afin de présenter de manière agréable et facilement lisible vos données. Vous pouvez réaliser des “camemberts”, des diagrammes en bâtons, des diagrammes à bandes, des diagrammes à lignes brisées, des boites à moustaches… Mais vous pouvez également utiliser un fond de carte du monde pour réaliser des statistiques sur des pays (visiteurs de votre site par pays par exemple).

Exemple : diagramme en camembert

Je vais m’attacher à vous expliquer comme réaliser un diagramme en camembert montrant le top 5 du nombre de messages par auteur, sur un forum par exemple. La génération de ce diagramme se fera à partir de données enregistrées en bases de données, il est donc totalement dynamique puisqu’il s’adapte aux données présentes dans les tables. On veut voir l’importance du top 5 des auteurs de messages dans notre forum, on doit représenter en une seule “portion” le nombre de messages des autres utilisateurs. Voici le code complet de la page, détaillé à l’aide de commentaires :

Voici le résultat que l’on obtient avec des données prisent arbitrairement :

A vous d’adapter le code précédent à votre besoin ! La documentation complète de l’API Google Charts est disponible juste ici, je vous invite à la consulter.

[CODE] L’Ajax, c’est pas si compliqué que ça

Standard

Ajax
En utilisant Ajax dans un site web, un programme écrit en langage de programmation Javascript, incorporé dans une page web, est exécuté par le navigateur. Celui-ci envoie des demandes de calcul au serveur Web, puis modifie le contenu de la page actuellement affichée par le navigateur Web en fonction du résultat reçu du serveur, évitant ainsi la transmission et l’affichage d’une nouvelle page.

Voici pour la partie théorique, pour simplifier nous dirons que l’Ajax permet d’exécuter des actions côté serveur et de mettre à jour une page web côté utilisateur sans que ce dernier ne doive avoir à recharger la page, le changement se fait pour lui de manière quasi instantanée.

Pratique

Pour vous apprendre comment utiliser l’Ajax, je vais utiliser mon site Teen Quotes avec lequel j’avais déjà montré comment faire des traductions, créer un site mobile et comment traquer ses erreurs 404.

Comme nous l’avons vu, il faut pour utiliser Ajax, faire appel à du JavaScript. J’utilise la librairie jQuery qui facilite l’utilisation d’Ajax. Pour utiliser le script suivant, vous devrez donc inclure la dernière version de jQuery auparavant.

Code ajax.js

// déclaration de la fonction et des variables qui seront utilisées
function favorite(id_quote,id_user) {
	$(".favorite[data-id="+id_quote+"]").html("Wait..."); // texte que verra l'utilisateur sur l'élement HTML cible pendant l’exécution de la requête
	$.ajax({ // l'url désigne la page distante où le code PHP sera éxécuté, data désigne les variables qui seront envoyées ici en post à cette page
		type: 'post',
		url: 'http://teen-quotes.com/ajax/favorite.php',
		data: {
			id_quote: id_quote,
			id_user: id_user
		},
		success: function(data) {
			$(".favorite[data-id="+id_quote+"]").html(data);
		} // affiche un message définit dans la page PHP sur l'élément HTML ciblé quand la requête a été exécutée avec succès
	});
	
	return false;
}

J’ai bien détaillé chaque partie du code JavaScript, vous ne devriez pas avoir de mal à comprendre celui-ci.

Vous avez donc vu que nous faisons appel à une page distante, qui servira à exécuter l’action voulue puis à mettre à jour l’affichage de notre page.

Code de la page ajax/favorite.php

 
// Permet d’exécuter la page depuis un domaine extérieur ou un sous-domaine
header("Access-Control-Allow-Origin: *");

// Connexion en base de données
require "../kernel/config.php";
$db = mysql_connect($host, $user, $pass)  or die('Erreur de connexion '.mysql_error());
mysql_select_db($user, $db)  or die('Erreur de selection '.mysql_error()); 
require "../kernel/fonctions.php";

// Récupération des données envoyées par le script JS
$id_quote = mysql_real_escape_string($_POST['id_quote']);
$id = mysql_real_escape_string($_POST['id_user']);

// vérification que la requête ne provient pas d'un serveur externe
if (preg_match('/teen-quotes.com/', $_SERVER['SERVER_NAME'])) 
{
	if (empty($id_quote))
		echo 'Erreur id !';
	else
	{
		$query = mysql_query('INSERT INTO teen_quotes_favorite (id_quote, id_user) VALUES ('.$id_quote.','.$id.')');

		if ($query) 
			echo $add_succes;
		else
			echo $error;
	}
}
else
	echo ''.$_SERVER['SERVER_NAME'].'';

Encore une fois, rien de très compliqué, je pense avoir suffisamment détaillé pour que vous puissiez comprendre facilement.

Maintenant que notre Javascript va pouvoir éxécuter notre page PHP puis mettre à jour l’affichage, il ne reste plus qu’à appeler notre fonction JavaScript dans notre page de la manière suivante :

Vous devez faire en sorte que les informations que vous souhaitez envoyer à la fonction JavaScript soient dans le bon ordre, dans notre cas 900 désigne donc id_quote et 42 id_user

Pensez à bien cibler l’élément HTML dont vous souhaitez mettre à jour le contenu, une fois la requête exécutée avec succès, l’ancien contenu texte sera effacé et mis à jour par ce que vous avez défini dans votre page appelée par votre fonction JavaScript.

Vous voilà donc prêts à utiliser l’Ajax a foison, vous avez les clés en main !

Les outils pour développeurs web

Standard

Outils
Coder c’est bien, mais coder plus vite c’est encore mieux. Il existe des tâches rébarbatives dont on se passerait volontiers et auxquelles on aimerait consacrer moins de temps. De même, il existe des outils qui nous permettent d’optimiser nos performances ou nos manières de travailler toujours dans une logique de produire un travail de haute qualité, optimisé et propre sur un plan technique, le plus rapidement possible.

Dans cet article je vais vous présenter divers outils que j’utilise pour travailler et qui me sont bien utiles au quotidien. J’espère qu’ils le seront pour vous aussi et qu’ils vous permettront d’accroître votre productivité ou simplement de vous faciliter la vie.

Optimiser votre site

La recherche de performance doit être constante : toujours plus rapide à charger, toujours moins de requêtes HTTP à exécuter, toujours moins d’espace disque utilisé… C’est la somme de toutes ces petites choses qui fera de votre site un monstre sur un plan technique.

  • CSS Sprites

Outils
Si vous ne connaissez pas encore cette technique, je vous renvoie à cet excellent tutoriel d’Alsacreations qui vous détaillera ce que sont les CSS Sprites et comment s’en sert t’on.

Le principe général consiste à créer une grande image regroupant plusieurs petites images (des icônes, ou des images qui possèdent une image normale et une image pour le hover par exemple !) et de les afficher en jouant sur la propriété background-position en CSS.

Le site csssprites.com fait presque tout le travail à notre place. Il suffit de lui fournir toutes les images que l’on souhaite mettre dans notre Sprite et le site se charge de “fusionner” toutes ces images en une seule et de générer le CSS qui va de paire.

  • smush.it

Toujours pour les images, smush.it permet de réduire le poids des images sans altérer leur qualité. Une image avec un poids plus faible permet de charger plus rapidement la page, ce qui est très important si votre site comporte de nombreuses images par exemple. punypng.com propose les mêmes services que smush.it.

Si vous créez vos images vous même, pensez bien à choisir “Enregistrer pour le web”. Vous pouvez également réduire le poids d’une image en PNG en la convertissant en JPG, en ouvrant ce JPG et en l’enregistrant à nouveau en PNG.

Merci à @mygbb pour cette astuce.

  • Clean CSS

Votre code CSS n’est jamais très clair ? Vous ne savez pas comment l’organiser ? Il n’est jamais optimisé ? Le site cleancss.com fait le travail à votre place en organisant votre code CSS et en l’optimisant, ainsi, vous aurez une feuille de style rapide à charger et plus facile à modifier par la suite.

Je vous conseille de choisir l’option “Très compact” de compression et je vous laisse cocher ce qui vous convient pour la suite des options. Attention aux propriétés CSS 3 que cleancss ne reconnait pas toujours ! N’hésitez pas à les inclure après la compression par le site.

  • Javascript Compressor

Dans la même logique que Clean CSS, Javascript Compressor compresse votre code JavaScript, de quoi gagner encore un peu de temps au chargement.

Des outils pour vous faciliter la vie

  • Border Radius

Border Radius est selon moi la propriété CSS3 la plus intéressante et la plus utile pour nous autres, développeurs. Créer des bordures arrondies avec seulement quelques lignes de code, quel rêve ! Néanmoins le rêve tourne au cauchemar quand on veut utiliser ces bordures arrondies uniquement sur certains coins. La preuve en code :

/* Utilisation classique aux 4 coins */
-webkit-border-radius: 10px;
-moz-border-radius: 10px;
border-radius: 10px;

/* Utilisation uniquement sur les coins inférieurs */
-webkit-border-bottom-right-radius: 10px;
-webkit-border-bottom-left-radius: 10px;
-moz-border-radius-bottomright: 10px;
-moz-border-radius-bottomleft: 10px;
border-bottom-right-radius: 10px;
border-bottom-left-radius: 10px;

Ça se complique hein ? Heureusement border-radius.com se charge de générer le code pour nous : il suffit de rentrer les valeurs désirées en pixels aux 4 coins de la bordure et le site nous montre la forme obtenue et le code nécessaire pour réaliser ceci. Facile, n’est ce pas ?

  • Text Shadow

Comme border-radius, text-shadow est une propriété CSS3. Elle permet de rajouter de l’ombre interne ou externe sur un texte ce qui donne un effet sympathique, sans avoir besoin de créer une image pour un texte ! Encore une facilité pour les développeurs webs ! William Agay (@william_agay) propose un outil pour tester cette propriété en ligne et observer les variations quand on change des valeurs : www.css3dev.williamagay.fr

  • Tabifier

Un code bien indenté est un code beaucoup plus lisible et donc beaucoup plus facile et rapide à modifier. Même si chacun s’efforce de bien indenter son propre code, il est parfois utile de faire appel à de petits utilitaires qui le font à notre place (et qui eux le font bien !).

Tabifier fonctionne avec le HTML, le CSS et le C (dommage pour le PHP !), il vous faudra néanmoins que votre code soit valide car Tabifier se contente d’indenter votre code, et non de le corriger (ce qui est déjà pas mal) !

  • Code couleur

code-couleur.com est un site mettant à votre disposition une palette qui permet d’obtenir le code HTML d’une couleur et d’un autre outil qui vous permet d’obtenir l’aperçu d’une couleur à partir d’un code HTML.

Sont également présentes sur le site diverses palettes de couleurs qui vous seront bien utiles lors d’une recherche de tons pour votre site !

Retrouvez mes codes source sur GitHub

Standard


Il peut être parfois intéressant de jeter un coup d’oeil au code source d’autres développeurs afin de découvrir de nouvelles fonctionnalités, des logiques d’organisation, de nouvelles méthodes ou juste pour la curiosité, savoir “comment fonctionne” ce projet.

C’est pourquoi je mets à votre disposition mon GitHub où vous pourrez retrouver l’intégralité du code source de mes projets. N’hésitez donc pas à jeter un oeil, à fouiner où l’envie vous chante et surtout de me poser des questions si vous ne comprenez pas quelque chose ! C’est toujours un plaisir d’échanger avec d’autres développeurs et de s’enrichir mutuellement.

J’essaie de mettre à jour assez régulièrement les projets sur lesquels je travaille actuellement (en particulier Teen Quotes, P-W.fr et ClockFace) en faisant des push tous les 2 jours environ. Si vous êtes intéressés par d’autres code source qui ne sont pas disponibles sur mon GitHub, n’hésitez pas à me contacter.

Les sites web pour mobile : développement et optimisation

Standard


Le web mobile est en pleine expansion ! J’avais écrit un article il n’y a pas si longtemps là dessus, vous pouvez toujours aller jeter un oeil par ici (STATS : Mobile around the world). En bref, le secteur du mobile n’est pas à laisser de côté, surtout si votre projet possède une utilité directe en déplacement ou qu’il peut être facilement adapté pour être consulté sur un support mobile. Dès lors, il est parfois nécessaire de proposer une version mobile de son site web pour couvrir les besoins de ses utilisateurs.

Détection et redirection automatique de l’utilisateur sur appareil mobile

Dans la plupart de vos projets il est fortement recommandé de faire 2 parties bien distinctes de votre site si vous décidez de pouvoir proposer une version mobile. Par convention, on utilise www.exemple.com pour la version principale de votre site et m.exemple.com ou www.exemple.com/mobile/ pour la version mobile. J’ai une préférence pour la version sous-domaine, qui me semble plus claire (et surtout plus courte comme URL !). En proposant ainsi 2 versions, il est nécessaire d’orienter l’utilisateur vers la version qui sera la plus adaptée à son support.

Voici donc un exemple que j’utilise pour gérer cette redirection :

function mobile_device_detect($iphone=true,$android=true,$opera=true,$blackberry=true,$palm=true,$windows=true,$mobileredirect=true,$desktopredirect=false){

  $mobile_browser   = false; // set mobile browser as false till we can prove otherwise
  $user_agent       = $_SERVER['HTTP_USER_AGENT']; // get the user agent value - this should be cleaned to ensure no nefarious input gets executed
  $accept           = $_SERVER['HTTP_ACCEPT']; // get the content accept value - this should be cleaned to ensure no nefarious input gets executed
  $iphone="http://m.teen-quotes.com";
  $android=$iphone;
  $opera=$iphone;
  $blackberry=$iphone;
  $palm=$iphone;
  $windows=$iphone;

  switch(true){ // using a switch against the following statements which could return true is more efficient than the previous method of using if statements

    case (eregi('ipod',$user_agent)||eregi('iphone',$user_agent)); // we find the words iphone or ipod in the user agent
      $mobile_browser = $iphone; // mobile browser is either true or false depending on the setting of iphone when calling the function
      $status = 'Apple';
      if(substr($iphone,0,4)=='http'){ // does the value of iphone resemble a url
        $mobileredirect = $iphone; // set the mobile redirect url to the url value stored in the iphone value
      } // ends the if for iphone being a url
    break; // break out and skip the rest if we've had a match on the iphone or ipod

    case (eregi('android',$user_agent));  // we find android in the user agent
      $mobile_browser = $android; // mobile browser is either true or false depending on the setting of android when calling the function
      $status = 'Android';
      if(substr($android,0,4)=='http'){ // does the value of android resemble a url
        $mobileredirect = $android; // set the mobile redirect url to the url value stored in the android value
      } // ends the if for android being a url
    break; // break out and skip the rest if we've had a match on android

    case (eregi('opera mini',$user_agent)); // we find opera mini in the user agent
      $mobile_browser = $opera; // mobile browser is either true or false depending on the setting of opera when calling the function
      $status = 'Opera';
      if(substr($opera,0,4)=='http'){ // does the value of opera resemble a rul
        $mobileredirect = $opera; // set the mobile redirect url to the url value stored in the opera value
      } // ends the if for opera being a url 
    break; // break out and skip the rest if we've had a match on opera

    case (eregi('blackberry',$user_agent)); // we find blackberry in the user agent
      $mobile_browser = $blackberry; // mobile browser is either true or false depending on the setting of blackberry when calling the function
      $status = 'Blackberry';
      if(substr($blackberry,0,4)=='http'){ // does the value of blackberry resemble a rul
        $mobileredirect = $blackberry; // set the mobile redirect url to the url value stored in the blackberry value
      } // ends the if for blackberry being a url 
    break; // break out and skip the rest if we've had a match on blackberry

    case (preg_match('/(pre\/|palm os|palm|hiptop|avantgo|fennec|plucker|xiino|blazer|elaine)/i',$user_agent)); // we find palm os in the user agent - the i at the end makes it case insensitive
      $mobile_browser = $palm; // mobile browser is either true or false depending on the setting of palm when calling the function
      $status = 'Palm';
      if(substr($palm,0,4)=='http'){ // does the value of palm resemble a rul
        $mobileredirect = $palm; // set the mobile redirect url to the url value stored in the palm value
      } // ends the if for palm being a url 
    break; // break out and skip the rest if we've had a match on palm os

    case (preg_match('/(iris|3g_t|windows ce|opera mobi|windows ce; smartphone;|windows ce; iemobile)/i',$user_agent)); // we find windows mobile in the user agent - the i at the end makes it case insensitive
      $mobile_browser = $windows; // mobile browser is either true or false depending on the setting of windows when calling the function
      $status = 'Windows Smartphone';
      if(substr($windows,0,4)=='http'){ // does the value of windows resemble a rul
        $mobileredirect = $windows; // set the mobile redirect url to the url value stored in the windows value
      } // ends the if for windows being a url 
    break; // break out and skip the rest if we've had a match on windows

    case (preg_match('/(mini 9.5|vx1000|lge |m800|e860|u940|ux840|compal|wireless| mobi|ahong|lg380|lgku|lgu900|lg210|lg47|lg920|lg840|lg370|sam-r|mg50|s55|g83|t66|vx400|mk99|d615|d763|el370|sl900|mp500|samu3|samu4|vx10|xda_|samu5|samu6|samu7|samu9|a615|b832|m881|s920|n210|s700|c-810|_h797|mob-x|sk16d|848b|mowser|s580|r800|471x|v120|rim8|c500foma:|160x|x160|480x|x640|t503|w839|i250|sprint|w398samr810|m5252|c7100|mt126|x225|s5330|s820|htil-g1|fly v71|s302|-x113|novarra|k610i|-three|8325rc|8352rc|sanyo|vx54|c888|nx250|n120|mtk |c5588|s710|t880|c5005|i;458x|p404i|s210|c5100|teleca|s940|c500|s590|foma|samsu|vx8|vx9|a1000|_mms|myx|a700|gu1100|bc831|e300|ems100|me701|me702m-three|sd588|s800|8325rc|ac831|mw200|brew |d88|htc\/|htc_touch|355x|m50|km100|d736|p-9521|telco|sl74|ktouch|m4u\/|me702|8325rc|kddi|phone|lg |sonyericsson|samsung|240x|x320vx10|nokia|sony cmd|motorola|up.browser|up.link|mmp|symbian|smartphone|midp|wap|vodafone|o2|pocket|kindle|mobile|psp|treo)/i',$user_agent)); // check if any of the values listed create a match on the user agent - these are some of the most common terms used in agents to identify them as being mobile devices - the i at the end makes it case insensitive
      $mobile_browser = true; // set mobile browser to true
      $status = 'Mobile matched on piped preg_match';
    break; // break out and skip the rest if we've preg_match on the user agent returned true 

    case ((strpos($accept,'text/vnd.wap.wml')>0)||(strpos($accept,'application/vnd.wap.xhtml+xml')>0)); // is the device showing signs of support for text/vnd.wap.wml or application/vnd.wap.xhtml+xml
      $mobile_browser = true; // set mobile browser to true
      $status = 'Mobile matched on content accept header';
    break; // break out and skip the rest if we've had a match on the content accept headers

    case (isset($_SERVER['HTTP_X_WAP_PROFILE'])||isset($_SERVER['HTTP_PROFILE'])); // is the device giving us a HTTP_X_WAP_PROFILE or HTTP_PROFILE header - only mobile devices would do this
      $mobile_browser = true; // set mobile browser to true
      $status = 'Mobile matched on profile headers being set';
    break; // break out and skip the final step if we've had a return true on the mobile specfic headers

    case (in_array(strtolower(substr($user_agent,0,4)),array('1207'=>'1207','3gso'=>'3gso','4thp'=>'4thp','501i'=>'501i','502i'=>'502i','503i'=>'503i','504i'=>'504i','505i'=>'505i','506i'=>'506i','6310'=>'6310','6590'=>'6590','770s'=>'770s','802s'=>'802s','a wa'=>'a wa','acer'=>'acer','acs-'=>'acs-','airn'=>'airn','alav'=>'alav','asus'=>'asus','attw'=>'attw','au-m'=>'au-m','aur '=>'aur ','aus '=>'aus ','abac'=>'abac','acoo'=>'acoo','aiko'=>'aiko','alco'=>'alco','alca'=>'alca','amoi'=>'amoi','anex'=>'anex','anny'=>'anny','anyw'=>'anyw','aptu'=>'aptu','arch'=>'arch','argo'=>'argo','bell'=>'bell','bird'=>'bird','bw-n'=>'bw-n','bw-u'=>'bw-u','beck'=>'beck','benq'=>'benq','bilb'=>'bilb','blac'=>'blac','c55/'=>'c55/','cdm-'=>'cdm-','chtm'=>'chtm','capi'=>'capi','cond'=>'cond','craw'=>'craw','dall'=>'dall','dbte'=>'dbte','dc-s'=>'dc-s','dica'=>'dica','ds-d'=>'ds-d','ds12'=>'ds12','dait'=>'dait','devi'=>'devi','dmob'=>'dmob','doco'=>'doco','dopo'=>'dopo','el49'=>'el49','erk0'=>'erk0','esl8'=>'esl8','ez40'=>'ez40','ez60'=>'ez60','ez70'=>'ez70','ezos'=>'ezos','ezze'=>'ezze','elai'=>'elai','emul'=>'emul','eric'=>'eric','ezwa'=>'ezwa','fake'=>'fake','fly-'=>'fly-','fly_'=>'fly_','g-mo'=>'g-mo','g1 u'=>'g1 u','g560'=>'g560','gf-5'=>'gf-5','grun'=>'grun','gene'=>'gene','go.w'=>'go.w','good'=>'good','grad'=>'grad','hcit'=>'hcit','hd-m'=>'hd-m','hd-p'=>'hd-p','hd-t'=>'hd-t','hei-'=>'hei-','hp i'=>'hp i','hpip'=>'hpip','hs-c'=>'hs-c','htc '=>'htc ','htc-'=>'htc-','htca'=>'htca','htcg'=>'htcg','htcp'=>'htcp','htcs'=>'htcs','htct'=>'htct','htc_'=>'htc_','haie'=>'haie','hita'=>'hita','huaw'=>'huaw','hutc'=>'hutc','i-20'=>'i-20','i-go'=>'i-go','i-ma'=>'i-ma','i230'=>'i230','iac'=>'iac','iac-'=>'iac-','iac/'=>'iac/','ig01'=>'ig01','im1k'=>'im1k','inno'=>'inno','iris'=>'iris','jata'=>'jata','java'=>'java','kddi'=>'kddi','kgt'=>'kgt','kgt/'=>'kgt/','kpt '=>'kpt ','kwc-'=>'kwc-','klon'=>'klon','lexi'=>'lexi','lg g'=>'lg g','lg-a'=>'lg-a','lg-b'=>'lg-b','lg-c'=>'lg-c','lg-d'=>'lg-d','lg-f'=>'lg-f','lg-g'=>'lg-g','lg-k'=>'lg-k','lg-l'=>'lg-l','lg-m'=>'lg-m','lg-o'=>'lg-o','lg-p'=>'lg-p','lg-s'=>'lg-s','lg-t'=>'lg-t','lg-u'=>'lg-u','lg-w'=>'lg-w','lg/k'=>'lg/k','lg/l'=>'lg/l','lg/u'=>'lg/u','lg50'=>'lg50','lg54'=>'lg54','lge-'=>'lge-','lge/'=>'lge/','lynx'=>'lynx','leno'=>'leno','m1-w'=>'m1-w','m3ga'=>'m3ga','m50/'=>'m50/','maui'=>'maui','mc01'=>'mc01','mc21'=>'mc21','mcca'=>'mcca','medi'=>'medi','meri'=>'meri','mio8'=>'mio8','mioa'=>'mioa','mo01'=>'mo01','mo02'=>'mo02','mode'=>'mode','modo'=>'modo','mot '=>'mot ','mot-'=>'mot-','mt50'=>'mt50','mtp1'=>'mtp1','mtv '=>'mtv ','mate'=>'mate','maxo'=>'maxo','merc'=>'merc','mits'=>'mits','mobi'=>'mobi','motv'=>'motv','mozz'=>'mozz','n100'=>'n100','n101'=>'n101','n102'=>'n102','n202'=>'n202','n203'=>'n203','n300'=>'n300','n302'=>'n302','n500'=>'n500','n502'=>'n502','n505'=>'n505','n700'=>'n700','n701'=>'n701','n710'=>'n710','nec-'=>'nec-','nem-'=>'nem-','newg'=>'newg','neon'=>'neon','netf'=>'netf','noki'=>'noki','nzph'=>'nzph','o2 x'=>'o2 x','o2-x'=>'o2-x','opwv'=>'opwv','owg1'=>'owg1','opti'=>'opti','oran'=>'oran','p800'=>'p800','pand'=>'pand','pg-1'=>'pg-1','pg-2'=>'pg-2','pg-3'=>'pg-3','pg-6'=>'pg-6','pg-8'=>'pg-8','pg-c'=>'pg-c','pg13'=>'pg13','phil'=>'phil','pn-2'=>'pn-2','pt-g'=>'pt-g','palm'=>'palm','pana'=>'pana','pire'=>'pire','pock'=>'pock','pose'=>'pose','psio'=>'psio','qa-a'=>'qa-a','qc-2'=>'qc-2','qc-3'=>'qc-3','qc-5'=>'qc-5','qc-7'=>'qc-7','qc07'=>'qc07','qc12'=>'qc12','qc21'=>'qc21','qc32'=>'qc32','qc60'=>'qc60','qci-'=>'qci-','qwap'=>'qwap','qtek'=>'qtek','r380'=>'r380','r600'=>'r600','raks'=>'raks','rim9'=>'rim9','rove'=>'rove','s55/'=>'s55/','sage'=>'sage','sams'=>'sams','sc01'=>'sc01','sch-'=>'sch-','scp-'=>'scp-','sdk/'=>'sdk/','se47'=>'se47','sec-'=>'sec-','sec0'=>'sec0','sec1'=>'sec1','semc'=>'semc','sgh-'=>'sgh-','shar'=>'shar','sie-'=>'sie-','sk-0'=>'sk-0','sl45'=>'sl45','slid'=>'slid','smb3'=>'smb3','smt5'=>'smt5','sp01'=>'sp01','sph-'=>'sph-','spv '=>'spv ','spv-'=>'spv-','sy01'=>'sy01','samm'=>'samm','sany'=>'sany','sava'=>'sava','scoo'=>'scoo','send'=>'send','siem'=>'siem','smar'=>'smar','smit'=>'smit','soft'=>'soft','sony'=>'sony','t-mo'=>'t-mo','t218'=>'t218','t250'=>'t250','t600'=>'t600','t610'=>'t610','t618'=>'t618','tcl-'=>'tcl-','tdg-'=>'tdg-','telm'=>'telm','tim-'=>'tim-','ts70'=>'ts70','tsm-'=>'tsm-','tsm3'=>'tsm3','tsm5'=>'tsm5','tx-9'=>'tx-9','tagt'=>'tagt','talk'=>'talk','teli'=>'teli','topl'=>'topl','hiba'=>'hiba','up.b'=>'up.b','upg1'=>'upg1','utst'=>'utst','v400'=>'v400','v750'=>'v750','veri'=>'veri','vk-v'=>'vk-v','vk40'=>'vk40','vk50'=>'vk50','vk52'=>'vk52','vk53'=>'vk53','vm40'=>'vm40','vx98'=>'vx98','virg'=>'virg','vite'=>'vite','voda'=>'voda','vulc'=>'vulc','w3c '=>'w3c ','w3c-'=>'w3c-','wapj'=>'wapj','wapp'=>'wapp','wapu'=>'wapu','wapm'=>'wapm','wig '=>'wig ','wapi'=>'wapi','wapr'=>'wapr','wapv'=>'wapv','wapy'=>'wapy','wapa'=>'wapa','waps'=>'waps','wapt'=>'wapt','winc'=>'winc','winw'=>'winw','wonu'=>'wonu','x700'=>'x700','xda2'=>'xda2','xdag'=>'xdag','yas-'=>'yas-','your'=>'your','zte-'=>'zte-','zeto'=>'zeto','acs-'=>'acs-','alav'=>'alav','alca'=>'alca','amoi'=>'amoi','aste'=>'aste','audi'=>'audi','avan'=>'avan','benq'=>'benq','bird'=>'bird','blac'=>'blac','blaz'=>'blaz','brew'=>'brew','brvw'=>'brvw','bumb'=>'bumb','ccwa'=>'ccwa','cell'=>'cell','cldc'=>'cldc','cmd-'=>'cmd-','dang'=>'dang','doco'=>'doco','eml2'=>'eml2','eric'=>'eric','fetc'=>'fetc','hipt'=>'hipt','http'=>'http','ibro'=>'ibro','idea'=>'idea','ikom'=>'ikom','inno'=>'inno','ipaq'=>'ipaq','jbro'=>'jbro','jemu'=>'jemu','java'=>'java','jigs'=>'jigs','kddi'=>'kddi','keji'=>'keji','kyoc'=>'kyoc','kyok'=>'kyok','leno'=>'leno','lg-c'=>'lg-c','lg-d'=>'lg-d','lg-g'=>'lg-g','lge-'=>'lge-','libw'=>'libw','m-cr'=>'m-cr','maui'=>'maui','maxo'=>'maxo','midp'=>'midp','mits'=>'mits','mmef'=>'mmef','mobi'=>'mobi','mot-'=>'mot-','moto'=>'moto','mwbp'=>'mwbp','mywa'=>'mywa','nec-'=>'nec-','newt'=>'newt','nok6'=>'nok6','noki'=>'noki','o2im'=>'o2im','opwv'=>'opwv','palm'=>'palm','pana'=>'pana','pant'=>'pant','pdxg'=>'pdxg','phil'=>'phil','play'=>'play','pluc'=>'pluc','port'=>'port','prox'=>'prox','qtek'=>'qtek','qwap'=>'qwap','rozo'=>'rozo','sage'=>'sage','sama'=>'sama','sams'=>'sams','sany'=>'sany','sch-'=>'sch-','sec-'=>'sec-','send'=>'send','seri'=>'seri','sgh-'=>'sgh-','shar'=>'shar','sie-'=>'sie-','siem'=>'siem','smal'=>'smal','smar'=>'smar','sony'=>'sony','sph-'=>'sph-','symb'=>'symb','t-mo'=>'t-mo','teli'=>'teli','tim-'=>'tim-','tosh'=>'tosh','treo'=>'treo','tsm-'=>'tsm-','upg1'=>'upg1','upsi'=>'upsi','vk-v'=>'vk-v','voda'=>'voda','vx52'=>'vx52','vx53'=>'vx53','vx60'=>'vx60','vx61'=>'vx61','vx70'=>'vx70','vx80'=>'vx80','vx81'=>'vx81','vx83'=>'vx83','vx85'=>'vx85','wap-'=>'wap-','wapa'=>'wapa','wapi'=>'wapi','wapp'=>'wapp','wapr'=>'wapr','webc'=>'webc','whit'=>'whit','winw'=>'winw','wmlb'=>'wmlb','xda-'=>'xda-',))); // check against a list of trimmed user agents to see if we find a match
      $mobile_browser = true; // set mobile browser to true
      $status = 'Mobile matched on in_array';
    break; // break even though it's the last statement in the switch so there's nothing to break away from but it seems better to include it than exclude it

    default;
      $mobile_browser = false; // set mobile browser to false
      $status = 'Desktop / full capability browser';
    break; // break even though it's the last statement in the switch so there's nothing to break away from but it seems better to include it than exclude it

  } // ends the switch 

  // tell adaptation services (transcoders and proxies) to not alter the content based on user agent as it's already being managed by this script
//  header('Cache-Control: no-transform'); // http://mobiforge.com/developing/story/setting-http-headers-advise-transcoding-proxies
//  header('Vary: User-Agent, Accept'); // http://mobiforge.com/developing/story/setting-http-headers-advise-transcoding-proxies

  // if redirect (either the value of the mobile or desktop redirect depending on the value of $mobile_browser) is true redirect else we return the status of $mobile_browser
  if($redirect = ($mobile_browser==true) ? $mobileredirect : $desktopredirect){
    header('Location: '.$redirect); // redirect to the right url for this device
    exit;
  }else{ 
    return $mobile_browser; // will return either true or false 
  }

} // ends function mobile_device_detect

Le code est lui même n’est pas très intéressant, et pour l’utilisation, il vous suffira juste de modifier le haut avec votre URL de destination. Dans mon cas je n’utilise pas différentes URL selon l’appareil, mais vous pouvez le faire évidemment !

Voici donc la fonction pour rediriger vers la version mobile, mais comment l’utiliser ? Faut il l’appeler sur toutes les pages ? Et bien vous pouvez faire ceci, si vous voulez que votre utilisateur n’ait pas le choix : quelle que soit la page qu’il visitera de votre version normale, il sera redirigé vers la version mobile, un petit peu gênant.

Le mieux est de proposer le choix à l’utilisateur : le rediriger automatiquement vers la version mobile initialement (c’est ce qu’il désire la plupart du temps) mais sans pour autant empêcher son retour vers la version normale.

Version mobile avec possibilité de retour à la version normale

Ça semble facile, ça demande quand même de la réflexion au final ! Pour ce faire, on va regrouper toutes les fonctions qui vont gérer ceci dans un unique fichier, qui regroupera déjà les fonctions PHP du site. Dans mon cas, il se trouve dans le dossier kernel/fonctions.php à la racine du site et est inclut sur chaque page tant mobile, que classique.

if (isset($_GET['mobile'])) {
setcookie("mobile", 1 , time() + (((3600*24)*30)*12));
}
 // On insère ici la fonction précédente permettant de rediriger

$url_page=$_SERVER["SCRIPT_URI"]; // URL complète de la page visitée
$m_url=substr($url_page, 0, 25); // Vérifie si on est sur le sous-domaine ou non

if (empty($_COOKIE['mobile']) && $m_url!="http://m.teen-quotes.com/" && !isset($_GET['mobile'])){mobile_device_detect();} 

// On applique la fonction de redirection seulement quand c'est nécessaire

Le GET[‘mobile’] permet de créer un cookie quand l’utilisateur revient sur la version classique (on fera donc un lien du type www.exemple.com/?mobile).

Ensuite on applique la fonction qui permet de rediriger vers le site mobile si et seulement si l’utilisateur n’a pas le cookie (il veut rester sur la version classique) ou s’il vient de revenir sur la version classique (le cookie mobile va lui être créé) ou alors s’il se trouve sur le site mobile (on récupère les 25 premiers caractères de l’URL car tous les liens du site mobile commenceront par ça). Dans ce dernier cas, on empêche une redirection car sinon il y aurait une boucle de redirection vers le site mobile, ce qui causerait un méchant bug !

Attention de ne pas oublier de rediriger votre utilisateur vers www.exemple.com/?mobile, sinon il sera toujours redirigé vers la version mobile sans son cookie ! D’ailleurs, afin d’alléger les cookies de l’utilisateur on pourra effacer celui-ci dès qu’il se trouve sur la version mobile (il ne sera pas redirigé car dans ce cas $m_url=”http://m.teen-quotes.com/”). Voici donc le code à mettre dans une portion de page que vous incluez sur toutes vos pages de partie mobile.

if(!empty($_COOKIE['mobile']))
	{
	setcookie("mobile", Yo, time()-4200);
	}

L’optimisation de sa version mobile

Pour la version mobile de votre site, ce que vous devez retenir avant tout est que votre site mobile doit être léger ! Attention, on ne rigole pas du tout avec cette consigne, elle est primordiale !

En effet n’oubliez pas que votre utilisateur visite votre site depuis un mobile (d’où la version mobile, c’est une évidence !) et que donc sa vitesse de connexion est limitée (pour ne pas dire lente…). Dès lors, si la vitesse de chargement est trop lente, votre utilisateur va vite se décourager et abandonner tout simplement.

Il est donc nécessaire que la page se charge vite. Pour ceci, il n’y a pas des milliards de solutions : le temps de chargement d’une page provient principalement du temps à charger les images / feuilles de style / scripts et non du calcul lui même de la page (qui se fait côté serveur et qui est renvoyé en un “bloc” à l’utilisateur). En effet, pour chaque image il y a une aura une requête HTTP qui sera envoyée, faites le calcul si vous chargez 25 images…

Pour éviter toutes ces requêtes superflues on utilisera au maximum le CSS (les navigateurs mobiles modernes comprennent les propriétés CSS3, utilisez les !) et on limitera les images. On se contentera par exemple d’utiliser une image de fond (très légère aussi, généralement une image repeat) et les seules autres images qu’on utilisera seront des images dont on ne peut pas se passer (logo / miniatures d’articles…) et les icones (qu’on regroupera grâce à la méthode du CSS sprites !)

Pour les fonctionnalités du site on utilisera seulement les principales et on enlèvera tout le superflu (pas besoin de pouvoir commenter par exemple sur mobile, généralement les gens souhaitent trouver de l’information). Néanmoins, il n’y a que vous qui pouvez juger selon votre projet des fonctionnalités qui sont indispensables sur mobile ou non, ce sera donc à vous de faire ces choix et d’adapter l’interface à vos besoins.

Enfin, la règle d’or du CSS mobile : votre content ne doit pas avoir une largeur fixée ! Votre largeur de page est par défaut de 100 %, et votre contenu peut être par exemple de 90-95 % : les navigateurs mobiles affichent mal un content de 900-1000px de large (vous aurez des soucis de lisibilité car le navigateur va vouloir vous afficher la page entièrement). De même, réduisez vos espaces, vos bordures, votre padding : tout est plus petit sur mobile.

Pour un exemple plus concret, je vous invite à visiter le site mobile de Teen Quotes : http://m.teen-quotes.com et de jeter un coup d’oeil au CSS ! Vous pouvez zoomer quasiment au maximum pour simuler l’utilisation d’un téléphone portable.

Testez, testez, testez !

Toutes ces consignes sont purement théoriques : le meilleur moyen de proposer un site mobile efficace est de le tester ! Si vous ne possédez pas de smartphone, vous allez être embêté, mais c’est clairement le meilleur moyen pour se rendre compte des imperfections ou des améliorations à réaliser.

[CODE] Traduire facilement votre interface web en plusieurs langues

Standard


C’est une fonctionnalité de plus en plus demandée sur les sites web et qui va devenir un incontournable : votre site doit pouvoir être consultable en plusieurs langues. C’est vrai qu’il existe des moyens de traduire du contenu par l’utilisateur lui même, mais les traductions proposées par Google Traduction ne sont jamais fidèles. Voici donc la méthode que j’utilise et que j’ai créé pour Pretty Web.

Comment savoir en quelle langue faut-il traduire ?

Avant de traduire votre site en biélorusse, il faudra d’abord le traduire dans les incontournables : la langue locale du pays dans lequel votre site à sa place, et l’anglais qui est la langue internationale.

Et comment savoir ce que l’utilisateur veut ? Après y avoir longtemps pensé, j’ai préféré choisir l’enregistrement par cookies. Enregistrer en base de données était impossible pour les utilisateurs visiteurs et ne possédant pas de comptes (la grande majorité) et l’enregistrement par variables de sessions ne permet pas de garder en mémoire le choix de l’utilisateur lorsqu’il revient après le time out de session.

Ce système peut être facilement améliorer : il suffit d’enregistrer en cookies pour les visiteurs non enregistrés et en BDD pour les membres (on préférera enregistrer dans une colonne int pour optimiser l’enregistrement, inutile de faire trop lourd avec une colonne varchar).

Voici donc le code que j’utilise :

if (isset($_GET['english']))
{
setcookie("french", 1 , time() -4200);
setcookie("english", 1 , time() + (((3600*24)*30)*12));
echo "";
}

if (isset($_GET['french']))
{
setcookie("english", 1 , time() -4200);
setcookie("french", 1 , time() + (((3600*24)*30)*12));
echo "";
}

if (isset($_COOKIE['english']) OR !isset($_COOKIE['french'])) {
$language="english";
}
else{
$language="french";
}

Le code se passe de commentaires, il reste très basique. J’ai fais le choix de définir l’anglais par défaut, sans cookies ce sera cette langue qui sera utilisée. Bien évidemment il est très facile de rajouter une autre langue, il suffit de suivre le même schéma !

Comment traduire notre interface ?

Maintenant que nous savons quelle langue nous avons choisi d’utiliser pour notre utilisateur, il faut donc traduire le site. Notre langue est enregistrée dans la variable $language, il est temps de s’en servir.

La méthode la plus simple est de créer un dossier “lang” qui regroupera tous vos fichiers de traduction. Dans ce dossier, vous créerez des sous-dossiers, un par langue. Dans mon cas j’ai donc créé un dossier “french” et un autre “english”. A l’intérieur de ces dossiers, vous mettrez tous vos fichiers, qui ne contiendront donc que des fichiers PHP avec des variables et du texte.

Je vous conseille de créer un fichier par page (par exemple pour la page search.php, vous créerez un fichier search.php dans chaque sous dossier de langues de traduction qui contiendra le texte utilisé dans la page search.php à la racine). Enfin, vous pouvez créer un fichier general.php (toujours dans chaque sous-dossier !) qui contient les textes qui sont présents sur chaque page.

Voici un exemple de fichier general.php que j’utilise :

$next_page = "Page suivante";
$previous_page = "Page précédente";
$search = "Rechercher";
$sign_in = "Connexion";
$log_me = "Connexion";
$sign_up = "S'inscrire";
$forget = "J'ai oublié !";
$about = "À propos";
$created_by = "Créé par";
$legal_terms = "Mentions légales";
$home = "Accueil";
$by = "par";
$share = "Partager";
$on = "le";
$comment="commentaire";
$comments="commentaires";
$no_comments="Pas de commentaires";
$logout = "Déconnexion";
$my_account = "Mon compte";
$my_profile = "Mon profil";
$connected_as = "Connecté en tant que";
$co_succes = "Vous vous êtes bien connecté.";
$deco_succes = "Vous vous êtes bien déconnecté.";
$lien_retour='



» Retour

'; $error = "Erreur !"; $edit = "Éditer"; $random_quote = "Citation aléatoire"; $add_a_quote = "Ajouter une citation"; $developer="Développeur"; $add_favorite="Ajouter cette citation à vos favoris !"; $unfavorite="Supprimer cette citation de vos favoris"; $mobile_website="Site mobile"; $full_website="Site normal";

Et le même en anglais :

$next_page = "Next page";
$previous_page = "Previous page";
$search = "Search";
$sign_in = "Sign in !";
$log_me = "Log me";
$sign_up = "Sign up";
$forget = "Forget ?";
$about = "About";
$created_by = "Created by";
$legal_terms = "Legal terms";
$home = "Home";
$by = "by";
$share = "Share";
$on = "on";
$logout = "Logout";
$comment="comment";
$comments="comments";
$no_comments="No comments";
$my_account = "My account";
$my_profile = "My profile";
$connected_as = "Connected as";
$co_succes = "You have successfully logged.";
$deco_succes = "You have been disconnected successfully.";
$lien_retour='



» Back

'; $error = "Error !"; $edit = "Edit"; $random_quote = "Random Quote"; $add_a_quote = "Add your quote"; $developer="Developer"; $add_favorite="Add this quote to your favorites !"; $unfavorite="Delete this quote from your favorites"; $mobile_website="Mobile website"; $full_website="Full website";

Vous noterez que j’ai mis toutes mes variables en anglais, c’est un choix, il est toujours mieux de coder et de commenter en anglais : si vous avez besoin d’aide, vous serez plus facilement compris !

Utiliser ces fichiers de traduction

Rien de plus facile, il suffit juste de faire des include et des echo des variables !

Voici la ligne à mettre dans votre header.php que vous incluez sur chaque page :

$page=$_SERVER['PHP_SELF'];
$taille= strlen($name_page);
$taille2=$taille-4;
$name_page = substr("$page",1,$taille2);

require 'lang/'.$language.'/general.php'; 
if ($page!="/index.php") {require 'lang/'.$language.'/'.$name_page.'';}

Ce code ci est plutôt facile aussi à comprendre, mais il est ingénieux ! Comme je vous l’ai conseillé auparavant, il est mieux de créer un fichier par page que l’on veut traduire (on s’y retrouve plus facilement…) avec ce code c’est exactement ce qui est fait !

Il ne vous reste plus qu’à faire de jolis echo partout dans votre code, et vous aurez votre interface disponible dans autant de langues que vous le voulez (et que vous pouvez traduire !)

# - '1'){echo "$nombre_commentaires $comments";}elseif($nombre_commentaires=='1'){echo "$nombre_commentaires $comment";}else{echo"$no_comments";} ?>   

Ça fait beaucoup de PHP, mais on s’y retrouve je vous assure !

Pourquoi utiliser un dossier static sur son nom de domaine

Standard

Peut être vous êtes vous déjà demandé, si vous avez déjà fait plusieurs projets utilisant Internet, s’il était utile de faire un dossier “static” sur un de vos noms de domaines afin de pouvoir l’utiliser sur vos autres projets.

En effet, il arrive souvent que lorsque l’on travaille beaucoup sur plusieurs projets on arrive à avoir souvent besoin des mêmes fichiers (scripts, images, feuilles de style…). Dès lors, on se demande si il n’est pas intéressant de regrouper tous ces fichiers, dont on a souvent l’utilité, sur un endroit précis. Voici donc l’idée d’utiliser un sous domaine “static” sur un de ses noms de domaine.

Les avantages

  • Vous pouvez regrouper tous les fichiers dont vous vous servez très souvent, et pratiquement sur chaque projet (bibliothèque JS, CSS, icones…)
  • Vous améliorez le temps de chargement de vos pages (vos fichiers sont sur plusieurs serveurs)
  • Vous n’avez pas besoin de stocker tous les fichiers que vous utilisez à chaque fois sur chaque serveur
  • Ce procédé est utilisé par la plupart des grands sites (qui utilisent également un système de cache afin d’optimiser)
  • Il est conseiller de compresser au maximum vos fichiers, pour économiser de la bande passante et gagner de la rapidité lors du chargement de vos fichiers

Les inconvénients

  • Vous devez posséder un nom de domaine qui à les capacités de supporter un trafic qui peut être important (plusieurs appels simultanés depuis plusieurs serveurs)
  • Vous ne devez pas renommer vos fichiers ou les déplacer : vos autres projets utilisant ces fichiers ne pourront plus fonctionner !
  • Si le nom de domaine où vous avez utilisé le sous domaine “static” est down, tout vos projets dépendants de ces fichiers ne fonctionneront pas normalement.