Essai Netbook Dell Mini 12

Le netbook Dell Mini 12 est un ordinateur léger, surtout en poids, il s’agit d’une machine a base de processeur Atom Z520 qui est 1 processeur bi core cadencé à 1.3GHz. La configuration inclue 1 Go de Ram et un disque dur de 80Gb. L’intérêt de cette machine par rapport à un eeepc est qu’elle intègre un écran 12″ de résolution 1280×800 de bonne facture. Son usage peut donc couvrir selon d’un ordinateur portable classique dans les usage de bureautique/Internet classique avec un poids de seulement 1Kg (et quelques) et une autonomie de 2 à 3 heures.

Bien que la machine soit vendue avec une distribution Ubuntu, je vais commencer par la remplacer par une version OpenSuse 11.1 (vous me connaissez… je suis fan) – en fait, certain add-on dont j’ai besoin pour mon travail son mieux adaptés à Suse. J’en profiterai pour faire un petit test de cette nouvelle version.
L’installation de l’Opensuse s’est bien passé si ce n’est que la machine n’ayant aucune autre entrée que des ports USB (et reseau) il faudra pour une installation utiliser un DVD externe ou une clef usb bootable avec l’iso de la distribution. Même si à première vue tout semble fonctionner une fois l’installation terminée, c’est en réalité là que les problèmes commencent:
* La carte wifi pour commencer, il s’agit d’un chip Brandcom 4312 non supporté en standard. Après quelques essai infructueux, la solution est finalement d’ajouter le Repository PackMan et de chercher le driver broadcom qui est packagé. Une fois le reboot passé et le choix du noyau debug au demarrage, le wifi peut être configuré.
* La carte vidéo pose elle aussi problème : le chip intel GMA500 n’est pas reconnu et la résolution sera bloquée en 1024×768 situation très dommage, rapport a l’intérêt que l’écran représente sur cette machine. J’ai essayé de nombreuses pistes qui se sont toutes avérées des échecs. Il doit cependant y avoir une solution puisque le Linux Ubuntu installé par défaut fonctionne ; j’ai cependant lu que certain drivers pouvaient marcher mais avec des versions de noyau plus anciennes. En bref .. on oublie.

Pour ce qui est de l’opensuse 11.1, je lui trouve un gros inconvéniant : pourquoi avoir remplacé Yast2 qui permetait assez simplement d’accéder à tous les outils de configuration pour le remplacer par une liste d’applications indépendentes beaucoup moins pratique !! Pour le reste, ca fonctionne bien.

Quelques notions Oracle

En ce moment, je bricole pas mal avec Oracle pour chercher pourquoi certaines de nos applications rament … D’où l’envie de mettre quelques informations sur les principaux point à regarder. Cet article n’a pas de vocation exhaustive mais ce sont plutôt quelques notes sur un coin de table…

