skip to main | skip to sidebar
Code 18
Manuel du savoir-faire à l'usage des geeks et des curieux
RSS
  • Accueil
  • Le web au Québec
  • Liens
  • Twitter
  • Facebook
  • À propos

dimanche 31 octobre 2010

On est tous des attention whores

Publié par Infinite Loop, à 11 h 47 0 commentaire

Complétez le vieux proverbe suivant : On the internet, nobody knows you're a dog. La meilleure réponse serait peut-être : But everybody knows you're an attention whore. C'est un peu l'impression que me donnent les médias sociaux dans un ère de web 2.0.

Selon Urban Dictionary, attention whore est une étiquette donnée à toute personne qui aspire l'attention à un point tel qu'elle fera tout pour en recevoir. Le type d'attention (positive ou négative) n'a pas d'importance.

Comme le dit l'adage, parlez-en en bien, parlez-en en mal mais parlez-en. Et ouvertement, sur la place publique aux yeux de tous. Mes pensées font immédiatement référence aux clips vidéos amateurs de toutes sortes postés sur YouTube, au marketing viral et aux nombreux sites de réseautage social. On est rendu à l'ère du "m'as-tu vu ?". J'existe, la preuve étant que j'étale ma vie sur les réseaux sociaux.

Tout ça n'est pas normal, même que c'est malsain. Quand on sait que les plus gros utilisateurs de Facebook sont considérés par certains psychologues comme étant le reflet d'une personnalité narcissique, peut-être qu'est venu le temps d'une remise en question ? La possibilité de vivre son 15 minutes de gloire est maintenant accessible à tous, facilement. Le web est la nouvelle télé qui peut créer une vedette instantanément. Tasse-toi mononcle, je tente ma chance!

Après tout, suis-je si différent de l'utilisateur moyen sur les Internets ? Quand j'obtiens un ami de plus sur Facebook, j'ai l'étrange l'impression de vivre ma vie sociale à fond. Comme pour un trophée de chasse, j'expose ma liste à la vue de tous, fier de pouvoir dire que j'en ai plus que toi, toi et toi. Le positivisme ? C'est moi tout craché. À croire qu'ils ont inventé le bouton "J'aime" pour que j'en abuse. J'ajoute toutes les semaines des photos à mon compte, surtout des poses de moi-même sous tous les angles, vu à travers le miroir de la salle de bain. Je deviens fébrile à l'idée de commenter les banalités de la vie quotidienne. Parce que mes opinions comptent autant que les tiennes, je vais me mettre à bloguer. Puis me rendre compte que mon lectorat brille par son absence, qu'il ne vient pas à moi si facilement. Une idée de génie me vient alors : utiliser son statut Facebook pour imposer ses états d'âme à sa liste de contacts. Au moins je saurai que quelques amis virtuels seront forcés de lire mes platitudes, jusqu'à ce qu'ils me masquent de leur interface. Le pire cauchemar de tout individu est de se sentir exclu. L'être humain a le besoin de faire parti d'un groupe et idéalement d'en être le leader pour rayonner pleinement.

Tout ça, ce sont des choses que les soi-disant spécialistes en médias sociaux savent et qu'ils sont convaincus savoir mieux utiliser que vous. Sinon, ils sauront vous convaincre et vendre leurs services aux entreprises qui souhaitent rejoindre une clientèle différemment des moyens traditionnels. La mode est clairement au web social qui se commercialise. La profession est née il y a quelques années, à peu près au même moment où le web 2.0 était un buzzword qui se propageait à la vitesse de l'éclair et infectait le cerveau des décideurs. Personne ne savait ce que c'était et tout le monde voulait s'assurer de ne pas manquer le bateau.

Pour avoir le droit d'inscrire sur sa carte d'affaire le titre d'expert en médias sociaux, c'est facile. Il vous faut :

  • GBS 101 (gros bon sens)
  • beaucoup de temps libre
  • la force de persuasion
  • vous autoproclamer comme expert parce que personne ne le fera à votre place. En effet, aucun diplôme ne reconnaîtra vos compétences
  • s'arranger pour avoir de la visibilité sur le web, que vous soyez vu partout, même là où l'on ne veut pas vous voir
Ensuite, il vous faudra ouvrir un blogue et un compte Twitter pour prouver que vous êtes actif. Et tweeter beaucoup, énormément, tout le temps. Idéalement, un minimum de 25 à 50 gazouillis par jour est requis. Le but, tout comme pour Facebook, est d'obtenir le plus grand nombre de followers. Plus vous en aurez, plus votre influence sera grande. Tous les coups sont permis pour agrandir son cercle d'influence. Commencez à suivre des gens au hasard et lorsqu'ils vous suivront à leur tour (par politesse ?), cessez de les suivre. Lorsque vous serez sur le point d'atteindre un chiffre rond, lancez un tweet du genre : dans x followers, j'atteinds le cap des 500 ! J'avoue avoir déjà fait l'expérience une fois. J'en garde un souvenir très médiocre.

Après tout, ça demeure une vaste opération de marketing web, pour soi ou au service des entreprises. On veut être le centre d'attention à tout prix, agrandir son cercle d'influence et améliorer sa réputation web. Et avouons le, nous le faisons en majorité avec un niveau d'amateurisme inégalé. Et on pourrait pratiquement reléguer les experts en médias sociaux au niveau du mythe parce qu'ils se font rares tellement qu'on peut commencer à douter de leur existence.

Je sais que je suis cruel envers le marketing par médias sociaux. D'autres commentaires vont aussi en ce sens (il y a encore de l'espoir) :
  • 10 questions pour évaluer un "expert" des médias sociaux (anglais)
  • 5 mythes sur les médias sociaux
  • J'en ai marre des marchands de tapis de prétentions et d'illusions
Je le répète : on est tous des attention whores. Je pense plus particulièrement à deux personnalités québécoises que je ne nommerai pas, qui sont sur Twitter, et que je me suis empressé à ne plus les suivre tellement leurs interventions étaient d'une inutilité déconcertante (pourtant, ils ont des milliers de followers chacun!). Peut-être suis-je aussi en manque d'attention ? Pourquoi faire un blogue si ce n'est pas pour avoir les projecteurs sur soi ? Le fait d'être anonyme me permet-il d'être en retrait du faisceau lumineux ? De mettre en valeur le sujet plutôt que la personne qui le présente ? Un seul de mes amis connaît mon projet. Mes collègues de travail et mon patron l'ignorent complètement. Qui sait s'ils ne l'ont pas déjà consulté ?

Et qu'est-ce que ça changerait si je dévoilais mon nom ? Parti de l'idée d'un pense-bête personnel, Code 18 est aussi un gros laboratoire où je mène mes expériences. Je peux prendre des risques car ça n'affecte pas ma e-réputation et que mon projet n'a pas d'objectif commercial. Je suis juste un gars ordinaire qui, jusqu'à maintenant, a eu le ténacité et la motivation de réaliser un projet DIY durant plus de 2 ans. Ma dernière lubie web avait duré 5 ans. Et c'est par ce projet que j'ai rencontré mes meilleurs amis (vous savez, la vraie amitié, ceux qui se comptent sur les doigts d'une main et qu'on voit dans la vraie vie ?). J'aurais tout avantage de sortir de l'ombre mais j'ai encore une réserve.

Lors de mon plus récent projet, j'ai connu le succès et j'étais mal à l'aise avec la popularité. J'aimais mieux vivre dans l'ombre, être low profile, mettre les idées à l'avant-plan. Juste pour vous dire, j'étais un média respecté dans le domaine de la musique. À chaque spectacle que j'assistais, je serrais tellement de mains que je n'avais pas la chance de profiter de la performance musicale. Parfois plus populaire que l'artiste sur scène. Parfois du léchage de bottes par les artistes eux-mêmes pour essayer de s'attirer des faveurs. J'aurais pu faire la grosse tête et jouer la vedette mais j'ai préféré rester terre à terre, allant même jusqu'à me retirer complètement du milieu pour pouvoir redevenir un simple fan. Toute cette attention me puait au nez. Le succès du webzine reposait sur un mélange de créativité, de contenu de qualité, d'éthique de travail et sur la possibilité d'étendre mes activités web à travers une expérience sociale enrichissante.

Cette fois-ci, je n'ai aucune idée quelle direction prendra ce blogue dans l'avenir ou combien de temps je pourrai tenir à bout de bras ce défi quotidien. Il gagne chaque jour en popularité et me demande de plus en plus de temps. Je ressens déjà le besoin de ralentir parce que j'ai d'autres projets sur la table. Tant mieux si mon blogue peut servir à d'autres qui ont des intérêts communs avec les miens.

Quand même, merci de votre attention.


Tags: Lois et principes

Citation no. 105 sur le cannibalisme

Publié par Infinite Loop, à 08 h 12 0 commentaire

Un cannibale rencontre un homme-sandwich.
Et il s'écrie : - Chic ! il est déjà tout préparé.

- Noctuel


Tags: Citations

samedi 30 octobre 2010

Réseaux sans fil de mes voisins

Publié par Infinite Loop, à 22 h 49 3 commentaires

Alors que j'allais configurer une connexion VPN à partir de mon laptop Ubuntu, j'ai remarqué ceci dans la liste des réseaux sans fil détectés par le système d'exploitation.



À votre avis, WIN ou FAIL ?


Tags: Humour

vendredi 29 octobre 2010

Piège JavaScript no. 7

Publié par Infinite Loop, à 19 h 26 0 commentaire

J'ai aussi échoué la deuxième question du quiz JavaScript avancé. La question était la suivante : dans l'exemple suivant, qu'affichera typeof ?

var f = function g(){ return 23; };
typeof g();
Choix de réponse :
  • number
  • undefined
  • function
  • error
Logiquement, je m'étais dit que la fonction g() était bel et bien définie et qu'elle était simplement assignée à f. J'ai donc répondu "function" sachant, à cause du piège #6, que typeof sur une fonction retourne "function".

