0

How is it possible to close a div that's currently open when you click on its trigger that usely opens the div or any other trigger (that opens a different event on the page)?

So basicaly I have two links: Login and Register. When you click Register, the Login block/div disappears and the Register div shows up. When I hit Login, the Register div hides and the Login div shows up.

Also when I, e.g. click Login and the Login div is already shown - the Login div must hide aswell.

How do I accomplish this? I tried for days now, but unfortunately i'm a beginner to jQuery and my skills in jQuery aren't great at the moment. I made the following script that works. I only can hide/show divs when you click the same trigger. If you click Register AND Login the divs will just show up on top of eachother, without the hiding.

;(function($) {
var $jq = jQuery.noConflict();
$jq.fn.login_switch = function(options) {
    var o = $jq.extend({}, $jq.fn.login_switch.defaults, options);
    var $this = $jq(this);

  $jq(this).click(function(e) 
  {  
      e.preventDefault(); 
    // hides matched elements if shown, shows if hidden 
    $jq(this).closest("div#wrapper").children("div#member_login").eq(0)[o.method](o.speed);

  });

};
$jq.fn.reg_switch = function(options) {
    var o = $jq.extend({}, $jq.fn.reg_switch.defaults, options);
    var $this = $jq(this);

  $jq(this).click(function(e) 
  {  
      e.preventDefault(); 
    // hides matched elements if shown, shows if hidden 
    $jq(this).closest("div#wrapper").children("div#member_reg").eq(0)[o.method](o.speed);
  });

};
$jq.fn.login_switch.defaults = {
    speed : "slow",
    method: "slideFadeToggle"
};
$jq("a.log-expand").login_switch();

$jq.fn.reg_switch.defaults = {
    speed : "slow",
    method: "slideFadeToggle"
};
$jq("a.reg-expand").reg_switch();


var msie = false;
if(typeof window.attachEvent != 'undefined') { msie = true; }

$jq.fn.slideFadeToggle = function(speed, easing, callback) {
    return this.animate({opacity: 'toggle', height: 'toggle'}, speed, easing, function() { 
    if (msie) { this.style.removeAttribute('filter'); }
    if (jQuery.isFunction(callback)) { callback(); }
  }); 
};

};
})(jQuery);

My html is:

    <div id="member_reg" style="display:none;">
        <div class="container">
            <div class="sixteen columns">
            REGISTRATION.
            </div>
        </div>
    </div>
    <div id="member_login" style="display:none;">
        <div class="container">
            <div class="sixteen columns">
                LOGIN.
            </div>
        </div>
    </div>

with the trigger buttons:

<ul class="user">
<li><a href="javascript:void(0);" class="reg-expand register">Register</a></li>
<li><a href="javascript:void(0);" class="log-expand login">Login</a></li>
</ul>
Kallewallex
  • 523
  • 1
  • 6
  • 24
nerdrocker
  • 81
  • 1
  • 11

1 Answers1

1

Here I have created a FIDDLE for you with the behavior I think you are trying to achieve.

Let me know if you have any questions or if I'm way off base.

HTML

<button id="btnLogin" data-bound="login">Login</button><button id="btnRegister" data-bound="register">Register</button>

<hr />

<div id="login" class="area" data-state="closed">
    Login div
</div>

<div id="register" class="area" data-state="closed">
    Register div
</div>

CSS

.area{
    float:left;
    width:200px;
    height:0;
    margin:10px;
    overflow:hidden;
    text-align:center;
    line-height:100px;
}
#login{
    background:#41cc36;
}
#register{
    background:#3764e3;
}

JAVASCRIPT

$(document).ready(function(){
    $('button').bind('click', function(){
        //close any open areas
        $('.area').each(function(){
            if($(this).data('state') == 'open'){
                $(this).animate({'height': 0}, 750, function(){
                    $(this).data('state', 'closed');
                });
            }
        });
        //retrieve the div we need to toggle and it's state
        var divID = $(this).data('bound'),
            div = $('#' + divID),
            state = div.data('state');
        //animate the div based on it's state, then set the new state
        if(state == 'closed'){
            div.animate({'height': 100}, 750, function(){
                div.data('state', 'open');
            });            
        }else{
            div.animate({'height': 0}, 750, function(){
                div.data('state', 'closed');
            });
        }
    });

    //init
    $('#btnLogin').trigger('click');
});
zgood
  • 12,181
  • 2
  • 25
  • 26
  • Thank you so much for your answer, this is exactly what I tried to achieve. First thing I noticed is that your approach is much different than mine. Why's that if I may ask? Why not try to make it with jQuery's toggle()? Also I never have tried data-bound and data-state before in HTML. Is it HTML5? Btw, all the containers are now closed after a page load. How to show i.e. #login as a default container being open already? – nerdrocker Jan 14 '14 at 17:08
  • Well there really is no right or wrong way, just a ton of different ways to code the same thing lol. In your approach you are creating a like a plugin for jQuery using `fn` which is like `prototype`... see [here](http://stackoverflow.com/questions/4083351/what-does-jquery-fn-mean). Whereas I am just directly attaching click events to your buttons on page load. Your approach is longer, but makes the code re-useable on different pages. You could even combine both and make jQuery plugin using my code approach. The best approach usually depends on the project and what you're comfortable with. – zgood Jan 14 '14 at 18:17
  • You could use `toggle()` if you wanted to fade the div in and out, but I am animating heights (just because I like how it looks) so `toggle()` would not work for me. – zgood Jan 14 '14 at 18:20
  • `data` is a [jQuery](http://api.jquery.com/data/) thing and an [HTML5](http://ejohn.org/blog/html-5-data-attributes/) thing working together. Basically you can create any custom attribute in HTML (like data-myproperty or data-foo) and then access that value via jQuery like this: `$('#someDiv').data('foo');` or set the value: `$('#someDiv').data('foo', 'new value');`. You could also use global javascript variables to store values if you want, I just think this `data` approach is cleaner. – zgood Jan 14 '14 at 18:26
  • I have updated this answer to include an initial `btnLogin` click so that your Login div will be open when the page first loads. – zgood Jan 14 '14 at 18:30
  • Once again, thank you for your time and great explanations. I will play a bit more with it and start reading about it. :) Cheers – nerdrocker Jan 14 '14 at 19:40