Sol@rweb weblog

dimanche 1 octobre 2006

Prise en charge du tri sur plusieurs niveaux avec tool-man

Ayant eu besoin récemment de réaliser un tri par drag and drop sur plusieurs niveaux j'ai souhaité utiliser ma librairie habituelle à savoir celle de tool-man.org

Après plusieurs test et quelques recherches je me suis rendu compte que ce n'était pas faisable ou alors j'étais passé à côté (ce qui est possible).

Ce qu'il se passe c'est que la zone de "saisie" pour le drag and drop n'est pas définie et prend donc tout l'élément li. Or pour imbriquer des listes il faut insérer un ul dans un élément li, l'ul imbriqué ne pourra donc pas être trié à cause de la zone de saisie du dessus.

J'ai donc effectué une légère modification au script afin de pouvoir définir une zone clickable en englobant ce que l'on souhaite par un div avec la class "clickable".

Vous pouvez voir le résultat ci-dessous et accéder à la source dans mon labo. J'espère que ça vous sera utile ;)

vendredi 25 août 2006

Activation du flash sous Internet Explorer

Il y a peu, Microsoft à publié un patch correctif qui a ajouté un nouveau problème pour les développeur vis à vis de Internet Explorer.

En effet, lors de la visualisation de flash, on nous oblige maintenant à cliquer une première fois sur l'animation pour l'activer. Cela a été mis en place pour éviter l'utilisation d'un swf sur un autre domaine que celui d'origine mais cette modification a surtout posé des problèmes à tout le monde...

Voici donc 2 méthodes au choix qui permettent de régler ce problème grâce au javascript, vous pouvez suivre cela dans le labo et bien évidemment sous Internet Explorer 6 avec le patch.

  1. La première méthode est artisanale, je l'ai découverte dans cet article mais je l'ai optimisée car celle-ci ne respectait pas les standards, afin d'utiliser la méthode flash satay que vous pouvez voir dans cet article-ci..
    Elle consiste à appeler une fonction javascript en html pour afficher le flash :
    <script type="text/javascript">
    displayFlash("bouton.swf", 200, 50, "Contenu alternatif");
    </script>
    Et en javascript, à ajouter un paramètre et a simplement afficher le flash :
    function displayFlash(swf, hauteur, largeur, alternatif)
    {
    	document.write('<object type="application/x-shockwave-flash" data="'+swf+'" width="'+hauteur+'" height="'+largeur+'">');
    	document.write('<param name="allowScriptAccess" value="sameDomain" />');
    	document.write('<param name="movie" value="'+swf+'" />');
    	document.write(alternatif);
    	document.write('</object>');
    }
  2. La deuxième méthode consiste à utiliser un objet qui est fourni par adobe et que vous pouvez trouver sur cette page Cette méthode est plus complète, permet d'ajouter des paramètres, etc... mais on remarquera notamment un retard lors de l'affichage.
  3. EDIT : Une troisième méthode que j'ai trouvé sur le site de mon ami Nosegrind, assez simple, toujours en javascript, mais qui fera quand même fonctionner le flash si le javascript est désactivé, donc a priori une bonne méthode. Elle est a activer a la fin du chargement de tous les flash de la page :
    theObjects = document.getElementsByTagName("object");
    for (var i = 0; i < theObjects.length; i++)
    {
    	theObjects[i].outerHTML = theObjects[i].outerHTML;
    }

Au final, ces deux méthodes fonctionnent parfaitement, c'est à vous de choisir, personnellement, j'opterais pour la méthode artisanale (comme toujours ^^).

Externalisation totale du javascript

Une petite astuce que j'ai découverte récemment et testée pour trouver la meilleure utilisation. Le but est donc de ne plus avoir de gestion d'événements (onload, onlick...) dans le code xHTML mais que tout soit géré dans le javascript.

On va d'abord définir une fonction quelconque en javascript que l'on va essayer d'appeler avec l'événement interne, puis en externe :

function tell(personne, objet_creux_feminin_singulier)
{
	alert(personne+" rentre dans sa "+objet_creux_feminin_singulier);	
}

Voici la manière classique d'appeler cette fonction avec l'événement onclick dans un document xHTML :

<a href="#" onclick="tell('toto', 'maison')">Interne</a>

Maintenant le but est d'appeler cette fonction sans l'événement, on va donc ajouter un id à l'élément "a" mais on aurait pu essayer de le retrouver avec getElementsByTagName() (ce qui serait plus difficile dans une page avec x liens).

<a href="#" id="toto_maison">Externe</a>

La méthode pour lier un événement est tout simplement "element.evenement" lorsque il n'y a pas de paramètres et "element.evenement = function() {}" lorsqu'il y a un ou plusieurs paramètres.

Ce qui donne dans notre cas :

document.getElementById('toto_maison').onclick = function()
{
	tell('toto', 'maison');	
}

Seulement si vous insérez directement ce code dans votre fichier javascript, il ne va pas fonctionner car il va vouloir lier l'événement alors que la page n'est pas terminée de charger et que cet élément n'existe pas encore !

La solution est alors de faire une fonction pour englober les liaisons :

function loadEvents()
{
	// Evenement pour le lien toto
	document.getElementById('toto').onclick = function()
	{
		tell('toto', 'maison');	
	}
}

Une fois cette fonction créée il faut encore la charger elle aussi, on pourrait le faire avec un onload() sur le body mais on a décidé de tout externaliser.

La solution consiste alors à définir l'exécution de cette fonction une fois que la fenetre est chargée :

window.onload = loadEvents;

Et voila, nous avons notre code final qui externalise totalement le javascript. Exemple complet ci-dessous :

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Externalisation</title>
<script type="text/javascript" src="externalisation.js"></script>
</head>
<body>
	<a href="#" onclick="tell('toto', 'maison')">Interne</a>
	<br/>
	<a href="#" id="toto_maison">Externe</a>
</body>
</html>
// JavaScript Document
window.onload = loadEvents;
 
function loadEvents()
{
	// Evenement pour le lien toto
	document.getElementById('toto_maison').onclick = function()
	{
		tell('toto', 'maison');	
	}
}
 
function tell(personne, objet_creux_feminin_singulier)
{
	alert(personne+" rentre dans sa "+objet_creux_feminin_singulier);	
}

EDIT : Ce script est maintenant disponible dans mon labo