Erreur. Parce que la fonction est assignée à la variable, g est contenu dans f mais ne semble pas reconnu dans la portée globale :
console.log( f ); // g()
console.log( f() ); // 23
console.log( g() ); // g is not defined
Sauf si on procédait ainsi :
function g(){ return 23; }
console.log( typeof g ); // function
console.log( typeof g() ); // number
Ici, typeof g() retournerait un nombre mais dans le contexte du piège, g() n'est pas défini. La réponse undefined semble alors évidente. Faux.
console.log( g() == undefined ? true : false ); // g is not defined
Autrement dit, "is not defined" lancé par Firebug n'équivaut pas à "undefined". Ce serait indéfini dans le cas où une variable ne serait pas initialisée (si la fonction g() n'est pas assignée à f).
var f;
console.log(f); // undefined
La bonne réponse était : typeof g() provoque une erreur.


Tags: JavaScript

jeudi 28 octobre 2010

Piège JavaScript no. 6

Publié par Infinite Loop, à 19 h 46 1 commentaire

Maintenant que j'ai décortiqué les 5 pièges JavaScript proposés par Dmitry Baranovskiy, je suis prêt à me pencher sur ceux du quiz avancé. Essayez-le avant de poursuivre plus loin la lecture de ce billet.

Question # 1 du quiz : dans l'exemple suivant, de quel type est "arguments" ?

(function(){
return typeof arguments;
})();
Choix de réponse :
  • object
  • array
  • arguments
  • undefined
Lors du piège JavaScript no. 4, on a vu comment fonctionnait arguments. Comme on sait qu'il existe automatiquement dans le mécanisme d'une fonction, on peut procéder par élimination et rayer "undefined" de la liste. On peut aussi éliminer le type "arguments" parce qu'on a vu que si on imprimait le contenu de la variable, on obtenait une liste :
console.log(arguments); // []
console.log(arguments); // [1,2,3]
Donc un array. En effet, on ne se trompe pas si on dit que arguments est un array. Mais on n'a pas raison non plus.

Réponse : typeof arguments retourne "object".
// observez-le en assignant le résultat à une variable
// ou imprimez-le avec console.log()
var type = (function(){
console.log(typeof arguments);
return typeof arguments;
})();

alert(type);

// ou bien

var list1 = new Array(1,2,3);
var list2 = [1,2,3];

console.log(typeof list1); // object
console.log(typeof list2); // object
Curieux non ? Surtout si on observe la trace de différents types :
console.log( typeof true ); // boolean
console.log( typeof 1 ); // number
console.log( typeof "hello world" ); // string
console.log( typeof [1,2,3] ); // object
console.log( typeof function(){} ); // function
Contrairement à tous les autres types spécifiques, il faut savoir qu'un array JavaScript est toujours du type object.


Tags: JavaScript

mardi 26 octobre 2010

Piège JavaScript no. 5

Publié par Infinite Loop, à 19 h 17 1 commentaire

Nous voilà enfin au dernier piège de cette série de 5 astuces JavaScript. Après, je pourrai décortiquer une par une les 14 questions du Quiz que j'ai si bien réussi (3/14).

Dans cet exemple, savez-vous ce qu'affichera alert(this) ?

function a(){
alert(this);
}
a.call(null);
Est-ce que this fait référence à la fonction elle-même ? À sa portée locale ? Pourquoi appeler call() sur la fonction a() si on peut tout simplement appeler a() directement ? Pour ma part, j'ignorais la réponse. Mieux valait tester.

Réponse : alert(this) affichera [object Window] dans Firefox (object DOMWindow dans Chrome et object dans IE8).

Celle-là, je n'étais pas certain de la comprendre. Surtout parce que je ne connaissais pas le mécanisme de la fonction call appliqué à une fonction. Regardons de plus près son comportement.
a(); // affiche object Window
a.call(); // encore object Window
a.call(null); // toujours object Window
Alors c'est quoi le piège ? La fonction a() ne prend pas d'argument en entrée. Par contre, l'appel à call() avec null comme argument laisse sous-entendre qu'on peut lui passer quelque chose. Mais à quoi ça peut servir ?
var x = 18;
a.call(x); // affiche 18

var obj = { label : 'Code 18', value : 18 }
a.call(obj); // affiche object Object
Donc à l'intérieur de la fonction, this prend en référence l'objet qu'on passe en paramètre à call().

Si j'ai une fonction b(x, y) qui accepte 2 arguments :
function b(x,y){
console.log(x);
console.log(y);
}

b(10, 20); // affichera 10 et 20
b.call(10, 20); // affichera 20 et undefined
Si on change la fonction b() pour imprimer la valeur de this :
function b(x,y){
console.log(this); // 10 {}, un objet sans propriétés ?
console.log(x); // 20
console.log(y); // undefined
}
En utilisant le mécanisme de call(), le premier paramètre sera la référence à l'objet à utiliser, les suivants seront les arguments de la fonction. Pour obtenir le même résultat, il aurait fallu faire l'appel ainsi :
b(10, 20);
b.call(null, 10, 20);
Un exemple simple sur la référence :
var obj = { label : 'Code', value : 18 }
c.call(obj, 10, 20, 30);

function c(x, y, z){
console.log(this.label); // Code
console.log(this.value); // 18
console.log(x); // 10
console.log(y); // 20
console.log(z); // 30
}
À l'intérieur de c(), this n'égalera pas object Window mais bien l'objet obj avec ses propriétés. Si la valeur est omise ou nulle, this sera par défaut le plus proche parent.
var z = {
x : function(){
console.log(this);
}
}

var obj = { label : 'Code 18', value : 18 };

z.x(); // Object {}, Object étant z
z.x.call(obj); // Object { label="Code 18", more...}
Maintenant qu'on comprend l'astuce, je ne veux pas que vous restiez sur votre appétit et je vous suggère une lecture complémentaire qui présente de bons exemples sur l'utilisation de call(). J'ai adapté cet exemple de l'article call and apply que je vous recommande fortement :
var Character1 = {
name: "Itchy"
}

var Character2 = {
name: "Scratchy"
};

var friendlyGreet = function(somebody) {
console.log("Bonjour " + somebody.name + ", je suis " + this.name);
};

friendlyGreet.call(Character1, Character2); // Bonjour Scratchy, je suis Itchy
friendlyGreet.call(Character2, Character1); // Bonjour Itchy, je suis Scratchy


Tags: JavaScript

lundi 25 octobre 2010

Le plus vieil homme du monde avait 174 ans

Publié par Infinite Loop, à 20 h 34 0 commentaire

Du moins, c'est ce que semble prétendre la revue Science & Vie de juillet 2010 (no. 1114, page 121) dans son article sur les feux d'artifices où on indique que le chimiste français Claude Berthollet est décédé à l'âge vénérable de 174 ans (1748-1922).