Oracle est une base possédant un énorme moteur d’optimisation de requêtes, sans doute très fort pour le traitement massif de données, cependant, le moindre grain de sable transforme immédiatement votre Ferrarie en une 2CV. Au premier rang des grains de sable se trouvent les statistiques. Il s’agit d’une donnée Oracle indiquant le nombre de lignes que la table doit contenir. Fonction de ce nombre, l’optimiseur choisira une methode de recherche des données dans une table plutôt qu’une autre. Il pourra utiliser des INDEX ou des CLEFS ou choisir de faire un FULL SCAN (essayer les lignes une à une). S’il se trompe… c’est la cata. Le premier point est donc de vérifier ces stats en consultant le nombre de ligne qu’ORACLE pense avoir dans “all_tables” et le comparer aux nombre de lignes reellement dans la table count(*).
Ceci étant dit, je n’ai pas dit grand chose car il est avant nécessaire d’identifier quelles sont les tables concernées, ceci peut se faire de 2 façons, la première, lorsque le temps de réponse est catastrophique, consiste à regarder les session actives et visualiser le sql en cours de traitement. Ceci se fait facilement avec des outils comme TOAD ou DbVisualizer.
La requête peut aussi être identifiée à l’aide du stat_pack oracle. Cet outil permet de mémoriser l’état de la SGA avant et après un traitement puis de faire une comparaison de entre les deux images. Cet outil permet alors de savoir quelles sont les requêtes qui ont consommées le plus de temps, quelle est l’utilisation de la SGA ou de la PGA … Bref … une fois la requête identifiée, il est possible de demander à Oracle un Explain plan qui indiquera quels est la complexité de la requête et par quelles méthode les données sont recherchées (full scan, index…)
Il est alors possible d’identifier les problèmes. Il faut identifier s’il existe un index qui pourrait être utilisé et qui ne l’est pas par exemple ou s’il faudrait créer un nouvel index. Dans le premier cas, il est possible que les stats ne soient pas bonnes car si oracle préfère un fullscan à un index, c’est sans doute qu’il croit que la table ne contient que très peu de lignes.
Si tout semble normal de ce point de vue, il arrive que les index aient besoin d’être rebuildés : il se peu que les arbre binaires associés soient déséquilibrés, que le nombre de niveau devienne trop grand et que son utilisation ne soit pas efficace. Un rebuild peut résoudre cela. Il est aussi possible, à l’aide de Hints de forcer Oracle à utiliser un index donné. Mais ceci n’est valable que lorsque vous avez accès aux sources de l’application.
On peut enfin penser à faire un reset de la High Water Mark sur une table donnée si vraiment on constate des soucis sur cette table alors que tout le reste est ok.

Avant de vraiment s’attaquer à tout cela, il peut être utile de jeter un oeil aux estimations que donne le stat pack sur la taille des SGA, PGA et Shared Pool car des espaces mémoire trop réduits vont fortement pénaliser Oracle qui devra faire trop d’accès aux disques. Dans le même esprit, il faut jeter un oeil aux taille des redo-log qui peuvent conduire à des fréquences d’I/O trop élevées dans les système de type batch.

Bon courage avec toutes ces notions et idées un peu en vrac … il y a ici surtout des mots clefs pour chercher ensuite sur google. A l’occasion, je mettrai des information plus opérationnelles, promis !

Recalcul d’index dans une base Oracle

Deux petits scripts permettant le recalcul des index d’une base oracle lorsque ceux-ci ont l’air louche … Les scripts sont à passer l’un après l’autre sur la base

--- AnalyseIndex.sql
set pages 9999;
set heading off;
set feedback off;
set echo off;
set linesize 255;

spool step1.sql;
select 'drop table system.temp_stats_paul;' from dual;
select 'create table system.temp_stats_paul as select name, most_repeated_key, distinct_keys, del_lf_rows, height, blks_gets_per_access, lf_rows from index_stats;' from dual;

select 'analyze index '||owner||'.'||index_name||' validate structure;',
'insert into system.temp_stats_paul ( select name, most_repeated_key, distinct_keys, del_lf_rows, height, blks_gets_per_access, lf_rows from index_stats where height > 3 or ( 100 * del_lf_rows / (lf_rows+1) ) > 20 or BLKS_GETS_PER_ACCESS > 5 );'
from dba_indexes
where
owner not in ('SYS','SYSTEM');

spool off;
set heading on;
set feedback on;
set echo on;

@step1.sql
quit
--- RebuildIndex.sql
set pages 9999;
set heading off;
set feedback off;
set echo off;
set linesize 255;

spool step2.sql;

select 'alter index '||owner||'.'||name||' rebuild tablespace '||tablespace_name||';'
from system.temp_stats_paul, dba_indexes
where system.temp_stats_paul.name = dba_indexes.index_name;

spool off;

drop table system.temp_stats_paul;

set heading on;
set feedback on;
set echo on;

@step2.sql
quit

Mes déboirs Ameli.fr

