11548 sujets

JavaScript, DOM et API Web HTML5

J'ai un problème que je n'arrive pas à résoudre : Le clic fonctionne sous firefox et opera mais pas sous ie, et je ne trouve pas la solution.

Voudriez vous bien m'aider ?

Voilà le code :


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta http-equiv="Content-Type" content=
    "text/html; charset=us-ascii" />
    <title>
     Dom
    </title>
  </head>
  <body>
		<div id="test"></div>
		<script>
		 var balise=document.getElementById("test");
		 var texte = document.createTextNode("Du simple texte.");
		 var balisediv=document.createElement("div");
		 balisediv.setAttribute('onclick','foo();');
		 balisediv.appendChild(texte);
		 balise.appendChild(balisediv);
		 function foo()
		 {
		  alert('onclick');
		 }
		</script>
  </body>
</html>


Merci. Smiley murf
Modifié par sylvainmart (30 May 2007 - 16:04)
Bonjour et bienvenue parmi nous Smiley smile

En tant que modérateur, je me dois de te faire remarquer que tu n'as malheureusement pas respecté l'une des Règles de base du forum qui est d'afficher les codes et exemples proprement à l'aide des boutons [ code]... ici ton code HTML, CSS, PHP, etc.[ /code] (sans espace).

Je te remercie par avance de bien vouloir éditer ton message afin de le rendre conforme à cette règle. Smiley cligne

D'ailleurs, je rappelle que le lien qui apparaît en bandeau tout en haut du forum ("Nouveau sur le forum ?...") est important. Il contient des pistes de recherche, des indications sur les règles de vie de la communauté, etc.
Il serait courtois de ta part de bien vouloir en prendre connaissance.

Bonne continuation Smiley smile

upload/1-code.gif
Merci Shinuza,

ça fait 2 jours que je me pète la tronche sur le problème et tu m'as donné la solution. Alors encore un grand merci pour ton aide.


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta http-equiv="Content-Type" content=
    "text/html; charset=us-ascii" />
    <title>
     Dom
    </title>
  </head>
  <body>
		<div id="test"></div>
		<script>
		 var balise=document.getElementById("test");
		 var texte = document.createTextNode("Du simple texte.");
		 var balisediv=document.createElement("div");
		 addEvent( balisediv,'click', foo );
		 balisediv.appendChild(texte);
		 balise.appendChild(balisediv);
		 function foo()
		 {
		  alert('onclick');
		 }
     function addEvent( obj, type, fn ) 
		 {
      if ( obj.attachEvent ) 
			{
       obj['e'+type+fn] = fn;
       obj[type+fn] = function(){obj['e'+type+fn]( window.event );}
       obj.attachEvent( 'on'+type, obj[type+fn] );
      } 
			else
			{
       obj.addEventListener( type, fn, false );
      }
		 }
     function removeEvent( obj, type, fn ) 
		 {
      if ( obj.detachEvent ) 
			{
       obj.detachEvent( 'on'+type, obj[type+fn] );
       obj[type+fn] = null;
      } 
			else
			{
       obj.removeEventListener( type, fn, false );
			}
     }
		</script>
  </body>
</html>


Sylvain.
J'ajouterai que ajouter un event de cette manière est un peu crade plusieurs choix s'offrent à toi :



element.onclick = foo; 

directement la fonction, sans les parentheses

element.setAttribute("onclick", foo); 

en passant par setAttribute mais en passant bien foo en tant que reference de fonction, mais je ne suis pas sur que ça marche (ca ne marchera peut etre pas du tout.


element.onclick = function() '
  foo();
}

Modifié par Gatsu35 (30 May 2007 - 01:07)
Gatsu35 : la remarque concernant les balises [ code] est valable pour toi aussi. Smiley langue

De façon générale, il est inutile et peu robuste d'utiliser setAttribute pour les gestionnaires d'événement.
Julien Royer a écrit :
Gatsu35 : la remarque concernant les balises [ code] est valable pour toi aussi. Smiley langue

