2

I need help with binding back after I unbind an element. Basically, I have three anchor elements, and I want to achieve this:

When one of them is clicked, the other two can't be clicked. Then when the user clicks the close button, I want to bind back the click event for all three links.

To unbind is not a problem, but the binding back is not working. I didn't post any code because I think that the solution provided will work in general, not just in my case.

Is there maybe any other way to achieve what I want, but not with the use of bind/unbind or on/off?

Edit:

Here is how i have done it.The animated div is called miniContainer.This is the sample for one anchor, but it is the same thing for all three.

       //First Link         
krug1Link.click(function(element){
   if(miniContainer.hasClass('animirano')){
       return false;
   };
   element.preventDefault();
   miniContainer.stop().animate({ height:360 },{duration:500,easing: 'easeOutBack'});
   miniTekst1.animate({opacity:'1'},1200);
   polaroidMali.animate({opacity:'1'},1200);
   miniContainer.addClass('animirano');
});

//Close Mini Container
close.click(function(element){
    miniTekst1.animate({opacity:'0'},1200);
    miniTekst2.animate({opacity:'0'},1200);
    polaroidMali.animate({opacity:'0'},1200);
    polaroidMali2.animate({opacity:'0'},1200);
    miniContainer.animate({marginTop: 10, height:1},{duration:600,easing: 'easeInBack'});
    miniContainer.removeClass('animirano');
});
RightSaidFred
  • 11,209
  • 35
  • 35
fluxus
  • 559
  • 5
  • 15
  • 29

2 Answers2

8

Don't bind and unbind to do this.

Choose a common ancestor, and use jQuery's selector based event delegation.

var clickables = $('.clickable');

$('#some_ancestor').delegate( '.clickable', 'click', function() {
    // to disable the others
    clickables.not( this ).removeClass('clickable');
});

Then to reenable them all, just add the class back in.

clickables.addClass( 'clickable' );

If you're using jQuery 1.7 or later, then use .on() instead since it has event delegation built in.

$('#some_ancestor').on( 'click', '.clickable', function() {
    // to disable the others
    clickables.not( this ).removeClass('clickable');
});

Here's one of the solutions from the comments below.

demo: http://jsfiddle.net/c9Ydy/3/

<ul id="container"> 
    <li id="link1" class="box clickable">
        <a href="#">LINK ONE</a>
    </li>
    <li id="link2" class="box clickable">
        <a href="#">LINK TWO</a>
    </li>
    <li id="link3" class="box clickable">
        <a href="#">LINK THREE</a>
    </li>
</ul>

<div id="content_display">
    <button>CLOSE</button>
    <p id="link1_content">THIS IS THE CONTENT FOR THE FIRST LINK.</p>
    <p id="link2_content">THIS ONE IS FOR THE SECOND LINK</p>
    <p id="link3_content">AND THIS IS THE THIRD LINK</p>
</div>

js

var clickables = $('.clickable'),
    display = $('#content_display'),

    $content, // remember the one that was clicked
    display_animation_enabled = false;

$('#container').delegate( '.clickable', 'click', function() {

    display_animation_enabled = true;
    clickables.removeClass('clickable');

    if( $content ) { $content.hide(); }

    $content = $('#' + this.id + '_content').show();
    cycle();
});
display.find('p').hide();
display.find('button').click(function() {
    display_animation_enabled = false;
    clickables.addClass( 'clickable' );
    if( $content ) { $content.hide(); }
});
function cycle() {
    if( display_animation_enabled ) {
        display.animate({width:300,height:300})
               .animate({width:200,height:200}, cycle);
    }
}

css

div.box {
    width: 50px;
    height: 50px;
    background: yellow;
    margin: 10px;
}

div.clickable {
    background: orange;
}

