I have a div that slides down (opens) when I click a certain input select. Inside this div, I have some other input selects and my objective is to slide up the div when I click on the rest of the page.
My problem:
The div slides up when I select some item in the input selects inside it, and I don't want this to happen.
Is there some way to slide up the div only when I click outside it?
Why are the selects inside the div making it to slide up as well?
This is my javascript to slide up the div:
$(document).mouseup(function (e) {
var container = $('.myDiv');
if (container.has(e.target).length === 0) {
$(container).removeClass('close');
$(container).addClass('open');
$(container).next().slideUp(200);
}
});
The div slides up when I select some item in the input selects inside
it, and I don't want this to happen.
Is there some way to slide up the div only when I click outside it?
Why are the selects inside the div making it to slide up as well?
Use event.stopPropagation() on the child element(s) to prevent the slide event being triggered by them.
event.stopPropagation - Prevents the event from bubbling up the DOM
tree, preventing any parent handlers from being notified of the event.
Here's a simple jsFiddle and the basic example below.
jQuery:
$('div').click(function(){
$('#slideMeUp').slideUp();
});
$('select').click(function(e){
e.stopPropagation();
});
HTML:
<div>Clicking here will trigger it!
<select>
<option>This won't trigger the click event anymore!</option>
</select>
Clicking here will also trigger it!
</div>
<div id="slideMeUp">Only clicking the outer div will slide me up!</div>
you can check you e.target.id with your container id
$(document).mouseup(function (e) {
var container = $('.myDiv');
if(e.target.id==$(this).attr('id'))
{
if (container.has(e.target).length === 0) {
$(container).removeClass('close');
$(container).addClass('open');
$(container).next().slideUp(200);
}
}
});
If it's specific items that are causing problems, perhaps something like this?
On click tell it to to slideUp your div as long as the clicked item is "not" in the list.
('body').click(function(event) {
if (!$(event.target).is('#id_of_item .class_to_ignore')) {
var container = $('.myDiv');
$(container).removeClass('close');
$(container).addClass('open');
$(container).next().slideUp(200);
}
});
I'd suggest binding mousedown rather than mouseup. There are inconsistencies in behaviour between browsers, this may have something to do with your issue.
You should also add some logic to check the clicked element isn't the div itself, clicking just outside of an input, but still inside of the div would currently cause the slideUp to occur.
if (!container.has(e.target).length && !container.is(e.target)) {
...
}
Other than that, it should work fine.
Have a fiddle
Related
Hello I made drawer which appears when you click on it and then expands it's width, after second click, it back to it's minimalized form, inside this drawer I have table with checkboxes etc which I will use later to filter things. Thing is that if I click on checkbox inside the table, drawer is hiding. How to do it that event which allow for toggling of width of drawer would work only if I click on it except place where is table? As far as I know it should do something with stopPropagation but somehow I was unabled to implement it in working form.
<div class="filter_drawer" onclick="show_stat()">
<Table class="stat_table">
...some content
</Table>
</div>
function show_stat() {
event.stopPropagation()
var stats = document.querySelector('.filter_drawer')
var table = stats.querySelector('.stat_table')
var panels = document.querySelector('.main_container')
stats.classList.toggle('expanded_stat')
table.classList.toggle('show')
panels.classList.toggle('expanded_stat_panel')
}
Attach the listener to the element properly using Javascript instead, and then you can check if the event.target is the .filter_drawer element. If so, then it was a click directly on the element, and not one of its descendants:
document.querySelector('.filter_drawer').addEventListener('click', (e) => {
if (e.target.matches('.filter_drawer')) {
showStat();
}
});
(If the click was on a descendant element, and not the filter_drawer itself, then the e.target test won't match)
No need for stopPropagation.
I'm developing a web page using jQuery. In this web page, there is a div tag that contains a p and a button tag.
The HTML code is like this:
<div class="container">
<div id="attribute" style="border:solid;border-width:2px;border-color:#ccc">
<p id="cell-content" style="display:inline">Id</p>
<button id="remark-view" class="btn btn-primary">Detail</button>
</div>
</div>
and the corresponding JavaScript code is like this:
$(document).ready(function(){
$("#attribute").on('click', function(){
console.log("click on the div attribute");
});
$("#attribute").on('dblclick', function(){
console.log("double click on the div attribute");
});
$("#remark-view").on('click', function(){
console.log("click on the button remark-view");
});
});
As the code shows, a outer div has a p and button child element, and the outer div element listens on the single click and double click event while the inner button element listens on the single click event.
When I run the code in my browser and click on the button, the console shows that both click functions of the outer div and inner button element are called, which is against my purpose: only the click function of inner button should be called at this situation. Thus, is there any way to block the click event for the father element(in this case, outer div element).In other words, is there any way to stop passing the click event to the father element after the child element has handled it?
Thank you in advance!
stopPropagation function will stop the event from bubbling up the DOM.
$("#remark-view").on('click', function(event){
console.log("click on the button remark-view");
event.stopPropagation()
});
From the jQuery documentation
Prevents the event from bubbling up the DOM tree, preventing any
parent handlers from being notified of the event.
This is something I use in one of my sites to do something similar to your problem. What the below code does is it prevents the middle div from closing if the button click is on that div.
//Function for the pop up with the background dimmer
$(document).mouseup(function(x) {
var container = $("#divContent"),
dimmer = $('#bgDimmer');
if (container.is(":visible")) {
if (!container.is(x.target) //check if the target of the click isn't the container...
&& container.has(x.target).length === 0) {
container.hide();
dimmer.hide();
}
}
});
Let try to relate to your code.
//Function for the pop up with the background dimmer
$(document).mouseup(function(x) {
var attribute = $('#attribute');
if (attribute.is(":visible")) {
if (!attribute.is(x.target) //check if the target of the click isn't the container...
&& attribute.has(x.target).length === 0) {
console.log("click on the button remark-view");
}
}
});
I have a accordion menu which have for each parent menu a icon, and this icon is animated with css transition and transform. I added a class with a if condition to the click event. The problem is that when I click for example on Menu1, the icon animation does very well, but if I click directly on Menu2, the menu2 dropdown appear but icon from the menu1 don't take his original position.
This problem applies to each icon in each menu/submenu, I thinks that I have a mistake in my code.
$(document).ready(function() {
// Icons effect
$('#mw_nav .toggle').click(function() {
if($(this).hasClass('rotate_close'))
{
$(this).addClass('rotate_open').removeClass('rotate_close');
}
else {
$(this).addClass('rotate_close').removeClass('rotate_open');
}
});
// Toggle Menu Items
$(function () {
$("#m_nav > ul ul").hide();
$('#m_nav .toggle').click(function (e) {
e.preventDefault();
e.stopPropagation();
var $parentli = $(this).closest('li');
$parentli.siblings('li').find('ul:visible').slideToggle(400);
$parentli.find('> ul').stop().slideToggle(400);
$(this).remove;
});
});
});
FIDDLE
Any help would be appreciated
There are 2 issues I see with your code. The first is a recommendation to NOT have $(function() { // your code }) inside of $(document).ready(). $(function() {}) is actually just shorthand for $(document).ready() so you are adding code you do not need.
The second is an issue with your logic.
$('#mw_nav .toggle') and $('#m_nav .toggle') click listeners are essentially adding a click listener on the same exact element, but both run different logic. When the $('#mw_nav .toggle') click listener is getting called it checks for a class to exist to decide what class it needs to remove and add. When $('#m_nav .toggle') click listener is getting called it calls a slideToggle function on the current nested <ul> regardless if another menu is opened or closed and there is no check in place of whether or not the rotate_open/rotate_close classes exist allowing for the classes to get swapped. There is no relation between the swapping of rotate_open/rotate_close classes and the logic that slideToggles <ul> up/down.
UPDATE
I have edited your code and made updates that will now work seen here: https://jsfiddle.net/vhfn0q5a/9/
I have added a class of .top_level to the top level items in your HTML. I use this as a way of differentiating the top level <li> from the sub menus. Next, at the end of the click event listener I check to see if the .toggle element clicked is a top level element, if so I target all top level elements that are not the current selected and make sure they have the .rotate_close class.
$(function() {}) shorthand reference
Use this code in your first click handler:
$('#mw_nav .toggle').click(function() {
$(this).toggleClass('rotate_close rotate_open');
if ($('#mw_nav .toggle').not(this).hasClass('rotate_open')) {
$('#mw_nav .toggle').not(this).removeClass('rotate_open').addClass('rotate_close');
}
});
I've updated your FIDDLE with an working example.
Cheers!
I have an element inside an element, when I click the element underneath I want the slider to open. When I click on the outermost element I want the slider to close.
Unfortunately when I click on the outermost it clicks the underneath element as well. Is there a way to click only on the outermost element ignoring the click on the underneath element? The events are triggered on click and executed with javascript.
I tried with z-index but it still captures the underneath element clicked as well, and because the functions are contrary to one another nothing happens.
edit: on a "code is worth 1000 words" tip
var $target = $(this).data('pos', i) //give each li an index #
$target.data('hpaneloffsetw', $target.find('.hpanel:eq(0)').outerWidth()) //get offset width of each .hpanel DIV (config.dimensions.fullw + any DIV padding)
$target[haccordion.ismobile? "click" : "mouseenter"](function(){
haccordion.expandli(config.accordionid, this)
config.$lastexpanded=$(this)
})
if (config.collapsecurrent){ //if previous content should be contracted when expanding current
$('.close').click(function(){
$target.stop().animate({width:config.paneldimensions.peekw}, config.speed) //contract previous content
})
$target.dblclick(function(){
$(this).stop().animate({width:config.paneldimensions.peekw}, config.speed) //contract previous content
})
}
Because the code is borrowed, I don't understand much of it. But basically I want the "click" : "mousteenter" function to work on click, without interfering with the .close().click
It sounds like you need to stop the click event bubbling up the DOM to be caught by parent elements. You can use stopPropagation() to do this:
$('.close').click(function(e) {
e.stopPropagation();
$target.stop().animate({ width: config.paneldimensions.peekw }, config.speed);
})
$target.dblclick(function(e) {
e.stopPropagation();
$(this).stop().animate({ width: config.paneldimensions.peekw }, config.speed);
})
Try the following fiddle
$("#outer").click(function(){alert("outer clicked")});
$("#inner").click(function(e){
alert("inner clicked")
e.stopPropagation();
});
To identify the element you have "really" clicked on, you can try to identify it through accessing the target property of the jquery-event-object.
After you identified the target you clicked on, you could prevent other event handlers from firing.
Use CSS specific jquery to point exact element like below, use > to point exact child
table > tbody > tr > td > input[type='text']
like this.
I've a HTML div and I want to hide it whenever the user clicks on the page anywhere outside the div. Which clicking on which element should I trigger the onclick event??
$('#mydiv').click(function(e) { e.stopImmediatePropagation(); });
$(document.body).one("click", function() {
$('#mydiv').hide();
});
Since mydiv is also a child of the body element, you don't want that when clicking on that element, the element would dissappear.
So when people click on the mydiv, you want it to stop bubbling up to the body element, that is why first you register a click event on your mydiv, and tell it to stop bubbling.
Assuming you're using the latest jQuery, v1.4.4:
$(<the div you want hidden>).click(false); //stop click event from bubbling up to the document
$(document).one('click', function(){
$(<the div you want hidden>).hide(); //which will hide the div
});
In other words, this code says 'hide the div if you click on this page, unless you click on the div'.
Re: Toggle button
Then you'll have something like:
$('button').click(function(){
$('div').toggle();
});
$('div').click(false);
$(document).click(function(){
$('div').hide();
//reset the toggle state, e.g.
$('button').removeClass('selected');
});
The BODY element.