Le blog de Medialibs

Aller au contenu | Aller au menu | Aller à la recherche

Mot clé - javascript

Fil des billets - Fil des commentaires

lundi, avril 30 2007

Réaliser des aides pour les formulaires avec CSS et Javascript

Depuis la version 0.14a d'e-majne, vous avez certainement rencontré une nouveauté sur les formulaires. Lors de l'ajout de champs de formulaires, il est possible de remplir un nouveau champ, le champ d'information : informations.png On peut se servir de ce champ pour compléter le libellé du champ afin de donner plus d'informations sur le champ à compléter. Nous allons voir comment gérer l'affichage de ces champs de façon un peu moins brut, voir un peu tendance... Attention, ce billet est relativement long, donc pour ceux qui n'ont pas trop le temps voici le résultat final voir le résultat final

Le XHTML et le CSS :

Tout d'abord, il va falloir modifier vos templates si vous voulez pouvoir remonter ce champ de nouveauté pour qu'au niveau du HTML, cela nous donne quelque chose comme cela :

<div class="row">
        <label for="libelleid">
                libelle
                <span class="obligatory">*</span> :
        </label>
        <span>
                <input name="libelle" id="libelleid" type="text">
                <span class="aide">
                        <p>
                        voici mon champ d'information
                        </p>
                </span>
        </span>
</div>

Ce qui impose pour le template creator_form.html de rajouter cet élément à la place des champs de formulaire :

<span mXattribut="class:error2">
        <mx:text id="fields_input"/>
        <mx:bloc id="additionnals_informations">
                <span class="aide">
                        <mx:text id="additionnals_informations" />
                </span>
        </mx:bloc id="additionnals_informations">
</span>

Si maintenant on appliquait un peu de CSS afin de rendre tout ça un peu plus propre.

body{
        font-family: Verdana, Arial, Helvetica, sans-serif;
        font-size:65%;
}
*{
        margin:0;
        padding:0;
}
form{
        width:600px;
}
fieldset{
        border: 1px solid #757575;
        margin:10px;
        padding:5px;
}
legend{
        color:#757575;
        font-size:1.1em;
        font-weight: bold;
        padding:0 5px;
}
.row{
        clear:both;
        margin: 5px;
        padding: 5px;
        position:relative;
}
label{
        float:left;
        width:170px;
}
input, select, textarea{
        border: 1px solid #999999;
        text-align:left!important;
        width: auto;
}

Si maintenant on applique un style à nos aides, voici ce que cela donne. On pourra remarquer que les aides sur les champs de formulaires sont masqués par défaut à l'aide d'un display:none;, car nous allons afficher ces aides uniquement lorsque l'internaute aura placé sa souris dans le champs (focus).

.aide {
        display:none;
        width: 191px;
        z-index:800;
        margin:-5px 0 0 15px;
        position:absolute;
        background:url(/common_images/skin001/form_aide.gif) bottom right no-repeat;
}
.aide p{
        margin:0;
        padding:10px 12px 10px 18px;
        background:url(/common_images/skin001/pointer_form.gif) top right no-repeat;
}

Le Javascript :

On va maintenant en javascript parser notre page afin de trouver tout les champs de formulaire de type input, et pour chacun d'entre eux, nous allons réagir au focus en affichant l'aide et enlever cette aide lorsque le curser de la souris ne se trouve plus dans mon champ de formulaire (onblur).

function prepareInputsForHints() {
        var inputs = document.getElementsByTagName("input");
        for (var i=0; i<inputs.length; i++){
                inputs[i].onfocus = function () {
                        if(this.parentNode.getElementsByTagName("span").length>0){
                                this.parentNode.getElementsByTagName("span")[0].style.display = "inline";
                        }
                }
                inputs[i].onblur = function () {
                        if(this.parentNode.getElementsByTagName("span").length>0){
                                this.parentNode.getElementsByTagName("span")[0].style.display = "none";
                        }
                }
        }
}

Il va falloir faire exactement la même manipulation pour les champs de type select (liste déroulante) et textarea (texte multilignes), juste ici aucun soucis, on change les input par les champs de formulaire correspondant. Malheureusement, avec e-majine il existe un peu plus que ces champs de formulaire, il faut aussi prévoir l'affichage de mes champs de formulaire de type input radio et case à cocher qui ont une structure XHTML différente que des champs de formulaire normaux, donc il va falloir gérer des conditions et un fonctionnement différent de ce script. Et puis il y a aussi le soucis pour les champs de formulaire de type file, pour lesquelles la réaction au comportement focus se fait sur le bouton parcourir, ce qui en sera visible que pour les utilisateur qui naviguent à l'aide de la touche tabulation, donc pour ces champs de type fichier, l'affichage de l'aide se fera au survol.
Je vous fait grâce du fonctionnement de ce script, pour les plus curieux, tout se trouve dans le ficher à télécharger ci-dessous.

Télécharger la première version du script.

Un peu d'animation avec tout ça :