Je suis lassé de recevoir toutes les semaines des relevés de comptes de la Sécu, avec 1 enveloppe, 1 timbre, 3 feuilles et au moins autant de pub pour cet organisme alors que l’on entend toujours parler de son trou abyssal…
J’ai donc été heureux de découvrir l’existence d’ameli.fr, le site de la sécu permettant de faire du zéro papier ! je me suis donc précipité dessus pour m’y enregistrer … mais là commence l’horreur, la procédure semble des plus banales, saisir sont numéro de sécu et un code présent, selon la page, sur les relevés reçus … hors sur ces relevés .. rien, mais alors rien du tout !! Bref, mon élan est brisé et 15 minutes perdues à chercher ce fameux code… courageux et motivé (comme sans doute pas plus de 10% des Internautes) je choisis d’attendre que l’on m’envoie par courrier un nouveau code secret temporaire. Jusque là, tout va déjà mal mais bon …
10 jours plus tard, à la réception du code, je tente donc une nouvelle inscription, le code donné fonctionne et je passe à la seconde étape me demandant de changer mon mot de passe. Je saisis donc de nouveau le code temporaire (mais pour quelle raison puisque la session est déjà ouverte ?!?) puis mon nouveau code. Hors ce premier est rejeté … mauvais code secret… Fichtre !! Comme sans doute 10% des 10% d’Internautes restant, je prends mon courage à deux mains et appelle le numéro d’aide… où l’on m’explique très gentiment que pour la seconde étape, je doit être munis du code à 6 chiffres qui est sur mes relevés, mais qui en fait n’y est pas ..; D’où tout l’intérêt de fournir un code temporaire … bref, On m’expédie ce code par la poste, tout en me précisant que sur de vieux relevés… peut être pourrais-je le trouver…
Et là, coup de veine avant l’abandon …. Je retrouve un vieux relevé où le code n’est pas inscrit dessus, mais présent sur une autre feuille dans l’enveloppe … Je le tape … lui aussi est rejeté… Génial !
Bon, là, comme 1% des 10% des 10% d’internautes restants, je retourne au home directory du service ce qui me permet de revenir un peu en arrière, j’essaie de nouveau le mot de passe à 6 chiffres… rejet … puis le mot de passe temporaire … et là, miracle, ça passe !

Je ne sais pas si vous avez saisi l’astuce … moi en tout cas absolument pas (je précise que les mots de passe ont été essayés plusieurs fois et qu’il n’y avait pas de fautes de frappes dans les essais précédents).
Bon, au final je suis inscrit … j’ai eu beau chercher l’option 0 papier …. je n’ai pas trouvée, peut être est-ce automatique … on verra bien.

Je note simplement une chose, si un site marchand faisait la même chose… il n’aurait pas un client ! Alors que par ailleurs, la création de comptes utilisateur est le béa-ba du développement ouaib.
A bon entendeur ! salut !
_________
mise à jour …
_________

Voila, cette fois c’est fait, le fond du fond de l’amateurisme est atteint lors de la réception de l’email de confirmation de mon adresse mail … je vous fait un c/c c’est trop beau !

Veuillez cliquer sur le lien suivant pour valider votre email :
MTc3————–Z2aURrOGUwYU1LR1FkWFptUXJO?code=https://assure.ameli.fr/portal/page/portal/Espace_AS/Sommaire
Pour nous contacter, merci de ne pas répondre à ce mail mais connectez-vous à votre compte Ameli assures :
https://assure.ameli.fr/portal/page/portal/Espace_AS/validationAdresseCourriel.

Regardez bien ! l’url qui est donnée … le jeton de validation et l’adresse de la page sont inversées… Autant vous dire que d’une part personne ne risque de valider son email mais que surtout personne n’a testé cela… Ya de la sanction pour incompétence dans l’air !
Bon, pour continuer dans le parcours du combattant, j’ai fait comme 0% des assurés … j’ai remis l’url à l’endroit ! ben je vous le donne en mille :

Votre adresse électronique n’a pas été validée. Veuillez réessayer ou contacter le service support !
Pour vous connecter à votre compte ameli,

