views:

204

answers:

4

Hi there,

I have an image with a class of "actions_image" that when clicked shows a menu. This image with hidden menu appears several times on the same page. I'm having issues with the code below for 2 reasons:

1 - In the Javascript code, the first line is to ensure that if there's already a menu open, this will be closed before the new menu is shown. But when this line is added, then the second line with the toggle command no longer toggles. It only shows the div when you click, but won't hide it when you click again. All the rest of the actions work perfectly, as in the div hides when anything but the image that shows it is clicked

2 - IE 7 is throwing up an error for the 2nd line of javascript because of the use of :hover and won't show the menu at all (grrr...!)

Can anyone help?

Javascript code:

section_actions_menu: function(event){  
    $(".actions_image").next().hide();  
    $(".actions_image:hover").next().toggle();  
    $("body").click(function(e){  
        if(e.target.className !== "actions_image")  
        {  
            $(".actions_image").next().hide();  
        }     
    });                             

}

HTML Code:

<img src="/media/images/spacer.gif" width="31" height="18" alt="Section Actions Menu" title="Section Actions Menu" class="actions_image" onclick="section_actions_menu(event);"/>
<div class="toggle">
    <ul>
        <li><a title="Add">Add</a></li>
        <li><a title="Edit">Edit</a></li>
        <li><a title="Remove">Remove</a></li>
    </ul>
</div>

Any help would be much appreciated.

A: 

you could try using .not(), should be more efficent?

$('body').children().not('.actions_image').click(function(){....
Haroldo
Can you explain the efficiency gain? At a glance that looks like it will add lots of event handlers instead of just one and that doesn't sound like its going to be an efficiency gain over one event handler with a single comparison test.
Chris
Unfortunately that doesn't work. Although, this section of the code isn't broken, it's the IE 7 not accepting the code that I'm more interested in overcoming.
aligreene
@chris - Yep my mistake, it still doesnt seem very efficient to be manually delegating after every event has to bubble all the way up the dom?
Haroldo
A: 

I would think that the reason the toggle only shows is because the line before you are hiding everything. Its not just hiding other menus, its hiding all of them so when you toggle you are toggling something hidden to make it visible. You probably want to keep track of what is currently being shown (store the currently visible menu in a variable) and then you can check whether you are supposed to be hiding it or not.

Chris
That's exactly why it's happening - thanks a million. I'll let you know how I get on.
aligreene
A: 

First off the:

$("body").click(function(e){   
        if(e.target.className !== "actions_image")   
        {   
            $(".actions_image").next().hide();   
        }      
    });

stands alone, so does not need to be in that function - which seems to me to add that handler each time you click an image. SO I would put it outside the click handler for the image.

Second,

section_actions_menu: function(event){    ...

with the specific:

onclick="section_actions_menu(event);"

together is the same as:

$('.actions_image').click(function(e){
});

SO, I would remove the onclick=... and change to the specific jQuery handler which separates the markup from the behavior (no click function call on the element at all, it is all in the code).

Then we can handle the event for the click.

SO, I end up with this script:

$(document).ready(function()
{
    $("body").click(function(e)
    {   
      if (e.target.className !== "actions_image")   
      {   
         $(".actions_image").next().hide();   
      };
    });
    $('.actions_image').click(function(e)
    {
       if (e.target.next().is(':visible'))
       {
         $(".actions_image").next().hide(); 
       }
       else
       {
          $(".actions_image").next().hide(); //hides all menus if any showing
          e.target.next().show();//shows this specific one.
       };
    });
});

NOTE: this:

$(".actions_image").next().hide();

could also be:

$(".actions_image").next('.toggle').hide();

to use your class

Mark Schultheiss
Hi mark - thanks for the reply. I was shown another method, which I posted the answer to if you wanted to see. Also took away the onclick= as well. Thanks
aligreene
A: 

Hello - It turns out someone much cleverer than me also pointed out this method:

section_actions_menu: function() {

    var action_menu = $(".actions_image");
    action_menu.live('click', function(e) {
        var other_action_menus = $(".actions_image").not($(this));
        other_action_menus.next().hide();
        $(this).next().toggle();

});

and together with this:

$("body").click(function(e) { //hides menu when clicking outside the menu
    if(e.target.className !== "actions_image") {
    $(".actions_image").next().hide();
    }
});

... it allows to show and hide the menu when you click on an element with class ".actions_image", hides the menu when you click outside ".actions_image" and hides other menus that might be showing when you click on another element with class ".actions_menu".

aligreene