How to close this menu clicking outside? - javascript

I have this menu:
CSS
#message {
display: none;
position: absolute;
width: 120px;
background: #fff;
color: #000;
font-weight: bold;
}
When I click in it opens #message.
My problem is to close this thing.
JS:
$(function() {
$("#subm").click(function(evt) {
$("#message").css({
top: 55,
left: evt.pageX - 55
}).show();
});
});
I try to put this code inside function above:
$('html').click(function(evt) {
if($('#message').is(":visible")) {
$('#message').hide();
}
});
but nothing is happening, apparently menu is opening and closing in the same time.
What is wrong? how can I close this menu clicking outside message box or even in span class?
JSFiddle

You can bind a click handler to the document to close it:
Example: https://jsfiddle.net/jmpf1usu/4/
$("#subm").click(function(evt) {
$("#message").css({
top: 55,
left: evt.pageX + 55
}).show();
evt.stopPropagation();
});
$(document).click(function(){
$("#message").hide();
});
evt.stopPropagation()is required so that the click never reaches the document, thus immediately triggering it to close again.

Try changing your js to this:
$("#subm").click(function() {
$("#message").show();
});
$("#message").mouseleave(function(){
$("#message").hide();
});
When the user hits the button the menu will open. When the user mouse leaves the div it will hide it. Is that what you're looking for?
If you really want a click to remove the visibility you can do:
$("body").on('click',function(){
$("#message").hide();
});
I just prefer the mouse leave, tbh.

You can use the below code for hide message
$(function() {
$("#subm").click(function(evt) {
$("#message").css({
top: 55,
left: evt.pageX + 55
}).show();
});
$(document).click(function(event) {
if (!$(event.target).is("#subm")) {
$("#message").hide();
}
});
});
#message {
display: none;
position: absolute;
width: 120px;
background: red;
color: #fff;
font-weight: bold;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<span id="subm">open</span>
<div id="message">
message
</div>

please try with below code snippet.
$(function() {
$("#subm").click(function(evt) {
evt.stopPropagation();
$("#message").css({
top: 55,
left: evt.pageX + 55
}).show();
});
$('html').click(function() {
$("#message").hide();
});
});
JSFiddle

Try this:
$(function () {
$("#message").click(function (evt) {
evt.stopPropagation();
});
$("#subm").click(function (evt) {
evt.stopPropagation();
$("#message").css({
top: 55,
left: evt.pageX + 55
}).toggle();
});
$('html').click(function (evt) {
if ($('#message').is(":visible")) {
$('#message').hide();
}
});
});
#message {
display: none;
position: absolute;
width: 120px;
background: red;
color: #fff;
font-weight: bold;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<span id="subm">open</span>
<div id="message">message</div>

You can simply use .hide to hide that element. Add an event listener for #message and do the following:
$("#message").click(function(evt) {
$("#message").hide();
});
I put a working example here:
https://jsfiddle.net/jmpf1usu/8/

To do it without stopPropagation() shenanigans you can add the following:
$(document).ready(function(){
$(document).click(function(event) {
if(event.target.id != "message"
&& event.target.id != "subm"
&& $('#message').is(':visible'))
{
$('#message').hide();
}
});
});
This is set up so that if the user clicks anything that is not the #message and is not the #subm open span, the message div will hide.
Expanded your fiddle: https://jsfiddle.net/jmpf1usu/10/
Good luck :).

Related

jQuery - multiple button clicks

