11550 sujets

JavaScript, DOM et API Web HTML5

Smiley smile Bonjour,

Je post pour la première fois, le forum et le site m'ayant souvent aidé a résoudre mes soucis.
Mais la je bloque. Smiley bawling

Je souhaiterais afficher/cacher une div (qui contient un textaera).
Si le textarea est vide il reste a cacher, mais on peut cliquer dessus pour le remplir.
Si le textarea contient du texte il est affiché, mais au clique on peut le cacher.

J'ai utilisé ce code trouvé sur le forum:

function openClose(id)
{
if(document.getElementById)
var elt = document.getElementById(id);
else if(document.all)
var elt = document.all[ id];
else
return;

if (elt.style) {
if (elt.style.display == 'none')
elt.style.display = 'block';
else
elt.style.display = 'none';
}
}

Il permet le Afficher/cacher mais ne controle pas le contenu.

Pour la div:
<a href="javascript:openClose('Commentaire')" title="Afficher/Masquer le contenu">
<b>Commentaire:</b><br></a>
<div name="Commentaire" id="Commentaire" class="openClose" style="display: none">
<textarea name="COMMENTAIRE" cols="192" rows="4" class="textinfield" id="COMMENTAIRE" onMouseOut="fitToText.call(this)" onMouseOver="fitToText.call(this)" onBlur="fitToText.call(this)">COMMENTAIRE</textarea>
</div>

