Javascript hide element (when clicked outside) with certain conditions - javascript

So there is much questions here about hiding div when you clicking outside of it. But I have one thing, there is a div(accounts-edit-table-name-edit) which showing hidden div(account-edit-group) on click first. And then - if I will click somewhere else out of the div(account-edit-group) - it must hide. Here is my code where I am trying to do two different conditions (OR):
$(document).click(function(event) {
if($(event.target).parents().index($('.account-edit-group')) == -1 || $(event.target).parents().index($('.accounts-edit-table-name-edit')) == -1)
{
if($('.account-edit-group').is(":visible"))
{
$('.account-edit-group').removeClass('acc-edit-f');
alert("hiding")
}
}
});
HTML:
<div class="accounts-edit-table-name-edit">"button"</div>
<div class="account-edit-group">block</div>
(class "acc-edit-f" just contains "display: block")
Well, if I will click on the div with class "accounts-edit-table-name-edit" - system will immediately show me alert("hiding") though it must look through the conditions and ignore that. Is there any ways to fix this?

see the jsfiddle if it is what you want :
http://jsfiddle.net/5E6C6/2/
$(event.target).parents().index($('.account-edit-group')) //always return -1
$(event.target).parents().index($('.accounts-edit-table-name-edit')) // this too

That's because parents doesn't include the first element, which is e.target.
Here what you could do :
if(!$(event.target).closest('.account-edit-group, .accounts-edit-table-name-edit').length)

try using .hide() instead of removeclass
$( ".account-edit-group" ).hide();

Here is what you need:
add the element that is shown/hidden inside the button
stop event propagation when one of the two elements are clicked
bind onclick event on the document and hide all child elements
here is a working example i wrote for you:
http://jsfiddle.net/T2b4z/2/
$(document).click(function(event) {
var clickedElement = $(event.target);
if (clickedElement.hasClass('accounts-edit-table-name-edit') || clickedElement.parents().hasClass('accounts-edit-table-name-edit')) {
$('.account-edit-group').removeClass('acc-edit-f');
return false;
}else {
$('.account-edit-group').addClass('acc-edit-f');
}
});

Related

Two OnClick events overlap

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.

check if one of the the elements in propagation has a specific class, on jquery.click() method

In jQuery.click() method it's possible to get the class of element which has fired the event using even.target. I want to check if the element which has been clicked or one of its parent has some specific class.
<div class="c1">Click</div>
<script>
$(document).click(function(e){
if($(e.target).hasClass("c1"))
alert("It's C1");
});
</script>
But it always failes because c2 has been clicked. Despite using .parent(), I'm wondering if there is a way to check the propagation on on-click event.
From what you said is C1 was clicked and you want to know if
You need to see if the element is inside that was clicked.
var target = $(e.target);
if (target.hasClass("c2") || target.find(".c2").length) {
alert("C2 is a child");
}
EDIT, now what you orginally asked is not what you really wanted.
Now if it is a parent it is as simple as
var target = $(e.target);
if (target.hasClass("c1") || target.parents(".c1").length) {
alert("C1 child was clicked");
}
or as Ian pointed out
if (target.closest(".c1").length) {
alert("C1 child was clicked");
}
You can use $(this).hasClass instead of $(e.target). Also $(this).parent() will lead to parent of a target

How to see if a user has clicked on two elements?

I am working on a selection menu. I want the user to be able to select two different options and have something displayed depending on what they have selected. Right now, I am just using images to represent the selections. I am wondering if there is a way to see if a user has selected/clicked two of the images consecutively. After the user has clicked two pictures, I want them to be redirected to another page and have something displayed.
/*clicked on certain two images*/(function(){
document.location.href="#page";
$('option').css('display', 'inline');
});
Use a class to mark selection and after each click, check to see if two are selected:
$('img').click( function() {
$(this).toggleClass('selected');
if($('img.selected').length == 2) {
alert("Two images selected!");
// Or redirect to new page, etc.
}
});
Demo:
http://jsfiddle.net/G9NXA/
This is, of course, a generic solution. You probably don't want to use img as your selector, but some other class that defines your selectable images.
If you want to make sure the clicks/selections are consecutive clicks, simply clear the selection if the user clicks anywhere else:
Demo: http://jsfiddle.net/G9NXA/1/
And if you meant spatially consecutive, rather than temporally consecutive, here is another example:
Demo: http://jsfiddle.net/G9NXA/2/
If you don't want to store javascript state, you could try adding a marker class to the selected images on click and count how many are found then redirect.
This is the easiest method I came up with:
var tracker = [];
$('*').click(
function(e){
e.stopPropagation();
var lastEl = tracker.length ? tracker.pop() : '',
tag = this.tagName.toLowerCase();
tracker.push(tag);
if (tag == lastEl) {
doSomething();
}
else {
return false;
}
});​
JS Fiddle demo.
This applies a click handler to all elements, though (and prevents propagation/bubbling of the event, so you should be more specific in your selector than I have here); it also stores the tag-name each clicked-element in an array and then matches the tag-name of the currently-clicked element with the tag-name of the previously-clicked item.
If the two are the same, then the if evaluation returns true and the doSomething() is executed; otherwise the click-handler returns false, and nothing happens.
This depends. If the images are sibling nodes you could check .prev() and .next(). You the image on click with a class like 'imageClicked'. Then check if the .prev() or .next() also has that class.
$('img').click( function() {
var clickedImg = $(this);
clickedImg.toggleClass('imageClicked');
if(clickedImg.hasClass('imageClicked')) {
if(clickedImg.prev().hasClass('imageClicked') ||
clickedImg.next().hasClass('imageClicked'))
alert('Siblings Selected!');
}
});