allez ! une dernière avant que vous vous étouffiez de rire … J’ai voulu envoyer un message pour les prévenir du problème … mais je ne peux pas tant que l’email n’est pas validé ! trop bon !

Des nouvelles de mon aventure au bout de 3 mois … Nous sommes en Décembre et si l’email de validation n’est toujours pas corrigé, lorsque l’on remet dans le bon ordre les champs, il ets enfin possible de valider l’email !! OUAIIII trop fort la sécu ils ont corrigé un bug ! Bon, maintenant, il ne reste plus qu’a mettre l’option 0 papiers dedans et j’aurais enfin l’impression que mes efforts auront était utiles pour la société.
Bon je vous en donne encore une pas mal … une fois mon email validé, j’ai souhaité envoyer un message pour leur indiquer le problème mais pas de bol … quand le message est trop long, il entraine une erreur “service indisponible” … Quand on pense que la sécu paye des gens a plein temps pour vendre leur service et des spots de pub à plusieurs millions d’Euro pour un site qui ne sert à rien … et bien j’aimerai franchement qu’on me rembourse mes 40 euros de franchise de l’année tien !

Bilan à 8 mois

Un bref bilan de l’utilisation de cette machine après 8 mois… Je suis plutôt satisfait, même si je dois avouer que je me satisfait de peu …

Coté bruit, rien à  redire, l’objectif est atteint, même avec une alim refroidie par air (suite à  mes déboire avec la fanless) la machine est très silencieuse. Elle est à  0 db ou presque hors utilisation et en utilisation, son bruit varie selon la température, dans une plage raisonnable. Coté stabilité, c’est correct, la machine plante un peu plus que mon PC précédent, je n’ai pas trop investigué là  dessus, son usage n’est pas celui d’un serveur et des éléments comme les drivers video me semble plus en cause que le coeur du système. Par ailleurs, l’usage de RAM fs pour /tmp par exemple est aussi une cause de crash à  prendre en compte et à  accepter. Bref, là  dessus c’est ok. Là  ou je suis moins satisfait, c’est pour ce qui touche aux drivers sous Linux, je me bas avec des soucis autour de la détection des périphériques et je dois dire que pour l’instant, il m’est impossible de graver un CD ou même de charger automatiquement une clef USB sans passer par la ligne de commande… La source du problème n’est pas claire, j’attends donc une mise à  jour de noyau qui pourrait régler ce genre d’ennuis ainsi qu’un peu de temps pour faire des essais. Ce que je regrette par conséquent, est la petitesse de la communauté utilisant la carte epia sn 18000 ; il faut donc chercher par soit-même !

Bilan donc positif à  mon sens, mais beaucoup plus compliqué qu’un système classique.

Trou de sécurité Joomla, un serveur piraté

L’histoire commence par un trou de sécurité dans l’outil de CSM joomla que j’utilise sur certains sites. Ce bug permet à tout utilisateur sachant l’exploiter d’imposer une nouveau mot de passe à l’utilisateur administrateur du site pour faire simple. Le bug est identifié en version 1.5.x depuis le 1er Aout.
Un de mes sites a donc été attaqué vers le 14 Aout : un utilisateur a pris le contrôle d’un des site pour y poster son article sur son sentiment au sujet de la Russie.
Un second est passé sur le même site pour le fermer, tout en modifiant la message et ce ventant de ce magnifique acte de bravoure… A noté que n’importe quel gamin de 10 ans ayant connaissance de la procédure à suivre peut en faire autant … enfin !
La dernière attaque est d’hier (17 Aout) et m’aura permis de me rendre compte de la faille. Celle-ci, bien qu’utilisant le même procédé est beaucoup plus intéressante car mettant en œuvre une technique plus évoluée et ayant plus de conséquences sur mes sites.

