Jamie Hartnoll
Jamie Hartnoll

Reputation: 7341

jQuery showing an element if a main wrapper is clicked, but not if a specific element is clicked

I'm having troubles with a simple menu hide/show with jQuery.

The HTML markup is as follows:

<div class="content borderRad5" id="mainWrapper">

    <div id="ticketControl" class="noPrint blackBoxShadow">
        <span id="printThis" class="TicketButton">Print</span>
        <span id="emailThis" class="TicketButton">Email as Word</span>
            <div id="emailDoc" class="blackBoxShadow borderRad5">
                <div class="underline">Email to:</div>
                <label>Email</label> 
                <span>
                    <input type="text" class="smallText" />
                </span>
            </div>
        <span id="wordThis" class="TicketButton">Save as Word</span>
        <span id="addToLoyalty" class="TicketButton">Add to Account</span>
        <span id="addNote" class="TicketButton">Add Note</span>
        <span id="refundThis" class="TicketButton">Refund</span>
    </div>

  ---- THE REST OF THE PAGE ----

</div>

#ticketControl is a hidden div containing the menu. When the mouse is clicked anywhere within the .content div, I want it to slide into view. The jQuery below does this just lovely.

    $('.content').live('click', function () {
        $('#ticketControl').slideToggle('slow');
    });

However, I have a second hidden div within this main menu #emailDoc which needs to slide into view when #emailThis is clicked, obviously this is easy, BUT, I can't stop it from hiding the menu again.

I realise why it's doing it, because anything within .content triggers the slideToggle function as above, but I can't seem to stop it, I've tried using .not('.TicketButton') and also trying to get parent IDs and excluding them and so on, but I'm clearly missing something obvious!

Any help much appreciated (and yes, I realise I should be using jquery on but I'm sticking with live for now...!)

Upvotes: 0

Views: 229

Answers (2)

Felix Kling
Felix Kling

Reputation: 816492

As you said you don't have to use live, directly attach the click event handler to both elements and call event.stopPropagation() [docs] to prevent the event from bubbling up and triggering other event handlers:

$('.content, #emailThis').click(function(e) {
    e.stopPropagation();
    $(this).children().slideToggle('slow');
});

If you cannot use the event handler like this, I suggest you use generic classes which associate elements with their children which have to toggled. For example the elements which should have such a behaviour could have the class header and the children which are supposed to be toggled toggle (sorry, I'm a bit uncreative at the moment):

$('.header').click(function(e) {
    e.stopPropagation();
    $(this).children('.toggle').slideToggle('slow');
});

Otherwise you have to duplicate basically the same behaviour for a couple of elements, which reduces maintainability of your code.

Upvotes: 0

Anthony Grist
Anthony Grist

Reputation: 38345

Call event.stopPropagation() in the click callback function for #emailThis so that the event doesn't bubble up the DOM to the parent elements.

Upvotes: 0

Related Questions