De façon générale, il est inutile et peu robuste d'utiliser setAttribute pour les gestionnaires d'événement.

d'ouù les précisions que j'ai apporté. Normalement j'utilise tout le temps .onclick=mafunc;
Gatsu35 a écrit :
d'ouù les précisions que j'ai apporté.

Pas très claires, les précisions en question... De toute façon, le second paramètre de setAttribute doit être une chaîne de caractères.

Et puis, pendant que l'on y est, il ne faut pas oublier que l'utilisation directe d'un attribut (onclick par exemple) sur l'élément ne permet pas d'attacher plusieurs gestionnaires d'événement du même type à un même noeud.
Un gestionnaire d'évènements encore plus complet :


/*
 * Handler.js -- Portable event handler registration functions
 *
 * This module defines event handler registration and deregistration functions
 * Handler.add() and Handler.remove(). Both functions take three arguments:
 * 
 *   element: the DOM element, document, or window on which the handler
 *      is to be added or removed.
 * 
 *   eventType: a string that specifies the type of event for which the
 *      handler is to be invoked.  Use DOM-standard type names, which do
 *      not include an "on" prefix. Examples: "click", "load", "mouseover".
 *
 *   handler: The function to be invoked when an event of the specified type
 *      occurs on the specified element.  This function will be invoked as
 *      a method of the element on which it is registered, and the "this"
 *      keyword will refer to that element.  The handler function will be
 *      passed an event object as its sole argument.  This event object will
 *      either be a DOM-standard Event object or a simulated one. If a 
 *      simulated event object is passed, it will have the following DOM-
 *      compliant properties: type, target, currentTarget, relatedTarget,
 *      eventPhase, clientX, clientY, screenX, screenY, altKey, ctrlKey,
 *      shiftKey, charCode, stopPropagation(), and preventDefault()
 * 
 * Handler.add() and Handler.remove() have no return value.
 * 
 * Handler.add() ignores duplicate registrations of the same handler for
 * the same event type and element.  Handler.remove() does nothing if called
 * to remove a handler that has not been registered.
 *
 * Implementation notes:
 * 
 * In browsers that support the DOM standard addEventListener() and
 * removeEventListener() event registration functions, Handler.add() and
 * Handler.remove() simply invoke these functions, passing false as the 
 * third argument (meaning that the event handlers are never registered as
 * capturing event handlers).
 * 
 * In versions of Internet Explorer that support attachEvent(), Handler.add()
 * and Handler.remove() use attachEvent() and detachEvent(). To
 * invoke the handler function with the correct this keyword, a closure is
 * used.  Since closures of this sort cause memory leaks in Internet Explorer,
 * Handler.add() automatically registers an onunload handler to deregister
 * all event handlers when the page is unloaded. To keep track of
 * registered handlers, Handler.add() creates a property named _allHandlers on
 * the window object and creates a property named _handlers on any element on
 * which a handler is registered.
 */
var Handler = {};