Mon ami de Turquie est donc venu visiter l’un de mes site à partir d’une simple recherche google à partir de laquelle il identifie les site basés sur joomla et offrant la porte d’entrée adéquat. La méthode est simple, ingénieuse. Une fois entré, il profite des fonctionnalités de ce CSM permettant de modifier manuellement les templates pour injecter son propre code PHP à la place de celui du template par défaut. Il a ainsi plus placer une petit script PHP rigolo aux fonctionalités diverse : scan de fichiers avec sticky bit, recherche de fichiers, édition de fichiers, exécution de commande shell … Le tout heureusement limité au droits de l’utilisateur apache…. mais c’est déjà pas mal !
Au final, mon ami aura passé une dizaine de minutes, le temps d’installer sa tambouille puis de modifier tous les index.php de mes sites ouaib hébergés sur ce même serveur pour les remplacer par le sien, une bannière php statique se ventant de cet acte de piraterie à l’intérêt au combien inutile.
Vient alors le temps de la résolution et du retour à la normale … de quoi me remettre dans le bain apres 15j de vacances bien mérités… Toutes ses actions étant convenablement tracées dans les fichiers de log apache il restait à réaliser le retour en arrière puis à colmater les brèches. Je suis en général bien armé pour cela avec une batterie de backup… Mais lois de l’emmerdement maximal oblige, ceux-ci ne fonctionnaient plus depuis trop longtemps sur ce serveur pour être utilisable … bref une journée de galère pour une récupération complète, aux pertes près issues de mauvaises manipulations de ma part …

Au final, je tire quelques conclusions de cela:

  • Je suis conforté sur les risques liés à l’usage de CMS qui nécessitent d’être à même de patcher à tout moment les sites ainsi construits. Cette manip n’étant pas évidente dès que la version en ligne est un peu trop ancienne ou que des éléments ont été modifiés suite à une adaptation du site. Un développement custom, même s’il possède des trous de sécurité ne sera victime que d’une attaque ciblée et non de ce type d’attaque hasardeuse
  • L’utilisateur apache ne devrait pas avoir de droits d’écriture sur aucun des fichiers / répertoire ; seulement, avec tous les automatismes offerts par les site ouaib actuels (installation de modules, templates) il est difficile de réaliser cela sans se priver de certaines fonctionnalités. Je tire donc comme conclusion que l’usage d’un CMS, entre autre doit passer par une étude approfondie des droits à affecter à chaque fichiers/rep avant une monté en production.
    Je pense d’ailleurs que les CMS devraient intégrer des scripts de protection et de dé-protection des fichiers par exemple, ou prévoir que certaines opérations soient réalisées en sudo avec un autre utilisateur que apache. En tout cas, il vaut mieux désactiver des fonctionnalités que de perdre un site suite à un crack.
  • Enfin il est vraiment nécessaire de vérifier ses backup à une fréquence suffisante … en vérifiant qu’ils puisse bien être décompressés et qu’ils sont donc utilisable.

Voici donc quelques pensés sur la forme suite à cette attaque … Sur le fond, je ne cesse de considérer qu’il n’y a aucun héroïsme à utiliser des failles trouvées par d’autres, pas plus que de taguer un mur, ça n’exprime rien de plus que lorsqu’un chien pisse sur un lampadaire et la première pluie emmènera tout avec elle. Le seul Hacker est celui qui trouve – invente la faille par la lecture du code ou l’analyse du protocole, il n’a pas besoin d’en faire l’illustration sur l’espace public pour que son travail soit reconnu.

Tutoriel Ajax – Création d’un diaporama

(‘Article rédigé par un groupe d’étudiants d’IUT dans le cadre d’un projet tutoré)

Dans cet article, je vais vous montrer comment réaliser un diaporama en Ajax. Pour cela je vais utiliser trois langages: le HTML, du JavaScript ainsi que du PHP.
Le code du diaporama est scindé en 3 fichier: galerie.html, galerie.js et galerie.php.
Le premier est la page web contenant la mise en page avec les différents évènements possibles tels que le clic sur la flèche précédente ou suivante.
Voici son code avec des explications:
—————————————

