Handle events from central script

Discussion in 'Javascript' started by Markus Ernst, Jun 23, 2005.

  1. Markus Ernst

    Markus Ernst Guest

    Hello

    I try to hanlde events centrally for avoiding the need to write four event
    handler attributes to every link. The task is changing the class name of a
    link's containing <div> element. After lots of googling I came to this:

    if (document.getElementsByTagName) {
    a = document.getElementsByTagName("a");
    for (var i=1; i<a.length; i++) {
    var element = a;
    element.onmouseover = function() { element.parentNode.className =
    "aktiv"; };
    element.onMouseOut = function() { element.parentNode.className =
    "passiv"; };
    element.onFocus = function() { element.parentNode.className =
    "aktiv"; };
    element.onBlur = function() { element.parentNode.className =
    "passiv"; };
    }
    }

    The script does not throw any errors neither in IE 6 nor in Firefox, but it
    does only change the last element to aktiv, regardless of which element is
    hovered or unhovered.

    I thought of the a overwriting the element variable in every loop and
    also tried calling a directly, and other things such as
    var element = document.getElementById(a.id);
    or an for-in-loop; the result is only the same.

    Is my approach totally wrong, or is there anything I am missing?

    Thanks for any hint
    Markus
     
    Markus Ernst, Jun 23, 2005
    #1
    1. Advertising

  2. On 23/06/2005 14:24, Markus Ernst wrote:

    [snip]

    > if (document.getElementsByTagName) {
    > a = document.getElementsByTagName("a");
    > for (var i=1; i<a.length; i++) {
    > var element = a;
    > element.onmouseover = function() { element.parentNode.className =
    > "aktiv"; };
    > element.onMouseOut = function() { element.parentNode.className =
    > "passiv"; };
    > element.onFocus = function() { element.parentNode.className =
    > "aktiv"; };
    > element.onBlur = function() { element.parentNode.className =
    > "passiv"; };
    > }
    > }


    The problem is that you're forgetting about case-sensitivity: for
    instance, there is no recognised onMouseOut property, but there is a
    generally recognised onmouseout property. The same goes for onFocus and
    onBlur.

    However, you don't need a script to do what you're attempting. CSS is
    quite capable:

    a:link {
    /* Declarations used by the .passiv class */
    }
    a:focus,
    a:hover {
    /* Declarations used by the .aktiv class */
    }

    Note: IE doesn't support the :focus pseudo-class, though others do.

    [snip]

    Mike

    --
    Michael Winter
    Replace ".invalid" with ".uk" to reply by e-mail.
     
    Michael Winter, Jun 23, 2005
    #2
    1. Advertising

  3. Markus Ernst

    Markus Ernst Guest

    Michael Winter wrote:
    > On 23/06/2005 14:24, Markus Ernst wrote:
    >
    > [snip]
    >
    >> if (document.getElementsByTagName) {
    >> a = document.getElementsByTagName("a");
    >> for (var i=1; i<a.length; i++) {
    >> var element = a;
    >> element.onmouseover = function() {
    >> element.parentNode.className = "aktiv"; };
    >> element.onMouseOut = function() {
    >> element.parentNode.className = "passiv"; };
    >> element.onFocus = function() {
    >> element.parentNode.className = "aktiv"; };
    >> element.onBlur = function() {
    >> element.parentNode.className = "passiv"; };
    >> }
    >> }

    >
    > The problem is that you're forgetting about case-sensitivity: for
    > instance, there is no recognised onMouseOut property, but there is a
    > generally recognised onmouseout property. The same goes for onFocus
    > and onBlur.


    Thank you very much for your input. The case sensitivity issue does indeed
    solve a part of my problem - now all four events are performed, but still
    always on the last element.
    I think I need to find a way to save a reference to a which is not
    overwritten by the following loop.

    > However, you don't need a script to do what you're attempting. CSS is
    > quite capable:


    Yes I use this for the <a> element itself. The task is to highlight also the
    containing element of this html structure:

    <div class="passiv">
    <a href="koepfe/paolo_tonti.html">Paolo Tonti</a>
    <span>Werbung / Konzept / Graphic Design</span>
    </div>

    I don't know if CSS provides a syntax to address the parent element - but I
    am sure that it would not be supported by today's common browsers anyway...

    Of course I have a working solution with four event handlers in every link -
    but I would be happy to find a solution that makes a maximum separation of
    content and presentation.

    --
    Markus
     
    Markus Ernst, Jun 23, 2005
    #3
  4. On 23/06/2005 15:11, Markus Ernst wrote:

    [snip]

    > Thank you very much for your input. The case sensitivity issue does indeed
    > solve a part of my problem - now all four events are performed, but still
    > always on the last element.


    Sorry, I forgot to comment on the functions.

    Closures do not take a 'snapshot' of the variables in their scope chain,
    but remain live. All of these functions will share the same element
    value, and that value will always be the last A element in the
    collection at the end of the loop. The solution is simple though, and is
    more efficient, too:

    function setAktiv() {
    var pN = this.parentNode;

    if(pN) {pN.className = 'aktiv';}
    }
    function setPassiv() {
    var pN = this.parentNode;

    if(pN) {pN.className = 'passiv';}
    }

    if(document.getElementsByTagName) {
    var a = document.getElementsByTagName('a'),
    i = a.length;

    while(--i) {
    a.onmouseover = a.onfocus
    = setAktiv;
    a.onmouseout = a.onblur
    = setPassiv;
    }
    }

    By the way, if you didn't mean to ignore the first A element in the
    collection (arrays and collections use zero-based indices), then change
    the while condition to a postfix decrement: i--

    [snip]

    > The task is to highlight also the containing element of this html structure:


    Sorry. I'm clearly not being very attentive today. :(

    [snip]

    Mike

    --
    Michael Winter
    Replace ".invalid" with ".uk" to reply by e-mail.
     
    Michael Winter, Jun 23, 2005
    #4
  5. Markus Ernst

    Markus Ernst Guest

    Michael Winter wrote:
    >
    > [snip]
    >
    > Closures do not take a 'snapshot' of the variables in their scope
    > chain, but remain live. All of these functions will share the same
    > element value, and that value will always be the last A element in the
    > collection at the end of the loop. The solution is simple though, and
    > is more efficient, too:
    >
    > function setAktiv() {
    > var pN = this.parentNode;
    >
    > if(pN) {pN.className = 'aktiv';}
    > }
    > function setPassiv() {
    > var pN = this.parentNode;
    >
    > if(pN) {pN.className = 'passiv';}
    > }
    >
    > if(document.getElementsByTagName) {
    > var a = document.getElementsByTagName('a'),
    > i = a.length;
    >
    > while(--i) {
    > a.onmouseover = a.onfocus
    > = setAktiv;
    > a.onmouseout = a.onblur
    > = setPassiv;
    > }
    > }


    This is really amazing, thanks a lot!

    > By the way, if you didn't mean to ignore the first A element in the
    > collection (arrays and collections use zero-based indices), then
    > change the while condition to a postfix decrement: i--


    I actually meant to leave out index 0, anyway it is a better solution to
    only address the links below a specified main container (such as navigation,
    contents or whatever). So my final solution can be called with a list of
    containers:
    <body onLoad="aktiviereLinks('navigation', 'contents')>

    That's the script:

    function machAktiv() {
    var pN = this.parentNode;
    if (pN) {
    var klasse = "aktiv";
    if (pN.className.indexOf("Unten") != -1) klasse = klasse + "Unten";
    pN.className = klasse;
    }
    }
    function machPassiv() {
    var pN = this.parentNode;
    if (pN) {
    var klasse = "passiv";
    if (pN.className.indexOf("Unten") != -1) klasse = klasse + "Unten";
    pN.className = klasse;
    }
    }
    function aktiviereLinks() {
    if (document.getElementsByTagName) {
    args = aktiviereLinks.arguments;
    j = args.length;
    while (j--) {
    a = document.getElementById(args[j]).getElementsByTagName("a");
    i = a.length;
    while (i--) {
    a.onmouseover = a.onfocus = machAktiv;
    a.onmouseout = a.onblur = machPassiv;
    }
    }
    }
    }

    Thank you very much for your great inputs, I learnt a lot today!

    --
    Markus
     
    Markus Ernst, Jun 23, 2005
    #5
  6. Markus Ernst

    Mick White Guest

    Markus Ernst wrote:

    [snip]
    > function aktiviereLinks() {
    > if (document.getElementsByTagName) {
    > args = aktiviereLinks.arguments;
    > j = args.length;
    > while (j--) {
    > a = document.getElementById(args[j]).getElementsByTagName("a");
    > i = a.length;
    > while (i--) {
    > a.onmouseover = a.onfocus = machAktiv;
    > a.onmouseout = a.onblur = machPassiv;
    > }
    > }
    > }
    > }
    >


    Couple of things:
    [1] "Function.arguments" deprecated
    [2] Localize scope of loop variables (i & j)

    See rewritten function below:

    function aktiviereLinks() {
    if (document.getElementsByTagName) {

    var j = arguments.length;
    while (j--) {
    a = document.getElementById(args[j]).getElementsByTagName("a");
    var i = a.length;
    while (i--) {
    a.onmouseover = a.onfocus = machAktiv;
    a.onmouseout = a.onblur = machPassiv;
    }
    }
    }
    }

    Mick
     
    Mick White, Jun 23, 2005
    #6
  7. Markus Ernst

    Markus Ernst Guest

    Mick White wrote:
    >
    > Couple of things:
    > [1] "Function.arguments" deprecated
    > [2] Localize scope of loop variables (i & j)
    >


    Thanks a lot. Now I added a recursive function call to make the hover in all
    elements up to the next <div> element:

    function machAktiv() {
    var pN = this.parentNode;
    umschalten(pN, "aktiv");
    }
    function machPassiv() {
    var pN = this.parentNode;
    umschalten(pN, "passiv");
    }
    function umschalten(pN, klasse) {
    if (pN) {
    var kl = klasse;
    if (pN.className.indexOf("Unten") != -1) kl = kl + "Unten";
    pN.className = kl;
    if (pN.nodeName.toLowerCase() != "div") umschalten(pN.parentNode,
    klasse);
    }
    }
    function aktiviereLinks() {
    if (document.getElementsByTagName) {
    var j = arguments.length;
    while (j--) {
    a =
    document.getElementById(arguments[j]).getElementsByTagName("a");
    var i = a.length;
    while (i--) {
    a.onmouseover = a.onfocus = machAktiv;
    a.onmouseout = a.onblur = machPassiv;
    }
    }
    }
    }

    So in the following HTML the "person" element and all children will be
    highlighted if one of the links is hovered:

    <body onLoad="aktiviereLinks('head')">
    <div id="person" class="passiv">
    <img src="myimage.gif" alt="">
    <p class="passiv">
    My name<br>
    <a href="mailto:"></a><br>
    <span class="passiv"><a
    href="http://www.domain.com">www.domain.com</a></span>
    </p>
    </div>
    </body>

    Thank you all for your help!!
    Markus
     
    Markus Ernst, Jun 27, 2005
    #7
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Hrvoje Vrbanc
    Replies:
    0
    Views:
    471
    Hrvoje Vrbanc
    Aug 12, 2003
  2. =?Utf-8?B?UGl0Y2Fpcm5pYQ==?=

    Script Callback in ASP.Net 2.0 events to handle

    =?Utf-8?B?UGl0Y2Fpcm5pYQ==?=, May 25, 2005, in forum: ASP .Net
    Replies:
    0
    Views:
    584
    =?Utf-8?B?UGl0Y2Fpcm5pYQ==?=
    May 25, 2005
  3. Andrea Williams

    Adding client-script to handle client events

    Andrea Williams, Apr 12, 2004, in forum: ASP .Net Datagrid Control
    Replies:
    1
    Views:
    145
    Andrea Williams
    Apr 12, 2004
  4. Chris

    Events Events Events Please Help

    Chris, Aug 30, 2005, in forum: ASP .Net Web Controls
    Replies:
    0
    Views:
    425
    Chris
    Aug 30, 2005
  5. Replies:
    1
    Views:
    167
    Peter Michaux
    Apr 27, 2007
Loading...

Share This Page