Maintenant, si on jouait avec des effets à la sauce 2.0, jouer d'accord mais en toute légèetré d'abbord, voici donc une librairie qui regroupe juste des effets graphique pour seulement 4ko, simple.js. Parmis tout les effets que propose cette librairie javascript, il y en a un qui m'intéresse tout particulièrement c'est $opacity qui va me permettre d'afficher l'aide nom seulement dans la bulle grâce à mes styles, mais aussi en fondu, il faut donc tout d'abord faire appel à cette librairie :

<script type="text/javascript" src="/common_scripts/simple.js"></script>

Lorsqu'on regarde la documentation de cette librairie javascript pour cette fonction, il est écrit :

$opacity(id, opacStart, opacEnd, millisec)

On remarque donc que cette fonction s'applique à un identifiant, avec une opacité de départ et de fin, et une durée en millisecondes entre les deux opacités. Le soucis c'est qu'avec e-majine, nous n'avons pas d'identifiant sur les balises span qui entourent nos aides, pas de soucis, grâce au javascript et surtout du DOM, nous allons recréer ces identifiants.

var identifant = this.parentNode.getElementsByTagName("span")[0].setAttribute("id", this.id+'aide');

Et nous allons donc pouvoir appliquer la fonction qui gère l'opacité

$opacity(this.id+'aide', 0, 100, 1500);

Ce qui nous donne au final :

inputs[i].onfocus = function () {
        if(this.parentNode.getElementsByTagName("span").length>0){
                this.parentNode.getElementsByTagName("span")[0].style.display = "inline";
                var identifant = this.parentNode.getElementsByTagName("span")[0].setAttribute("id", this.id+'aide');
                $opacity(this.id+'aide', 0, 100, 1500);
                return false;
        }
}
inputs[i].onblur = function () {
        if(this.parentNode.getElementsByTagName("span").length>0){
                var identifant = this.parentNode.getElementsByTagName("span")[0].setAttribute("id", this.id+'aide');
                $opacity(this.id+'aide', 100, 0, 1500);
                this.parentNode.getElementsByTagName("span")[0].style.display = "none";
                return false;
        }
}

Attention, il est important de remarquer qu'à la réaction sur le onblur, je repasse l'opacité à 0, sinon lorsqu'on clique deux fois sur un même élément de formulaire, la gestion de l'opacité ne sera pas bonne.

Et l'accessibilité dans tout ça

Exact, comment font les utilisateurs ne disposant pas de javascript pour avoir accès à ces champs d'aide dans les formulaires. Et bien plutôt que d'appliquer les styles (avec un style display:none;) à ces champs pour tout les utilisateurs, je vais insérer ces styles la via javascript.

document.write('<style type="text/css">.aide {filter:Alpha(opacity=0); -moz-opacity:0; opacity:0;display:inline;width: 191px;z-index:800;margin:-5px 0 0 15px;position:absolute;background:url(/common_images/skin001/form_aide.gif) bottom right no-repeat;}.aide p{margin:0;padding:10px 12px 10px 18px;background:url(/common_images/skin001/pointer_form.gif) top right no-repeat;}</style>');

Désormais, il ne reste plus qu'a intégrer ces deux fichiers javascript

<script type="text/javascript" src="/common_scripts/simple.js"></script>
<script type="text/javascript" src="/common_scripts/helpForm.js"></script>

Voici le résultat final.

Télécharger les deux scripts ainsi que le template et la feuille de style permettant de faire fonctionner ces aides pour les formulaires.

Billet original sur Simon Bonaventure

lundi, décembre 4 2006

faire une galerie d'images avancée autre part que dans un article en blocs.

Une galerie quoi ?

Avec e-majine, dans l'interface d'administration, lorsque vous créez un article en bloc, vous avez la possibilitée de faire un bloc de type médias. Dans la configuration de ce bloc, il suffit de lui demander d'afficher pour les types de médias des images. Ensuite, pour type d'affichage, on va demander une galerie d'images,a fin de pouvoir mettre plusieurs images, après avoir séléctionné toutes les images voulues, il faut cocher la case à cocher vignettes, qui va faire en sorte d'afficher tout d'abord les vignettes des images et avoir une action en cliquant dessus. Après avoir caché cette case, il faut choisir dans la liste déroulante, le mode de fonctionement avancé.

Comment cela fonctionne ?

Beaucoup d'entre vous apprécie le fonctionnement du bloc de type média lorsqu'il affiche une galerie d'images en mode avancé. On me pose souvent la question sur son fonctionnement et les technologies qui sont utilisés pour faire fonctionner cela, certains parlent de flash, d'autres d'AJAX. En fait il s'agit de DHTML, qui n'est pas à proprement parler un language mais une combinaison de languages. Le DHTML est une combinaison de technologies entre le Javascript, le CSS et le XHTML. Et donc cette galerie d'images proviens du site lightbox.

Comment l'intégrer autre part?

On fait appel aux fichiers externes

