0

There is a menu button on the left of my site in progress.

This is the Javascript code which opens the menu:

var main = function()
$('.icon-menu').click(function() {
    $('.menu').animate({
        left: "0px"
    }, 400);
    $('body').animate({
        left: "285px"
    }, 400);
});

And this is the Javascript code which closes the menu:

$('.icon-close').click(function () {
    $('.menu').animate({
        left: "-285px"
    }, 400);
    $('body').animate({
        left: "0px"
    }, 400);
});

What I would like to be able to do is, instead of using a "close" icon, I would like for a click anywhere on the page (including the original menu button) to close the menu.

As the code is currently written, when the menu is opened/closed, it slides in from the left, and the main body of the page slides to the right the same amount of pixels, and vice-versa when closed.

EDIT:

Here's the skeleton of the HTML as requested:

<div class="menu">
    <div class="icon-close">
        <img src="close.png">
    </div>
    <ul>
        <li><a href="home.html">Home</a>
        </li>
        <li><a href="home.html">Gallery</a>
        </li>
        <li><a href="home.html">Locations</a>
        </li>
        <li><a href="home.html">Contact Us</a>
        </li>
    </ul>
</div>
<div class="jumbotron">
    <div class="icon-menu">
        <i class="fa fa-bars"></i>Menu
    </div>
</div>
dda
  • 6,030
  • 2
  • 25
  • 34
  • Please add a JSfiddle and/or your HTML to the question. And This might help. http://stackoverflow.com/q/8800515/3639582 – Shaunak D May 02 '15 at 03:36

2 Answers2

1

You can capture a document.onclick event then check the event target id against a set of allowed id's Note that to do this you have to add id attributes to the close button and the "body". I've also taken the liberty of adding an id to the menu and a wrapper around the "body" of the document and changed your body tag animation to that wrapper, as you shouldnt move the body tag directly. Note that to resize the body on menu open just change the body position: absolute and set right: 0px;

(Demo keep body size on menu open)

(Demo resize body to keep within viewport on menu open)

$(document).on('click', function(e) {
  if ($("#menu").position().left != '0') {
    if (e.target.id === "open") {
      $('#menu').animate({
        left: "0px"
      }, 400);
      $('#body').animate({
        left: "285px"
      }, 400);
    }
  } else {
    if (e.target.id === "body" || e.target.id === "close" || e.target.id === "open") {
      $('#menu').animate({
        left: "-285px"
      }, 400);
      $('#body').animate({
        left: "0px"
      }, 400);
    }
  }
});
html, body, #menu, #body {
  height: 100%;
}
.menu {
  position: absolute;
  width: 285px;
  left: -285px;
}
#body {
  position: relative;
  left: 0px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="menu" id="menu">
  <div class="icon-close">
    <img src="close.png" id="close">
  </div>
  <ul>
    <li><a href="#">Home</a>
    </li>
    <li><a href="#">Gallery</a>
    </li>
    <li><a href="#">Locations</a>
    </li>
    <li><a href="#">Contact Us</a>
    </li>
  </ul>
</div>
<div id="body">
  <div class="jumbotron">
    <div class="icon-menu" id="open">
      <i class="fa fa-bars" id="open"></i>Menu
    </div>
  </div>
</div>

Pure JS and CSS

The following is a pure javascript and css method for achieving the same effect. I'm including this for reference as it is a lot lighter weight than including jquery, however if you have jquery included already there is no reason to not use the jquery methods. Notice that on older browsers that do not support css transitions the menu will still open but will not be animated (which is a good thing for older browsers as javascript animations can slow things down quite a bit)

(Demo keep body size on menu open)

(Demo resize body to keep within viewport on menu open)

var menu = document.getElementById("menu");
var body = document.getElementById("body");
menu.style.transition = "0.3s linear";
body.style.transition = "0.3s linear";
document.onclick = function(e) {
  if (menu.style.left != "0px") {
    if (e.target.id === "open") {
      menu.style.left = "0px";
      body.style.left = "285px";
    }
  } else {
    if (e.target.id === "body" || e.target.id === "close" || e.target.id === "open") {
      menu.style.left = "-285px";
      body.style.left = "0px";
    }
  }
};
html, body, #menu, #body {
  height: 100%;
}
.menu {
  position: absolute;
  width: 285px;
  left: -285px;
}
#body {
  position: relative;
  left: 0px;
}
<div class="menu" id="menu">
  <div class="icon-close">
    <img src="close.png" id="close">
  </div>
  <ul>
    <li><a href="#">Home</a>
    </li>
    <li><a href="#">Gallery</a>
    </li>
    <li><a href="#">Locations</a>
    </li>
    <li><a href="#">Contact Us</a>
    </li>
  </ul>