Using :not to select all elements except inside box with certain class

I have an overlay that I want to hide on mousedown outside it.
Here is what I tried out but unfortunately :not selector is not working as I expected.
$('body:not(.overlay)').one('mousedown',function(){
//hide overlay here
});
I also tried $('* :not(.overlay)') but same issue.
The overlay gets hidden even when clicking inside the overlay box
$(document).on( "mousedown.hideoverlay", function(e){
if( $(e.target).closest(".overlay").length === 0 ) { //overlay wasn't clicked.
//hide overlay
$(document).off("mousedown.hideoverlay");
}
});
Your selector body:not(.overlay) matches the body element if it doesn't have a class overlay, I'm assuming what you meant was its descendant without the class overlay:
$('body :not(.overlay)'); //note the space - descendant selector
The problem with such an assignment is that it matches too many elements (in particular, parents of selected elements). Tehnically, even clicking on any container div would match the selector, fiddled. This happens because even clicks on elements with overlay class continue propagating up the DOM.
I agree with other suggestions here i.e. it's appropriate to listen to all clicks and do nothing if the selector doesn't match, however preventing event propagation on them could interfere with the rest of the page's logic.
I'd rather advocate an approach where there is an explicit subset of "overlayable" items that could be clicked on - and filter them with :not(.overlay) selector:
$('.some-generic-container-name:not(.overlay)')...
Try the .not() function: http://api.jquery.com/not/ . It specifically removes elements from a selected group which is probably the problem you are getting here. Saves having to do complex if's etc to solve this
$('*').not('.overlay').on('mousedown', function(){
alert("here");
});
Edit
Heh, Didn't read the question fully:
$(document).on('mousedown', function(e){
var target = $(e.target);
if(!target.parents().hasClass('overlay') && !target.hasClass('overlay')){
// hide stuff
}
});
Edit: I prefer to use click here (Dunno why):
$(document).on('click', function(e){
var target = $(e.target);
if(!target.parents().hasClass('overlay') && !target.hasClass('overlay')){
// hide stuff
}
});
It just looks nicer in my opinion, call me weird...

JavaScript IF statement problem

I have a problem writing an if statement, due to my lack of programing skills.
there's the code :
$("div.footerMenu li div.onScreen").click(
function(e) { e.stopPropagation(); e.preventDefault(); return false; }
);
Inside this div I have simple <a></a> links. And the problem is, when i click on that link, nothing happens. I'm trying to make a function, that would not execute that function(e) if the target of .click would be an <a></a> tag. Is there a simple way to do that?
You problem is that because you're link is inside the div, your code is blocking the click event, hence why nothing happens. You could try this:
$("div.footerMenu li div.onScreen").click(function(e) {
if(e.target.tagName.toLowerCase() != 'a') {
e.stopPropagation();
e.preventDefault();
return false;
}
});
I'm using .toLowerCase() because I'm not 100% the tagName will always be uppercase in all browsers. Just a sanity check.
I had a similar problem and here is the solution that works :)
$("div.footerMenu li div.onScreen").click(function(e) {
if( !( $(e.target).is('a') ) )
e.stopPropagation(); e.preventDefault(); return false;
}
);
Yup, very easy
if (e.target.nodeName !== "A") {
// your code here
}
You will need to check if the node has tagName == 'A'
if (this.tagName == 'A')
"this" should reference to the node being clicked, otherwise lookup e.target or e.targetSrc (don't know the jQuery equivalent)
When you click on an element, only events it will be running. But not events atached on parent elements.
You need to change your selector to match all child elements.
$("div.footerMenu li div.onScreen > *")
$("div.footerMenu li div.onScreen > a")
Rather than check if target was an a (to me, it's a bit messy), I'd prefer to separate it out and handle the links separately. By using e.stopPropagation only, you'll be able to click the link and have whatever action you want on it as well as preventing the event from bubbling up to the div.
$("div").click(function(e){
alert('You clicked me, I am the div!');
});
$("div a").click(function(e){
// Allows the link to be clicked but prevents
// the event from bubbling up to the div
e.stopPropagation();
});
Example: http://jsfiddle.net/jonathon/s2TxS/

Categories