// In DOM-compliant browsers, our functions are trivial wrappers around
// addEventListener() and removeEventListener().
if (document.addEventListener) {
    Handler.add = function(element, eventType, handler) {
        element.addEventListener(eventType, handler, false);
    };

    Handler.remove = function(element, eventType, handler) {
        element.removeEventListener(eventType, handler, false);
    };
}
// In IE 5 and later, we use attachEvent() and detachEvent(), with a number of
// hacks to make them compatible with addEventListener and removeEventListener.
else if (document.attachEvent) {
    Handler.add = function(element, eventType, handler) {
        // Don't allow duplicate handler registrations
        // _find() is a private utility function defined below.
        if (Handler._find(element, eventType, handler) != -1) return;
        
        // To invoke the handler function as a method of the
        // element, we've got to define this nested function and register
        // it instead of the handler function itself.
        var wrappedHandler = function(e) {
            if (!e) e = window.event;

            // Create a synthetic event object with partial compatibility
            // with DOM events.
            var event = {
                _event: e,    // In case we really want the IE event object
                type: e.type,           // Event type
                target: e.srcElement,   // Where the event happened
                currentTarget: element, // Where we're handling it
                relatedTarget: e.fromElement?e.fromElement:e.toElement,
                eventPhase: (e.srcElement==element)?2:3,

                // Mouse coordinates
                clientX: e.clientX, clientY: e.clientY,
                screenX: e.screenX, screenY: e.screenY,
                
                // Key state
                altKey: e.altKey, ctrlKey: e.ctrlKey,
                shiftKey: e.shiftKey, charCode: e.keyCode,

                // Event management functions
                stopPropagation: function() {this._event.cancelBubble = true;},
                preventDefault: function() {this._event.returnValue = false;}
            }

            // Invoke the handler function as a method of the element, passing
            // the synthetic event object as its single argument.
            // Use Function.call() if defined; otherwise do a hack
            if (Function.prototype.call) 
                handler.call(element, event);
            else {
                // If we don't have Function.call, fake it like this
                element._currentHandler = handler;
                element._currentHandler(event);
                element._currentHandler = null;
            }
        };

        // Now register that nested function as our event handler.
        element.attachEvent("on" + eventType, wrappedHandler);
        
        // Now we must do some record keeping to associate the user-supplied
        // handler function and the nested function that invokes it.

        // We have to do this so that we can deregister the handler with the
        // remove() method and also deregister it automatically on page unload.

        // Store all info about this handler into an object
        var h = {
            element: element,
            eventType: eventType,
            handler: handler,
            wrappedHandler: wrappedHandler
        };

        // Figure out what document this handler is part of.
        // If the element has no "document" property, it is not
        // a window or a document element, so it must be the document
        // object itself.
        var d = element.document || element;
        // Now get the window associated with that document
        var w = d.parentWindow;

        // We have to associate this handler with the window,
        // so we can remove it when the window is unloaded
        var id = Handler._uid();  // Generate a unique property name
        if (!w._allHandlers) w._allHandlers = {};  // Create object if needed
        w._allHandlers[id] = h; // Store the handler info in this object

        // And associate the id of the handler info with this element as well
        if (!element._handlers) element._handlers = [];
        element._handlers.push(id);

        // If there is not an onunload handler associated with the window,
        // register one now.
        if (!w._onunloadHandlerRegistered) {
            w._onunloadHandlerRegistered = true;
            w.attachEvent("onunload", Handler._removeAllHandlers);
        }
    };

    Handler.remove = function(element, eventType, handler) {
        // Find this handler in the element._handlers[] array.
        var i = Handler._find(element, eventType, handler);
        if (i == -1) return;  // If the handler was not registered, do nothing

        // Get the window of this element
        var d = element.document || element;
        var w = d.parentWindow;

        // Look up the unique id of this handler
        var handlerId = element._handlers[i];
        // And use that to look up the handler info
        var h = w._allHandlers[handlerId];
        // Using that info, we can detach the handler from the element
        element.detachEvent("on" + eventType, h.wrappedHandler);
        // Remove one element from the element._handlers array
        element._handlers.splice(i, 1);
        // And delete the handler info from the per-window _allHandlers object
        delete w._allHandlers[handlerId];
    };

    // A utility function to find a handler in the element._handlers array
    // Returns an array index or -1 if no matching handler is found
    Handler._find = function(element, eventType, handler) {
        var handlers = element._handlers;
        if (!handlers) return -1;  // if no handlers registered, nothing found

        // Get the window of this element
        var d = element.document || element;
        var w = d.parentWindow;

        // Loop through the handlers associated with this element, looking
        // for one with the right type and function.
        // We loop backward because the most recently registered handler
        // is most likely to be the first removed one.
        for(var i = handlers.length-1; i >= 0; i--) {
            var handlerId = handlers[i];        // get handler id
            var h = w._allHandlers[handlerId];  // get handler info
            // If handler info matches type and handler function, we found it.
            if (h.eventType == eventType && h.handler == handler) 
                return i;
        }
        return -1;  // No match found
    };

    Handler._removeAllHandlers = function() {
        // This function is registered as the onunload handler with 
        // attachEvent.  This means that the this keyword refers to the
        // window in which the event occurred.
        var w = this;

        // Iterate through all registered handlers
        for(id in w._allHandlers) {
            // Get handler info for this handler id
            var h = w._allHandlers[id]; 
            // Use the info to detach the handler
            h.element.detachEvent("on" + h.eventType, h.wrappedHandler);
            // Delete the handler info from the window
            delete w._allHandlers[id];
        }
    }

    // Private utility to generate unique handler ids
    Handler._counter = 0;
    Handler._uid = function() { return "h" + Handler._counter++; };
}
[/i][/i]
Juste ! Pas la peine de compliquer l'affaire pour le problème posé puisque ça fonctionne bien avec la solution proposée.
sylvainmart a écrit :
Juste ! Pas la peine de compliquer l'affaire pour le problème posé puisque ça fonctionne bien avec la solution proposée.