<!DOCTYPE html PUBLIC “-//W3C//DTD HTML 4.01 Transitional//EN”>
<html>
<head>
<meta content=”text/html; charset=ISO-8859-1″
http-equiv=”content-type”/>
<!– On inclut notre future fichier JavaScript –>
<script type=”text/javascript” src=”/ajax/galerie.js”></script>
<title>galerie</title>
</head>

<body style=”background-color: rgb(170, 0, 0);”>
<h1 style=”text-align: center;”>GALERIE D’ IMAGES</h1>
<hr />
<!– Voilà l’endroit où le résultat sera affiché, reconnu dans notre futur fichier JavaScript par son id. Pour le moment, on affiche rien. –>
<div style=”background:black; text-align: center” >
<br /><br />
<img id=”i_pred” src=”/ajax/pred.png” onClick=”javascript:galerie=pred()” style=”cursor:pointer”/>
———-
<img id=”i_suiv” src=”/ajax/suiv.png” onClick=”javascript:galerie=suiv();” style=”cursor:pointer”/>
<br />
<img id=”image” src=”/ajax/start.jpg”/>
<br /><br />
</div>
<hr />
<script type=”text/javascript” >galerie=suiv();</script>
</body>
</html>

—————————————

Ce sont les fonctions pred et suiv, appelées une fois qu’une flèche a été cliquée, qui modifieront l’image. A la fin du body, on appel la fonction suiv pour initialiser l’image.

Jetons un coup d’oeil dans le fichier JavaScript:

—————————————

/*
Fonction qui crée un objet XHR.
Cette fonction initialisera la valeur dans la variable globale “requete”
*/

var requete = null; /* On crée une variable qui contiendra l’objet XHR */
var galerie =-1;

function creerRequete() {
try {
requete = new XMLHttpRequest(); /* On essaye de créer un objet XmlHTTPRequest */
} catch (microsoft) {
/* Si cela ne marche pas, on a peut-être affaire à un navigateur de Microsoft. On tente alors de créer un objet ActiveX */
try {
requete = new ActiveXObject(‘Msxml2.XMLHTTP’);
} catch(autremicrosoft) {
/* Autre méthode si la première n’a pas marché */
try {
requete = new ActiveXObject(‘Microsoft.XMLHTTP’);
} catch(echec) {
/* Si aucune méthode ne fonctionne, on laisse l’objet vide*/
requete = null;
}
}
}
if(requete == null) {
alert(‘Votre navigateur ne semble pas supporter les object XMLHttpRequest.’);
}
}

function pred()
{
creerRequete();
galerie –;
var url = ‘galerie.php?image=’+galerie;
requete.open(‘GET’, url, true);
requete.onreadystatechange = function() {
if(requete.readyState == 4) {
if(requete.status == 200) {
if(requete.responseText!=””)
{
document.getElementById(‘image’).src=”/ajax/img/” + requete.responseText;
}
}
}
};
requete.send(null);
return galerie;
}

function suiv()
{
creerRequete();
galerie ++;
var url = ‘galerie.php?image=’+galerie;
requete.open(‘GET’, url, true);
requete.onreadystatechange = function() {
if(requete.readyState == 4) {
if(requete.status == 200) {
if(requete.responseText!=””)
{
document.getElementById(‘image’).src=”/ajax/img/” + requete.responseText;
}
}
}
};
requete.send(null);
return galerie;
}
—————————————

On initialise la variable galerie. Elle servira d’index.
Comme vous pouvez le voir, nos fonctions pred et suiv ont un code similaire.
Chacune effectue la création de l’objet XHR en appelant la fonction creerRequete.
Puis elles incrémentent ou décrémentent la variable relative à l’identifiant de l’image.
On construit ensuite l’URL, les arguments seront passés par la méthode GET.
On initialise la fonction de renvoi d’information.
On teste si on est au début du diaporama (galerie = 0) ou si on est a la fin (la requête retourne rien).
Si l’on est dans le cas optimal, on affiche la nouvelle image.
On retourne la variable galerie à la page HTML.
Pour comprendre la totalité du diaporama, il faut ensuite regarder le code qui sera exécuté sur le serveur : galerie.php