(fitToText.call(this) me permet d'adapter le textarea au texte tapé)

Voila, je suis preneur de toute idées.
Merci d'avance! Smiley cligne
Modifié par loic74 (22 Sep 2010 - 21:12)
Modérateur
Salut, Bienvenue sur Alsacréations ! Smiley smile

loic74 a écrit :
(fitToText.call(this) me permet d'adapter le textarea au texte tapé)
Lors du mouseover, du mouseout et du blur ?!! C'est pour le moins bizarre. Smiley sweatdrop
J'aurais imaginé que l'adaptation de la taille du textarea s'effectue pendant que le texte est tapé voire par l'intermédiaire d'un contrôle (et donc lors d'un clic sur un bouton) mais pas lors des événements dont tu t'es servi.

Pour le reste, ton code est obsolète et quelque chose comme suit serait déjà préférable (bien qu'on puisse encore améliorer tout çà) :
<!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" lang="fr" xml:lang="fr">
    <head>
        <meta http-equiv="content-type" content="text/html; charset=utf-8" />
        <title>Exemple</title>
        <script type="text/javascript">
        
document.documentElement.className += ' hasJS';
        
function OpenClose(oControl, oTarget, fTest) {
    if(!(oControl && oTarget)) {
        return;
    }
    var _affiche = function() {
        oControl.innerHTML = 'Masqu' + oControl.innerHTML.slice(6);
        oTarget.className += ' showComm';
        if(arguments.length == 0) {
            oTarget.select();
        }
    };
    if(fTest && fTest(oTarget)) {
        _affiche(true);
    }
    oControl.onclick = function() {
        if(/\bshowComm\b/.test(oTarget.className)) {
            oControl.innerHTML = 'Affich' + oControl.innerHTML.slice(5);
            oTarget.className = oTarget.className.replace(/\bshowComm\b/, '');
        }
        else {
            _affiche();
        }
        return false;
    };
};

function selectControl(sFor) {
    var _aLabels = document.getElementsByTagName('label');
    for(var _iLabel = 0, _iCount = _aLabels.length; _iLabel < _iCount; _iLabel++) {
        if(_aLabels[_iLabel].htmlFor == sFor) {
            _aLabels[_iLabel].innerHTML = '<a href="#">Afficher les ' + _aLabels[_iLabel].innerHTML.toLowerCase() + '</a>';
            return _aLabels[_iLabel].getElementsByTagName('a')[0];
        }
    }
    return;
};

window.onload = function() {
    var _oComm = document.getElementById('commentaires');
    OpenClose(
        selectControl('commentaires'),
        _oComm,
        function(oEl) {
            return oEl.value.length != 0;
        }
    );
};
        
        </script>
        <style type="text/css">
        
@media screen {
    .hasJS #commentaires {position:absolute; left:-20000px;}
    .hasJS #commentaires.showComm {position:static;}
}
        
        </style>
    </head>
    <body>
    
        <form action="index.php" method="post">
            <div>
                <label for="commentaires">Commentaires :</label>
                <textarea name="commentaires" id="commentaires" cols="192" rows="4"></textarea>
            </div>
            <div>
                <input type="submit" value="Transmettre" />
            </div>
        </form>
    
    </body>
</html>
Salut koala64!

Merci de ton aide précieuse. Je suis vraiment novice en javascript, d'ailleur mon niveau ne m'a pas permis de comprendre tous le code que tu as donné... Smiley confused

Pour ma fonction fitToText... j'ai un peu honte mais je n'ai pas trouvé comment la faire fonctionné en direct a la saisie du texte. Smiley sweatdrop

J'ai bien mis en place ton code, le soucis c'est qu'il me cache bien le textarea mais impossible de le déployer pour écrire dans le textarea.

sais tu d'ou cela peut venir?

merci de ton aide!!! Smiley cligne
Modérateur
Sans code, il m'est difficile de deviner Smiley cligne m'enfin Madame Irma me souffle que tu n'as pas dû transformer ceci :
<a href="javascript:openClose('Commentaire')" title="Afficher/Masquer le contenu">
<b>Commentaire:</b><br></a>
en celà :
<label for="commentaires">Commentaires :</label>


En fait, l'idée est de partir d'une page fonctionnant sans JS. Si tu désactives ce langage, ta page restera fonctionnelle.

Aussi, le lien de contrôle pour afficher / masquer ton textarea n'a lieu d'être que dans le cas où JS est actif, ce pourquoi il est généré via ce langage.
Modifié par koala64 (21 Sep 2010 - 18:19)
Mme Irma est plutôt doué, tu lui dira, j'avais bien fais comme ca.
Je viens de remplacer comme ceci:

<div> 
<a href="javascript:OpenClose('commentaires')" title="Afficher/Masquer le contenu"> 
<b>Commentaire:</b><br></a>
<textarea name="commentaires" id="commentaires" cols="192" rows="4"></textarea> 
</div>


La, on a déjà plus l'impression de pouvoir cliquer mais cela ne s'ouvre toujours pas.

Est ce que je me suis trompé? Smiley sweatdrop
Modifié par loic74 (21 Sep 2010 - 18:36)
Modérateur
Hum... euh... non ! Smiley biggol Je te disais justement de passer par un "label" associé à ton "textarea" car c'est ce que prévoit le script.

Regarde de nouveau la page d'exemple que je t'ai filé (et qui fonctionne) puis assure-toi que tu as bien :

- un élément "label "avec un attribut "for" ayant une valeur "commentaires"
- un élément "textarea" avec un attribut "id" ayant une valeur "commentaires"

Attention à la casse et à l'orthographe lors de tes vérifications ! Smiley cligne
Modifié par koala64 (21 Sep 2010 - 18:42)
Smiley lol Excuse moi au départ j'avais bien remplacé par ceci:
<div> 
<label for="commentaires">Commentaires :</label> 
<textarea name="commentaires" id="commentaires" cols="192" rows="4">


C'est après que c'était n'importe quoi...

Donc toujours le même soucis présent.

Je suis sous firefox, mais je viens de tester sur IE8 et cela fonctionne, a par qu'il me sort un textarea de malade en largeur, lol
Modérateur
Dans ce cas, il faut vérifier :

- que ta page html est valide.
- que tu n'as aucune erreur au sein de la console de Firebug
- que tu n'as aucun conflit avec d'autres scripts (ce qui me semble plausible étant donné que l'exemple que je t'ai donné est basé sur un window.onload)

Désolé d'être si succinct dans mes explications mais ce n'est pas facile de répondre à partir d'un téléphone. Smiley lol

Au pire, si tu ne t'en sors pas, mets donc une page en ligne pour que je puisse cerner le problème. Smiley smile
Modifié par koala64 (21 Sep 2010 - 21:26)
Modérateur
Salut,

Je réponds ici à tes MP car ce n'est vraiment pas dans les habitudes du forum que de passer par ce biais pour résoudre un problème. Smiley cligne D'autant plus que d'autres personnes peuvent avoir le même type de soucis et que, dans ce cas, il ne trouveront pas de réponse; juste un sujet non résolu. Je continue donc ici. Smiley smile

Aussi, vu que tu ne peux dévoiler ta page, le préférable serait :

1- soit de reproduire une page de test comportant le même problème et de la mettre en ligne,
2- soit de fournir les codes HTML (page complète) et JS (tout ce qui touche à la zone traitée)

En parallèle, je te refournis un code documenté (à outrance) et posant moins de risque d'interactions avec d'autres scripts.

code HTML :
<!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" lang="fr" xml:lang="fr">
    <head>
        <meta http-equiv="content-type" content="text/html; charset=utf-8" />
        <title>Exemple</title>
        <script type="text/javascript" src="openclose.js"></script>
        <link rel="stylesheet" type="text/css" href="openclose.css" />
    </head>
    <body>
    
        <form action="index.php" method="post">
            <div>
				
				<!-- Label visé par la fonction _selectControl -->
                <label for="commentaires">Commentaires :</label>
				
				<!-- Textarea recherché lors de l'éxécution de la fonction _openClose -->
                <textarea name="commentaires" id="commentaires" cols="192" rows="4"></textarea>
				
            </div>
            <div>
                <input type="submit" value="Transmettre" />
            </div>
        </form>
    
    </body>
</html>


Fichier openclose.css
@media screen {

	/* Position, au chargement de la page, du textarea lorsque Javascript est actif (on le sort de l'écran) */
    .hasJS #commentaires {position:absolute; left:-20000px;}
	
	/* Classe showComm permettant l'affichage du textarea */
    .hasJS #commentaires.showComm {position:static;}
}


Fichier openclose.js
// Encapsulation du script au sein d'une fonction anonyme éxécutée directement pour limiter la portée du script
// Voir tuto :  http://www.alsacreations.com/article/lire/565-JavaScript-organiser-son-code-en-modules.html
 
(function() {

    // Fonction d'ajout de gestionnaire d'événements non intrusifs
    // Voir tuto :  http://www.alsacreations.com/article/lire/562-bonnes-pratiques-javascript.html#event
 
    var _addEvent = function(oEl, sEvType, fn, bCapture) {
        return document.addEventListener ?
            oEl.addEventListener(sEvType, fn, bCapture || false):
            oEl.attachEvent ?
                oEl.attachEvent('on' + sEvType, fn):
                false;
    };

    // Ajout d'une classe sur l'élément html afin de disposer des styles initiaux lorsque Javascript est disponible
    // Voir astuce :  http://www.alsacreations.com/astuce/lire/834-prechargement-styles-css-js.html
 
    document.documentElement.className += ' hasJS';
    
    // Fonction d'affichage et masquage sous certaines conditions
    // @param: (object) oControl -> lien pilotant l'affichage / masquage
    // @param: (object) oTarget -> élément affiché / masqué
    // @param: (function) fTest -> Fonction déterminant si l'élément doit être affiché ou masqué
    var _openClose = function(oControl, oTarget, fTest) {
    
        // Si on ne dispose pas, au minimum, d'un lien pilote et d'un élément à afficher / masquer,
        // on sort de la fonction
        if(!(oControl && oTarget)) {
            return;
        }
        
        // Fonction d'affichage
        var _affiche = function() {
        
            // On modifie le contenu du lien pour avoir un texte adapté à la situation
            oControl.innerHTML = 'Masqu' + oControl.innerHTML.slice(6);
            
            // On ajoute la classe CSS affichant l'élément cible (textarea)
            oTarget.className += ' showComm';
            
            // Si la fonction _affiche n'a pas d'argument, on sélectionne le contenu de l'élément cible
            if(arguments.length == 0) {
                oTarget.select();
            }
        };
        
        // Si une fonction est passée en troisième paramètre d'OpenClose et si celle-ci retourne true,
        // on affiche l'élément cible (sans sélectionner son contenu)
        if(fTest && fTest(oTarget)) {
            _affiche(true);
        }
        
        // Gestionnaire d'événement au clic sur le lien de contrôle
        var _clickHandler = function(e) {
        
            // Si l'élément cible comporte la classe showComm (élément cible affiché)
            if(/\bshowComm\b/.test(oTarget.className)) {
            
                // On modifie le contenu du lien pour avoir un texte adapté à la situation
                oControl.innerHTML = 'Affich' + oControl.innerHTML.slice(5);
                
                // On supprime la classe CSS pour masquer l'élément cible (textarea)
                oTarget.className = oTarget.className.replace(/\bshowComm\b/, '');
            }
            
            // ou bien, on affiche l'élément cible en sélectionnant son contenu
            else {
                _affiche();
            }
            
            // On annule l'action par défaut du lien pour éviter de suivre son href
            e.preventDefault();
        };
        
        // On ajoute le gestionnaire d'événement au clic sur le lien de contrôle
        _addEvent(oControl, 'click', _clickHandler);
    };

    // Fonction sélectionnant le "label" ayant l'attribut "for" indiqué en paramètre
    // @param: (string) sFor -> valeur de l'attribut "for" recherché
    var _selectControl = function(sFor) {
    
        // On sélectionne tous les labels
        var _aLabels = document.getElementsByTagName('label');
        
        // On les parcourt un par un
        for(var _iLabel = 0, _iCount = _aLabels.length; _iLabel < _iCount; _iLabel++) {
        
            // Si le label courant a l'attribut "for" recherché
            if(_aLabels[_iLabel].htmlFor == sFor) {
            
                // On lui ajoute un lien interne en modifiant le contenu initial
                // pour expliquer le type de contrôle
                _aLabels[_iLabel].innerHTML = '<a href="#">Afficher les ' + _aLabels[_iLabel].innerHTML.toLowerCase() + '</a>';
                
                // On sort de la fonction en retournant le lien de contrôle ainsi créé
                return _aLabels[_iLabel].getElementsByTagName('a')[0];
            }
        }
        
        // On sort de la fonction en retournant une valeur nulle si le label n'a pas été trouvé
        return;
    };

    // Gestionnaire d'événement au chargement de la page
    var _loadHandler = function() {
    
        // On lance la fonction d'affichage / masquage en lui passant les paramètres souhaités
        _openClose(
            
            // On sélectionne le label ayant l'attribut "for" de valeur "commentaires"
            _selectControl('commentaires'),
            
            // On sélectionne l'élément ayant l'identifiant "commentaires"
            document.getElementById('commentaires'),
            
            // On charge une fonction vérifiant que le contenu de l'élément cible est non nul.
            function(oEl) {
                return oEl.value.length != 0;
            }
        );
    };
    
    // On ajoute le gestionnaire d'événement au chargement de la page
    _addEvent(window, 'load', _loadHandler);
    
})();
Salut,

Bien sur, c'est plus que normal que le cas soit traité dans le forum.
Je t'ai envoyé le mp uniquement pour t'expliquer pourquoi je ne pouvais mettre en ligne ma page. Smiley murmure Smiley lol

Je te remercie de m'avoir détailler l'ensemble du code, j'espere que ca n'a pas ete trop ch***t a faire... C'est vrai que comme cela j'arrive a mieux comprendre ce que le code fait.

J'ai tous bien remis en ordre comme indiqué.
Résultat: Cela fonctionne très bien dans firefox et IE8!!!
(J'ai inclus les label dans une div a l'intérieur pour qu'il ne fasse pas la longueur du textarea)

<div style="width:1000px;"> 
<div style="width:1000px;"> 
                <!-- Label visé par la fonction _selectControl --> 
                <label for="commentaires">Commentaires :</label> 
</div>
                <!-- Textarea recherché lors de l'éxécution de la fonction _openClose --> 
                <textarea name="commentaires" id="commentaires" cols="122" rows="4">commentaires</textarea>  
                  
</div>

Par contre dans ma page j'ai 3 zones avec textarea. la premier est toujours ouverte, c'est la description, la 2eme et la 3eme doivent pouvoir s'ouvrir (commentaire et conclusion).

Alors j'ai fais cela dans le js:

       
 _openClose(  
              
            // On sélectionne le label ayant l'attribut "for" de valeur "commentaires"  
            _selectControl('commentaires','conclusion'),  
              
            // On sélectionne l'élément ayant l'identifiant "commentaires"  
            document.getElementById('commentaires','conclusion'),  
              
            // On charge une fonction vérifiant que le contenu de l'élément cible est non nul.  
            function(oEl) {  
                return oEl.value.length != 0;  
            }  
        );  
    };  




Résultat: uniquement le commentaire vois sa propriété fonctionner, conclusion reste figé.
Est ce que je me suis trompé?

Encore merci! Smiley prie
Modérateur
loic74 a écrit :
Est ce que je me suis trompé?
Oui, parce que les méthodes auxquelles tu passes 2 arguments ("commentaires" et "conclusion") ne sont pas prévues pour accepter plusieurs paramètres.

En revanche, tu peux lancer 2 fois _openClose :

        _openClose(
            _selectControl('commentaires'),
            document.getElementById('commentaires'),
            function(oEl) {
                return oEl.value.length != 0;
            }
        );
        _openClose(
            _selectControl('conclusion'),
            document.getElementById('conclusion'),
            function(oEl) {
                return oEl.value.length != 0;
            }
        );
voire, en généralisant, tu peux remplacer ces 2 expressions par :
var _aTargets = ['commentaires', 'conclusion']; // Tableau dans lequel tu peux ajouter autant d'association label/textarea que tu veux
var _fCondition = function(oEl) {
    return oEl.value.length != 0;
};
for(var _iTarget = 0, _iCount = _aTargets.length; _iTarget < _iCount; _iTarget++) {
    _openClose(
        _selectControl(_aTargets[_iTarget]),
        document.getElementById(_aTargets[_iTarget]),
        _fCondition
    );
}
FRANCHEMENT! TU ES UN CHEF!!!!!!!

MERCI!!!! Smiley clapclap

Tous fonctionne!
Pour que cela fonctionne j'ai rajouté cela dans le fichier CSS:

  
.hasJS #conclusion {position:absolute; left:-20000px;} 

.hasJS #conclusion.showComm {position:static;} 

Vraiment merci! (de ta patience entre autre)

J'espere que tous cela servira a d'autre. Je n'y sera jamais arrivé seul.

Bon maintenant je vais m'atteler au dernier point qui me gêne et dont j'avais parler en début de post (fonction fitToTexte), je pense que je vais surement avoir besoin de la communauté... Smiley cligne

Merci!!!!!