nous allons maintenant voir comment intégrer cette magnifique galerie d'images. Si on suit les recommendations du site de l'auteur, il va tout d'abord faire appel aux fichiers jaavscripts qui permettent de faire les effets de redimentionnement. Je vous conseille de déposer ces fichiers dans le dossier prévu à cet effet Scripts, qui se trouve à la racine de votre FTP :

<script type="text/javascript" src="/scripts/prototype.js"></script>
<script type="text/javascript" src="/scripts/scriptaculous.js?load=effects"></script>
<script type="text/javascript" src="/scripts/lightbox.js"></script>

Ensuite, il va aussi falloir faire appel à la feuille de style de cette galerie, sans oublier de déposer dans le dossier images, à la racine du FTP toutes les images qui sont appellées dans la feuille de style. :

<link  rel="stylesheet" type="text/css" href="/modeles/fr/Modele1/css/gallery.css" title="normal" />

On défnit le(s) endroit(s) on vont le trouver les images

Ensuite, il va falloir définir dans votre template l'endroit ou va se trouver la galerie d'images, en encapsulant les images dans un div qui va devoir porter un attribut de class qui vous aurez définit.

<div class="gallery">
         <img src="/medias/thumbnail/image1.png" alt="texte alternatif 1" />
         <img src="/medias/thumbnail/image2.png" alt="texte alternatif 2" />
         <img src="/medias/thumbnail/image3.png" alt="texte alternatif 3" />
</div>

Pour ceux qui ne

On s'amuse avec javascript et le DOM

Après avoir fait cela, il falloir intégrer un nouveau fichier javascript de mon fait, qui aura pour but de rajouter avec le DOM pour chaque image le lien avec les bons attributs qui vont pouvoir faire en sorte d'afficher le galerie d'images. Dans ce fichier, on va tout d'abord commencer par retrouver une fonction qui va nous permettre de travailler avec les classname, car il n'existe pas de fonction native en javascript qui récupère chaque classname, et qui stock le contenu dans un tableau.

function getElementsByClassName(oElm, strTagName, strClassName){

        var arrElements = (strTagName == "*" && document.all)? document.all : oElm.getElementsByTagName(strTagName);
        var arrReturnElements = new Array();
        strClassName = strClassName.replace(/\-/g, "\\-");
        var oRegExp = new RegExp("(^|\\s)" + strClassName + "(\\s|$)");
        var oElement;
        for(var i=0; i<arrElements.length; i++){
                oElement = arrElements[i];    
                if(oRegExp.test(oElement.className)){
                        arrReturnElements.push(oElement);
                }
        }
        return (arrReturnElements)

}

Ensuite, on à une seconde fonction, qui à chaque fois qu'on va rencontrer le nom de class qu'on aura choisi de mettre sur notre div qui englobe les images de notre galerie, va regarder toutes les images. Pour chacune des images, je rajoute une lien dans le div parent, à ce lien, je lui met l'image à l'interieure, et ensuite je créer les attributs href, title et rel (qui av parmettre de créer la galerie). Je vous fait grace du fonctionnement de tout ça.

function createGallery(class){
        var className = getElementsByClassName(document, "div", class);
        // à chaque fois qu'on rencontre la classname, on crée uen nouvelle gallerie
        for(var i=0 ; i<className.length ;i++){
                var imagesGallery = className[i].getElementsByTagName("img");
                //pour chacune des images de la gallerie
                for(var j=0 ; j<imagesGallery.length ;j++){
                        //création du lien
                        var lien = document.createElement("a");
                        className[i].appendChild(lien);
                        lien.appendChild(imagesGallery[j]);
                        //création des attributs du lien
                        lien.setAttribute('rel', 'lightbox['+class+']');
                        lien.setAttribute('href', '/media/'+imagesGallery[j].src.split("/")[5]);
                        lien.setAttribute('title', '<h3>'+lien.title+'</h3><p>'+imagesGallery[j].alt+'</p>');
                        //alert(lien.innerHTML);
                }
        }

}

Et enfin, une fois que tout cela est fait, il ne reste plus qu'a lancer cette dernière fonction à la fin du chargement de la page. En n'oubliant pas de faire apple au même nom de class qui est mis sur le div en englobe nos images.

window.onload = function(){
        var classname = "gallery";
        if (getElementsByClassName(document, "div", classname).length>=1){
                createGallery(classname)
        }
}

Ces trois dernieres fonctions se trouvent aussi dans un fichier externe, il va falloir y faire appel comme précédemment :

<script type="text/javascript" src="/scripts/Gallery.js"></script>

Je laisse à disposition une archive contenant tout les fichiers susciétes

A vos claviers, il ne vous reste plus qu'à insérer cela dans vos annuaires, catalogues, articles préformatés, etc.

PS : si dans votre site vous avez déjà intégré du javascript avec la fonction onload, il est fort probable qu'il y ai un conflit avec deux fonctions onload. Si c'est le cas, n'hésitez pas à lire cet article

Billet original sur Simon Bonaventure