—————————————

<?php
/*
On vérifie que le paramètre GET est bien présent
*/
function isnotpoint($var)
{
return $var!=”.” && $var !=’..’;
}

if(isset($_GET[‘image’]))
{
$image = $_GET[‘image’];
$image = abs($image);
$tableau = scandir(‘./img/’);
$tableau = array_filter($tableau,”isnotpoint”);
$nbimage = count ($tableau);
$image = ($image%$nbimage)+2;

echo $tableau[$image];

}
else
echo “Erreur GET”;
?>

—————————————

L’algorithme de ce code est le suivant:
On vérifie que le paramètre image est présent. On prend la valeur absolue de notre paramètre, ceci est utile lorsque l’index est inférieur à zéro. Si c’est le cas on utilise la fonction scandir et on stocke le résultat dans la variable tableau. La fonction scandir est très utile dans ce cas, en effet elle va retourner chacun des fichiers du dossier mais aussi un “.” et “..”, c’est pour cela que l’on utilise la fonction array_filter qui va les enlever du tableau. La fonction count permet de retourner le nombre d’éléments du tableau. On effectue un modulo de l’index avec ce nombre, et on ajoute 2. En effet, la fonction array_filter ne créer pas un nouveau tableau, mais efface juste les éléments correspondant à la recherche, C’est pour cela qu’il faut penser que les deux premiers éléments du tableau sont vides et ajouter 2. On retourne par la suite l’élément voulu.

Voilà, ce tutorial est terminé, vous pouvez à présent créer un diaporama utilisant Ajax pour votre site web.

 

Tutoriel Ajax – Infobulle

(Article rédigé par un groupe d’étudiant d’IUT dans le cadre d’un projet tutoré)

Voici un tutorial qui permet lorsque l’utilisateur passe la souris au dessus d’un mot définie a préalable, d’afficher dans une bulle un texte, une image ou ce que l’on veut.

On peut ainsi utiliser ce principe pour donner la signification de certains mots, ou même pour un lien afficher dans la bulle la première phrase de la page cible du lien.
Dans cet exemple les mots et leur significations ce trouvent dans le fichier xml.

Voici le fichier html :

<html>

<head>

<link rel=”stylesheet” type=”text/css” href=”/ajax/bulle.css” media=”all” />

<script type=”text/javascript” src=”/ajax/bulles.js”></script>

</head>

<body>

<div id=”curseur”></div>

Mot :<br />

Connaissez vous l'<span onmouseover=”javascript:affbulle(this)” onmouseout=”javascript:cache()”>ajax</span> ?<br />

C’est un concept <span onmouseover=”javascript:affbulle(this)” onmouseout=”javascript:cache()”>informatique</span> !<br />

Retour à la ligne

</body>

</html>

Explication : On peut remarquer les balises <span>, ce sont elles qui vont nous servir pour récupérer le mot associé à la définition ;

Deux fonctions JavaScript vont être appelés :

-affbulle va servir pour charger la définition du mot et afficher la bulle lorsque le mot est survolé.

-cache va comme son nom l’indique masquer la bulle lorsque la souris ne se trouve plus sur le mot concerné.

On peut se demander a quoi va servir la balise <div>, c’est tout simplement la déclaration de la bulle.

 

Voici le fichier css associé :

.infobulle{

position: absolute;

visibility : hidden;

border: 1px solid Black;

padding: 10px;

font-family: Verdana, Arial;

font-size: 10px;

background-color: #FFFFCC;

}

 

.lienbulle{

color: #0000ff;

cursor: help;

text-decoration: underline;

}

 

Rien de particulier, infobulle concerne la bulle et lienbulle concerne le mot en question.

 

Voici maintenant le fichier xml :

 

<?xml version=”1.0″ ?>

<root>

<ajax>Texte correspondant a l’Ajax</ajax>

<informatique>Texte correspondant a l’informatique</informatique>

</root>

 

Il suffit de créer la balise <nom> (nom étant le mot qui va être décrit), puis entre cette balise ouvrante et la balise fermante, on placera la description qui apparaîtra dans la bulle

 