My aim is for the users to click the button multiple times and on each click it changes the color and the wording on the button. I got the word and the color to change on the first and second click but it doesn't change when I click again. What am I doing wrong?
You can find my code below:
$(document).ready(function() {
$("button").click(function() {
$("#partyButton").text("Party Over!");
$(this).addClass("click").one("click", function() {
$("#partyButton").text("Party Time!");
$(this).removeClass();
});
});
});
button {
color: white;
font-family: 'Bungee';
background-color: #222;
border: none;
border-radius: 5px;
width: 25%;
padding: 20px;
cursor: pointer;
}
.click {
background-color: #0A8DAB;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button id="partyButton" type="button"> party time!</button>
You can achieve this By using toggleClass and check with .hasClass()
//button
$(document).ready(function (){
$("button").click(function (){
$(this).toggleClass("click").text($(this).hasClass('click') ? "Party Time":"Party Over!");
});
});
button{
color: white;
font-family: 'Bungee';
background-color:#222;
border: none;
border-radius: 5px;
width: 25%;
padding: 20px;
cursor: pointer;
}
.click{
background-color:#0A8DAB;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button id = "partyButton" type = "button"> party time!</button>
Code Explanation:
$(this).toggleClass("click") this will toggle between class on each click
$(this).hasClass('click') check if this element has a class it return true/false .. you can also use it like if($(this).hasClass('click')){}else{}
() ? : ; shorthand if statment
Also Take care when you use removeClass() without assign any class it will remove all the classes for this element
The problem is you are registering an one time click event for the button while the button is clicked for the first time, which will detach the event once clicked. This is the reason you are not getting the event further. It is unnecessary and confusing
You just need the below implementation
$("#partyButton").click(function(){
if($(this).hasClass('click'))//check whether it party time or not
{
$(this).text("Party Time!").toggleClass('click');
}
else
{
$(this).text("Party Over!").toggleClass('click');
}
})
https://jsfiddle.net/n5hdg7tv/
For example:
$(function() {
$('#partyButton').on('click', function () {
var $button = $(this);
if($button.hasClass('click')) {
$button.removeClass('click').text('Party Time !');
} else {
$button.addClass('click').text('Party Over !');
}
})
});

How to prevent continuous clicks on the element?

I want to prevent continuous clicks on the button .toggler. When I click on it div is toggling properly, but if I click on it continuously many times div toggles many times until all the click events have not been completed.
The expectation is that if I click the button, its click event should be off until the div has not been toggled properly. After that its click should be on.
Click the button continuously many times to see the issue.
$(document).ready(function() {
$('.toggler').on('click', function(event) {
event.preventDefault();
$('.main-div').slideToggle('slow');
});
});
* {
margin: 0px;
box-sizing: border-box;
}
.main-div {
width: 80%;
float: right;
height: 200px;
background: #ddd;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button type="button" class="toggler">Toggle</button>
<div class="main-div"></div>
The jQuery code I have tried is:
$(document).ready(function() {
$('.toggler').on('click', function(event) {
event.preventDefault();
var thisEement = $(this);
thisEement.off('click');
$('.main-div').slideToggle('slow', function(){
thisEement.on('click');
});
});
});
But that does not work as expected.
Any help would be appreciated <3.
The slideToggle has a callback function which is invoked when the operation is completed. So, you can introduce a new boolean variable that will be set to false when the operation starts and changed back to true when the toggle is completed.
$(document).ready(function() {
var flag = false;
$('.toggler').on('click', function(event) {
event.preventDefault();
if(!flag){
flag = true;
$('.main-div').slideToggle( "slow", function() {
flag = false;
});
}
});
});
* {margin: 0px; box-sizing: border-box;}
.main-div {width: 80%; float: right; height: 200px; background: #ddd;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button type="button" class="toggler">Toggle</button>
<div class="main-div"></div>
Try this,
$(document).ready(function() {
$('.toggler').on('click', function(event) {
event.preventDefault
$(".toggler").prop('disabled', true); // disable first
$('.main-div').slideToggle("slow", function() { // when slidetoggle ends
$(".toggler").prop('disabled', false); // enable button again.
});
});
});
jsfiddle demo
Hope helps,
Just use a boolean that will toggle when the slide starts and stops.
var inMotion = false;
$('.toggler').on('click', function(event) {
event.preventDefault();
if (inMotion == false) {
inMotion = true;
$('.main-div').slideToggle('slow', function() {
inMotion = false;
});
}
});
When the slideToggle() function finishes, that callback will run. The callback will set the boolean to false, allowing it to fire again.
Add the disabled attribute on click then remove it once the animation completes.
$(document).ready(function() {
$('.toggler').on('click', function(event) {
$(this).attr('disabled', 'disabled');
event.preventDefault();
$('.main-div').slideToggle('slow', function(){
$('.toggler').removeAttr('disabled');
});
});
});
* {margin: 0px; box-sizing: border-box;}
.main-div {width: 80%; float: right; height: 200px; background: #ddd;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button type="button" class="toggler">Toggle</button>
<div class="main-div"></div>
You can simply filter out the element while it's being animated and thus never queue up multiple toggles on it:
$('.main-div').not(':animated').slideToggle('slow');
No point in keeping track of this state yourself in some boolean when jQuery does it for you and lets you write functionally!
Full code (your original example modified):
$(document).ready(function() {
$('.toggler').on('click', function(event) {
event.preventDefault();
$('.main-div').not(':animated').slideToggle('slow');
});
});
FYI, your attempt would've worked if you properly re-bound the event handler function, but this is a much cleaner solution.
You can try this way...
$(document).ready(function() {
$('.toggler').on('click', function(event) {
$("#togglerButton").attr("disabled", "true");
$('.main-div').slideToggle('slow', function() {
$("#togglerButton").removeAttr("disabled");
});
});
});
* {
margin: 0px;
box-sizing: border-box;
}
.main-div {
width: 80%;
float: right;
height: 200px;
background: #ddd;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button type="button" class="toggler" id="togglerButton">Toggle</button>
<div class="main-div"></div>
You can also do this by using event object pass to the click event. you can get count for number of time the click event performed. based on which you can set condition in javascript code and prevent multiple clicks like code given below.
$(document).ready(function() {
$('.toggler').on('click', function(event) {
if (!event.originalEvent.detail || event.originalEvent.detail == 1) {
$('.main-div').slideToggle('slow');
}
});
});
$(document).ready(function() {
var res = false;
$('.toggler').on('click', function(event) {
event.preventDefault();
if(!res){
res = true;
$('.main-div').slideToggle( "slow", function() {
res = false;
});
}
});
});
* {margin: 0px; box-sizing: border-box;}
.main-div {width: 80%; float: right; height: 200px; background: #ddd;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button type="button" class="toggler">Toggle</button>
<div class="main-div"></div>

Is it possible to list multiple ID's in a function, that will not trigger a .hide function?

Got a problem with my slide in menu. Check the my JSfiddle here.
At the moment the slide-in menu closes, whenever clicked on everything else than the menu itself. The problem is, that the menu closes, when i click the text. I would like to perhaps list more ID's inside the same function, something like this;
if(isOpened && e.target.id!='slide-in,text')
My script:
var isOpened = false;
$(document).click(function(e) {
if(isOpened && e.target.id!='slide-in') {
$("#slide-in").removeClass("active");
isOpened = false;
$("#button").show();
} else if(!isOpened && e.target.id=='button'){
$("#slide-in").addClass("active");
isOpened = true;
$("#button").hide;
}
});
Thank you!
You can use an array and indexOf
['slide-in', 'text'].indexOf(e.target.id) === -1
Might I suggest that you add a class to the elements you don't want it to apply to?
!$(this).is('.someClass')
instead of checking for all the ids, check for existence of parent with id as slide-in
if(isOpened && e.target.id!='slide-in') {
if(!$(e.target).parents('#slide-in').length) {
$("#slide-in").removeClass("active");
isOpened = false;
$("#button").show();
}
}
check this fiddle
#slide-in {
position: fixed;
z-index: 10;
top: 0;
width: 300px;
height: 100%;
background-color: #eee;
border-right: 10px solid #ccc;
display:none;
}
and add this inside the .js
$(document).ready(function(){
$("#button").click(function(){
$("#slide-in").show(300);
})
$("#slide-in").click(function(){
$(this).hide(300);
});
});
and if you want more real use this.
in your css change this class like this
#slide-in {
position: fixed;
z-index: 10;
top: 0;
width: 0px;
height: 100%;
background-color: #eee;
border-right: 10px solid #ccc;
display:none;
}
for your js
$(document).ready(function(){
$("#button").click(function(){
$("#slide-in").animate({width: "300px"});
});
$("#slide-in").click(function(){
$(this).animate({width: "0px"});
});
});

Alternate z-index between 2 divs on click?

I'm not great with JS so been using trial and error to try and figure out how to get 2 divs to swap z-index on the click of a trigger (button).
I currently have 2 drawers that technically are on top of each other and slide out from the right. On click of 'Buy' the #QuickShopDrawer should open and on click of 'Cart' or 'Add to Cart' the #CartDrawer should open.
Link to my test store.
My code so far is making the open with the #CartDrawer on top with a higher z-index.
JS:
Drawer.prototype.init = function () {
$(this.config.open).on('click', $.proxy(this.open, this));
$('.js-drawer-open-right-two').click(function(){
$(this).data('clicked', true);
});
if($('.js-drawer-open-right-two').data('clicked')) {
//clicked element, do-some-stuff
$('#QuickShopDrawer').css('z-index', '999');
} else {
//run function 2
$('#CartDrawer').css('z-index', '999');
}
this.$drawer.find(this.config.close).on('click', $.proxy(this.close, this));
};
I've tried this which is more of what I want but it's only firing once?
$('.js-drawer-open-right-two').click(function() {
var i = $(this).index();
$('.drawer--right').hide();
$('.drawer--right-two' + (i+1)).show();
});
Any help would be greatly appreciated!
You need to swap the z-index of the elements on button click. Also, you can disable the button on click so that user cannot click it continiously.
Demo
$(document).ready(function() {
$('#buy').on('click', function(e) {
var myZindex = $('#QuickShopDrawer').css('z-index');
$('#QuickShopDrawer').css('z-index', $('#CartDrawer').css('z-index'));
$('#CartDrawer').css('z-index', myZindex);
$(this).prop('disabled', true).siblings('button').prop('disabled', false);
});
$('#addToCart').on('click', function(e) {
var myZindex = $('#CartDrawer').css('z-index');
$('#CartDrawer').css('z-index', $('#QuickShopDrawer').css('z-index'));
$('#QuickShopDrawer').css('z-index', myZindex);
$(this).prop('disabled', true).siblings('button').prop('disabled', false);
});
});
button {
position: absolute;
top: 150px;
left: 0;
clear: both;
}
#addToCart {
margin-left: 50px;
}
.red {
position: absolute;
width: 100px;
height: 100px;
background-color: red;
left: 20px;
top: 20px;
z-index: 1;
}
.green {
position: absolute;
width: 100px;
height: 100px;
background-color: green;
z-index: 2;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.0/jquery.min.js"></script>
<div>
<div id="QuickShopDrawer" class="red">fdsafdsafdsa</div>
<div id="CartDrawer" class="green">fdsafdsafdsa</div>
</div>
<button id="buy">Buy</button>
<button id="addToCart">Add To Cart</button>

Javascript "mouseover" and "mouseout" events

Consider the following code:
HTML:
<div class='a'></div>
<div class='b'></div>
CSS:
body {
position: relative;
}
.a {
position: absolute;
left: 100px;
top: 100px;
width: 100px;
height: 100px;
background: #777;
}
.b {
position: absolute;
display: none;
background: red;
}
JavaScript:
$(function() {
$('.a').live('mouseover mouseout', function(e) {
switch (e.type) {
case 'mouseover': {
$('.b').offset({'left': $(this).offset().left,
'top': $(this).offset().top})
.width($(this).outerWidth())
.height($(this).outerHeight())
.show();
break;
}
case 'mouseout': {
$('.b').hide();
break;
}
}
});
});
As you can see here, some kind of flickering occurs, because when .b is shown, mouseout automatically occurs. How would you solve this problem ?
The desired behavior is: when the mouse is over .a, .b should be shown (should cover .a), and when the mouse is not over .a, .b should not be shown. .a should always be shown.
The position and dimensions of .a is not constant (should be calculated on the fly).
I come up with this solution:
$(function() {
$('.a').live('mouseover', function(e) {
$('.b').offset({'left': $(this).offset().left,
'top': $(this).offset().top})
.width($(this).outerWidth())
.height($(this).outerHeight())
.show();
});
$('.b').live('mouseout', function(e) {
$(this).hide();
});
});
Try
$(function() {
$('.a').live('mouseover', function(e) {
$('.b').offset({'left': $(this).offset().left,
'top': $(this).offset().top})
.width($(this).outerWidth())
.height($(this).outerHeight())
.show();
});
$('.b').live('mouseout', function(e) {
$('.b').hide();
break;
});
});
This should mean that when the user moves thier mouse over area a, area b is shown and then when they move thier mouse out of area b, area a is reshown.

Categories