1

I have a Jquery for loop that is activated when I click an element with the same class apart from itself though it doesn't do anything.

Here is the loop:

$('.container').click(function(){
    for(i = 1; i != 20; i++) {
        $('.container' + i + ' h1 a').click(function(){
            $('.container:not(.container' + i +')').hide();
        });
    }
});

HTML:

<div class='container container1'>
    <div class='content'>
        <h1><a href='#'>Title</a></h1>
        <p>Content</p>
    </div>
</div>
<div class='container container2'>
    <div class='content'>
                <h1><a href='#'>Title</a></h1>
        <p>Content</p>
    </div>
</div>
<div class='container container3'>
    <div class='content'>
                <h1><a href='#'>Title</a></h1>
        <p>Content</p>
    </div>
</div>

I have looked around and have found that the problem is that you can't run a function inside a for loop.

I know that I could do it with exstensive code but I think as more containers will be added that it would be easier to do it this way.

Thanks in advance

3 Answers3

5

I want to hide them all other than the one that was clicked

I believe what you want is something like this:

var $container = $('.container').click(function(){
    $container.not(this).hide();
});

DEMO

This will hide all other containers if a container is clicked. Have a look at the jQuery API documentation to learn more about .not.


There are a couple of issues with your existing code:

  • You are creating a function inside a loop. Due to how closures are implemented in JavaScript, this can lead to unexpected behavior if you are trying to access loo variables inside the function (which you do). Please see JavaScript closure inside loops – simple practical example

  • You are binding new click event handler to all other .container elements whenever you click any of them of them. I.e. after you clicked three elements, every container will have 3 additional event handlers attached to it and each of them does the same.

Community
  • 1
  • 1
Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
  • This is a much cleaner solution and actually solves the OP's problem. Deleting mine. – Vivin Paliath Jul 12 '13 at 21:35
  • I meant that when you click ed the link the function was run –  Jul 12 '13 at 21:38
  • Anyway that hides the p tags not the container –  Jul 12 '13 at 21:39
  • @user2568107: I assumed you wanted some kind of accordion (since you didn't explain much about what you are trying to do). If you want to hide the other containers completely, how are you going to show them again? If you want to do that, just remove the `.find('.content > p')` part. – Felix Kling Jul 12 '13 at 21:41
  • I am going to have another button at the top that shows them and I know how to do that –  Jul 12 '13 at 21:42
  • @user2568107: Well ok then, updated my answer. – Felix Kling Jul 12 '13 at 21:43
1

You're making this way too complicated.

If you want to hide all other containers when you click one, you could just do this:

$(function () {
    $('.container').click(function () {
        $('.container').not(this).hide();
   });
});

Here's a fiddle with a working example...

If you want to make it so the <p> tags must get clicked, you can do it like this:

$(function () {
    $('p').click(function () {
        $('.container').not($(this).parents()).hide();
    });
});

Another fiddle

jahroy
  • 22,322
  • 9
  • 59
  • 108
  • I would use this solution instead of mine if you're trying to allow for hiding of the divs when the entire div is clicked. My solution is valid when you want only the title link to hide the divs and not the other content in the div. – SirTophamHatt Jul 12 '13 at 22:18
  • I could change about 8 characters and have mine do the same thing... Just change the first selector. – jahroy Jul 12 '13 at 22:20
  • so change the first selector to specify the anchor tag, hide all divs, then show the parent div.container of the anchor? – SirTophamHatt Jul 12 '13 at 22:24
0

You'd need to pass the reference to i as a parameter to the inner function such that the i is now local to the function. It appears that you're binding multiple events based on a click to the outer divs which is then binding multiple click events to the div's inner anchor tag to hide all divs which aren't a parent of the anchor tag.

Here is my solution:

HTML

 <div id="wrapper">
    <div class='container container1'>
        <div class='content'>
            <h1><a href='#'>Title</a></h1>
            <p>Content</p>
        </div>
    </div>
    <div class='container container2'>
        <div class='content'>
            <h1><a href='#'>Title</a></h1>
            <p>Content</p>
        </div>
    </div>
    <div class='container container3'>
        <div class='content'>
            <h1><a href='#'>Title</a></h1>
            <p>Content</p>
        </div>
    </div>
</div>

JavaScript

var $context = $('#wrapper'),
    $containers = $('#wrapper').find('div.container');

$context.on('click', '.container a', function() {
    var $theAnchorClicked = $(this),
        parentClassofAnchor = $this.parent().parent().parent().prop('class'); 

   $containers.each(function() {
       $theCurrentContainer = $(this);
       if (!$(this).hasClass(parentClass)) $(this).hide();
    });
});

First, I wrapped the all 'container' divs in a wrapper div ('#wrapper') which is used as a context for finding the containers. This is simply because finding an element by an id, tag, or within a context is much faster than finding by class name. Always.

I saved a reference to the wrapper ($context) and then from $context found all the divs with the class 'container' and also saved a reference to that.

Second, instead of binding a click function to each link, I'm delegating a click event to the $context when a link inside the context is clicked (1 event bound instead of 20). I'm also using jQuery's .on() method as it is recommended for jQuery 1.7+.

So what's going on in the click event being delegated to $context? The .on() method is specifying a 'click' event on an element matching '.container a' and then the function to perform. In the function, this is a reference to the link being clicked.

The link being clicked is saved, as well as the class(es) of the parent div.container, e.g. '.container .container1'. You'll notice there are several parents being traversed to find it since the link is nested in several other elements.

Now that these are saved, I'm using jQuery's .each() method to traverse through all the containers we saved in $containers. We need to check for all the containers that don't have the class we found (parentClassofAnchor) and hide those. In the .each() function, this is not a reference to the link, it is now a reference to the current div.container in the loop ($theCurrentContianer). Then we use a simple if statement to check if it doesn't have the class we want to show, in which case we hide that div.

I hope this helps! Please let me know if you were looking to do more with your click events.

SirTophamHatt
  • 1,581
  • 17
  • 23