</div>
<div id="body">
  <div class="jumbotron">
    <div class="icon-menu" id="open">
      <i class="fa fa-bars" id="open"></i>Menu
    </div>
  </div>
</div>
  • Hey, just want to thank you for your comments. I know I needed a bit of more logic, to be honest, I rushed into answering. I shouldn't have posted an incomplete answer, and your comments were very helpful; really appreciate the fact that you even commented! I'm afraid this might be flagged as an unhelpful comment, so I'll try to add something helpful: your script is great, but perhaps you could add some filtering so that when you click on the menu, only the close button closes it? I think that's the intended functionality. Correct me if I'm wrong, though (as you have done! haha). –  May 02 '15 at 06:14
  • I in fact did not want the close button to be the only thing to close the menu, this was exactly what I was looking for, Thanks @humble.rumble.6x3! – Phoenix Aero May 02 '15 at 13:54
  • @humble.rumble.6x3 Glad my way of thinking helped you! Also, if you read my last comment, after I tested BOTH methods, you were both technically right in regards to what I wanted. You both just focused on two different sides and I kind of needed a hybrid. – Phoenix Aero May 02 '15 at 16:16
  • In my example you can do `$('.menu, body').animate` If you really want to animate the whole body (and you have to set body's position to `relative`), just pointing that out, but I think it's a better idea to have your main contents in a big div beside the menu. Either way, this definitely deserves to be the answer. One thing, though, I agree that CSS anims are really cool, but browser support isn't that great yet, and you have to make sure to include the vendor prefixes. –  May 02 '15 at 18:55
0

Here's humble's version of the snippet below:

http://jsfiddle.net/humbleRumble/3j7s9ggz/

You can just bind a click event to the document that does the same thing as the click on the close button:

$(document).on('click', function (e) {
    // Filter some elements out so that this function doesn't
    // execute when it's not intended to.
    var target = e.target,
        isMenuElem = $(target).parents('.menu').length || $(target).is('.menu'),
        isMenuClose = $('.icon-close').has(target).length,
        isIconMenu = $(target).is('.icon-menu');
    // Simply return if the clicked element falls under the filter.
    // This allows the close button to close,
    // the menu to not close itself if you click its body,
    // the function to not interfere with the menu button functionality,
    // and that a click on anywhere will close the menu.
    if (isMenuElem && !isMenuClose || isIconMenu) return;
    $('.menu, #jumbotron').animate({
        left: "-285px"
    }, 400);
});

$('.icon-menu').click(function () {
    // This is a 'toggle' value for left,
    // if the menu is opened (left: 0), close it (left: -285)
    // and vice-versa.
    var toggleAnim = $('.menu').css('left') === '-285px' ? 0 : '-285px';
    $('.menu, #jumbotron').animate({
        // Apply the toggle
        left: toggleAnim
    }, 400);
});
html, body {
    padding: 0;
    margin: 0;
}
#jumbotron {
    position: relative;
    height: 500px;
    width: 300px;
    float: left;
}
.menu {
    position: relative;
    width: 285px;
    height: 500px;
    background: red;
    float: left;
}
.icon-menu {
    background: black;
    color: #fff;
    cursor: pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="menu">
    <div class="icon-close">
        <img src="close.png" alt="Close Me">
    </div>
    <ul>
        <li><a href="home.html">Home</a>
        </li>
        <li><a href="home.html">Gallery</a>
        </li>
        <li><a href="home.html">Locations</a>
        </li>
        <li><a href="home.html">Contact Us</a>
        </li>
    </ul>
</div>
<div class="jumbotron" id="jumbotron">
    <div class="icon-menu">
        <i class="fa fa-bars"></i>Menu
    </div>
</div>

This will trigger with a click anywhere on the page, but not on the elements inside of the menu (except the close button).

  • Thanks. It seems to glitch out if you click the menu button too fast, though. Will include it in my post either way. –  May 03 '15 at 16:47