Attaquons nous maintenant au fichier JavaScript :

 

/*

Fonction qui crée un objet XHR.

Cette fonction initialisera la valeur dans la variable globale “requete”

*/

 

var requete = null; /* On crée une variable qui contiendra l’objet XHR */

 

function creerRequete() {

try {

requete = new XMLHttpRequest(); /* On essaye de créer un objet XmlHTTPRequest */

} catch (microsoft) {

/* Si cela ne marche pas, on a peut-être affaire à un navigateur de Microsoft. On tente alors de créer un objet ActiveX */

try {

requete = new ActiveXObject(‘Msxml2.XMLHTTP’);

} catch(autremicrosoft) {

/* Autre méthode si la première n’a pas marché */

try {

requete = new ActiveXObject(‘Microsoft.XMLHTTP’);

} catch(echec) {

/* Si aucune méthode ne fonctionne, on laisse l’objet vide*/

requete = null;

}

}

}

if(requete == null) {

alert(‘Votre navigateur ne semble pas supporter les objets XMLHttpRequest.’);

}

}

 

Pour l’instant, nous avons le même code que pour l’implémentation.

 

function GetId(id)

{

return document.getElementById(id);

}

var i=false; // La variable i nous dit si la bulle est visible ou non

 

function move(e) {

if(i) { // Si la bulle est visible, on calcul en temps reel sa position idéal

if (navigator.appName!=”Microsoft Internet Explorer”) { // Si on est pas sous IE

GetId(“curseur”).style.left=e.pageX + 5+”px”;

GetId(“curseur”).style.top=e.pageY + 10+”px”;

}

else {

if(document.documentElement.clientWidth>0) {

GetId(“curseur”).style.left=20+event.x+document.documentElement.scrollLeft+”px”;

GetId(“curseur”).style.top=10+event.y+document.documentElement.scrollTop+”px”;

} else {

GetId(“curseur”).style.left=20+event.x+document.body.scrollLeft+”px”;

GetId(“curseur”).style.top=10+event.y+document.body.scrollTop+”px”;

}

}

}

}

 

La fonction qui précède ce charge de la position de la bulle par rapport au curseur

 

function montre() {

if(i==false) {

GetId(“curseur”).style.visibility=”visible”; // Si elle est cachée (la verification n’est qu’une sécurité) on la rend visible.

i=true;

}

}

 

La fonction montre() va simplement rendre visible la bulle.

 

function cache() {

if(i==true) {

GetId(“curseur”).style.visibility=”hidden”; // Si la bulle est visible on la cache

i=false;

}

}

 

A l’inverse cache() va masquer la bulle.

 

function affbulle(src) {

/* On crée notre super objet XHR global */

creerRequete();

 

/* On édite les propriété de l’objet : type de paramètre, url (avec paramètres) et une option autorisant une réponse du serveur */

requete.open(‘GET’, ‘test.xml’, true);

 

/* On initialise la fonction de renvoi d’information */

requete.onreadystatechange = function() {

if(requete.readyState == 4) {

if(requete.status == 200) {

 

/* On récupère le contenu de notre fichier */

var xml = requete.responseXML;

document.getElementById(‘curseur’).innerHTML = xml.getElementsByTagName(src.innerHTML).item(0).firstChild.data;//c’est ici que l’on charge la définition du mot

 

}

}

}

/* C’est partit ! On envoi la requête XHR au serveur */

requete.send(null);

montre();

}

document.onmousemove=move; // dés que la souris bouge, on appelle la fonction move pour mettre à jour la position de la bulle.

 

Cette fonction va donc accéder au fichier xml et charger la définition du mot et la retourner au ‘curseur’ pour qu’il affiche le tout dans la bulle.

Le ‘src.innerHTML’ correspond au mot qui se trouve dans le fichier html entre les balises span, ce mot doit être identique a la balise du fichier xml contenant la définition, il servira par conséquent d’identifiant.