Comme je le soulignais hier, Internet Explorer permet de définir et de modifier les favicons définis dans les favoris tandis que Firefox ne le permet pas par défaut. Au moment de l'enregistrement du lien, Firefox récupère le favicon spécifié dans la balise <link> du code HTML et il n'est plus possible de le modifier par la suite.
Étant donné que je traine mes favoris depuis longtemps (n'étant pas encore abonné à un service comme Delicious, je me suis promis d'ouvrir un compte d'ici la fin de mes vacances...), j'avais gardé Last.fm dans mes favoris de Firefox et à ce moment, le site ne proposait probablement pas encore de favicon. Maintenant que le site offre une icône, je n'avais pas d'autre solution que de supprimer le favori et l'ajouter à nouveau pour la récupérer. Mais je Je me doutais bien qu'il y aurait une extension pour le faire facilement : Favicon Picker 3.
Après avoir installé l'extension, on peut changer l'icône d'un lien en cliquant dessus avec le bouton droit de la souris et choisir "Properties". Ensuite, il suffit de cliquer "Browse" et de sélectionner une image sur son poste de travail ou de coller un lien web vers une image (jpg, gif, png, bmp ou ico). Dans mon cas, j'ai récupéré dans le code source de la page la valeur du href dans la balise <link rel="icon" href="http://cdn.last.fm/flatness/favicon.2.ico" /> et coller l'URL dans l'espace réservé au nom du fichier.
En utilisant le code source de Last.fm comme exemple, le hasard m'a fait découvrir une chose intéressante sur laquelle j'aimerais attirer votre attention. Sous la balise <head> se trouve une autre icône spécifiée explicitement pour le iPhone / iPod Touch :
<link rel="apple-touch-icon" href="http://cdn.last.fm/flatness/apple-touch-icon.png" />
Devinez un peu à quoi ça sert ? Il semblerait que ça soit pour ajouter une icône sur le tableau de bord de l'appareil. On s'en reparle bientôt...
L'idée du favicon vient d'Internet Explorer qui permettait d'associer une icône à un favori (bookmark), d'où il tire son nom. Au départ, comme l'icône associée était une extension .ico placée à la racine du site, c'est devenu le format par défaut que la plupart des fureteurs ont adopté, bien que le PNG et GIF soit acceptés par certains fureteurs.
Pour en créer un de base, il faudra d'abord faire une image de dimension 16 x 16 pixels. Pour y arriver, on peut utiliser Photoshop, GIMP ou un service web gratuit pour créer un favicon (il suffit de fournir une image et on nous renvoie un .ico). Dans mon cas, je procéderai avec GIMP pour Windows (GNU Image Manipulation Program).
- Créer un gabarit de format carré et de taille normale pour pouvoir créer l'image (pour un meilleur contrôle du résultat final, mieux vaut créer un gabarit de format 16 x 16 et l'agrandir en utilisant la touche "+" du clavier numérique)
- Créer l'image
- Réduire le format à 16 x 16 pixels (Menu Image / Échelle et taille de l'image, entrer les dimensions et cliquer sur le bouton Échelle)
- Dans le menu Fichier, sélectionner "Enregistrer sous" et choisir "Windows Icon Format" dans le panneau "Sélectionner le type de fichier (selon l'extension)"
- Enregister
- Déposer le fichier .ico à la racine du site (le fichier peut se trouver n'importe où en réalité, il suffira de spécifier le chemin relatif ou absolu)
- Créer le lien sur les pages comme ceci :
<link rel="shortcut icon" href="favicon.ico">
Si on ne voit pas le favicon après l'avoir placé ou remplacé sur un site, c'est soit que :
- le nom de la ressource comporte une erreur
- il faut vider la cache du fureteur ou dans certains cas le redémarrer
- le format ou les dimensions ne sont pas compatibles
- Internet Explorer reconnait par défaut le favicon s'il est placé à la racine du site et s'il porte le nom favicon.ico
- pour Firefox, l'option des favicons peut être désactivée. Dans ce cas, on peut le réactiver en entrant about:config dans la barre d'adresse, ensuite utiliser le filtre pour trouver la propriété browser.chrome.favicons et changer sa valeur pour true
script.aculo.us est une librairie JavaScript d'effets visuels qui repose sur la base de prototype, un peu comme si elle agissait comme une extension du framework. Il faut donc inclure les deux librairies pour pouvoir commencer à créer des effets. En téléchargeant le fichier zip contenant scriptaculous, une version de prototype est incluse dans le répertoire /lib/ mais comme j'utilise généralement prototype dans la plupart de mes projets, j'ai tendance à utiliser une version indépendante plutôt que la version fournie dans le fichier compressé.
Lors de l'inclusion des librairies, il faudra tenir compte que scriptaculous est dépendant de prototype, donc celui-ci devra apparaître en premier pour que scriptaculous puisse être reconnu correctement. Si les scripts sont inversés ou si la version de prototype est trop vieille, un message d'erreur indiquera "uncaught exception: script.aculo.us requires the Prototype JavaScript framework >= 1.6.0".
<script type="text/javascript" src="/js/prototype/1.6.0.3/prototype-1.6.0.3.js"></script>
<script type="text/javascript" src="/js/scriptaculous/1.8.2/src/scriptaculous.js"></script>
À partir de ce moment, on peut créer des effets. Contrairement à la documentation de scriptaculous qui utilise les attributs d'événements (onclick="fonction"), je préfère extraire le code JS des balises HTML pour initialiser les événements en utilisant prototype (les deux méthodes fonctionnent bien, c'est une préférence au niveau de la structure).
Pour introduire les effets, je commencerai simplement avec l'affichage et le masquage d'un élément. Si on se rappele bien, l'objet Element de prototype.js offre deux méthodes pour y arriver : show() et hide(). Cependant, l'utilisation de ces méthodes n'offre que deux états à l'objet (affiché ou pas) et on note qu'il n'y a aucune transition dans le changement d'état. C'est ici que scriptaculous vient ajouter un peu d'effets pour rendre le visuel plus intéressant :
1. Toggle
Inverse automatiquement l'état de la fenêtre en utilisant l'effet "Appear", "Slide" ou "Blind".
Event.observe('btnToogle', 'click', function() {
Effect.toggle('box1', 'Slide');
} );
2. Appear
Permet de faire apparaître ou disparaitre un élément en faisant varier l'opacité.
Event.observe('btnShow', 'click', function() {
$('box1').appear({ from: 0, to: 1 });
} );
Event.observe('btnHide', 'click', function() {
$('box1').appear({ from: 1, to: 0 }); }
);
3. Slide
Permet de faire apparaître ou disparaitre un élément horizontalement comme un store de fenêtre (imaginez que le contenu de l'élément s'enroule dans le store).
Event.observe('btnSlideUp', 'click', function() {
Effect.SlideUp('box1');
} );
Event.observe('btnSlideDown', 'click', function() {
Effect.SlideDown('box1');
} );
4. Blind
Semblable à l'effet "Slide" sauf que le contenu ne se déplace pas, c'est le conteneur qui semble se déplacer.
Event.observe('btnBlindUp', 'click', function() {
Effect.BlindUp('box1');
} );
Event.observe('btnBlindDown', 'click', function() {
Effect.BlindDown('box1');
} );
5. switchOff
Permet de faire disparaitre un élément un peu comme lorsqu'on éteint un poste de téléviseur.
Event.observe('btnSwitchOff', 'click', function() {
$('box1').switchOff();
} );
Ce n'est qu'un bref aperçu de que ce scriptaculous propose. On peut paramétrer les effets pour contrôler le jeu de transition, combiner des effets ensemble et modifier dynamiquement les propriétés CSS d'un élément.
Sinon, un autre volet de scriptaculous que j'introduirai prochainement est le "drag and drop" qui permet de faire des fenêtres flottantes, déplacer les éléments sur une page, etc (un peu comme Facebook ou Blogspot font pour configurer la mise en page). Maintenant, amusez-vous à explorer les possibilités!
Quand un vrai génie apparaît en ce bas monde, on le peut reconnaître à ce signe que les imbéciles sont tous ligués contre lui.
Incroyable mais vrai. Hier, j'allais à un petit souper des fêtes chez des amis et à ma grande surprise, qu'est-ce que je vois sur le dos de Monsieur Jeune Padawan en personne ? Un t-shirt "Personal Soundtrack" provenant de Think Geek !
Mon rêve qui s'est matérialisé! Jamais je n'aurais pensé que ce chandail était sorti pour vrai car il faisait parti de la gamme de produits du dernier "April Fool's Day" de Think Geek.
Si quelqu'un vous pose une question à laquelle Google pourrait répondre, cherchez la réponse et envoyez lui le résultat à l'aide du site Let Me Google That For You.
Vous voyez, ce n'était pas si compliqué !
Comme chaque année, chaque réunion de famille devient propice à une discussion de hockey, suivi d'une séance de questions/réponses au geek de service. Parce que comme tout le monde le sait, quand on travaille en informatique, on connait tout de la technologie...
Au menu cette année :
- faire un bref exposé à "mononcle" pour expliquer ce qu'est le HD en vue des achats du boxing day
- dresser un tableau comparatif de NHL 09 sur les consoles PS2 et PS3 avec le cousin
- expliquer comment brancher une routeur sans fil
- initier grand-mère aux plaisirs du iPod touch
- décevoir quelqu'un parce que je n'ai pas su répondre à une question technique sur les GPS
- aider un ami en détresse parce que son ordinateur ne détectait plus le Master Boot Record (MBR)
L'extension que tous les développeurs web devraient installer est sans contredit Firebug. J'hésitais à en parler car ça me semblait trop évident que tout le monde l'aie déjà. Si vous ne le connaissez pas encore, c'est certainement la première qu'il vous faut installer. Firebug permet d'explorer le DOM, modifier et déboguer le code HTML, JavaScript et le CSS en temps réel sur vos projets ou sur des pages que vous visitez. C'est tellement pratique que ça devient dur de s'en passer.
Une fois installé, on peut accéder à Firebug en cliquant sur l'insecte qui se trouve en bas à droite dans la barre de statut. Le premier onglet présente une console qui est utilisée pour faire afficher différents messages : erreurs JavaScript, requêtes AJAX, requêtes GET et POST, etc.
Au moment du développement, on peut aussi avoir accès à cette console. Par exemple, pour déboguer du code JavaScript, j'avais souvent tendance à faire afficher une trace des variables ou faire un suivi sur une structure de contrôle en utilisant alert(). Avec Firebug, on peut prendre avantage de la console pour y faire afficher nos messages de trace sans avoir à fermer continuellement des fenêtres popup. Pour ce faire, on peut utiliser l'objet JavaScript "console" de Firebug :
<script type="text/javascript">
console.log("trace 1");
</script>
L'objet console possède aussi une fonction de profilage (console.profile()) qui permet de mesurer la performance de certaines actions.
Une autre fonction utile se trouve sous l'onglet NET (network) qui permet de suivre le temps de chargement et la taille des ressources utilisées sur une page (images, scripts, etc). C'est ainsi qu'on verra que www.google.ca ne charge que 3 ressources en 235 millisecondes tandis que www.yahoo.ca en utilise 22 qui se chargent en 1,29 seconde (le sommaire est indiqué à la dernière ligne).
Il est aussi possible de modifier le code HTML d'une page à partir de Firebug. Et c'est assez simple :
- Rendez-vous sur la page d'accueil de Google
- Ouvrez Firebug et cliquez sur le bouton Inspect
- En survolant les éléments de la page, cliquez sur le bouton "Google Search" (en passant par-dessus, il sera encadré et le click correspondra à sélectionner l'élément à inspecter plutôt qu'à soumettre le formulaire)
- Dans Firebug, sous l'onglet HTML, on remarquera que le code du bouton est surligné en bleu
- En cliquant sur le bouton Edit, le code du bouton sera isolé et on pourra utiliser l'onglet HTML pour modifier le code. Par exemple, modifiez la valeur de l'attribut "title" pour le texte de votre choix
- On pourra voir en temps réel le rendu de la page changer selon nos modifications
Et ce n'est qu'une partie des possibilités offertes par Firebug. Comme cette extension indispensable n'est offerte que sur Firefox, on pourra trouver du support pour Safari, Opera ou Internet Explorer en utilisant Firebug Lite, une version en JavaScript qu'il suffit d'inclure à sa page pour pouvoir bénéficier des fonctionnalités de base.
J'ai reçu un DVD contenant des fichiers vidéo au format .rmvb (RealMedia Variable Bitrate) et je dois dire que je n'avais vraiment aucune envie d'installer RealPlayer pour pouvoir les visionner. Il y a quelque chose dans ce lecteur multimédia que je déteste ou du moins, je suis toujours resté avec une mauvaise impression sur ce logiciel. Ma première expérience doit remonter autour de 1997 ou 1998 et je crois me souvenir qu'il fallait s'enregistrer, que la publicité était envahissante, qu'il y avait une tonne de gadgets inutiles, que pour télécharger des extraits audio, on devait ouvrir le fichier .ram et y extraire l'URL du fichier .ra et que je ne pouvais pas faire jouer les extraits avec mon lecteur audio préféré en raison du format propriétaire. C'est pour ces raisons que je m'étais vite tourné vers le format mp3.
Mais avec ce DVD en main, j'étais curieux de voir ce qu'on m'envoyait. J'ai cherché une alternative, une façon d'installer un CODEC (coder-decoder), pour me permettre de lire les fichiers. Et j'ai découvert RealAlternative, un substitut pour Windows qui installe les codecs et en option le lecteur multimédia Media Player Classic (peu gourmand en mémoire vive et compatible avec de nombreux formats).
Pour ce qui est de RealPlayer, je ne suis pas déçu d'en être débarassé...
C'est la première journée de mes vacances de Noël, une grosse tempête de neige est tombée sur le Québec et je dois aller pelleter pour dégager ma voiture (en fait, je me croise les doigts et j'espère que mon voisin qui a une voiture identique à la mienne se soit trompé et qu'il ait commencé le travail à ma place...). Aussi, Cyberpresse annonce que cette fois-ci, la neige ne sera pas ramassée avant la semaine prochaine puisque les travailleurs de la ville prennent congé durant le temps des fêtes. Est-ce qu'on peut s'inspirer de Toronto et appeler l'armée en renfort ?
Bon, j'ai le sentiment d'amorcer mes vacances du bon pied : paresse totale. Mais comme je me suis mis au défi d'écrire un article par jour, je crois qu'il est temps de sortir mon atout et jouer la carte du Lorem Ipsum.
Donc voici mon entrée pour aujourd'hui :
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla in nunc ac sem posuere aliquam. Aenean sodales pede id nibh. Integer id lectus a tortor adipiscing vestibulum. Duis ut felis. Aenean nulla. Vestibulum sagittis varius turpis. Aliquam imperdiet. Aenean sapien leo, porttitor et, sollicitudin eget, rutrum eu, quam. Fusce egestas ante eu eros. Aenean porttitor ante eu dui. Nunc ac tellus. Duis erat lectus, dictum et, bibendum ac, elementum et, enim. Proin consectetur elit vel lectus. Donec congue ultrices felis. Nulla vehicula hendrerit velit. Aliquam porta dui a tellus. Phasellus accumsan feugiat tortor. Duis ligula dui, tincidunt eget, aliquam eget, ullamcorper adipiscing, nisi. Praesent eros turpis, egestas at, accumsan eget, dignissim eget, tortor. Sed ut erat.
Si vous ne connaissez pas Lorem Ipsum, sachez qu'il s'agit de faux-texte utilisé en imprimerie ou en intégration web pour remplir une page de contenu et donner un aperçu de la mise en page. Plusieurs logiciels d'édition permettent de générer du texte générique en latin et s'il n'y en a pas, des extensions sont souvent disponibles. Dans mon cas, j'ai généré mon texte par le web avec le générateur de latin Lipsum.
La compétence, comme la vérité, beauté, et les verres de contact, est dans l'oeil du spectateur.
Il y a une fonction de PostgreSQL très peu documentée et pourtant très pratique qui se nomme generate_series(). Il s'agit d'une fonction qui permet de générer des séries de nombres entiers, un peu à la manière d'une boucle "for" où on indique la valeur de départ, la valeur maximale et de façon optionnelle le saut (step) entre chaque itération (1 par défaut).
Par exemple, pour obtenir 5 enregistrements (rows) allant de 1 à 5 :
SELECT * FROM generate_series(1,5)
--------------------------------------------------------
1
2
3
4
5
On peut aussi obtenir un jeu de résultats en utilisant un saut, positif ou négatif, qui sera passé comme troisième argument (optionnel, la valeur par défaut est +1) :
-- obtenir 0, 10, 20, 30, ... 90, 100
SELECT * FROM generate_series(0, 100, 10)
Dans mon cas, j'y ai trouvé une utilité lorsque j'ai eu à programmer un calendrier d'événements s'échelonant sur plusieurs jours, où la modélisation des dates n'était pas normalisée dans la base de données. Pour exposer l'idée de façon simpliste, on définira une table et un événement, par exemple la Conférence PHP Québec 2009, qui aura lieu du 4 au 6 mars 2009 (durée de 3 jours).
-- création de la table
CREATE TABLE events
(
pk_event integer serial,
eventname character varying(100),
start_date date,
nb_days integer
)
-- Insertion de l'événement (ici, la séquence sera auto-incrémentée et aura la valeur 1)
INSERT INTO events (eventname, start_date, nb_days)
VALUES ('Conférence PHP Québec 2009', '2009-03-04', 3);
Si on souhaite obtenir une liste calculée des trois dates, on pourra exécuter une requête SQL semblable à celle-ci :
SELECT start_date + generate_series(0, nb_days-1) as event_date
FROM events
WHERE pk_event = 1;
Résultat :
2009-03-04
2009-03-05
2009-03-06
C'est un peu comme si on disait en pseudo-code :
nb_days_max = (nb_days - 1) // 2
date = start_date; // '2008-03-04'
for (days = 0 ; days <= nb_days_max ; days++ ) {
// days = 0, 1, 2
echo (date + days);
}
Dans cette requête, j'utilise le champ "start_date" de l'événement comme valeur de départ, à laquelle j'ajoute un des nombres de la série générée qui correspond au nombre de jours. Comme l'événement débute le 4 mars et que cette date est déjà définie dans la base de données, on aura qu'à ajouter 0 à la date initiale pour la conserver telle quelle (première valeur de la série). La dernière date sera calculée en ajoutant 2 jours à la date initiale lors de la dernière itération de generate_series.
En fouillant un peu, je me suis aperçu qu'il n'existait pas d'implémentation native pour d'autres types de bases de données mais j'ai trouvé des scripts de définitions de fonctions similaires pour SQL Server et Oracle.
Une autre utilisation pratique de generate_series() serait de pouvoir effectuer des requêtes sur les listes de codes de statut HTTP ou de tout type de classement inspiré de la classification numérique de Dewey.
La langue française est difficile à maîtriser et moi-même je ne peux prétendre en être un expert. Mais je suis fier de ma langue et j'essaie le plus possible d'utiliser la meilleure qualité possible. Durant mes études, plusieurs de mes collègues programmeurs croyaient que les cours de français n'allaient pas être une nécessité dans une carrière en informatique. Pourtant, dès qu'on est appelé à participer à la rédaction d'un document d'analyse ou à rédiger du texte s'affichant sur un site web, on est responsable de la qualité de notre propre travail et ça devient vite tributaire de la crédibilité de l'entreprise.
Par exemple, lorsque je regarde un formulaire web où les libellés sont en français, une erreur courante que je remarque est une mention indiquant que "les champs avec des astérix sont obligatoires".
Mettons les choses au clair. Lui, c'est Astérix, le personnage populaire des bandes dessinées. Son nom est dérivé du mot "Astérisque", dont le symbole est *. Voilà, qu'on se le tienne pour dit.
A-S-T-E-R-I-S-Q-U-E
En informatique, un astérisque a plusieurs utilités :
- une convention indiquant un champ requis dans un formulaire
- permet de sélectionner toutes les colonnes d'une table dans une requête SQL
- un pointeur en C
- le symbole généralement utilisé pour faire une multiplication
- un caractère de remplacement (aussi nommé wildcard)
- dans une regexp, indique la répétition (0 ou plus) du pattern qui le précède
Cette semaine, j'ai terminé la lecture de la version française du livre "The Art of the Steal" (L'art de la fraude) de Frank Abagnale, ce célèbre fraudeur américain dont l'histoire fut relatée dans le film Catch Me If You Can. Le livre, sorti originalement en 2001, m'intéressait car j'étais curieux de lire ce qu'il avait à dire sur ce qui touche à Internet.
Dans le chapitre 8 ("L'arnaqueur internaute"), il raconte une anecdote sur sa seule expérience d'achat sur le web, alors qu'il acheta sur eBay une guitare pour l'anniversaire de son fils. Voulant payer à l'aide de PayPal, il explique avoir tout juste eu le temps d'entrer son numéro de carte de crédit mais qu'il se rétracta, annula la transaction et préféra payer le vendeur par chèque certifié. Il fut ensuite victime de fraude et son numéro de carte MasterCard fut utilisé pour faire d'autres achats par Internet. Selon lui, le simple fait d'avoir saisi son numéro de carte dans le formulaire le rendit vulnérable en moins d'une minute.
En me fiant à mon expérience personnelle sur ces sites, j'ai été étonné de lire son histoire et je la trouvais pratiquement invraisemblable. Il faut dire qu'au moment de ces faits, PayPal n'avait pas encore été acquis par eBay, donc ça revenait à effectuer le paiement de façon indépendante sur le site d'un tiers parti. J'imagine qu'il devait s'agir soit d'une faille de sécurité importante, soit qu'il fut victime de "phishing" ou de sa méconnaissance du système. Depuis son acquisition par eBay en octobre 2002, un gros travail a été fait afin d'intégrer adéquatement le service de paiement lié à PayPal. Aujourd'hui, c'est sans aucun doute la façon la plus sécuritaire de payer un article acheté sur eBay, principalement en raison des protections offertes.
Il reste que c'est quand même surprenant de voir qu'un fraudeur repenti se fasse frauder à son tour. De mon côté, j'ai eu la chance d'avoir une expérience positive et je me suis toujours senti en sécurité face aux transactions électroniques. À deux reprises, un vendeur ne m'a pas envoyé l'article commandé et un d'eux a même poussé l'audace jusqu'à fermer son compte immédiatement après la transaction (je crois que c'était le même vendeur car je tentais d'acheter le même article que la première fois). Il m'a suffit de signaler le cas à PayPal et si le vendeur ne fait pas suite à ma demande à l'intérieur de 10 jours, PayPal me rembourse automatiquement.
Comme le livre date d'environ 8 ans, on peut croire qu'il y a eu du progrès dans la détection de la fraude et dans la sécurité reliée à ces services. Dans mon cas, ça fait longtemps que je n'ai plus de crainte à acheter sur eBay, tant que je peux payer avec PayPal. J'ai d'autant plus confiance depuis que j'ai lu le chapitre consacré à PayPal, dans le livre Founders at Work, qui explique comment fonctionne son système de détection de la fraude (basé sur des statistiques et probabilités). Dans le fond, celui qui court le plus gros risque aujourd'hui est le vendeur...
Dans un monde idéal, ce serait merveilleux si on pouvait être la seule personne à avoir accès au développement d'un site web. On pourrait alors simplement conserver une copie du projet sur notre disque dur et lorsque des changements surviennent, on aurait qu'à les transférer sur le serveur, sans se soucier de savoir si on possède la version la plus récente. Or, la réalité nous démontre que c'est rarement le cas : nombreux sont les clients qui souhaitent avoir la liberté de faire des modifications mineures au contenu statique de leur site, de façon autonome.
C'est pourquoi à chaque fois que je travaille sur un projet web existant, je vérifie si le client possède un accès FTP et j'essaie de déterminer si une plateforme de publication comme Contribute est configurée. Si c'est le cas, on doit s'assurer de récupérer le fichier en ligne, y faire ses modifications et le renvoyer. Évidemment, le client doit suivre la même procédure, sans quoi il écrasera nos changements... et Dieu sait que c'est le genre de chose qu'on programmeur déteste (levez la main ceux à qui c'est jamais arrivé!). Bref, mieux vaut avoir une bonne communication pour éviter d'écraser mutuellement les plus récentes modifications apportées.
En tant que développeur, si on utilise l'éditeur Dreamweaver, son système de vérouillage pourra être activé (check in / check out) et permettra d'éviter le pire puisqu'un seul utilisateur à la fois est autorisé à apporter des modifications. Lorsqu'un fichier est en train d'être modifié par Contribute ou Dreamweaver, le logiciel envoie sur le serveur un fichier .LCK ("lock") qui indique le nom de la personne qui réserve la ressource. Si quelqu'un d'autre tente d'ouvrir le fichier, le logiciel vérifie d'abord si le fichier en question n'est pas vérouillé en recherchant le fichier .LCK sur le serveur distant. Ce mécanisme est transparent et l'explorateur de fichiers / FTP de DW ne les affichera pas (en mode "remote").
Une petite astuce pour savoir si un site utilise Contribute : on trouvera un répertoire nommé "_mm" à la racine du site (www.nom-du-site-web.com/_mm). Ce répertoire est automatiquement créé lorsqu'un site est configuré pour être utilisé avec Contribute. Il contient un fichier nommé contribute.xml où sont décrites différentes propriétés, dont le mot de passe (encrypté) pour autoriser la connexion. Ce répertoire aussi n'est pas visible à partir de Dreamweaver donc pour le voir, on devra se connecter par FTP ou entrer l'URL où se trouve le répertoire _mm dans un fureteur.
La procédure est différente si on utilise tout autre logiciel. Si notre éditeur est autre chose que Dreamweaver ou si on utilise un client FTP indépendant, il vaudra mieux mettre les choses au clair avant de faire les mises à jour. Si on voit des fichiers .LCK sur le serveur, cela indique que des changement sont encore en suspens par un utilisateur et que la version en ligne n'est peut-être pas la plus récente. Dans certains cas (de mauvaise utilisation), le fichier .LCK demeure sur le serveur alors qu'on en a plus besoin. On pourra le supprimer par FTP pour libérer l'accès à la ressource.
Requête SQL pour obtenir un enregistrement au hasard
Ça m'arrive souvent qu'un client me demande de faire afficher un élément aléatoire dans une page web. Que ce soit pour placer une publicité, mettre un produit en vedette ou pour faire afficher une rubrique "saviez-vous que", c'est le genre de fonctionnalité qui revient constamment et qui permet de mettre un peu de dynamisme dans l'affichage.
De plus, c'est très facile à faire lorsque le contenu est dynamique et géré par un CMS puisqu'on trouve normalement une référence sur les enregistrements dans la base de données. Voici une façon simple d'obtenir un enregistrement aléatoire à partir d'une requête SQL sur trois types de bases de données différentes.
PostgreSQL
Pour obtenir un enregistrement au hasard, on utilisera la fonction mathématique random() qui permet de générer un nombre flotant de 0 à 1. Comme chaque enregistrement se verra associé à un nombre aléatoire, on pourra le classer en ordre et restreindre le nombre de résultats retournés en utilisant la clause LIMIT.
SELECT *SQL Server
FROM table
WHERE condition
ORDER BY random()
LIMIT 1
Du côté de SQL Server, on pourra arriver au même résultat en utilisant la fonction newid(), qui crée un identificateur unique (de type uniqueidentifier) souvent nommé GUID (Globally Unique Identifier) ou UUID (Universally Unique Identifier). Ici, l'équivalent de LIMIT est le mot réservé TOP placé en début de requête.
SELECT TOP 1 *SQL Server possède une fonction rand() pour obtenir un float entre 0 et 1, mais elle est appelée une seule fois à l'intérieur de la requête, donnant toujours le même résultat et rendant impossible l'effet "aléatoire". C'est pourquoi on doit utiliser la fonction newid() qui est non-déterministe, c'est-à-dire qu'elle retournera une valeur différente pour chaque enregistrement (pour visualiser ce qui se passe, placez le dans la liste des colonnes du SELECT *, rand(), newid()...).
FROM table
WHERE condition
ORDER BY newid()
MySQL
Même si j'ai utilisé moins souvent MySQL dans mes projets, j'ai pu obtenir le même comportement avec la fonction rand(), équivalente au random() de PostgreSQL.
SELECT *
FROM table
WHERE condition
ORDER BY rand()
LIMIT 1
Lors d'une analyse de projet, j'ai du chercher une solution de traduction automatique pour du contenu web. Certains produits étaient intéressants mais aucun n'était vraiment satisfaisant à 100%. À vrai dire, la traduction était approximative et le français était généralement massacrée.
Par exemple, le produit qui me semblait le plus évolué était Systran. Il fallait donc le mettre à l'épreuve. Je l'ai mis au défi de traduire en français la phrase désormais classique "bill is a great fan of mark messier". Le résultat fut lamentable mais rigolo : "la facture est un grand ventilateur de marque plus malpropre".
Pour le plaisir, je me suis tourné vers d'autres sites de traduction en ligne dont Google Translate et Babel Fish. Ce dernier étant propulsé par Systran, le résultat fut le même.
De son côté, Google a abandonné Systran il y a un peu plus d'un an pour implanter son propre moteur de traduction. Ce qui est intéressant, c'est qu'il permet aux utilisateurs de proposer de meilleures traductions si celles proposées ne sont pas exactes.
Le résultat de Google est celui qui s'approche le plus de la traduction attendue mais il n'est pas tout à fait au point. Il proposera comme traduction "projet de loi est un grand fan de la marque Messier" et fera un pas de plus dans la bonne direction si on utilise les lettres capitales des noms propres : "Le projet de loi est un grand fan de Mark Messier" (seul le prénom Bill n'est pas reconnu, même si on y ajoute "My friend" devant).
À titre d'information, Mark Messier est un joueur de hockey retraité qui a connu ses derniers moments de gloire en faisant des publicités pour les croustilles Lay's.
Lorsque je suis à court de designer et que j'ai besoin d'utiliser des icônes dans un site ou une application web, je me tourne souvent vers la librairie des icônes Fam Fam Fam.
Offerte gratuitement par le développeur web Mark James, cette librairie compte environ 1000 icônes PNG de qualité (16 x 16 pixels). La librairie générale (silk) en compte 700, à laquelle s'ajoute celle des drapeaux (247 pays), dont les fichiers sont nommés selon les codes ISO.
Le format PNG (Portable Network Graphics) est l'idéal pour les icônes puisqu'il est le successeur du format GIF (Graphics Interchange Format), qui lui conserve principalement la propriété de transparence que le JPG ne peut avoir, tout en offrant un plus grand éventail de couleurs. Ainsi, on passera de 256 (8 bits) à 16 millions (24 bits) de couleurs, qui, contrairement au JPG, pourra se fondre à la couleur de fond sur laquelle l'icône est placée.
Encore une fois, le support dans Internet Explorer 5 et 6 est déficient mais est rendu correctement depuis la version 7. Pour une question de "back compatibility", il faudra faire un bug fix pour être compatible avec les versions antérieures (autrement, les éléments transparents ne seront pas pris en compte). Plusieurs méthodes sont disponibles sur le web, il suffit de rechercher "correct png javascript" ou mieux, iepngfix.htc.
Samedi prochain, ce sera le party de Noël, juste avant des vacances bien méritées. Après avoir passé toute l'année à programmer, c'est maintenant l'heure de se dégourdir un peu.
Voici ma sélection de chorégraphies à apprendre pour épater la galerie et faire lever le party :
Avec ça, fini les anti-dépresseurs.
Vive Internet.
Il m'est arrivé à quelques reprises, dont une fois cette semaine, à devoir superposer un élément HTML par dessus un Flash. En fait, pour être un peu plus précis, ce que je vais expliquer est un problème fréquent avec les menus DHTML qui comportent des portions qui doivent s'afficher par-dessus un élément Flash mais qui passent plutôt au dessous (donnant l'impression de disparaître).
En fait, ce n'est pas une question ici de modifier le z-index car il n'aura pas d'effet sur la superposition des éléments. La solution est plutôt d'ajouter une valeur de transparence à l'attribut wmode de l'objet Flash :
<object type="application/x-shockwave-flash" ...>
<param name="wmode" value="transparent" />
...
</object>
Ainsi qu'à la balise <embed> :
<embed src="" ... wmode="transparent"></embed>
Si la fonction AC_FL_RunContent est utilisée (pour contourner l'activation du Flash imposé par Internet Explorer), on aurait du aussi ajouter ceci à la liste des arguments de l'appel :
AC_FL_RunContent(..., 'wmode', 'transparent' );
Cependant, il faut noter que l'appel à la fonction AC_FL_RunContent devrait maintenant être optionnel puique Microsoft avait annoncé qu'il abolirait l'activation des composants Flash dès avril 2008. Comme les utilisateurs d'Internet Explorer sont encore nombreux, cette modification pourra s'avérer utile pour les utilisateurs qui n'ont pas mis à jour leur fureteur.
À l'origine, Flash était développé par l'entreprise FutureWave Software et l'application se nommait FutureSplash Animator. En 1996, Macromedia acheta la compagnie et renomma le produit Flash 1.0 (un hybride du nom Future Splash ?).
On connait la suite. Macromedia passa aux mains d'Adobe en 2005.
C'est une bonne pratique de détacher les événements JavaScript placés directement sur un élément HTML en les regroupant à la place sous la balise <head>.
Un exemple :
<input type="button" id="btnSubmit" value="OK" onClick="myFunction" />
Pour attacher la fonction dans la balise HEAD, on doit attendre que le DOM (Document Object Model) soit chargé, autrement, il ne trouvera pas l'élément puisqu'il n'existe pas encore.
En utilisant la librairie prototype.js, on pouvait généralement le faire comme ceci :
Event.observe(window, 'load', function() {
/* initialisation suite au chargement de la page */
Event.observe('btnSubmit', 'click', myFunction);
});
Depuis la version 1.6, il est possible de remplacer cet appel par :Event.observe(document, 'dom:loaded', function() {Qui est aussi équivalent à :
/* initialisation suite au chargement du DOM */
Event.observe('btnSubmit', 'click', myFunction);
});
document.observe("dom:loaded", function() {Ainsi, le code HTML est plus "propre", mieux structuré et surtout plus facile à lire. Ce qui me fait penser que ça fait pratiquement un an que la librairie prototype.js n'a pas évolué. Qu'est-ce qui se passe ?
/* initialisation */
Event.observe('btnSubmit', 'click', myFunction);
});
Configurer son routeur sans fil pour travailler à distance
Tempête de neige sur Montréal... Pourquoi ne pas travailler de la maison ? Un coup d'oeil par la fenêtre... Je ne demande pas mieux. Dans mon cas, il suffit que je me connecte par VPN (Virtual Private Network) sur le réseau du bureau, pour ensuite accéder à mon poste de travail à distance (qui doit être ouvert) en utilisant Remote Desktop (je lance toujours l'application par le menu Start / Run / mstsc). Mais ce matin, un petit problème est apparu.
Comme j'ai installé un routeur la semaine dernière pour pouvoir m'amuser avec mon iPod touch, il semblerait que mon réseau local entre maintenant en conflit avec le réseau au travail. Je peux me connecter au VPN, mais plus rien n'est accessible. Ce qui m'indique que le problème est relié au routeur est que si je le retire de ma configuration, tout fonctionne correctement. Il me faudra donc modifier la configuration du routeur pour qu'il soit heureux.
D'abord, je dois dire que je ne suis pas très doué en ce qui concerne la réseautique. Par contre, je suis débrouillard et je réussis généralement à faire ce dont j'ai besoin. Je possède un routeur D-Link DIR-615 que j'accède par mon fureteur à l'adresse 192.168.0.1 pour le configurer. Une fois connecté en administrateur, je me rends à l'onglet Setup et je choisis Network Settings dans le menu de gauche. À ce que j'ai lu, je peux changer le default gateway (router IP address) pour l'adresse IP 10.0.0.1 (lorsque ce sera enregistré, on pourra retourner à la console de gestion du routeur par cette adresse plutôt que par 192.168.0.1). Une fois redémarré, je suis capable d'accéder normalement à Internet, le VPN et le Remote Desktop.
Je ne sais pas s'il s'agit de la meilleure solution mais ça fonctionne. Si quelqu'un a une meilleure alternative, merci de la partager avec moi.
La plupart des programmeurs PHP que je connais utilisent les fonctions PHP var_dump() et print_r() pour effectuer la trace des variables pendant le débogage. Voici un petit aide-mémoire qui résume les fonctions à utiliser au besoin.
Pour un array donné :
$arrTest = array('a', 'b', 'c');
var_dump
var_dump($arrTest);
Résultat :
array(3) { [0]=> string(1) "a" [1]=> string(1) "b" [2]=> string(1) "c" }
- Accepte une ou plusieurs variables en entrée
- Dans le cas de notre array, il retournera le type et la valeur de chaque clé dans une forme lisible
- Récursif, pour afficher la structure complète de l'objet
print_r($arrTest);
Résultat :
Array ( [0] => a [1] => b [2] => c )
- Accepte une seule variable en entrée
- Retourne la valeur de chaque clé, sans le type
- Accepte un deuxième argument (booléen) pour indiquer si on veut retourner le résultat dans une variable plutôt que de l'afficher. Par exemple : $result = print_r($arrTest, true);
Il existe une troisième façon intéressante et pratique, soit var_export, qui s'appele aussi avec un ou deux arguments.
var_export($arrTest);
ou
$result = var_export($arrTest, true);
Résultat :
array ( 0 => 'a', 1 => 'b', 2 => 'c', )
- Accepte une seule variable en entrée
- Retourne la valeur de chaque clé, sans le type
- Contrairement aux deux autres, le résultat est du code PHP valide
Comme ce que contient $result est une chaîne de caractère représentant un array PHP valide, on pourrait l'enregistrer et le récupérer plus tard en appelant la fonction eval() :
eval('$arrRecuperation = ' . $result . ';');
Ainsi, la variable $arrRecuperation est un array à nouveau.
Pour du débogage avancé (pour les tâches plus coriaces!), je vous recommande de jeter un oeil aux puissants outils fournis avec Zend Studio (breakpoints, stacks, introspection de variables, etc).
Pour Noël, faites un heureux. Offrez à votre programmeur préféré le livre PHP 5 Objects, Patterns, and Practice (1ère édition, 2004), disponible sur eBay pour la modique somme de 700$ canadiens (550$ US). Et oui, vous avez bien lu, le vendeur est nul autre que Best Bargain Books. Ironie ?
Faites vite, seulement 8 copies disponibles !
Pour les autres qui ne peuvent se payer ce luxe en temps de récession, Amazon offre la deuxième édition pour seulement 35$...
Lorsqu'on télécharge un fichier, on remarque parfois dans la liste une clé md5 ou un fichier avec l'extension .md5. Un MD5 (Message-Digest Algorithm 5) est une fonction d'encryption à 128 bits qui donne comme résultat un hash de 32 caractères en notation hexadécimale. Ce résultat peut être utilisé pour effectuer une validation que le fichier téléchargé a été transféré correctement et que l'intégrité des données est respectée.
C'est une technique généralement utilisée sur Linux mais on peut la reproduire sans trop de problème sous Windows en utilisant UnxUtils. En installant cet outil, on aura accès à plusieurs des commandes disponibles sous Linux dont md5sum.
Si on regarde la page de téléchargement de PHP, on remarquera que sous chaque lien se trouve une clé md5. Il s'agit du résultat attendu lorsqu'on exécute la commande md5sum sur le fichier téléchargé. Dans le cas du fichier php-5.2.6.tar.bz2, le résultat devrait être le suivant : 7380ffecebd95c6edb317ef861229ebd.
La commande md5sum php-5.2.6.tar.bz2 affichera le checksum du fichier (plusieurs fichiers peuvent être passés comme arguments et chacun aura son propre hash) :
7380ffecebd95c6edb317ef861229ebd *php-5.2.6.tar.bz2
On pourra le comparer manuellement à ce qui est inscrit sur le site. Mieux, si un fichier .md5 est déjà disponible en téléchargement, on pourra faire la comparaison directement. S'il n'est pas présent, on pourra le créer, simplement en ajoutant à un fichier texte une ligne pour chaque fichier, composée de la clé md5 attendue, suivie du nom de fichier correspondant (comme le résultat plus haut).
On terminera la vérification à l'aide du fichier .md5 qui utilisera le nom de chaque fichier indiqué pour vérifier sa clé :
md5sum -c result.md5
php-5.2.6.tar.bz2: OK
Dans ce cas-ci, tout est conforme. Si un fichier avait été altéré lors de la transmission, ce serait indiqué FAILED. La commande md5sum peut être utile lorsqu'on télécharge des images ISO de CD ou de DVD, par exemple une distribution Linux. Elle permet de vérifier que le contenu n'est pas corrompu avant de le graver sur un média.
Mise à jour, 2008-12-08
Les noms de fichiers des exemples de cet article ont été modifiés pour utiliser la version 5.2.6 de PHP plutôt que la plus récente version 5.2.7 en raison d'un bogue de sécurité. Pour l'instant, l'utilisation de la version 5.2.6 est recommandée en attendant la sortie de PHP 5.2.8.
En cette période d'instabilité économique, on apprend que 71 000 emplois ont été perdus au Canada, au mois de novembre seulement (et plus de 500 000 aux États-Unis). Moins d'emplois se traduira inmanquablement par une diminution des revenus dans les coffres de l'état, donc moins d'investissements, tant dans les infrastructures que dans les programmes sociaux.
On devra donc s'attendre à ce que les gouvernements fassent des compressions budgétaires un peu partout pour pouvoir arriver. Si on y réfléchit bien, combien d'argent pourraient-ils économiser s'ils troquaient uniquement la suite Microsoft Office pour son rival gratuit OpenOffice ? En se basant sur les prix de vente affichés sur le site de Microsoft, on peut certainement figurer de quel ordre pourrait se chiffrer les économies pour la fonction publique.
Il existe probablement une entente commerciale à plus ou moins long terme avec le géant Microsoft mais lorsqu'elle sera échue, peut-on s'attendre à ce que les gouvernements révisent leur position ? Ce point a été soulevé en juillet dernier par l'organisme FACIL qui estime que le gouvernement dépense annuellement 80 millions de dollars pour des licenses de Windows. Le débat a déjà eu lieu et personnellement, je ne crois pas que se tourner vers un système d'exploitation comme Linux puisse se traduire par des économies substancielles. Mais il faudrait au moins considérer l'adoption de la suite bureautique OpenOffice.
Plusieurs pays ont déjà fait le saut au logiciel libre mais le Québec sembre prendre du retard à cet effet. Peut-être est-ce le moment approprié pour forcer un changement ? Et qui sait, pourquoi ne pas adopter la même approche dans les Cegeps, universités et les bibliothèques ?
Après avoir complètement réinitialisé mon iPod touch (1ère génération, de 8 Go d'espace de stockage), je l'ai branché à iTunes pour pouvoir mettre à jour le firmware et espérer pouvoir installer les applications gratuites offertes dans leur boutique (tout à fait légalement, sans jailbreak). Après avoir télécharger quelques applications intéressantes, je me suis rendu compte que plusieurs demandaient à être installées sur un firmware 2.0 ou plus. Comme la seulement mise à jour disponible pour mon appareil était la version 1.1.5 (améliorations de base), je devais soit jailbreaker mon iPod, soit payer la mise à jour à la version 2.2 proposée par iTunes.
Il y a environ un an, lorsque j'avais jailbreaké mon iPod pour la première fois, je devais d'abord restaurer le iPod avec un firmware précis et j'avais réussi à en trouver un sans trop de problème sur Google. Encore une fois, j'ai procédé de la même façon et j'ai découvert un site où on peut télécharger les firmwares pour iPod. J'ai sélectionné dans la liste "iPod touch 1G (2.2/5G77)" et j'ai téléchargé le fichier .ipsw d'environ 250 Mo.
Une fois en possession de ce fichier, j'ai branché mon iPod touch et j'ai ouvert iTunes 8. Dans la liste de droite, j'ai sélectionné mon appareil pour faire apparaître l'onglet "Summary". Dans cet écran, j'ai cliqué sur le bouton "Restore" tout en gardant enfoncée la touche "shift" de mon clavier. Cette combinaison permet d'ouvrir une fenêtre qui donne la possibilité de choisir le fichier .ipsw à partir duquel effectuer la restauration ou la mise à jour plutôt que d'utiliser celui par défaut. Une fois sélectionné, tout se fait automatiquement, il suffit d'être patient.
Lorsque le processus s'est terminé, j'ai retrouvé mon iPod comme un neuf, avec les applications du iPod touch 2ème génération dont Google Maps, Stocks, Weather, Mail, la possibilité de déplacer les icônes et surtout, j'ai pu installer énormément d'applications gratuites provenant du iTunes store.
Je me retrouve donc avec un jeu de batterie, un autre de air hockey, la pinte de bière Carling, Tap Tap Revenge (inspiré du jeu Guitar Hero), un traducteur, un jeu de darts, le fameux sabre laser de Star Wars et beaucoup d'autres trucs, souvent inutiles qui ne servent qu'à impressionner les amis (surtout ceux qui n'ont pas encore de iPod touch ou iPhone).
Pour la prochaine étape, je me demande si ça vaudrait la peine de jailbreaker le tout avec QuickPwn ?
Vous vous souvenez de la vieille blague du téléchargement de l'Internet ?
Bien que l'idée soit farfelue (évidemment), voilà qu'on peut maintenant télécharger l'encyclopédie Wikipedia pour en faire une archive sur DVD. Mieux, vous pouvez toujours installer une copie complète sur votre iPod touch / iPhone, en installant l'application Encyclopedia, moyennant 2.2 Go d'espace et 8$. Comme ils le disent si bien, c'est peu demandé pour avoir au bout des doigts la somme de toutes les connaissances humaines!
En fouillant un peu, j'ai aussi découvert un autre projet dans le même genre sur Sourceforge, gratuit et fonctionnant sur les anciens types de iPod : Encyclopodia.
Malheureusement, le gros défaut ici est que l'encyclopédie est créée à partir d'un dump (copie fixée dans le temps) de la base de données de Wikipedia, donc l'information n'est pas mise à jour automatiquement. Ça en fait donc une solution idéale pour le iPod mais sans intérêt pour le iPhone. Du moins, à moins de vouloir gaspiller beaucoup dl'espace disque, aussi bien y accéder normalement par Safari.
Ce soir, j'ai réinitialisé mon iPod touch (1ère génération de 8 Go) car j'avais fait plusieurs tests récemment, entre autre en testant deux façons différentes de le "jailbreaker" avec le firmware original (JailbreakMe et ZiPhone). Comme j'avais installé de nombreuses applications pour explorer ses nouvelles capacités, il ne restait plus beaucoup de place pour la musique et les vidéos. Un petit ménage s'imposait.
Parmis les applications que j'ai testé, il y avait un lecteur de eBooks et un émulateur de jeux NES. Dans les deux cas, les applications s'installaient facilement, mais les PDF et les ROMS devaient être déposés dans l'appareil par S-FTP/SSH car contrairement aux fichiers mp3, on ne peut pas les ajouter par iTunes.
Pour y arriver, on doit d'abord ouvrir une connexion sans fil avec le iPod jailbreaké (autrement, la connexion est refusée). Il faudra ensuite obtenir l'adresse IP qu'utilise l'appareil :
- Ouvrir l'icône Settings
- Sélectionner Wi-Fi
- Repérer la connexion utilisée (celle avec un crochet)
- Entrer dans la configuration de cette connexion par la flèche bleue à droite
- Noter ce qui est indiqué à IP Address (192.168.0.x)
- Type : SFTP - SSH File Transfert Protocol
- Entrez comme hôte l'adresse IP utilisée par le iPod
- Par défaut, l'appareil utilise root comme nom d'utilisateur et alpine comme mot de passe
Pour faire suite au Startup Camp de jeudi dernier, je reviens cette semaine avec le livre Founders at Work. Ce bouquin est constitué d'une collection d'entrevues effectuées par Jessica Levingston (mariée depuis 2008 à Paul Graham) qui s'est entretenue avec une trentaine de fondateurs d'entreprises informatiques dont plusieurs sont devenues les leaders dans leur domaine.
Loin d'être technique, on explorera plutôt leur histoire à travers diverses anecdotes qui nous permettra de mieux comprendre les opportunités qui se sont offertes à eux, le contexte dans lequel les idées sont nées, les compromis à faire et les défis qu'ils avaient à relever, y compris au niveau du financement (VCs et Angels).
On lira par exemple l'histoire du succès de PayPal (vendu 1.5 milliards à eBay en 2002), la naissance d'un des premiers web-mail nommé Hotmail (acquis par Microsoft en 1997 pour 400 millions) ou encore un chapitre incontournable où Paul Graham (Y Combinator) parle de ViaWeb, un service permettant de construire une boutique de vente en ligne... devenu par la suite le Yahoo! Store. Ce type est un vrai passionné et c'est toujours intéressant de voir ce qu'il a à dire.
Sinon, le chapitre le plus impressionnant est probablement celui où Steve Wozniak, le co-fondateur et génie technique derrière Apple, parle de la conception révolutionnaire de ses premiers ordinateurs en faisant le maximum avec le moins de puces possible.
Tout ça, en passant par Firefox, Adobe, Research in Motion (fabriquant du BlackBerry), Gmail, Craiglist, Flickr, la plateforme Blogger (où je suis publié), Lotus, VisiCalc (ancêtre du tableur Excel), Hot or Not (précurseur du site québécois Do You Look Good ?), le site Internet Archive, Alexa (maintenant propriété d'Amazon), le déploiement de Ruby on Rails par 37 Signals, et bien plus.
Une source d'information inspirant le succès que tous les entrepreneurs en informatique devraient lire.
La documentation officielle de PHP indique que les balises de fermeture (?>) sont optionnelles. Depuis la sortie de Zend Framework, le standard de formatage exige que ces balises soient omises pour les pages qui ne contiennent que du code PHP (par exemple la définition d'une classe).
Lorsqu'on utilise les instructions (include|require)(_once)? pour attacher une librairie, PHP copie dans le script principal le contenu du fichier avant d'exécuter le tout. Dans ces cas-ci, l'idée de ne pas fermer les balises PHP permet d'éviter que des sauts de lignes ou des espaces, souvent positionnés à la fin des fichiers inclus (après le tag de fermeture), se retrouvent imprimés en sortie dans le script principal. Par la suite, lorsqu'on voudra employer l'instruction header() pour faire une redirection ou encore pour faire du output buffering, cela provoquera la fameuse erreur "headers already sent".
Or, certaines personnes prétendent qu'une balise ouverte devrait toujours pouvoir être fermée et que c'est la responsabilité du programmeur de formater convenablement le code de ses librairies. D'autres, dont les concepteurs du Zend Framework, de Zend Studio, et plus particulièrement du Zend Engine sur lequel repose PHP, croient le contraire.
Simple préférence ou bonnes pratiques de programmation ?
Quoi qu'il en soit, l'éditeur Zend Studio for Eclipse 6 permet de tirer profit du formatage automatique du code (Menu Windows / Preferences / PHP / Formatter) et de le configurer pour utiliser les conventions PHP ou celles du Zend Framework. Et pourtant, même en spécifiant celles de ZF pour créer une nouvelle classe, j'ai remarqué que la balise de fermeture de PHP est automatiquement créée. Comme si c'était voulu...
Vendredi, j'ai parlé de l'utilisation du fichier hosts pour des objectifs beaucoup moins professionnels que ceux dont que je m'apprête à vous parler. En fait, lorsque je développe des projets personnels, j'utilise souvent mon poste de travail comme laboratoire et j'accède à mes différents projets à partir de http://localhost (127.0.0.1).
Cependant, plutôt que de créer chaque projet dans un répertoire à la racine du répertoire www d'Apache, je préfère utiliser ce qu'on appele un hôte virtuel (VirtualHost ou vhost). Je peux donc placer mes projets à différents endroits sur mon poste. Pour chaque projet, je crée ensuite un sous-domaine à localhost. Par exemple si mon premier projet est placé dans www : http://localhost/projet1/ deviendra http://projet1.localhost/. Ainsi, je peux continuer à programmer en utilisant la racine du répertoire comme référence, comme si le projet était en ligne sur son propre nom de domaine.
Voici pour configuration possible pour Apache (je baserai mon exemple en utilisant EasyPHP mais le fonctionnement reste identique si on utilise Apache seul) :
- D'abord, je crée deux projets, le premier dans le répertoire www d'Apache, le deuxième à un autre endroit, par exemple sur la partition D:
- On doit accéder au fichier httpd.conf d'Apache (C:\Program Files\EasyPHP 2.0b1\conf_files\) et s'assurer que la ligne suivante n'est pas commentée (elle ne doit pas avoir de symbole # devant) :
Include conf/extra/httpd-vhosts.conf - Ouvrir le fichier httpd-vhosts.conf (C:\Program Files\EasyPHP 2.0b1\apache\conf\extra\) et ajouter un hôte virtuel pour chaque projet :
NameVirtualHost *:80
Où :<VirtualHost *:80>
<VirtualHost *:80>
DocumentRoot "C:\Program Files\EasyPHP 2.0b1\www\projet1"
ServerName projet1.localhost
</VirtualHost>
DocumentRoot D:\Programmation\Web\projet2
ServerName projet2.localhost
</VirtualHost>
DocumentRoot est le chemin où se trouve le projet
ServerName est le nom du serveur - Dans le fichier hosts (Sous XP : C:\WINDOWS\system32\drivers\etc\), ajouter une ligne pour chaque projet :
127.0.0.1 projet1.localhost
127.0.0.1 projet2.localhost - Redémarrer Apache (pour que la nouvelle configuration prenne effet. EasyPHP a un raccourci pour le redémarrer à partir du système tray)
- Ouvrir un invite de commande et exécuter la commande suivante (pour que les domaines soient associés aux adresses IP spécifiées - pour notre poste seulement!) :
ipconfig /flushdns - À partir de votre fureteur préféré, tester l'accès à http://projet1.localhost et à http://projet2.localhost. Le tout devrait maintenant fonctionner.
Un intellectuel est quelqu'un qui rentre dans une bibliothèque même lorsqu'il ne pleut pas.
Saviez-vous que Google tient vraiment à ce que vous l'utilisiez ?
À l'image de leur pagination de résultats de recherche, vous pouvez y accéder avec un des domaines suivants :
- gogle.com
- google.com
- gooogle.com
- gogole.com
- googel.com
- googil.com
Sinon, voici deux parodies intéressantes :
Un mauvais tour à jouer à un ami est de faire en sorte que lorsqu'il tente d'accéder à un site web populaire, il se retrouve ailleurs sans savoir pourquoi. C'est possible de le faire en modifiant le fichier hosts de son poste de travail.
Pour comprendre l'astuce, il faut savoir que lorsqu'on accède à un site web, le domaine entré est traduit en adresse IP grâce à un service nommé DNS (Domain Name System). Il est possible de modifier le fichier hosts pour y ajouter des règles de correspondance ou de les remplacer.
Dans cet exemple, je ferai en sorte que lorsqu'on voudra accéder à Google, on se retrouvera à la place chez Yahoo. Pour y arriver, on devra d'abord connaître l'adresse IP de Yahoo.
En ouvrant un invite de commande, exécuter un ping pour obtenir l'adresse IP du domane : ping www.yahoo.com
Identifier et noter l'adresse IP dans la réponse
Reply from 69.147.76.15: bytes=32 time=34ms TTL=52
Ouvrir ensuite le fichier hosts avec un éditeur texte. Sous Windows XP, il est placé dans C:\WINDOWS\system32\drivers\etc\hosts. Le même type de fichier existe sous Linux (dans /etc/hosts) mais ses utilisateurs ne sont généralement pas les cibles de ce genre d'attrapes ;-)
Sous la ligne 127.0.0.1 localhost, ajouter une ligne pour chaque domaine à remplacer sous la forme [adresse ip] [domaine] :
69.147.76.15 www.google.com
69.147.76.15 google.com
69.147.76.15 www.google.ca
69.147.76.15 google.ca
A noter que j'inclus des entrées sans les sous-domaines www car certaines personnes les omettent dans les urls, ainsi que les extensions .com et .ca afin de couvrir les principaux domaines de Google susceptibles d'être utilisés. Enregistrer le fichier et exécuter l'instruction suivante dans l'invite de commande pour réinitialiser la table de correspondance locale : ipconfig /flushdns
Normalement, ça fonctionne immédiatement (et seulement sur le poste de notre victime). Cependant, j'ai cru remarquer que certains fureteurs gardaient en cache l'information DNS et la rafraîchissait au bout de quelques minutes. Généralement, c'est assez rapide.
Lorsque votre victime (ou vous-même) tentera d'accéder au site de Google, elle attérira sur Yahoo. Autant que possible, je ne vous conseille pas de faire cette plaisanterie au bureau, à moins d'avoir la complicité de votre administrateur réseau, ou que vous occupiez vous-même ce poste. Essayez de garder un minimum de bon goût mais assurer-vous de faire durer le plaisir.
Oh, j'oubliais... Pour revenir à la normale, il suffit de retirer les entrées dans le fichier hosts et de réexécuter la commande ipconfig /flushdns.
Je viens à l'instant de revenir de la troisième édition du Startup Camp Montreal qui se tenait à la Société des Arts Technologiques. Cet événement a pour but d'aider les entreprises en démarrage à présenter leurs idées aux investisseurs, où chaque invité a droit à 5 minutes au micro pour convaincre les gens de l'audience de la pertinence de leur projet. L'assistance peut ensuite participer à un échange de conseils et d'informations pour aider les entrepreneurs à paufiner leurs présentations afin de pouvoir mieux convaincre les futurs investisseurs (VCs, angels, etc).
La soirée débuta avec une introduction de Patrick Lor (iStockPhoto.com) qui usa de son expérience pour présenter ses précieux conseils au public, jusqu'à ce que les discours des startups commencent. Les projets présentés étaient les suivants :
En fin de soirée, Austin Hill (Akoha, Standout Jobs) démontra de façon pertinente et très amusante de quelle façon on pouvait transformer un discours morne et singulier en quelque chose de très dynamique et personnalisé. Une grande réussite! Une phrase m'a particulièrement fait rire : Even a pig can get a chance to fly in a tornado.
En résumé, ce fut une soirée très agrébable, où l'on avait droit à un petit buffet, une bière et une tonne de gens passionnés. Pour ceux qui voudraient en savoir plus sur l'univers des startups, je vous invite à lire le livre Founders at Work de Jessica Livingston (qui est aussi la femme d'un certain Paul Graham...).
Tous les jours, quand je suis au travail, j'ai l'habitude d'écouter de la musique. La plupart du temps, j'utilise Winamp Lite pour sa légereté (très peu gourmand en mémoire) et lorsque j'ai le goût de découvrir de la musique, je vais fouiner sur iTunes dans les répertoires partagés de mes collègues. Chez moi, j'utilise 3 autres types de lecteur selon mes besoins. Je suis peut-être exigeant, mais aucun des lecteurs ne me donne entière satisfaction. Certains possèdent des fonctionnalités intéressantes, d'autres un look plus intuitif, et certains gèrent mieux que d'autres les librairies les plus larges.
Dans ma quête du lecteur idéal, j'ai découvert Songbird, un lecteur personnalisable à la manière de Firefox grâce à des extensions indépendantes. Encore en version beta, ce projet open source multi-plateforme (Windows, OS X et Linux) est développé par des membres de l'ancienne équipe de Winamp et de Yahoo! Music Engine.
En voici les grandes lignes :
- Interface graphique s'inspirant énormément de iTunes
- Possibilité d'appliquer des skins (qu'ils appelent des feathers) et de le réduire en version miniature
- Prises en charge plusieurs formats audio comme les MP3, FLAC, Vorbis, Ogg, etc.
- Support pour plus de 25 langages
- Gestionnaire de pochettes
- Bâti sur l'engin Mozilla XULRunner (comme Firefox), il est donc aussi un fureteur
- LyricMaster : utilise les metadatas des fichiers musicaux pour obtenir automatiquement les paroles
- MediaFlow : permet de visualiser les pochettes des albums comme dans iTunes
- iPod Device Support : pour faire le plein! Mon iPod mini est compatible mais mon iPod Touch a plus de difficulté...
- Wikipedia Extension : obtenir de l'information sur l'artiste
- Album List : un type d'affichage comme dans iTunes
- Album View : un autre type d'affichage comme dans iTunes 8, où l'on voit toutes les pochettes
- Last.fm : intégration du service pour mettre à jour son compte de profilage musical
Pour chaque application web ou CMS que j'ai développé, j'ai souvent eu de la difficulté à figurer de quelle façon j'allais implémenter la gestion des droits d'accès (par utilisateur, par niveau, par module et même par fonctionnalité). Malgré mes tentatives, je n'étais jamais tout à fait satisfait de l'élégance et de la lisibilité du code produit. Jusqu'à ce que je découvre Zend_Acl (Access Control List), un composant faisant parti de la librairie Zend Framework pour PHP.
Ce qui est bien avec le Zend Framework, c'est qu'il ressemble davantage à une librairie de code et de compostants plutôt qu'un framework imposant un cadre de travail prédéfini à respecter. Ça nous laisse donc la possibilité d'utiliser seulement les objets que nous avons besoins, tout en conservant nos bonnes (et parfois mauvaises!) habitudes de travail.
Pour pouvoir utiliser le composant, il faut d'abord télécharger Zend Framework (actuellement la version 1.7) et inclure les fichiers sources à son projet.
Dans un fichier php global au projet, on ajoutera les références aux objets nécessaires :
require_once('Zend/Acl.php');
require_once('Zend/Acl/Role.php');
require_once('Zend/Acl/Resource.php');
Instancier un objet ACL :
$oAcl = new Zend_Acl();
Définir les rôles :
$oAcl->addRole( new Zend_Acl_Role('programmers') );
$oAcl->addRole( new Zend_Acl_Role('designers') );
$oAcl->addRole( new Zend_Acl_Role('sysadmin') );
On spécifiera ensuite les ressources du site ou de l'application (par exemple un module ou une section) :
$oAcl->add( new Zend_Acl_Resource('internet') );
$oAcl->add( new Zend_Acl_Resource('databases') );
$oAcl->add( new Zend_Acl_Resource('zend_studio') );
$oAcl->add( new Zend_Acl_Resource('coffee') );
$oAcl->add( new Zend_Acl_Resource('photoshop') );
$oAcl->add( new Zend_Acl_Resource('servers') );
$oAcl->add( new Zend_Acl_Resource('porn') );
Pour terminer, on indiquera pour chaque module quels sont les privilèges qu'un niveau d'utilisateur a droit :
// Tous les niveaux
$oAcl->allow(null, 'internet', 'view');
$oAcl->allow(null, 'coffee', 'drink');
$oAcl->allow(null, 'porn', 'view');
$oAcl->allow('programmers', array('databases', 'zend_studio'), 'use' );
$oAcl->allow('designers', 'photoshop', 'use');
$oAcl->allow('sysadmin', 'servers', 'update');
$oAcl->deny( array('programmers', 'designers'), 'porn');
Je crois que vous avez compris, nul besoin de m'acharner puisque le code parle de lui-même. On pourra ensuite vérifier les droits aux endroits nécessaires et agir en conséquence (afficher une section, refuser l'accès, etc.) :
if ( !$oAcl->isAllowed($userLevel, 'coffee', 'drink') ) {
...
}
Avec Zend_Acl, il devient facile de faire la gestion des ressources, des rôles et des privilèges. En plus d'être facile à lire, le code se maintient très facilement. On peut ajouter de nouveaux rôles et de nouvelles ressources en un rien de temps. Exactement le genre de composant que j'aime pour être efficace dans mon travail.
Aujourd'hui, à mon travail, j'ai eu une discussion intéressante avec un autre développeur. Son OS préféré avait prit en otage la mémoire vive de son ordinateur et il avait énormément de difficulté à faire quoi que ce soit sur son poste, dont sa fonction principale, programmer. En vérifiant les processus de Windows, nous avons remarqué que l'éditeur web était en cause et que la mémoire virtuelle du processus dépassait 1 Go. En réaction à tout cela, ma matière grise s'éveilla et je me souvins d'une époque pas si lointaine où les éditeurs web étaient tellement moins gourmands. Époque dont je ne m'ennuie pourtant pas du tout...
Sur le chemin du retour, j'ai tenté de faire le compte de tous les éditeurs web que j'ai pu utiliser depuis mes premiers pas sur le web. Lorsque je suis arrivé chez moi, j'ai fouillé dans mes boîtes et à ma grande surprise, j'y ai trouvé une copie authentique du logiciel WebExpert de Visicom Media. Datant de 1997, cette petite disquette contenait la version 2.03a de WebExpert pour Windows 95 / NT 4.0 et permettait de créer des sites compatibles avec Netscape 3 et Internet Explorer 3. Et ce n'est rien! Permettez-moi de vous dire que j'avais acquis ce classique pour la modique somme de 56.32$, au défunt Aventure Électronique :-)
Selon mes souvenirs, voici la liste des éditeurs web que je me souviens avoir utilisé, en ordre chronologique :
- NotePad
- Netscape Gold (1996)
- WebExpert (1997)
- HotDog
- HoTMetaL
- SimpleWeb 1.0 (projet d'études d'un étudiant dans mes cours, vers 1999)
- Arachnophilia (2001)
- Allaire HomeSite (probablement la version 5, 2001)
- Dreamweaver UltraDev 4.0 / Dreamweaver 4 (2000)
- Dreamweaver MX (2002)
- Dreamweaver MX 2004 (2003)
- Dreamweaver 8 (2005)
- Eclipse / PDT (2006)
- Zend Studio 5.5 (2007)
- Zend Studio for Eclipse (2008)
Il y a quelques années, je me souviens avoir travaillé sur un projet ASP assez complexe qui avait nécessité l'écriture de nombreuses classes. Comme certaines classes fonctionnaient par composition d'objets, je devais inclure en entête du script principal toutes les dépendances et surtout ne pas en oublier. Parfois, un fichier en incluait un autre (à éviter) ou incluait le même qu'une autre librairie et comme ASP n'avait pas de mécanisme équivalent aux méthodes include_once() ou require_once() de PHP, certaines erreurs de redéfinitions survenaient.
En PHP 5, on a la possibilité d'utiliser une fonction nommée __autoload() qui permet, lorsqu'on déclare un objet qui n'est pas défini, de charger automatiquement la librairie reliée. Ce mécanisme permet donc d'inclure dynamiquement les librairies dépendantes lorsqu'elles sont requises, plutôt que de les inclure comme on le faisait traditionnellement en PHP 4 ou en ASP.
Dans un fichier de configuration global au projet (c'est-à-dire inclus à toutes les pages), on pourra définir la fonction qui effectuera le travail pour nous. Idéalement, on ajoutera aussi le chemin menant au répertoire des classes dans le fichier php.ini (variable de configuration include_path). Sinon, on devra spécifier le chemin d'accès aux classes à l'intérieur de la fonction __autoload().
Pour simplifier l'exemple suivant, j'ai spécifié dans php.ini le chemin du répertoire où je conserve toutes mes classes (donc transparent dans le code).
Dans le fichier principal, comme la librairie DBI.php n'est pas incluse et que la classe DBI n'est pas définie, lorsque PHP tente de créer l'objet DBI et qu'il ne le trouve pas, la fonction __autoload() est déclenchée pour tenter de la charger. La fonction reçoit en paramètre le nom de la classe et lui concatène l'extension PHP pour obtenir le nom du fichier à inclure. Malgré une légère perte de performance, ce service nous donne un souci en moins et peut être utilisé même si les classes sont incluses explicitement au projet car la fonction __autoload() est appelée seulement lorsqu'il ne trouve pas la définition de la classe. Il n'y a donc pas de raison de ne pas en tirer profit.// Dans le fichier de configuration config.php
<?php
function __autoload($classname) {
require_once($classname . '.php');}
// Dans le fichier principal
<?php
require_once('config.php');
$obj = new DBI();
The internet is a place where absolutely nothing happens. You need to take advantage of that.
Sous Apache, il est possible de créer des redirections au niveau serveur grâce au fichier .htaccess. Cette méthode possède au moins quatre avantages :
- Permet d'éviter d'utiliser le tag <meta http-equiv="refresh"> (non recommandé)
- Avoir des règles de redirections même sur des pages HTML non dynamiques ou des répertoires
- Garde le code source dynamique plus "propre"
- Meilleure structure puisque les redirections sont regroupées dans un même fichier
Sous Linux, un fichier commençant par un point est un fichier caché. On pourra prendre pour acquis que le fichier .htaccess en est un qui ne comporte pas de nom, seulement une extension. Pour ajouter une redirection, il faudra d'abord créer le fichier .htaccess et le déposer à la racine du site (s'il n'existe pas déjà; il est aussi possible d'en avoir un dans chaque répertoire).
Pour créer une règle de redirection :
- Ajouter une ligne dans le fichier en respectant la syntaxe suivante :
Redirect 301 [ancien chemin] [nouveau chemin]
Par exemple :
Redirect 301 /Dev/ancienne_page.html /Dev/nouvelle_page.html - La redirection fonctionnera même si l'ancienne page ou répertoire n'existe plus physiquement sur le serveur
- Le chemin redirigé correspond à la nouvelle adresse de la ressource, donc on peut spécifier aussi l'URL complète pointant vers un site se trouvant sur un autre domaine
- Enregistrer le fichier et l'envoyer sur le serveur
- Tester en accédant à l'ancien chemin. La redirection se fera automatiquement.
J'ai commencé à utiliser la librarie prototype.js quelque part en 2006 et dès le départ, j'ai apprécié la facilité à laquelle je pouvais écrire du code et la clareté des énoncés. Le DHTML et le Ajax étant maintenant devenus des incontournables dans des Rich Internet Applications (RIA), les programmeurs qui font aujourd'hui le saut à prototype doivent changer leurs habitudes et intégrer les nouvelles façons de faire.
Notion fondamentale de la librairie
La notation utilisée dans prototype permet d'utiliser le raccourci $ pour accéder à un élément par son id. Ainsi, les deux notations suivantes sont équivalentes :
/* Sans prototype */
document.getElementById('divContent')
/* Avec prototype */
$('divContent')
Un premier appel
Le framework de prototype met à la disposition des programmeurs plusieurs objets pratiques dont Element, qui permet de modifier directement le DOM (Document Object Model) d'une page web. Par exemple, pour cacher une portion de la page en JavaScript pur, on utilisait généralement quelque chose comme ceci :
/* Cacher l'élément */
document.getElementById('divContent').style.display = 'none';
/* Afficher l'élément */
document.getElementById('divContent').style.display = '';
Tandis que prototype nous permet d'y aller plus simplement :
/* Cacher l'élément */
Element.hide('divContent'); ou $('divContent').hide();
/* Afficher l'élément */
Element.show('divContent'); ou $('divContent').show();
Attacher des événements
Prototype permet aussi de détacher le code JavaScript initialement placé "inline" dans le code HTML. Ainsi, une fonction attachée à un événement onClick d'un bouton pourra être remplacée comme ceci:
Fonction JavaScript attachée inline dans le HTML
<input type="button" id="btn" onClick="myFunction()" />
La portion onClick="myFunction()" de l'exemple ci-dessus pourra être remplacée par une fonction attachée à l'événement click par prototype
Event.observe('btn', 'click', myFunction);
Une fois ces notions de base assimilées, le vrai plaisir commence...
Pour commencer la fin de semaine du bon pied, allons-y en humour avec le site satirique The Best Page in the Universe, un site ayant généré plus de 225 millions de visites depuis 1997 (9346 ème site le plus visité selon Alexa). Corrosif à souhait, pour des heures de plaisir.
Une façon simple de créer un environnement de développement de type WAMP (Apache, MySQL et PHP pour Windows, le terme LAMP étant son alter-ego Linux) est d'installer EasyPHP. Cet exécutable installe le tout et crée une configuration pour que ça soit fonctionnel facilement, sans se casser la tête. On accédera au serveur local par http://localhost ou http://127.0.0.1/, où les fichiers (php, html, etc) auront préalablement été déposés dans le répertoire par défaut (dans mon cas C:\Program Files\EasyPHP 2.0b1\www).
Ce qui est bien, c'est que plusieurs extensions d'Apache sont disponibles mais elles ne sont toutefois pas activées lors de l'installation. C'est le cas pour mod_rewrite, un module populaire permettant de créer des règles pour réécrire les urls. Par exemple, on pourra faire en sorte qu'un url comme :
http://www.digg.com/technology.php?popular=24hours
soit traduit par l'engin par :
http://digg.com/technology/popular/24hours
Pour activer le module mod_rewrite dans Apache, on devra modifier la configuration du fichier httpd.conf d'Apache (ce n'est pas exclusif à EasyPHP) :
- Ouvrir le fichier httpd.conf (dans le répertoire d'installation de Apache ou à partir du tray, cliquer sur l'icône EasyPHP / Configuration / Apache)
- Trouver la ligne #LoadModule rewrite_module modules/mod_rewrite.so et retirer le dièse (#) pour décommenter la ligne
- Chercher dans le fichier les instructions AllowOverride None et remplacer par AllowOverride All aux endroits nécessaires. Comme il y en a plusieurs, on pourrait tous les remplacer si on n'est pas certain. La configuration initiale de EasyPHP étant plutôt stricte, ils sont tous à "none" par défaut. Dans mon cas, je développe sur un alias, donc sa configuration se trouve à la toute fin du fichier httpd.conf (un seul changement).
Lorsque l'on surf sur le web, certains sites prennent en considération le type de fureteur utilisé pour adapter le contenu ou offrir une mise en page différente. Par exemple, c'est le cas de Google, Yahoo, Facebook et Amazon, qui offrent une mise en page adaptée lorsqu'ils détectent que le visiteur utilise un appareil iPhone (Safari). Au niveau de la programmation, ceci est rendu possible en vérifiant une propriété propre à chaque fureteur qui s'appele le "user-agent".
Si on entre la commande about:config dans la barre d'adresse de Firefox, on pourra voir le user-agent à partir de la propriété nommée general.useragent.extra.firefox dont la valeur est Firefox/3.0.4 (celui que j'utilise présentement).
Une extension de Firefox nommée User Agent Switcher permet de modifier la valeur du user-agent spéficié par le fureteur lors des visites. Pour ajouter un nouveau user-agent, il faut se rendre dans les options de l'extension, sous le menu User Agents, ajouter un nouveau type et le sélectionner dans le menu (Tools / User Agent Switcher).
Par exemple, pour visualiser un site comme le verrait un iPhone, il faut en créer un avec les information suivantes :
- Description: iPhone
- User Agent: Mozilla/5.0 (iPhone; U; CPU like Mac OS X; en)
- App Name: AppleWebKit/420+ (KHTML, like Gecko)
- App Version: Version/3.0
- Platform: Mobile/1A542a Safari/419.3
Sinon, certains sites, comme Experts Exchange, restreignent l'accès à leur contenu lorsqu'on y accède par un user-agent normal mais doivent en afficher des portions pour pouvoir être indexé dans Google. En simulant le user-agent du Googlebot, on pourra avoir accès aux réponses, sans même devoir s'inscrire.
Googlebot
- Description: Googlebot 2.1 (New version)
- User Agent: Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)
Lorsqu'on effectue une mise en page d'un site web, il est souvent question de savoir si on doit intégrer les données en utilisant des tableaux ou non. Lorsque vous serez dans le doute, voici un site pratique qui vous permettra de trancher sur la question.
Should I Use Tables for Layout :
http://www.shouldiusetablesforlayout.com/
Récemment, j'ai eu à travailler sur un vieux projet ASP et j'ai eu la joie de redécouvrir le serveur IIS (Internet Information Services). En développant localement, j'ai eu à effectuer certaines configurations qui ont nécessité à quelques reprises un redémarrage du serveur web. Plutôt que de procéder à chaque fois à partir du GUI, j'ai préféré utiliser un petit script batch qui me permettait de faire un redémarrage complet plus facilement (un double-click), en terminant tous les services dépendants (à l'aide de net stop). Selon la documentation de Microsoft, cette opération est nécessaire lorsque la configuration modifie le régistre de IIS et le force donc à en faire une relecture.
Dans un fichier texte, inscrire les commandes suivantes et renommer l'extension du fichier .bat.
@echo off
net stop iisadmin /y
net start iisadmin
net start w3svc
net start "FTP Publishing Service"
Deux petites remarques :
- Selon ce qui a été installé, d'autres services peuvent être ajoutés à la liste
- Pour que le script puisse fonctionner, on doit avoir le contrôle de son poste (administrateur ou droits associés)