Évidemment, ça semble être une erreur typographique. On aurait dû y lire les années 1748-1822 (74 ans). Selon nos sources (c'est fiable Wikipedia!), la personne qui détient le record de longévite est la française Jeanne Calment (1875-1997). Elle vécut 122 ans. On est encore loin de Yoda qui s'éteignit à l'âge de 900 ans...


Tags: Curiosités

dimanche 24 octobre 2010

Détruire le web, un site à la fois

Publié par Infinite Loop, à 19 h 10 1 commentaire

Plus tôt aujourd'hui, j'étais occupé à isoler les fenêtres en prévision de l'hiver quand je suis entré à l'intérieur et que je me suis dirigé vers le bureau. Ma copine était assise à l'ordinateur et était visiblement sur mon blogue en train de faire explorer les éléments de la page d'accueil.

- Qu'est-ce que tu fais là ? Je n'ai pas travaillé 2 ans là-dessus pour rien !
- Non, ce n'est pas ce que tu penses. C'est un jeu sous forme d'extension Firefox. Ça consiste à détruire le plus rapidement possible les éléments affichés dans la page et ça cumule des points.

Pour y jouer, installez d'abord l'extension de Destroy The Web pour Firefox (version 3.5 et plus) et rendez-vous sur un site que vous souhaitez démolir. Dans la barre de navigation de Firefox, cliquez sur l'icône encerclé pour démarrer une partie.



Tenez-vous prêt, le jeu commence dans 3, 2, 1, GO ! Vous avez 30 secondes pour cliquer sur les éléments à faire exploser et accumuler le plus de points.



À la fin, votre pointage final s'affiche en tenant compte du type d'éléments détruits : liens, images, divs, entêtes, tables, éléments de formulaires, etc.



Vous pouvez alors soumettre votre score et voir le palmarès des sites qui ont été le plus souvent démolis (Facebook, Google, Wikipedia et Yahoo sont parmi les plus populaires) ainsi que les meilleurs pointages.


Tags: Extensions Firefox

Citation no. 104 sur la vie

Publié par Infinite Loop, à 09 h 28 0 commentaire

Que votre vie soit comme le papier de toilette : longue et utile.

- Anonyme


Tags: Citations

samedi 23 octobre 2010

Parce que vous n'avez pas eu le temps de tout voir, j'ai vu pour vous...

Publié par Infinite Loop, à 10 h 03 0 commentaire

Aux États-Unis, les Zombies prennent d'assaut le magasin à rayon Sears. Superbe coup de promotion pour l'Halloween, on peut même visualiser le site en langage Zombian (switch to Zombian) ! www.sears.com/Zombies



Le temps c'est de l'argent. Calculez-le à l'aide de l'horloge TIM (Time Is Money).



Il faut croire que le joueur de hockey Ilya Kovalchuk l'a compris. Avec son contrat de 100 millions pour 15 ans avec les Devils du New Jersey, il gagne exactement 114,16$ de l'heure, même quand il dort (il s'enrichit d'environ 0,03$ par seconde). On se consolera en se disant qu'au moins, il n'a pas réussi à s'inscrire sur la feuille de pointage lors du match de jeudi contre nos Canadiens.

Vu sur Twitter : cette fille prend les décisions dans sa vie selon les résultats des sondages qu'elle publie. Un bel exemple de crowdsourcing appliqué à la vie de tous les jours.

Une page 404 comme on les aime sur 501st Legion :



On apprend aussi qu'un rapport suggère que pour chaque 1000$ vendu, un musicien reçoit en moyenne 23,40$. Comme j'ai assisté au spectacle de Misteur Valaire mercredi dernier, je me demande quelle portion du prix du billet (21,73$) revient directement dans les poches de cet excellent groupe de Sherbrooke ? Peut-être que Guillaume Déziel pourra me fournir une réponse encourageante.

Fan 2.0 : un admirateur techno de Barack Obama sollicite un autographe : Mr President, sign my iPad.



Via Geekbecois, on apprend que Vin Diesel, la coqueluche de ces dames, est un joueur de Donjons & Dragons. Mes doutes se confirment enfin!



Potin Plateau
Le rôle de Bilbo Baggins dans le film The Hobbit sera joué par Martin Freeman. Joël Legendre et Yves Corbeil sont présentis pour le doublage au Québec.

Il s'en passe tu des choses sur les Internets !


Tags: Curiosités, Humour, Le coin du geek

vendredi 22 octobre 2010

Piège JavaScript no. 4

Publié par Infinite Loop, à 18 h 32 0 commentaire

Pour moi, ce fût une grosse semaine au travail. Beaucoup de bidules à fignoler dans la programmation en vue d'une livraison en plus d'une révision des spécifications du cahier des charges à passer au peigne fin. Pour bien amorcer le weekend, je suis revenu chez moi, j'ai pris un comprimé d'aspirine et je suis prêt à voir avec vous le 4ème piège JavaScript. Après quoi, un repos sera bien mérité.

Ceux qui ont un peu d'expérience en programmation trouveront que ce piège est probablement le plus facile jusqu'à maintenant. En fait, c'est une question de logique et de portée des variables :

function b(x, y, a) {
arguments[2] = 10;
alert(a);
}
b(1, 2, 3);
Si on appelle la fonction b() avec 3 paramètres, qu'affichera l'alerte ? 10, 2 ou 3 ? Que représente arguments ? A-t-il un effet direct pour modifier la valeur de la variable a (troisième paramètre) ? Est-ce que arguments[2] représente la deuxième valeur, soit 2 ? Si c'est le cas, on assignerait 10 à la variable y et a resterait inchangé.

Réponse : alert(a) affichera 10.

Vous avez sûrement déjà vu dans du code "arguments.length" ? Dans ce contexte, le mot clé arguments est une variable qui existe automatiquement et qui fait référence à la liste des arguments reçus par la fonction, même s'ils n'étaient pas nommés explicitement (le concept existe dans de nombreux autres langages de programmation). En JavaScript, les arrays commencent à l'indice 0. Donc une liste d'une longueur de 2 éléments sera composée des indices 0 et 1.
function c(){
for(var i=0 ; i<arguments.length ; i++){
console.log(arguments[i]);
}
}

c('Code', 18);
Dans l'exemple initial de la fonction b(), en modifiant la valeur à l'indice 2, on écrase la valeur passée en paramètre lors de l'appel. Parce que la variable est nommée localement, arguments[2] est une référence à la variable a.

On peut vérifier le tout avec une trace :
function b(x, y, a) {
console.log(arguments); // [1, 2, 3]
console.log(a); // 3
console.log(arguments[2]); // 3
arguments[2] = 10;
alert(a); // 10
}
b(1, 2, 3);


Tags: JavaScript

jeudi 21 octobre 2010

Piège JavaScript no. 3

Publié par Infinite Loop, à 19 h 19 0 commentaire

Avec ce qu'on a vu jusqu'à maintenant, ce troisième piège JavaScript me semble déjà plus facile à résoudre. Lors du dernier exercice (piège JavaScript no. 2), on a vu qu'une variable et une fonction pouvaient porter le même nom si elles n'étaient pas dans la même portée. Or ici, une fonction a() est définie, suivie d'une déclaration de variable du même nom (dans la même portée).

function a(x) {
return x * 2;
}
var a;
alert(a);
Si vous avez répondu que alert(a) afficherait undefined, vous êtes tombé dans le piège.

Réponse : alert(a) affichera la définition de la fonction a.

Ici, ce n'est pas une question de priorité dans l'ordre des déclarations. Si on déplace "var a" avant la définition de la fonction, le résultat sera le même. JavaScript semble avoir la particularité de prioriser la fonction à la variable si les deux possèdent un nom identique.

Dès qu'on assigne une valeur à la variable a, on remarque que la fonction a est écrasée, ce qui rend la fonction totalement inutilisable.
console.log(typeof a); // function
console.log(a(2)); // 4
var a = 1;
console.log(typeof a); // number
console.log(a); // 1
console.log(a(2)); // a is not a function
Pour éviter ce type de conflit, on peut assigner la fonction à une variable avant de lui assigner une autre valeur (var fct = a; fct(2); a = 1;) ou encore utiliser une convention de notation qui vous permettra de distinguer les fonctions des variables.


Tags: JavaScript

mardi 19 octobre 2010

Piège JavaScript no. 2

Publié par Infinite Loop, à 19 h 39 0 commentaire

Avez-vous digéré le piège JavaScript d'hier ? Par curiosité, avez-vous mis vos connaissances à l'épreuve au quiz JavaScript avancé ? Si oui, quel pointage avez-vous obtenu ?

Si vous êtes disposés à continuer, je suis prêt à m'attaquer au piège suivant.

var a = 1,
b = function a(x) {
x && a(--x);
};
alert(a);
Qu'est-ce que ce code vous suggère ? Est-ce possible qu'une variable possède le même nom qu'une fonction ? Si oui, la valeur de la variable a pourrait être transformée par la fonction a(). ou encore, l'appel à alert(a) affichera-t-elle la valeur de la variable ou le résultat de la fonction ?

Exécutons le code ci-dessous pour mieux comprendre le fonctionnement interne :
console.log(typeof a); // number
console.log(a); // 1
console.log(b); // a(x)
console.log( a(7) ); // erreur : a is not a function
Résultat : alert(a) affichera 1

L'explication est que la fonction peut s'appeller a car elle n'entre pas en conflit avec la variable a puisqu'elles ne sont pas dans la même portée (la fonction est dans la portée de b alors que la variable est dans la portée globale). En fait, la fonction a, qui aurait pu être anonyme (sans nom) est une définition de fonction qui est assigné à b, ce qui fait qu'on ne peut pas appeler la fonction a() directement, sauf à l'intérieur de lui-même (concept de récursivité). Par contre, on peut l'appeler à l'aide de b() qui est reconnu dans la portée globale :
b(7); // appel de la fonction a() en passant 7 comme paramètre
Si on glisse une instruction alert(x) ou console.log(x) pour suivre la trace au début de la fonction a(), on verra que la fonction est appelée récursivement (elle s'appelle elle-même) : 7, 6, 5, 4, 3, 2, 1, 0. À la ligne de code x && a(--x), si x vaut 0, la valeur zéro est considérée comme false dans l'évaluation de la condition (les conditions if(!0) et if(false) sont équivalentes). Dès que false est rencontré dans le ET logique, les conditions suivantes ne sont pas évaluées, ce qui met fin à la récursivité. Sinon, la fonction se rappelle elle-même en utilisant la valeur de x décrémentée (opérateur --).


Tags: JavaScript

lundi 18 octobre 2010

Quelques pièges JavaScript

Publié par Infinite Loop, à 22 h 08 0 commentaire

Après avoir effectué le quiz JavaScript avancé puis avoir obtenu un pointage lamentable de 3 sur 14, je me suis résolu à ravaler ma fierté et à essayer de comprendre un par un les pièges où j'étais tombé.

Mais tout d'abord, j'ai mis au banc d'essai les 5 attrapes proposées originalement par Dmitry Baranovskiy que je tenterai de décortiquer. Pour aujourd'hui, voyons la première attrape. À première vue, elle semble si simple...

Piège JavaScript # 1

if (!("a" in window)) {
var a = 1;
}
alert(a);
Qu'est-ce qui sera affiché ? Si on y réfléchit un peu :
  • Dans la condition, est-ce que "a" représente une chaîne de caractères ou correspond à la variable a ?
  • On vérifie si a n'est pas déclarée à l'intérieur de l'objet fenêtre (window) à l'aide de l'opérateur in et de la négation ! mais on y fait référence pour la première fois qu'à la ligne suivante avec la déclaration et l'assignation d'une valeur
  • Si var a = 1 est dans le if, la variable existe-t-elle au niveau de l'objet window au moment d'évaluer la condition if ?
Réponse : alert(a) affiche undefined.

Êtes-vous surpris de constater que la valeur de a soit indéfinie dans l'objet window ? Si on affiche la trace de l'objet dans la console de Firebug :
console.log(typeof window);
console.log(window);
La première ligne affiche le type "Object". La deuxième détaille les propriétés de l'objet window. On voit que la propriété a existe et fait partie de window mais qu'elle n'est pas initialisée (sa valeur est undefined).



Comment l'interpréteur JavaScript connaît globalement toutes les variables déclarées dans sa portée avant d'exécuter le code séquentiellement ? Ou bien est-ce dû à l'extension Firebug qui est lancée par la suite qui analyse le code ? Avec l'exemple suivant, l'impression du contenu de window indique bien l'existence de b et c qui apparaissent pourtant après l'appel. Leurs valeurs respectives sont aussi affichées correctement.
console.log(window);
var b = 1;
c = 2;
Par contre, si j'essaie cet autre test, un curieux comportement se produit. La première alerte (b) retoure "true" alors que la deuxième qui n'est pas déclarée par var (c) affiche false.
alert("b" in window); // true
alert("c" in window); // false

var b = 1;
c = 2;

// b et c s'affichent pourtant dans la portée de window!
console.log(window);
La différence ici est que b est une déclaration de variable dans sa portée courante qui crée du même coup une propriété à l'objet window alors que pour c, il s'agit d'une assignation de valeur à une propriété de l'objet global window. C'est pour cette raison que c ne fait pas parti de window en tant que variable mais bien en tant que propriété. Étrange différence, non ?

Si vous êtes dans une fonction, "var" créera une variable locale tandis que le fait d'omettre var cherchera à remonter la chaîne de portée jusqu'à ce qu'il trouve la variable ou frappe la portée globale (où il finira par la créer). C'est le concept des closures.

Pour mieux comprendre ce qui se passe, l'explication la plus complète se trouve sur ce billet de StackOverflow : Difference between using var and not using var in JavaScript. Dans le piège initial, retirez var dans le if pour que la condition devienne positive et l'alerte affichera 1.


Tags: JavaScript

dimanche 17 octobre 2010

Citation no. 103 sur le déjeuner

Publié par Infinite Loop, à 09 h 35 0 commentaire

Une toast au beurre d'arachides avec 1 verre de lait au chocolat Quik me donne l'impression d'avoir mangé un Reese pour déjeuner.

- Moi-même


Tags: Citations

samedi 16 octobre 2010

Quand le heavy metal ne se prend pas au sérieux

Publié par Infinite Loop, à 10 h 56 0 commentaire

La musique métal a la réputation d'être intense, d'avoir un côté méchant avec des sujets obscurs et occultes. Mais dans la réalité (pour en connaître quelque uns), ce sont des gens qui ont le sens de l'humour. La preuve, j'ai un défi pour vous : j'ai fait une sélection de trois vidéos produits à des décennies différentes et je vous gage que vous ne pourrez pas vous empêcher de rire. Comme quoi le ridicule ne tue pas.

Le premier est tiré du faux rockcumentaire This Is Spinal Tap (1984). En spectacle, le clip de la pièce Stonehenge est tout simplement savoureux. Attendez le moment où 2 nains déguisés en lutins gambadent au rythme de la musique autour d'une reproduction miniature du monument historique. Tout ça parce que selon le schéma de conception dessiné par le chanteur, il aurait écrit 18 pouces au lieu de 18 pieds. Priceless.



Breaking news: IMDB Easter Egg Alert!
En allant chercher l'information sur Internet Movie Database, j'ai remarqué un petit détail. Contrairement à tous les autres films, la note de celui-ci n'est pas calculée sur un total de 10 mais bien sur 11 ! Cliquez ici pour comprendre la référence :-)



Pour son clip "New Millenium Cyanide Christ" (1998), la formation suédoise de "math metal" Meshuggah a repoussé les limites du concept du "air guitar" en l'appliquant à l'ensemble de la formation. Remarquez tout le sérieux qu'y appliquent les musiciens, surtout le drummer. Absurde et tellement drôle!



Quand un ami m'a envoyé ce vidéoclip d'un groupe écossais du nom de Alestorm (2009), j'ai eu un fou rire immédiat. Du métal pirate! Le visuel est bien fait mais l'anachronisme de la guitare-piano sur le bateau, on n'y croit juste pas.

Sur leur site, ils n'hésitent pas à afficher leur position : Support music piracy!


Tags: Club Vidéo, Easter Eggs, Musique

vendredi 15 octobre 2010

23 sites pour explorer le HTML5

Publié par Infinite Loop, à 13 h 07 0 commentaire

En cette dernière journée de la semaine, je vous présente une rétrospective de 23 sites qui traitent du HTML5.

  1. A Preview of HTML5 Article qui survole le HTML5 paru en 2007 sur A List Apart
  2. Spécifications HTML5 sur W3C
  3. WhatWG (Web Hypertext Application Technology Working Group) Communauté qui maintient le HTML et qui le fait évoluer (collaboration non officielle des différents développeurs de navigateurs web)
  4. HTML5 sur W3Schools
  5. Validateur HTML5 Encore à titre expérimental
  6. The HTML5 Test Pour voir à quel point votre browser supporte les nouveaux éléments HTML5
  7. HTML5 Readiness Pour suivre l'évolution de la compatibilité des browsers au HTML5 et CSS3
  8. HTML5 du côté de Mozilla
  9. HTML5 et les standards web chez Apple
  10. Internet Explorer 9 Test Drive sur le HTML5 La preuve que le HTML5 et IE9 s'entendent bien. Vous pouvez aussi voir les exemples sur d'autres browsers compatibles
  11. Chrome Experiments Expériences HTML5 du fureteur de Google
  12. HTML5 Doctor Clinique sur le HTML5 en anglais
  13. Docteur HTML5 Le site précédent, traduit en français
  14. Smokescreen - Convertisseur Flash à HTML5/JavaScript
  15. HTML5 Boilerplate Un gabarit qui peut servir de base à un site HTML5
  16. HTML 5 Demos and Examples
  17. HTML5 Rocks Allez faire un tour du côté du Code Playground
  18. The Wilderness Downtown Clip interactif impressionnant d'Arcade Fire, gracieuseté de l'équipe de Google
  19. Expérimentations du canvas HTML5 et JavaScript
  20. Nevermind the bullets Une histoire interactive de cowboys en montrant les possibilités du HTML5 (chargement font face, image de fond SVG, accélération JavaScript, arrière-plan multiple CSS3, contenu éditable)
  21. Beauty of the web Créer des sites plus attrayants avec HTML5 et Internet Explorer 9 (promo pour IE9 par la bande)
  22. HTML5 Gallery Répertoire d'idées créatives
  23. Dive into HTML5 Survol très cool à lire (extrait du livre HTML5: Up & Running publié chez O'Reilly)
Bonne lecture !


Tags: HTML

jeudi 14 octobre 2010

Jouer à Snake sur un vidéo YouTube

Publié par Infinite Loop, à 20 h 01 0 commentaire

J'avais entendu parler que YouTube avait intégré un easter egg qui nous permettait de jouer à Snake sur les vidéos de la catégorie Gaming. On disait que lorsqu'une vidéo est en chargement, il suffisait de mettre le lecteur sur pause et de faire la combinaison FLÈCHE HAUT + FLÈCHE GAUCHE en même temps pour que le jeu démarre. Sans succès.

Tout à l'heure, je me suis risqué à essayer la combinaison FLÈCHE HAUT + FLÈCHE DROITE et ça a fonctionné, comme en témoigne l'imprimé d'écran ci-dessous. Mieux, ça fonctionnait sur des vidéos de toutes catégories.

L'extrait que j'ai utilisé pour tester était celui-ci, annonçant la réunion du 25ème anniversaire de Back To The Future.

Scream Awards 2010 with Michael J. Fox on Spike
BTTF 25th Anniversary Reunion Nov 5-12, 2010



J'avoue ne pas avoir joué longtemps, le défi étant un peu trop simpliste par rapport au niveau des jeux d'aujourd'hui (manger les points qui apparaissent pour que le serpent allonge sans toucher les rebords ou lui-même). Quand Google avait remplacé son logo par un jeu de Pac Man (pour souligner le 30ème anniversaire), on raconte que le temps passé par les visiteurs à jouer représenterait une perte de productivité de 120 millions de dollars. Dans ce cas-ci, heureusement que la raison d'être de YouTube est la perte de temps :-)


Tags: Easter Eggs

mercredi 13 octobre 2010

Faire du son par programmation C++, partie 2

Publié par Infinite Loop, à 20 h 54 0 commentaire

Je ne sais pas si mon dernier billet sur la façon de produire du son par programmation C++ vous a impressionné, mais quand on commence dans quelque chose, il faut partir par la base pour bien comprendre ce qu'on fait. Alors je poursuis l'exemple en poussant un peu plus loin les notions sans toutefois aller jusqu'à la lecture de fichiers musicaux (ça viendra).

Le programme initial comportait une limitation importante : celle de jouer des sons uniquement au même octave (j'avais choisi le 4ème). Pour ma démonstration, j'ai apporté quelques modifications en calculant la fréquence des notes de la gamme majeure à chaque octave, du 4ème au 7ème (les plus jolis et perceptibles à l'oreille). Si vous souhaitez tester à des octaves plus hauts, remarquez que plus la fréquence est élevée, plus le volume du son baisse. L'oreille humaine est sensible à des sons compris entre 20 et 20000 Hz (expérimentez le avec ce programme).

Pour commencer, j'inclus 2 librairies supplémentaires :

  • math.h pour pouvoir utiliser la fonction pow (calcul de puissance)
  • stdio.h pour utiliser printf et imprimer à l'écran la fréquence de chaque note calculée pour suivre la trace (optionnel)
Ensuite, j'ai redéfini les constantes en indiquant la fréquence de base des notes à l'octave 0 (notation A0 = La à l'octave 0, A4 = La au 4ème octave). Comme le ratio de l'octave est de 2/1, la formule mathématique pour calculer n'importe quelle note à son octave supérieur est : (ratio exposant octave) multiplié par sa fréquence de base. Par exemple, pour un A4: 24 * 27,5 = 440 Hz.

Dans la fonction principale (main), je déclare les différentes variables utilisées au cours du programme. Ceux qui ne sont pas familiers avec la programmation se demanderont peut-être ce que représente notes[]. C'est un tableau qui contient 7 éléments (numérotés dans son fonctionnement interne de 0 à 6). J'y place les notes de base dans l'ordre, ce qui me permettra de parcourir la liste un élément à la fois.

Je lance ensuite 2 boucles imbriquées (for). La première indique que pour chaque octave, je fais aussi une itération sur chaque note du tableau en calculant sa fréquence et en l'envoyant vers le haut-parleur système.
#include <windows.h>
#include <math.h>
#include <stdio.h>

using namespace std;

/* Définition des contantes à l'octave 0 et de chaque fréquence */
#define C0 16.35 // DO
#define D0 18.35 // RE
#define E0 20.60 // MI
#define F0 21.83 // FA
#define G0 24.50 // SOL
#define A0 27.50 // LA
#define B0 30.87 // SI

#define RATIO_OCTAVE 2

int main()
{
float notes[] = {C0, D0, E0, F0, G0, A0, B0};

float current_note;
float frequency;
float freq_octave;
int idx;
int octave;

for(octave=1 ; octave<=7 ; octave++){
freq_octave = pow(RATIO_OCTAVE, octave);

for(idx=0 ; idx<7 ; idx++){
current_note = notes[idx];
frequency = current_note * freq_octave;
printf("%f\n", frequency);
Beep( (int)frequency, 250);
}
}

system("PAUSE");

return EXIT_SUCCESS;
}
Une autre notion qui peut être nouvelle pour vous est l'appel à printf qui permet d'envoyer du texte dans le terminal. Sa syntaxe particulière permet le formatage des données, dans ce cas-ci %f indique que la variable passée comme deuxième paramètre sera de type float (nombre à virgule flottante). Il est suivi d'un \n pour faire un saut de ligne à l'écran. On peut visualiser les notes au même moment qu'elles jouent dans le terminal mais la fenêtre se fermera toute seule si on ne fait pas l'appel à system("PAUSE") à la fin. Ceci permettra d'interrompre le programme et d'afficher la phrase "Press any key to continue...". Comme Homer Simpsons, essayez de figurer quelle touche correspond à "Any"...

Enfin, c'est possible que vous rencontriez l'erreur suivante au moment de la compilation, si vous omettez un léger détail :

Beep(current_note * freq_octave, 250);
[Warning] passing float for converting 1 of BOOL Beep(DWORD, DWORD)

En effet, la fonction Beep() prend comme paramètre un nombre entier (integer en anglais) qui correspond à la fréquence ainsi qu'un deuxième paramètre pour la durée en millisecondes. Or, nous avons calculé la fréquence et l'avons stocké dans une variable de type float, ce qui est incompatible. Pour corriger le tout, il sera nécessaire d'arrondir la valeur de la variable en convertissant son type de float à integer en utilisant un mécanisme qu'on appelle "casting". Devant la variable frequency, on ajoutera entre parenthèse le type dans lequel on veut caster : (int).

En résumé, si vous êtes nouvellement initié à la programmation C++, vous avez déjà vu plusieurs concepts par la pratique :
  • inclusion de librairies pour utiliser des fonctions spécialisées
  • déclaration de constantes, de différents types de variables dont les tableaux (listes)
  • le code placé entre /* et */ n'est pas compilé et exécuté, ce qui permet de mettre des commentaires pour documenter le programme
  • boucles for imbriquées
  • impression à l'écran en mode terminal
  • faire sortir du son système


Tags: Musique, Programmation

mardi 12 octobre 2010

Le secret de l'inclinaison de la tour de Pise

Publié par Infinite Loop, à 20 h 01 0 commentaire

Ça fait déjà quelques fois que je vois passer des commentaires au sujet du gratte-ciel Capital Gate en construction à Abu Dhabi, non loin de Dubai. Le bâtiment semble susciter de plus en plus d'intérêt à mesure que la date d'inauguration approche (fin 2010), en partie dû à son architecture qui présente la caractéristique d'être inclinée 4,5 fois plus que la tour de Pise. Cette dernière était penchée dans son axe plutôt involontairement.

Justement, j'ai récemment découvert le secret de l'inclinaison de la tour de Pise, clairement illustré dans le dessin ci-dessous.Clair comme ça, on ne peut pas se tromper, hein ?



Pour en revenir aux extravagences des Émirats arabes, c'est vrai que dans la région de Dubai, ils ne font pas les choses à moitié. Tout se doit d'être démesuré et sensationnel : la tour la plus haute au monde Burj Khalifa, l'hôtel Burj Al Arab, les îles en palmiers The Palm, les World Islands, la station de ski intérieure, etc. Mon correspondant là-bas me disait aussi que la femme n'est pas considérée l'égale de l'homme, qu'il faut un permis spécial pour acheter de l'alcool et que des milliers d'immigrants sont exploités pour construire ces chef-d'oeuvres (ils confisquent leurs passeports et réduisent le salaire négocié au contrat). Bref, c'est la joie.

La nouvelle tour Capital Gate prévoit une inclinaison de 18 degrés... et ça passe pour un exploit. Pas de quoi être fier! Faites juste comparer pour voir :

Torre pendente di Pisa
Pise, Italie

Construction : de 1173 à 1372
Hauteur : 8 étages, 54,5 mètres
Inclinaison : 3,99 degrés

En 1993, l'inclinaison allait même jusqu'à 5,66 degrés. Des travaux ont permis de corriger l'inclinaison avant que l'irréparable se produise.

Capital Gate
Abu Dhabi, Émirats arabes

Construction : 2010
Hauteur : 35 étages, 160 mètres
Inclinaison : 18 degrés

Détient le record Guinness du "World's Furthest Leaning Manmade Tower" (tour artificielle la plus inclinée).

Euh, ai-je besoin de rappeler que c'est à Montréal que se trouve la plus haute tour inclinée au monde ? C'est une injustice! Et notre tour ne surpasse pas seulement Capital Gate en hauteur mais aussi en angle d'inclinaison!

Tour du Stade Olympique de Montréal
Montréal, Québec, Canada

Construction : pour les Olympiques de 1976, la tour fût finalisée pratiquement 10 ans plus tard
Hauteur : 40 étages, 175 mètres
Inclinaison : de 23 à 63,4 degrés de la base à son sommet

Aux touristes qui seront de passage à Montréal, remarquez la démarcation dans le milieu de la tour. Elle est construite en béton jusqu'à 92 mètres puis en acier jusqu'au sommet.



On est fier de la tour, ce symbole architectural qui a mis Montréal "sur la map". Par contre, on entretien une relation amour-haine avec le stade qui lui est rattaché. D'ailleurs, on l'appelle affectueusement notre bol de toilette géant...


Tags: Montréal

lundi 11 octobre 2010

Barre de progression HTML5

Publié par Infinite Loop, à 13 h 35 2 commentaires

Une des lacunes du HTML a toujours été le manque de contrôle pour afficher une barre de progression. Avec le développement moderne des applications web et les requêtes asynchrones en AJAX, il était encore impossible d'imiter nativement le comportement des applications "desktop" sur l'évolution d'un processus, chose que vient rectifier la nouvelle balise <progress> en HTML5.



Dans peu de temps, on pourra dire adieu aux multiples contrôles JavaScript qui ont été inventés pour palier à ce manque, comme par exemple le plugin Progressbar dans jQueryUI (pour ne nommer que celui-là). Donc double avantage : plus léger à charger et possibilité de construire sur une base standard plus solide.

Pour une barre de progression graduée de 0 à 100, on écrira :

<progress id="pbar" value="0" min="0" max="100"></progress>
Contrairement à l'exemple de l'image plus haut, le pourcentage textuel à la droite ne fait pas parti du contrôle. Néanmoins, il faudra quand même contrôler en JavaScript la progression du processus et j'en ai profité pour écrire le pourcentage.

HTML
<progress id="pbar" value="0" min="0" max="100"></progress>
<span id="txtPcnt">0%</span>
JavaScript
$j = jQuery.noConflict();
$j(document).ready( progress );

function progress(){
var pbar = document.getElementById('pbar');
var pcntLabel = document.getElementById('txtPcnt');
var pcnt = 0;

var intervalId = setInterval(
function(){
pcnt += 10;

if(pcnt <= pbar.max){
pbar.value = pcnt;
pcntLabel.innerHTML = pcnt.toString() + '%';
}
else{
clearInterval(intervalId);
}
, 500);
}
Compatibilité

À ce jour, cet exemple ne fonctionnait que sous Chrome (testé avec la version 6). J'ai aussi rencontré un problème avec jQuery 1.4.2 : si je remplace document.getElementById('pbar') par la notation $j('#pbar'), l'exécution s'arrête. En inspectant ce qui se passe sous Chrome avec Firebug Lite, la référence à l'objet du DOM semble bien créée mais il ne reconnaît pas les propriétés de la balise.

Aussi, j'ai été obligé d'utiliser setInterval() pour arriver à faire progresser le visuel de la barre car dans une boucle for ou while, si on utilise une fonction de pause pour simuler le processus et nous laisser le temps de voir l'effet, seul le résultat final est affiché à la toute fin.

Exemple incorrect
function pause(milliseconds){
var dt = new Date();
while ((new Date()) - dt <= milliseconds){}
}

var pcnt=0;
while(pcnt<=100){
pcnt+=10;
document.getElementById('pbar').value = pcnt;
pause(250); // problème!
}
C'est bien la fonction pause() qui cause problème ici car si on remplace l'appel par alert(), on verra la barre de progression se remplir à chaque itération. Allez savoir pourquoi!


Tags: HTML, JavaScript

dimanche 10 octobre 2010

3 façons de charger une librairie JavaScript populaire

Publié par Infinite Loop, à 21 h 17 1 commentaire

En règle générale, chaque fois que j'ai à utiliser une librairie JavaScript, je télécharge la dernière version du composant et je la dépose dans l'arborescence du projet (en milieu professionnel, nous créons une référence pour que le fichier puisse être partagé dans n'importe quel projet et pour faciliter le processus de mise à jour). La copie locale demeure la façon de faire la plus répandue chez les programmeurs web. Même si elle demande un peu plus d'efforts, elle apporte la certitude d'avoir le contrôle absolu sur la librairie. D'autres préféreront la simplicité de charger un script externe sur demande, même si ça peut comprendre certains inconvénients. Explorons les alternatives pour inclure une librairie JavaScript populaire à un projet web (jQuery, Prototype, Scriptaculous, YUI, Dojo, MooTools, etc).

1. Télécharger une copie de la librairie et la placer sur votre serveur

Ici, c'est votre responsabilité de maintenir les librairies en téléchargeant manuellement les nouvelles versions qui sont lancées (bug fixes, nouvelles fonctionnalités, compatibilité de fureteurs, etc). Un avantage est de pouvoir compresser vous-même les librairies, les empaqueter en un fichier unique pour pouvoir minimiser les requêtes HTTP et accélérer le téléchargement des ressources et l'affichage du contenu.

<script type="text/javascript" src="/js/jquery-1.4.min.js"></script>
Sur une page vide, j'ai testé le temps de chargement de chaque type d'inclusion. Dans ce cas-ci, YSlow indiquait :

Score : 96, Grade A
Temps de chargement : 0,258 seconde

La note n'est pas parfaite car je n'ai pas pris le temps d'optimiser ces éléments sur mon serveur de développement :

B : Add Expires headers
B : Compress components with gzip

2. Service de distribution externe

C'est l'équivalent d'inclure un fichier local sauf que plutôt d'être hébergé sur votre serveur, il se trouve sur un serveur externe auquel vous avez confiance, par exemple le service offert par Google Libraries API.
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
YSlow score : 99, Grade A
Temps de chargement :0,292 seconde

Le temps de chargement est rapide et les librairies sont optimisées convenablement mais chaque script nécessitera une requête HTTP sur le serveur, ce qui rend impossible d'empaquetage groupé des fichiers. Les scripts cross-sites ne pourront pas fonctionner sur un intranet web offline (reposant sur la technologie web sans toutefois avoir un accès externe).

Le bon fonctionnement est aussi dépendant de la disponibilité du service, ce qui rendrait le site inutilisable si le serveur distant est en panne. Si le service est fourni par un géant comme Google, le risque est faible, sauf en cas d'attaques par les chinois ! Certains craindront aussi la brèche XSS possible si le serveur distant est attaqué.

3. Par le loader de Google AJAX Libraries API

Plutôt que de lier directement chaque script par le service de distribution, on peut utiliser le chargeur prévu à cet effet. Une librairie principale (loader) récupérera elle-même chaque librairie demandée. Google suggère d'obtenir une clé (gratuite) pour avoir accès à certaines librairies, comme Google Maps par exemple.
<script type="text/javascript" src="http://www.google.com/jsapi?key=VOTRE-CLE"></script>
<script type="text/javascript">
google.load("jquery", "1.4.2");
</script>
YSlow score : 95, Grade A
Temps de chargement :0,395 seconde

Le script de chargement demandera 5.4 kb supplémentaires à charger et rend le temps d'exécution légèrement plus lent.

C : Use a Content Delivery Network (CDN)
B : Add Expires headers
B : Compress components with gzip

YSlow suggère parfois de mettre les scripts le plus près possible de la balise de fermeture du BODY plutôt que dans le HEAD pour que la page s'affiche le plus rapidement. Un problème courant est que si l'utilisateur voit apparaître le contenu de la page en premier et qu'un des composants JavaScript soit plus lent que les autres à charger, les événements JavaScript ne seront pas initialisés immédiatement, ce qui pourrait laisser croire à un mauvais fonctionnement des contrôles qui n'auraient aucune réaction au moment de les utiliser (par exemple, un bouton ayant un événement attaché par JS). Personnellement, je préfère les laisser en entête, quitte à ce que ça soit plus long au premier chargement. De toute façon, les scripts iront immédiatement dans la cache du fureteur.


Tags: JavaScript

Citation no. 102 sur les discussions

Publié par Infinite Loop, à 08 h 40 0 commentaire

Les grands esprits discutent d'idées.
Les esprits moyens discutent d'événements.
Les petits esprits discutent des gens.

- Eleanor Roosevelt

Et ceux qui discutent de la pluie et du beau temps ?


Tags: Citations

samedi 9 octobre 2010

Composer de la musique par programmation avec C++

Publié par Infinite Loop, à 12 h 22 7 commentaires

Vous connaissez ma passion pour la musique et la programmation. Aujourd'hui, je vous propose un cours 101 sur la façon de composer de la musique par programmation, dans sa forme la plus simpliste : en utilisant le haut-parleur interne de votre ordinateur et le langage C++ (Windows).

Avant de commencer, téléchargez un éditeur de code source comme Bloodshed C++ (gratuit) qui vient avec un compilateur. Le compilateur est nécessaire à la traduction du code source texte en code binaire. Au final, vous obtiendrez un fichier exécutable (.exe).

Une fois installé, lancez l'environnement de développement et créez un nouveau projet (File / New / Project). Choisissez Console application, C++ Project et nommez votre projet. Faites OK. Une fenêtre vous demandera à quel emplacement vous voulez enregistrer le projet. Je vous recommande de créer un nouveau répertoire et de le conserver à l'intérieur car une fois compilé, plusieurs fichiers seront générés (le dossier devrait contenir un fichier source .cpp, le fichier du projet .dev, le .exe, Makefile.win et main.o).

Un premier fichier source sera affiché dans l'éditeur (.cpp). Effacez son contenu, copiez le code ci-dessous et enregistrez.

#include <windows.h>

using namespace std;

/* Définition des contantes et de chaque fréquence */
#define C4 261 // DO
#define D4 293 // RE
#define E4 329 // MI
#define F4 349 // FA
#define G4 392 // SOL
#define A4 440 // LA
#define B4 493 // SI
#define C5 523 // DO

int main()
{
Beep(C4, 250);
Beep(D4, 250);
Beep(E4, 250);
Beep(F4, 250);
Beep(G4, 250);
Beep(A4, 250);
Beep(B4, 250);
Beep(C5, 250);

return 0;
}
La première ligne représente une librairie à utiliser à l'intérieur du projet. Ici, windows.h est nécessaire parce qu'on aura besoin d'utiliser une fonction du système d'exploitation. Par défaut, on peut inclure les librairies en indiquant uniquement le nom du fichier d'entête (header, fichier .h).

Si vous explorez un peu l'outil de développement, il comprend habituellement une configuration qui permet d'indiquer au compilateur où chercher pour trouver les librairies. Dans Bloodshed, vous pourrez la voir dans Tools / Compiler Options / Onglet Directories / Sous-onglet C++ Includes. Notez que vous n'avez rien à configurer pour le moment, tout s'est fait par défaut au moment de l'installation. Lorsque viendra le temps de compiler, le processus sera lancé pour assembler le programme correctement.

Pour en revenir au code source, la portion #define permet de définir des constantes à utiliser dans l'application. J'ai indiqué quelques notes pour débuter en utilisant la notation internationale et chacune est suivie de la fréquence correspondante. Pour faciliter la lisibilité, il sera plus pratique de faire référence aux noms des constantes (C4 pour DO 261 MHz) plutôt que d'inscrire les fréquences numériques.

Dans la fonction principale (main), chaque note à jouer appellera la fonction Beep qui prend 2 paramètres : le premier pour la note (fréquence indiquée dans la constante), la deuxième pour la durée du son en millisecondes.

Pour tester et entendre la mélodie, enregistrez le fichier et compilez le projet (menu Execute / Compile ou le raccourci CTRL+F9). Si tout s'est bien passé, un fichier .exe sera créé dans le répertoire du projet. Cliquez dessus pour l'exécuter ou bien à partir de l'éditeur, utilisez le raccourci CTRL+F10. Vous devriez entendre Do Re Mi Fa Sol La Si Do. Chaque changement au fichier source .cpp nécessitera une nouvelle compilation du projet.

Expérimentez en essayant différentes variations et si vous êtes habiles, amusez-vous à récupérer une partition pour transcrire la mélodie, par exemple une musique de jeu vidéo (vous aurez à définir un plus grand jeu de notes, par exemple les dièses et d'autres octaves).


Tags: Musique, Programmation

vendredi 8 octobre 2010

Outlook en mode sans échec qui ne répond pas

Publié par Infinite Loop, à 11 h 02 0 commentaire

Microsoft Outlook est un outil de gestion de courriels formidable. Quand j'ai voulu transférer un message, le logiciel a gelé et après quelques minutes, a fini par planter. Au moment de le réouvrir, il m'a suggéré de le repartir en mode sans échec pour être certain de tout récupérer correctement. Et a fini par ne plus répondre du tout.

Le titre de cet écran prouve que le concept ne fonctionne pas :

Microsoft Office Outlook (Mode sans échec) (ne répond pas)



Verdict : FAIL.


Tags: Le coin du geek

jeudi 7 octobre 2010

La tête du banquet de Salomé

Publié par Infinite Loop, à 23 h 15 2 commentaires

Comme il avait cessé de pleuvoir, je suis allé me promener dans le coin de la rue Prince Arthur à Montréal. J'ai stationné ma voiture dans le secteur et sur mon chemin, j'ai croisé l'Usine 106U où il semblait y avoir un vernissage vu le nombre de gens qui se trouvaient à l'intérieur.



Usine 106U, 160 rue Roy Est, Montréal

Je me suis mêlé à la foule pour jeter un oeil aux oeuvres d'arts exposées. Certaines démontraient un vrai potentiel artistique, d'autres ressemblaient de l'art enfantin (Crayola ?), des trucs aux allures de bricolage, de l'art populaire à l'effigie d'éléments du jeu Mario Bros, une représentation d'un Game Boy, certaines illustrations explicitement pornographiques pour faire réagir les plus pudiques...

Pourtant, l'oeuvre qui m'a le plus marqué et la plus dérangeante à mon oeil était placée au pied d'un mur, difficilement visible au premier coup d'oeil : le banquet de Salomé avec la tête de St-Jean-Baptiste posée sur la table au milieu d'une nature morte. Dérangeant sans être choquant. J'imaginais tellement voir la tête ouvrir grand les yeux ou juste rouler pour tomber en bas de la table le temps que le photographe prenne la pose!


Artiste : Sebastien Nudo de Montréal, finaliste, grand concours photo 2009 du site photo.fr.

Avis aux intéressés, le prix de vente est de 1155$ (
quand on y pense, quand même pas cher pour une oeuvre originale).

À propos du mythe de Salomé
La réputation de Salomé doit beaucoup à la princesse qui portait ce nom, vers l'an 30, à Jérusalem. Elle était la fille de la reine Hérodiade qui avait épousé le roi Hérode, après avoir été la femme de son frère, Philippe. Le prophète Jean le Baptiste, cousin et annonciateur de Jésus, avait à plusieurs reprises dénoncé publiquement ce remariage scandaleux. À la demande d'Hérodiade, le roi Hérode le fit mettre en prison mais hésitait à le condamner. Un soir, après un long banquet, Hérode demanda à la jeune et gracieuse Salomé de danser devant les convives. Elle le fit avec tant de charme que, pour la remercier, il lui promit de lui offrir le cadeau qu'elle voudrait. Salomé consulta sa mère et déclara au roi qu'elle souhaitait la tête de Jean le Baptiste. Hérode la lui fit apporter sur un plateau ! Cette horrible histoire fit peser, jusqu'au XIXe siècle, une sorte de tabou sur le prénom de Salomé.
Source


Tags: Montréal

mercredi 6 octobre 2010

La disparition de la lettre E

Publié par Infinite Loop, à 20 h 16 1 commentaire

Pas plus tard qu'hier, j'écrivais au sujet de l'imaginaire de certains écrivains et des nombreuses possibilités qu'ils peuvent emprunter comme source d'inspiration. Pourtant, la palme de l'originalité reviendrait probablement à Georges Perec (1936-1982), un auteur français qui, en 1969, s'est prêté à un exercice de style en écrivant un roman sans même utiliser la lettre "E" (évidemment, sans compter les 4 "e" dans son nom).

Le résultat : un roman lipogrammatique (du grec qui veut dire "à qui il manque une lettre") de 300 pages ayant pour titre "La disparition".

Je n'ai pas encore eu la chance de le lire mais je l'achèterai sans doute pour pouvoir le placer dans ma collection de curiosités qui meuble ma bibliothèque. Que l'histoire soit palpitante ou non, c'est quand même tout un exploit ! Sinon, vous aurez le mérite de passer pour un intellectuel au goût raffiné :-)

Extrait :

Anton Voyl n'arrivait pas à dormir. Il alluma. Son Jaz marquait minuit vingt. Il poussa un profond soupir, s'assit dans son lit, s'appuyant sur son polochon. Il prit un roman, il l'ouvrit, il lut; mais il n'y saisissait qu'un imbroglio confus, il butait à tout instant sur un mot dont il ignorait la signification.

Il abandonna son roman sur son lit. Il alla à son lavabo; il mouilla un gant qu'il passa sur son front, sur son cou.

Son pouls battait trop fort. Il avait chaud. Il ouvrit son vasistas, scruta la nuit. Il faisait doux. Un bruit indistinct montait du faubourg. Un carillon, plus lourd qu'un glas, plus sourd qu'un tocsin, plus profond qu'un bourdon, non loin, sonna trois coups. Du canal Saint-Martin, un clapotis plaintif signalait un chaland qui passait.

Sur l'abattant du vasistas, un animal au thorax indigo, à l'aiguillon safran, ni un cafard, ni un charançon, mais plutôt un artison, s'avançait, traînant un brin d'alfa. Il s'approcha, voulant l'aplatir d'un coup vif, mais l'animal prit son vol, disparaissant dans la nuit avant qu'il ait pu l'assaillir.

Perec a réutilisé la même technique qu'Ernest Vincent Wright dans son texte de 50000 mots intittulé Gadsby. Ce texte, publié en 1939, présente lui aussi la particularité de ne pas utiliser la lettre E. Vous pourrez voir un aperçu en allant zieuter le texte intégral.

Juste pour que vous réalisiez bien l'ampleur de la prouesse, ce court billet comptant un peu plus de 200 mots en excluant l'extrait du roman, compte plus de 100 fois la lettre E !


Tags: Curiosités, Livres

mardi 5 octobre 2010

Paradis sur mesure

Publié par Infinite Loop, à 20 h 23 2 commentaires

Je viens de terminer la lecture de Paradis sur mesure, un recueil de 17 courtes nouvelles de Bernard Werber. J'avais déjà lu plusieurs de ses livres (La trilogie du Cycle des Dieux, L'arbre des possibles et L'encyclopédie du savoir relatif et absolu) et comme j'avais apprécié, mon choix s'est arrêté sur celui-ci lorsqu'est venu le temps de bénéficier de la promotion "achetez 4 livres, le moins cher est gratuit" chez Archambault.

Ce qui est bien avec les nouvelles, c'est qu'on peut lire une histoire de temps en temps tout en appréciant le style d'écriture, ce qui est parfait si vous n'avez pas le courage d'embarquer dans une de ses trilogies.

Ça doit bouillonner dans la tête de Werber parce que je n'ai aucune idée où il va pêcher toute la créativité pour mettre sur papier tout ce qu'il lui passe par la tête. Ce n'est certainement pas pour rien qu'il est si populaire.

Parfois, l'idée semble germer à partir d'une simple question. Et si une loi était votée stipulant qu'il est interdit de polluer ? On pendrait les pollueurs. Voilà quelque chose de concret sur quoi écrire. L'imagination prolifique, il se met ensuite à la place d'un garde du corps pour célébrités qui se voit confronté à des affaires louches. Ensuite, un monde où les gens deviendraient stériles et ne pourraient plus se reproduire, sauf par l'entremise des fleurs...

Fidèle à son sujet de prédilection, le thème des fourmis est repris alors qu'un groupe d'archéologues part explorer le monde à la découverte de civilisations disparues. Dans une autre nouvelle, on se transporte en Afrique avec Kouassi Kouassi, son gri-gri, une capote pour le village, zig-zig-pan-pan, du cannibalisme et une colonie de fourmis carnivores.

Plus loin, un journaliste est assigné à une enquête sur le meurtre d'un enfant dans une petite communauté. De ses deux gamins, la mère, trop pauvre, a volontairement avoué en avoir tué un en basant son choix selon lequel était le plus mignon. Le journaliste doit passer sous silence le meurtre et déguiser la réalité en écrivant un article qui asceptise les circonstances du décès.

Une histoire futuriste où la Terre ne pourrait être habitée que par des femmes et où les enfants naîtraient dans des oeufs grâce à des reptiles (des Lepidodactylus, des geckos)... Un autre bon récit est Le maître du cinéma, où les chef-d'oeuvres à l'affiche ne représentent pas tout à fait ce qu'elle croit contempler (essayez d'imaginer que le Grand collisionneur de hadrons du CERN est impliqué).

Une nouvelle qui m'a moins plu est celle où un homme suit une séance d'hypnose pour revivre le plus grand amour qu'il aurait vécu dans une vie antérieure, soit quelques années avant la disparition de l'Atlantide, avec la fin dramatique qu'on connait de la légende. Faut croire que je ne soit pas assez romantique...

En revanche, la nouvelle que j'ai le plus apprécié est Ça va vous plaire. Un scénariste se rend compte qu'on vit dans une société qui nous dicte ce qui est susceptible de nous plaire parce que trop de gens renoncent à leur liberté de choisir. Et la croisade commence...

Il y a juste Werber d'assez fou pour se demander où naissent les blagues. Un humoriste au sommet de la gloire abandonne tout et part en quête pour retracer l'origine ultime des blagues racontées par la tradition orale. Il se rend compte que c'est plus risqué qu'il aurait imaginé.

En résumé, je vous le dis, ça va vous plaire.


Tags: Livres

lundi 4 octobre 2010

Éviter de perdre le contenu rédigé sur le web, revu et corrigé

Publié par Infinite Loop, à 19 h 48 0 commentaire

Cet après-midi, j'ai eu à apporter des modifications à un projet utilisant le framework JavaScript Prototype. Après un coup d'oeil rapide sur le projet, j'ai remarqué qu'il y avait un formulaire spécifique que l'utilisateur devait remplir et que la rédaction en ligne à l'intérieur d'un RTE pouvait représenter beaucoup de travail. Pour une raison qui m'a semblé évidente, je me suis dit que j'allais intégrer le snippet de code dont j'avais déjà parlé pour éviter de perdre le contenu rédigé en cas d'erreur de navigation (bouton back, cliquer sur un lien de navigation, etc). En intégrant ce code, ça permet d'offrir à l'utilisateur une dernière chance avant de changer de page.

De plus, le formulaire contenait un champ RTE avec le composant CKeditor. Petite anecdote sur CKeditor si vous ne la connaissez pas déjà : le nom original était FCKeditor, et provenait des initiales du nom de son créateur, Frederico Caldeira Knabben. Or, comme il l'a lui-même expliqué, au moment de lancer la version 3, il a rebaptisé son composant CKeditor en retirant la lettre F car ça causait un malaise chez certaines personnes dû à la ressemblance avec un "bad word" anglais (F*CK). Tous les détails ici. Passez le mot à la compagnie de voitures Audi, eux qui ont réussi à nommer un modèle E-Tron. En tant que francophone, je ressens un léger inconfort :-)

Je disais donc que je voulais protéger le formulaire contre la perte de données au cas où l'utilisateur changeait de page par accident. Je me suis fié au code de mon billet et j'ai testé. Un problème est apparu sur la ligne où Event.stopObserving est appelé. Cette ligne de code sert à retirer la vérification avant de soumettre le formulaire. En postant les données sur le serveur, un changement ou un rafraîchissement de page est nécessaire et on ne veut surtout pas embêter l'utilisateur avec un popup s'il clique volontairement sur le bouton Enregistrer!

JavaScript lance une erreur à travers la console de Firebug :

L.stopObserving is not a function

Pourtant, la documentation de Prototype est formelle : depuis la version 1.6, il existe 3 façons de désinscrire un événement de l'observateur. La version utilisée dans le projet ? 1.6.0.3. Alors pourquoi est-ce que ça ne marche pas alors qu'en avril dernier, lorsque j'ai écrit mon billet, ça fonctionnait bien ? J'ai trouvé la solution sur le forum de Prototype dans Google Groups. Le bogue est expliqué et la solution est de le mettre à jour pour la version la plus récente. Du coup, l'erreur disparaissait sous Prototype 1.6.1 (paru en sept.2009).

Pour CKeditor, je voulais plus particulièrement détecter si le contenu du RTE avait été modifié. Avec FCK 2.x, on pouvait appeler la fonction isDirty() pour vérifier si le contenu de l'éditeur avait changé. Depuis CK 3.x, la même fonction a été renommée checkDirty().

var editor = CKEDITOR.replace('rte_id', {
toolbar : 'Basic',
defaultLanguage : 'fr',
language : 'fr',
});

Event.observe(window, 'beforeunload',
function(event){
if( editor.checkDirty() ){
event.returnValue = "Oups... le contenu du RTE a changé et n'a pas été enregistré!";
}
}
);
C'est certain que pour cet exemple-ci, je ne fais que vérifier le champ le plus important, là où la majorité des efforts de rédaction sont concentrés. L'idéal serait de pouvoir faire la vérification pour l'ensemble du formulaire mais ce n'était pas nécessaire ici. Si compléter le formulaire prend du temps, malgré cette précaution, le plus fâchant est de perdre son travail au moment de l'enregistrer parce que la session est expirée. Assurez-vous d'augmenter suffisamment sa durée de vie et si possible, de trouver un moyen pour la maintenir active, par exemple avec une routine qui lance un appel AJAX à intervalle régulier.


Tags: JavaScript

dimanche 3 octobre 2010

Le stockage local HTML5 remplacera-t-il les cookies ?

Publié par Infinite Loop, à 11 h 21 0 commentaire

En réponse à cette question, je dirais que oui, pour certains usages mais le cookie ne disparaîtra pas de sitôt car il a encore son utilité. Alors pourquoi le concept de stockage local (aussi appelé Web Storage ou DOM Storage) fût intégré aux spécifications HTML 5 ?

En premier lieu, le stockage local ressemble beaucoup au cookie car il est lui aussi constitué de paires clé/valeur, qu'il peut être attribué à une session ou être persistent (enregistré sur le disque dur dans le but d'être réutilisé lors de la prochaine visite) et est associé au domaine qui l'a créé.

Où sont les différences ?
Le stockage local se veut plus persistent car il n'a pas de date d'expiration contrairement au cookie. De plus, il a la particularité que les données locales ne sont pas transmises au serveur par le protocole HTTP. Suivant le principe des transactions, si deux instances d'une application web sont ouvertes dans des fenêtres différentes du navigateur, les données locales en session n'interféreront pas entre elles.

Au niveau du volume de données pouvant être enregistrées, le stockage local présente un avantage de taille sur le cookie. Alors qu'un cookie permet l'enregistrement d'un maximum de 4 Kb d'information, que chaque fureteur accepte entre 30 et 50 cookies par domaine (200 Ko / domaine), le stockage local accepte entre 5 et 10 Mo de données par domaine.

Comment ça marche ?
L'API JavaScript pour stocker les informations localement se décline en deux objets qui appartiennent à l'objet parent Window :

  • localStorage
  • sessionStorage (session client side)
Si vous voyez globalStorage dans la documentation, sachez que cet objet est déjà obsolète (globalStorage[location.hostname] équivaut maintenant à localStorage). Les données placées dans localStorage seront persistentes même si le navigateur est fermé alors que celles placées dans sessionStorage seront détruites dès que la fenêtre sera fermée.

Enregistrer une valeur
localStorage.username = 'Code 18';
// ou
localStorage.setItem('username', 'Code 18');
Lire une valeur
localStorage.username;
// ou
localStorage.getItem('username');
Effacer une clé
localStorage.removeItem('username');
Tout vider le contenu
localStorage.clear();
Lister le contenu des objets
<h2>sessionStorage</h2>
<script type="text/javascript">
var items = sessionStorage.length
for(i=0;i<items;i++){
var itemName = sessionStorage.key(i);
document.write(itemName + ' = ' + sessionStorage.getItem(itemName) + '<br/>');
}
</script>

<h2>localStorage</h2>
<script type="text/javascript">
var items = localStorage.length
for(i=0;i<items;i++){
var itemName = localStorage.key(i);
document.write(itemName + ' = ' + localStorage.getItem(itemName) + '<br/>');
}
</script>
Un exemple simple
Dans un textarea, l'utilisateur inscrit du texte qui sera enregistré localement sur sa machine. Au chargement de la page, si la clé existe dans le stockage local, le contenu sera chargé dans le textarea.
<form>
<textarea id="content">Texte initial</textarea>
<input type="button" id="save" name="save" value="Enregistrer localement" />
</form>
JavaScript (avec jQuery) :
$(document).ready(init);

function init(){
if( localStorage['localContent'] ){
var localContent = localStorage.getItem('localContent');
$('#content').val(localContent);
}

$('#save').click(
function(){
var content = $('#content').val();
localStorage.setItem('localContent', content);
}
);
}
Enfin, au même titre que pour les cookies, l'utilisation du stockage local ne règle pas nécessairement les vulnérabilités d'attaques XSS contre l'extraction de données privées. Je vous invite à poursuivre votre lecture sur le billet HTML5, Local Storage, and XSS du blogue de Michael Coates.


Tags: HTML, JavaScript

Citation no. 101 sur les mets chinois

Publié par Infinite Loop, à 08 h 39 0 commentaire

J'aime beaucoup la cuisine chinoise. Mon plat préféré est le numéro 27.

- Jim Carrey


Tags: Citations

vendredi 1 octobre 2010

Où il est question de Bandcamp, Unwoman et d'une pancarte de robots

Publié par Infinite Loop, à 19 h 45 0 commentaire

J'étais sur le site Bandcamp à parcourir les fiches de groupes qui avaient décidé de vendre directement leur musique aux fans et en cherchant de la musique dans le style de Rasputina (cello rock), j'ai découvert l'artiste solo indépendante Erica Mulkey qui se produit sous le nom de Unwoman.

J'ai accroché sur le single The City que je me suis empressé d'acheter. Comme pour Misteur Valaire, vous donnez le montant que vous jugez acceptable pour vous procurer l'oeuvre. Je me rends compte que les artistes sont de plus en plus nombreux à choisir ce mode de mise en marché. Enfin, c'est une bonne nouvelle dans la mesure où l'argent va directement à l'artiste sans que plusieurs intermédiaires prennent leur cote au passage!

Sur Flickr, Erica a répertorié ses photos favorites dont celle-ci qui présente un écriteau parfait pour ma collection.



Si vous êtes de passage à Seattle, vous pourrez trouver cette pancarte indicant où sont les toilettes dans le Science Fiction Museum. Vous y trouverez aussi le Experience Music Project (EMP), fondé par Paul Allen, le co-fondateur de Microsoft. Juste pour l'architecture de la place, ça semble un incontournable !


Tags: Musique, Pancartes et écriteaux

Messages plus récents Messages plus anciens Accueil
S'abonner à : Messages (Atom)
    Suivre @code18 sur Twitter

    Catégories

    • Apache (21)
    • Citations (167)
    • Club Vidéo (24)
    • Coffre à outils (56)
    • CSS (8)
    • Curiosités (117)
    • Design Pattern (2)
    • Drupal (8)
    • Easter Eggs (22)
    • Extensions Firefox (20)
    • GIMP (7)
    • Histoire (21)
    • HTML (32)
    • Humour (57)
    • Intégration (34)
    • iPod (12)
    • JavaScript (110)
    • Jeu de combat (6)
    • Le coin du geek (128)
    • Liens (12)
    • Linux (56)
    • Livres (78)
    • Lois et principes (46)
    • Marché des saveurs (26)
    • Mathématique (18)
    • Mobile (5)
    • Montréal (32)
    • Musique (112)
    • Pancartes et écriteaux (16)
    • Perl (8)
    • Pérou (1)
    • PHP (130)
    • PostgreSQL (44)
    • Programmation (105)
    • Saviez-vous que (55)
    • Sécurité (22)
    • SEO (5)
    • SQL Server (22)
    • Vieilles publicités (6)
    • Virtualisation (8)
    • Voyages (1)
    • Zend Framework (26)

    Divers

    Archives

    • ►  2015 (6)
      • ►  août 2015 (1)
      • ►  juillet 2015 (1)
      • ►  février 2015 (3)
      • ►  janvier 2015 (1)
    • ►  2014 (8)
      • ►  décembre 2014 (1)
      • ►  novembre 2014 (1)
      • ►  octobre 2014 (1)
      • ►  août 2014 (2)
      • ►  juillet 2014 (2)
      • ►  janvier 2014 (1)
    • ►  2013 (53)
      • ►  décembre 2013 (2)
      • ►  novembre 2013 (1)
      • ►  octobre 2013 (3)
      • ►  septembre 2013 (2)
      • ►  août 2013 (5)
      • ►  juillet 2013 (3)
      • ►  juin 2013 (5)
      • ►  mai 2013 (3)
      • ►  avril 2013 (7)
      • ►  mars 2013 (7)
      • ►  février 2013 (11)
      • ►  janvier 2013 (4)
    • ►  2012 (105)
      • ►  décembre 2012 (8)
      • ►  novembre 2012 (5)
      • ►  octobre 2012 (4)
      • ►  septembre 2012 (1)
      • ►  août 2012 (8)
      • ►  juillet 2012 (7)
      • ►  juin 2012 (7)
      • ►  mai 2012 (10)
      • ►  avril 2012 (13)
      • ►  mars 2012 (15)
      • ►  février 2012 (15)
      • ►  janvier 2012 (12)
    • ►  2011 (146)
      • ►  décembre 2011 (14)
      • ►  novembre 2011 (11)
      • ►  octobre 2011 (12)
      • ►  septembre 2011 (13)
      • ►  août 2011 (15)
      • ►  juillet 2011 (17)
      • ►  juin 2011 (18)
      • ►  mai 2011 (15)
      • ►  avril 2011 (9)
      • ►  mars 2011 (7)
      • ►  février 2011 (3)
      • ►  janvier 2011 (12)
    • ▼  2010 (398)
      • ►  décembre 2010 (29)
      • ►  novembre 2010 (28)
      • ▼  octobre 2010 (32)
        • On est tous des attention whores
        • Citation no. 105 sur le cannibalisme
        • Réseaux sans fil de mes voisins
        • Piège JavaScript no. 7
        • Piège JavaScript no. 6
        • Piège JavaScript no. 5
        • Le plus vieil homme du monde avait 174 ans
        • Détruire le web, un site à la fois
        • Citation no. 104 sur la vie
        • Parce que vous n'avez pas eu le temps de tout voir...
        • Piège JavaScript no. 4
        • Piège JavaScript no. 3
        • Piège JavaScript no. 2
        • Quelques pièges JavaScript
        • Citation no. 103 sur le déjeuner
        • Quand le heavy metal ne se prend pas au sérieux
        • 23 sites pour explorer le HTML5
        • Jouer à Snake sur un vidéo YouTube
        • Faire du son par programmation C++, partie 2
        • Le secret de l'inclinaison de la tour de Pise
        • Barre de progression HTML5
        • 3 façons de charger une librairie JavaScript popul...
        • Citation no. 102 sur les discussions
        • Composer de la musique par programmation avec C++
        • Outlook en mode sans échec qui ne répond pas
        • La tête du banquet de Salomé
        • La disparition de la lettre E
        • Paradis sur mesure
        • Éviter de perdre le contenu rédigé sur le web, rev...
        • Le stockage local HTML5 remplacera-t-il les cookies ?
        • Citation no. 101 sur les mets chinois
        • Où il est question de Bandcamp, Unwoman et d'une p...
      • ►  septembre 2010 (34)
      • ►  août 2010 (22)
      • ►  juillet 2010 (35)
      • ►  juin 2010 (42)
      • ►  mai 2010 (36)
      • ►  avril 2010 (37)
      • ►  mars 2010 (34)
      • ►  février 2010 (32)
      • ►  janvier 2010 (37)
    • ►  2009 (430)
      • ►  décembre 2009 (32)
      • ►  novembre 2009 (34)
      • ►  octobre 2009 (33)
      • ►  septembre 2009 (37)
      • ►  août 2009 (37)
      • ►  juillet 2009 (39)
      • ►  juin 2009 (38)
      • ►  mai 2009 (37)
      • ►  avril 2009 (35)
      • ►  mars 2009 (37)
      • ►  février 2009 (32)
      • ►  janvier 2009 (39)
    • ►  2008 (84)
      • ►  décembre 2008 (34)
      • ►  novembre 2008 (39)
      • ►  octobre 2008 (11)

    Abonnés

Copyright © All Rights Reserved. Code 18 | Converted into Blogger Templates by Theme Craft