#content_display {
    width: 200px;
    height: 200px;
    background: yellow;
}
#content_display > p {
    margin: 10px;
    color: blue;
}
RightSaidFred
  • 11,209
  • 35
  • 35
  • Thanks RightSaidFred, but i would need more hand holding if i am to grasp what you wrote.I know some jQuery, but design is my bread and butter. – fluxus Dec 02 '11 at 21:13
  • please what do you think of my workaround, when clicking on any of the links, a new div is animated, so i added a class to that div on each click event.But the first line of the click event checks if the div has a class applied, and if it does it returns false.I am removing the class by clicking on the close button.Is my solution good, or should i maybe complicate things with delegates, binds, on/off? – fluxus Dec 02 '11 at 22:43
  • 1
    @suludi: You could certainly do that. I personally prefer event delegation. What happens is that you bind the handler to some common ancestor, so each clickable element is in that common container. When a user clicks on the page, a click event *"bubbles"*. That means that the click starts at the most deeply nested element, and works its way up, trying to trigger a handler on each element, until the `window` is reached, and there's no further to go. Because of this, it will encounter that common ancestor along the way and fire its handler. – RightSaidFred Dec 02 '11 at 22:52
  • So what the handler does is it tests the element that triggered the event to see if it matches the selector you provided. In my example, the selector is the `"clickable"` class. So if the element clicked has that class, your code will run. So in my example, I gave each element the `clickable` class. When I don't want it to be clickable, I remove the class. When I do, I give it the class again. If you provide more code, I can give you a more specific example. – RightSaidFred Dec 02 '11 at 22:52
  • [Here's an example.](http://jsfiddle.net/c9Ydy/) Notice that the handler is on the ancestor. When you click one the `clickable` class is removed from the others, and they no longer work. When the animation is done, they all get the `clickable` class back. – RightSaidFred Dec 02 '11 at 23:01
  • Hi, it is getting very late in my country(Croatia), and my mind is not working so good.I understand what you are saying, i know how event bubbling works, but i just can't get the desired behaviour in my example.I will try to explain it a little bit before posting some code.I have three anchors inside ul, when clicking on each a div is animated below with corresponding content to each link.When a div is animated, i don't want the user to have the option to click on the other two, i need it to be closed by clicking on close button. – fluxus Dec 03 '11 at 00:28
  • @suludi: [Something like this?](http://jsfiddle.net/c9Ydy/1/) When you say "closed", I assume you mean you want the animation to stop, and the links to be clickable again. – RightSaidFred Dec 03 '11 at 00:49
  • You are very close i think.What i meant by closed is that i want the animated div to go back to its original state.Please take a look i provided some code in the original question. – fluxus Dec 03 '11 at 00:58
  • @suludi: It does go back to its original state. If you meant the content should disappear, just add `$(this).siblings('p').text('');` to the `click` handler on the button. I'm going to have to let you take it from here. – RightSaidFred Dec 03 '11 at 01:02
  • Thanks for your help, i will play with it now. – fluxus Dec 03 '11 at 01:04
  • Please if you could help just a little bit.I understand your solution, but please if you could modify the jfiddle so that each clicked link provides different content to div#content_display. Thanks – fluxus Dec 03 '11 at 14:49
  • @suludi: They do provide different content. Each one copies the content of the `` into the display. If you need something more, you'll need to describe where the content comes from. – RightSaidFred Dec 03 '11 at 14:53
  • 1
    ...[here's an update](http://jsfiddle.net/c9Ydy/2/) that takes the content from an Array instead. It gets the `.index()` of the link that was clicked, and uses that index to get content from the Array. – RightSaidFred Dec 03 '11 at 14:57
  • Thanks, i think it's just what i needed. – fluxus Dec 03 '11 at 15:05
  • 1
    @suludi: [Here's another update](http://jsfiddle.net/c9Ydy/3/) that shows and hides like you described. I gave each `li` and id, and each content section the same id, but with `_content` added to it. This makes it easy to select the related content section from the `li` that was clicked. It also stores the current section in a `content` variable so that you can easily hide it when the close button is clicked. – RightSaidFred Dec 03 '11 at 15:18
5

Doesn't seem like you would need to unbind/re-bind to achieve the desired result. Just use a flag. i.e.

//This is a variable that you will use to check whether any of the anchors have been
//clicked. If this flag is set to true, then the click handler below will not 
//perform any action when the other anchors are clicked. When this flag is set to false
//the click handler will take the desired action. From your description it sounds like
//the action might be opening a window of some sort...  
var buttonClicked = false;

//Bind a click handler to each anchor
$('#anchor-1').click(function(){

     //check to see if one of the anchors has already been clicked. If none have been
     //clicked take execute the code inside the if statement.
     if(!buttonClicked){

          //set the flag to true, indicating that one of the anchors has been clicked.
          buttonClicked = true;

          //Here you would open your window or popup...
          //i.e. popup.open();
     }
});

$('#anchor-2').click(function(){
     if(!buttonClicked){
           //logic for second anchor..
     }
});

//Bind a click handler to the close button you mentioned
$('.close-button').click(function(){

     //Close the window or popup here...
     //i.e. popup.close();

     //set the flag to false, which will allow all of the anchors to be clicked.
     buttonClicked = false;
});

If your close button is generated dynamically you will need to use live, delegate, or on, rather than the shorthand click function...

Mark Brown
  • 12,026
  • 8
  • 27
  • 32
  • Plese if you could explain your answer in more detail, design is my main strength, not jQuery and programming.Does this mean that when clicking on one of links nothing would happen, because that is the behavior i want. – fluxus Dec 02 '11 at 21:07
  • @suludi Sure. See my additional comments in my answer. – Mark Brown Dec 02 '11 at 21:47
  • Thanks Mark for your efforts.It is not window that opens, but a div container is being animated.I managed to do it myself, when clicking on one of the links, i am adding a class to the div.I am removing it with close button.So every link first checks if the div has a class applied, if it does it returns false, so nothing happens.If it doesn't my code runs.I will now try your solution, and if it is good i will mark your answer as correct.Thanks! – fluxus Dec 02 '11 at 22:14
  • Hi Mark, the problem is that all of my three links perform different actions when clicked(mainly animating,effects,etc.), and i just can't implement that into your solution.Thanks anyway, i'm ok now, given that i managed to solve it by adding class to the animated div. – fluxus Dec 02 '11 at 22:38
  • @suludi The process would be exactly the same. You would just check the flag in each of the click handlers. See update. – Mark Brown Dec 02 '11 at 22:48