D'où vient le code que tu as donné ?
sylvainmart a écrit :
Le code vient du livre de David Flanagan chez o'reilly : Javascript la reference 5ème edition en français.

Merci !
Modérateur
Hello,

Un reproche par rapport au code de David Flanagan (ce n'en ai pas véritablement un, son code étant justifié dans le contexte du livre) :

La non-segmentation des méthodes utilisées...
Lorsqu'on comprend le code et qu'on choisit de baser son code dessus, pas de problème, on peut l'adapter assez facilement.

En revanche, si on n'en ai pas capable, on se retrouve systématiquement avec un code qui gère toute sorte de fonctionnalités alors qu'on a en réalité besoin que du tiers du code...

Certains diront, ok mais pourquoi réinventer la roue...

Il n'est pas question de la réinventer mais uniquement de savoir modifier le code (ce qui implique d'avoir des connaissances minimum effectivement... voire de savoir la réinventer)

A titre d'exemple, on me demande aujourd'hui d'intégrer de nombreuses fonctionnalités Ajax dans une application. Pour cela, on me montre des exemples générés à partir de la librairie Yahoo!, de prototype, de scriptaculous, de mootools, etc...
Croyez-vous sincèrement que je vais m'amuser à prendre chacune des bibliothèques (parce que je ne trouve pas la fonctionnalité exacte dans celle que je possède déjà) et intégrer 1Go de js ? Ce ne serait vraiment pas malin... Smiley cligne

Apprendre javascript (entre autres la gestion d'événements), ça a encore du bon... et lorsqu'on opte pour une bibliothèque, mieux vaut savoir faire son choix et en comprendre la structure.

Il y a un problème dans ta démarche sylvainmart : Tu as demandé un click et tu te retrouves, en plus, à contrôler des alt, ctrl, etc... alors que ça ne te servira probablement à rien.
Modifié par koala64 (31 May 2007 - 14:10)
Salut koala64,

Je l'utilise parceque, Intuitivement, je pense qu'elle est complète et qu'elle répond bien à la gestion de tous types d'évènements.

Cela me permet de ne pas me prendre la tête sur la gestion d'un évènement et de la réutiliser pour plusieurs fonctions différentes où il y a besoin de gérer un évènement.

C'est juste ce que tu dis. Pour le moment je ne la comprends pas entièrement. Et même parfois je ne l'utilise pas à bon escient.

Peut être quand je serais un peu plus expérimenté !

Sylvain.
Modérateur
Elle est pas mal oui. Smiley smile Ma remarque est plus là à titre de réflexion... Smiley cligne

Sans l'abandonner pour autant, ce serait bien que tu la tritures dans tous les sens (y compris en ajoutant ou supprimant des fonctionnalités) pour voir ce que tu peux en faire... ça va pas mal t'aider...

En cas d'incompréhension, il y a de bon cours. Smiley smile
Merci pour le lien sur le cours, cela parait très interessant et bien expliqué.

Je le mets en favori et j'y reviendrais un peu plus tard.

Quel merveilleux monde que celui de l'informatique et du web en particulier !