Testing if a click is in a div and all its children - javascript

I am facing an issue about this.
<div id="1">
<div id="2">
</div>
<div id="3">
<div id="4">
</div>
</div>
</div>
<div id="others_div">
</div>
I want to add the class "hidden" to "1" when I click on something which is not "1" nor one of its children.
Now I am using this but I have a lack of imagination for solving this issue...
document.onclick = function(e)
{
if(e.target.id!="1")
{
$("#1").addClass("hidden");
}
}

Well, to avoid e.stopPropagation() (maybe you want that event to bubble up to some other ancestor) You can check if it is not clicked on #1 nor on it's children like this:
$('body').on('click', function(e) {
if (!((e.target.id== "1") || $(e.target).closest('#1').length)) {
$("#1").addClass("hidden");
}
});

You could use a jQuery check like the following one to check if the current element is your 1 element or traverse the DOM to see if the current target is contained within an element with an ID of 1 :
<script>
$(function(){
// Trigger this when something is clicked
$(document).click(function(e){
// Toggle the hidden class based on if the current element is 1
// or if it is contained in an element with ID of 1
$("#1").toggleClass('hidden',!((e.target.id== "1") || $(e.target).closest('#1').length))
});
});
</script>
Generally, you should avoid using ID attributes that only consists of numbers as they are not valid (ID attributes must begin with a letter). Ignoring this could result in some issues with regards to CSS or jQuery selection.

JQuery
$('body').on( "click", function(e) {
if(e.target.id !== "1")
{
$("#1").addClass("hidden");
}
});

I think you want this
// taken from http://stackoverflow.com/questions/152975/how-to-detect-a-click-outside-an-element
$('html').click(function() {
//Hide the menus if visible
alert('hide');
});
$('#one').click(function(event){
event.stopPropagation();
});
div#one {
background: yellow;
}
div#others_div {
background: green;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<div id="one">
div one
<div id="2">
div two
</div>
<div id="3">
div three
<div id="4">
div four
</div>
</div>
</div>
<div id="others_div">
other div
</div>

Related

JavaScript loop over clickable elements on click event, and skip the specific clicked element

<div>
<div class="clickable">1</div>
<div class="clickable">2</div>
<div class="clickable">3</div>
<div class="clickable">4</div>
</div>
Upon clicking one of the 'clickable' elements i want to add a new class to all elements with 'clickable' class except the one that has been clicked.
$('.clickable').on('click', function (e) {
$('.clickable').each(function () {
$(this).addClass('new-class')
});
})
How, inside the loop, can i skip the specific element that was clicked?
$('.clickable').on('click', function() {
$(this).removeClass('new-class').siblings().addClass('new-class');
});
This is the simplest to control and read
You do not need the each
$('.clickable').on('click', function(e) {
$('.clickable').addClass('new-class');
$(this).removeClass('new-class');
})
.new-class {
color: red
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
<div class="clickable">1</div>
<div class="clickable">2</div>
<div class="clickable">3</div>
<div class="clickable">4</div>
</div>
If they are surely all in the same container, you can use siblings.
To chain you MUST remove before adding
$('.clickable').on('click', function(e) {
$(this)
.removeClass('new-class') // still necessary for the second click of another element
.siblings().addClass('new-class');
})
.new-class {
color: red
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
<div class="clickable">1</div>
<div class="clickable">2</div>
<div class="clickable">3</div>
<div class="clickable">4</div>
</div>
There is a not method in jQuery so the simplest thing you can do in my opinion is with the help of not method like below:
$('.clickable').on('click', function (e) {
$('.clickable').not(this).addClass('new-class');
})

Make div clickable, only when anchor is present in div (multiple divs)

Given a basic structure how can I turn a series of divs into links without turning every div into a link? Here's an example:
<div class="boxes">
<div class="box"><p>Some text with a link</p></div>
<div class="box"><p>Some text without a link</p></div>
<div class="box"><p>Some text with a link</p></div>
<div class="box"><p>Some text without a link</p></div>
</div>
And the associated jQuery I'm using to make the divs clickable:
$(document).ready(function() {
if($('.boxes p a').length){
$(".boxes .box").click(function() {
window.open($(this).find("a").attr("href"));
return false;
});
}
});
The problem I'm running into is the click function gets applied to all divs instead of only those with links.
The desired behavior is to only create a fully clickable div only when an anchor element is found.
For the purposes of this use case, the div (.box) is generated dynamically and wrapping the element in an anchor tag (<div> </div>) is not possible.
Fiddle: https://jsfiddle.net/fu8xLg0d/
Because you add event listeners on all the .boxes .box classes, which are all your divs.
Just add something like :
$(".boxes .box").has('a')...
to narrow it to those only containing an a element
JSFiddle
use .parent to solve your purpose:
$(document).ready(function() {
if($('.boxes p a').length){
$("a").parent().parent().click(function() {
window.open($(this).find("a").attr("href"));
return false;
});
}
});
But yes, it can even create a problem so i will say to give a class to your link and then call its parent... :)
Plotisateur just beat me by a minute or two! :P
if($('.boxes p a').length){
$(".boxes .box").has('a').click(function() {
window.open($(this).find("a").attr("href"));
return false;
});
Here's the code anyway: https://jsfiddle.net/fu8xLg0d/1/
You can try this.
$(document).ready(function() {
var anchorbox =$(".boxes p a");
if(anchorbox.length>0){
$(anchorbox).parent().click(function() {
window.open($(this).find("a").attr("href"));
return false;
});
}
});
div (.box) is generated dynamically.
Delegate the click event from the body to the target div and on click on the element check if it has anchor tag. For adding the pointer icon create a separate function which will add the icon to the div only if it has an anchor tag as child
$(document).ready(function() {
// separate function to add pointer only if a is present
addClassToElem();
$("body").on('click', '.box', function() {
if ($(this).find('a').length) {
window.open($(this).find("a").attr("href"));
return false;
}
})
});
function addClassToElem() {
$('.box a').each(function(a, b) {
$(this).parent().addClass('linkIcon')
})
}
.linkIcon {
cursor: pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="boxes">
<div class="box">
<p>Some text with a link</p>
</div>
<div class="box">
<p>Some text without a link</p>
</div>
<div class="box">
<p>Some text with a link</p>
</div>
<div class="box">
<p>Some text without a link</p>
</div>
</div>
This little change, helps you to resolve the issue.
$(document).ready(function() {
if($('.boxes p a').length){
$(".boxes .box").click(function() {
if ($(this).children('p').children('a').length) {
window.open($(this).find("a").attr("href"));
return false;
}
});
}
});
the difference from your code is, additionally add a checking
if ($(this).children('p').children('a').length) {
window.open($(this).find("a").attr("href"));
return false;
}

Track all elements on page

I'm attempting to track events for all UI elements on a page. The page contains dynamically generated content and various frameworks / libraries. Initially I tracked elements through creating a css class "track" , then adding style "track" to tracked elements. elements are then tracked using :
$('.track').on('click', function() {
console.log('Div clicked' + this.id);
console.log(window.location.href);
console.log(new Date().getTime());
});
As content can be dynamically generated I wanted a method to track these elements also. So tried this using wildcard jQuery operator.
In this fiddle : https://jsfiddle.net/xx68trhg/37/ I'm attempting to track all elements using the jquery '*' selector.
Using jQuery '*' selector appears to fire the event for all elements of given type.
So for this case if is clicked all the click event is fired for all divs. But id is just available for div being clicked.
For the th element the click event is fired twice , what is reason for this ?
Can the source be modified that event is fired for just currently selected event ?
fiddle src :
$(document).ready(function() {
$('*').each(function(i, ele) {
$(this).addClass("tracked");
});
$('.tracked').on('click', function() {
console.log('Div clicked' + this.id);
console.log(window.location.href);
console.log(new Date().getTime());
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<!-- <div id="1" data-track="thisdiv">
Any clicks in here should be tracked
</div>
-->
<div id="1">
Any clicks in here should be tracked 1
</div>
<div id="2">
Any clicks in here should be tracked 2
</div>
<div id="3">
Any clicks in here should be tracked 3
</div>
<th id="th">tester</th>
You can try with:
$(document).ready(function() {
$("body > *").click(function(event) {
console.log(event.target.id);
});
});
$(document).ready(function() {
$("body > *").click(function(event) {
console.log(event.target.id);
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="1">
Any clicks in here should be tracked 1
</div>
<div id="2">
Any clicks in here should be tracked 2
</div>
<div id="3">
Any clicks in here should be tracked 3
</div>
<table>
<tr>
<td>Cols 1</td>
<td id="td">Cols 2</td>
</tr>
</table>
<p id="th">tester</p>
You may want to use event delegation to target the elements you need. Advantage is that this also works for dynamically generated elements. See code for an example of this.
// method to add/set data-attribute and value
const nClicksInit = (element, n = "0") => element.setAttribute("data-nclicked", n);
// add data-attribute to all current divs (see css for usage)
// btw: we can't use the method directly (forEach(nClicksInit))
// because that would send the forEach iterator as the value of parameter n
document.querySelectorAll("div").forEach(elem => nClicksInit(elem));
// add a click handler to the document body. You only need one handler method
// (clickHandling) to handle all click events
document.querySelector('body').addEventListener('click', clickHandling);
function clickHandling(evt) {
// evt.target is the element the event is generated
// from. Now, let's detect what was clicked. If none of the
// conditions hereafter are met, this method does nothing.
const from = evt.target;
if (/^div$/i.test(from.nodeName)) {
// aha, it's a div, let's increment the number of detected
// clicks in data-attribute
nClicksInit(from, +from.getAttribute("data-nclicked") + 1);
}
if (from.id === "addDiv") {
// allright, it's button#addDiv, so add a div element
let newElement = document.createElement("div");
newElement.innerHTML = "My clicks are also tracked ;)";
const otherDivs = document.querySelectorAll("div");
otherDivs[otherDivs.length-1].after(newElement);
nClicksInit(newElement);
}
}
body {
font: 12px/15px normal verdana, arial;
margin: 2em;
}
div {
cursor:pointer;
}
div:hover {
color: red;
}
div:hover:before {
content: '['attr(data-nclicked)' click(s) detected] ';
color: green;
}
#addDiv:hover:after {
content: " and see what happens";
}
<div id="1">
Click me and see if clicks are tracked
</div>
<div id="2">
Click me and see if clicks are tracked
</div>
<div id="3">
Click me and see if clicks are tracked
</div>
<p>
<button id="addDiv">Add a div</button>
</p>
<h3 id="th">No events are tracked here, so clicking doesn't do anything</h3>
You can invoke the stopPropagation and the condition this === e.currentTarget to ensure invoke the handler function of the event source DOM.
And you must know the <th> tag must wrapped by <table>, otherwise it will not be rendered.
$(document).ready(function() {
$('*').each(function(i, ele) {
$(this).addClass("tracked");
});
$('.tracked').on('click', function(e) {
if (this === e.currentTarget) {
e.stopPropagation();
console.log('Div clicked' + this.id);
console.log(window.location.href);
console.log(new Date().getTime());
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<!-- <div id="1" data-track="thisdiv">
Any clicks in here should be tracked
</div>
-->
<div id="1">
Any clicks in here should be tracked 1
</div>
<div id="2">
Any clicks in here should be tracked 2
</div>
<div id="3">
Any clicks in here should be tracked 3
</div>
<table>
<th id="th">tester</th>
</table>

jQuery carousel dots on click always going to first item

I'm building a carousel with basic jquery - I'm using the .css() rule to simply toggle opacity between each slide.
The way I want to do this is on click of each dot I want to check if the specific class exists and if it does hide all other items and show that one. So far I have:
$('.dot').click(function() {
$('.review-module--reviews').children().css('opacity', 0);
if ($('.dot').hasClass('dot1')) {
$('.review-one').css('opacity', 1);
$('.dot1').addClass('dot-active');
} else if ($('.dot').hasClass('dot2')) {
$('.review-two').css('opacity', 1);
$('.dot2').addClass('dot-active');
} else {
$('.review-three').css('opacity', 1);
$('.dot3').addClass('dot-active');
}
});
HTML:
<div class="review-module">
<div class="review-module--reviews">
<div class="review-one">
</div>
<div class="review-two">
</div>
<div class="review-three">
</div>
</div>
<span class="slider-dots">
<div class="dot dot1"></div>
<div class="dot dot2"></div>
<div class="dot dot3"></div>
</span>
</div>
However when I click on dots 2 and 3, it always targets the dot1 slide in the DOM. The 'dot-active' class gets added successfully to dot1 but on click of 2 and 3, that class does not get added.
I also tried explicity checking for a true value in the if statement like so:
if ($('.dot').hasClass('dot1') === true)
Is this the best way to do this? Or should I consider a different thought process?
The error is in this code:
if ($('.dot').hasClass('dotX'))
What you're actually doing here is fetching the list of all .dot elements and checking if the first one has the dotX class. As you can imagine, this will always pick up the first .dot element, which has the dot1 class.
What you probably mean to do is to check if the element that was clicked on has the dotX class, for which you need to check only that element.
Either do so by using the current scope of the click handler:
if ($(this).hasClass('dotX'))
or by checking the target of the click event:
$('.dot').click(function(e) {
$('.review-module--reviews').children().css('opacity', 0);
if ($(e.target).hasClass('dot1')) {
Try this may be it can help you -
JAVASCRIPT CODE-
$('.dot').click(function() {
$('.review-module--reviews').children().css('opacity', 0);
$('.dot').removeClass('dot-active');
if ($(this).hasClass('dot1')) {
$('.review-one').css('opacity', 1);
$(this).addClass('dot-active');
} else if ($(this).hasClass('dot2')) {
$('.review-two').css('opacity', 1);
$(this).addClass('dot-active');
} else {
$('.review-three').css('opacity', 1);
$(this).addClass('dot-active');
}
});
I suggest to use data-* attributes instead so give every .dot a data-review that refer to the related review div :
$('.review-module--reviews div').hide(); //Hide all the slides
$('.dot').click(function() {
var review = $(this).data('review');
$('.review-module--reviews div').hide(); //Hide all slides
$('.slider-dots .dot').removeClass('dot-active'); //Remove 'dot-active' class from all the dots
$(this).addClass('dot-active'); //Active the clicked dot
$('.review-'+review).show(); //Show the related slide
});
Then on click just get the review using jQuery method .data() and show the div with related class.
Hope this helps.
$('.review-module--reviews div').hide();
$('.dot').click(function() {
var review = $(this).data('review');
$('.review-module--reviews div').hide();
$('.slider-dots .dot').removeClass('dot-active');
$(this).addClass('dot-active');
$('.review-'+review).show();
});
.dot-active{
color: green;
font-weight:bold;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<span class="slider-dots">
<div class="dot dot1" data-review="one">dot1</div>
<div class="dot dot2" data-review="two">dot2</div>
<div class="dot dot3" data-review="three">dot3</div>
</span>
<br>
<div class="review-module">
<div class="review-module--reviews">
<div class="review-one">
Review-one
</div>
<div class="review-two">
Review-two
</div>
<div class="review-three">
Review-three
</div>
</div>
</div>

jquery hide div when click outside

I am trying to style div and ul to function like . However, I have a problem that:
1) I only want to toggle the ul that I click and hide the other ul. So I wonder if jquery support some function such as 'not click'?
2) I want to hide all the ul when the mouse is click outside. I did some research, and see other people use mouseup or click on body. But I am not quiet sure how it works.
$(document).ready(function() {
$('.hide').each(function() {
$(this).hide();
});
$('.select').click(function() {
var id = '#' + $(this).attr('id');
var sub = id + '_sub';
$(sub).slideToggle();
});
$('body').mouseup(function() {
if($(this).length == 0) {
$(this).hide();
}
});
});
div.select {
display: inline-block;
margin: 10px;
padding: 20px;
background: red;
cursor: pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<body>
<div id="1" class="select">
<div class="main">
<span>1</span>
</div>
<div>
<ul id="1_sub" class="hide">
<li>1</li>
<li>2</li>
</ul>
</div>
</div>
<div id="2" class="select">
<div class="main">
<span>1</span>
</div>
<div>
<ul id="2_sub" class="hide">
<li>1</li>
<li>2</li>
</ul>
</div>
</div>
<div id="3" class="select">
<div class="main">
<span>1</span>
</div>
<div>
<ul id="3_sub" class="hide">
<li>1</li>
<li>2</li>
</ul>
</div>
</div>
</body>
here you go: DEMO
$(document).ready(function() {
$('.hide').hide(); //hide in the beginning
$('.select').click(function() {
$('.hide').slideUp(200); //hide all the divs
$(this).find('.hide').slideDown(200); //show the one that is clicked
});
$(document).click(function(e){
if(!$('.select').is(e.target) || !$('.select').has(e.target)){ // check if the click is inside a div or outside
$('.hide').slideUp(200); // if it is outside then hide all of them
}
});
});
you can define your notClick() function as below:
$.fn.notClicked= function(clickPosition){
if (!$(this).is(clickPosition.target) && $(this).has(clickPosition.target).length === 0){
return true;
}
else{
return false;
}
};
and then use it as:
$(document).click(function(e){
alert($('.select').notClick(e)); // will return true if it is not clicked, and false if clicked
});
You need to hide other ul whenever some one clicks on .select div.
Here is a working fiddle: http://jsfiddle.net/0mgbsa0b/1/
$(document).ready(function() {
$('.hide').each(function() {
$(this).hide();
});
$('.select').click(function() {
$('.hide').each(function() {
$(this).hide();
});
var id = '#' + $(this).attr('id');
var sub = id + '_sub';
$(sub).slideToggle();
});
$('body').mouseup(function() {
if($(this).length == 0) {
$(this).hide();
}
});
});
I'm interested in two concerns you raised, so i will be trying to share some ideas on them:
1)So I wonder if jquery support some function such as 'not click'?
personally, to quesiton1
i think there is no jQuery event method called .noclick()
PPL often use addClass & removeClass to log whether an element got clicked and after marking the element with class="active" , using jQuery selector to select ".active" or using jQuery ":not" selector to select elements that are not marked ".active" ( indirectly finding out those unclicked.)
3.You might also need to count in click propagation issues. meaning sometimes you click a children container and triggered click event towards all its parent inside.
fiddle link: `http://jsfiddle.net/hahatey/ctp5jngf/2/`
In the above case , if you clicked child box in red, will by default alert1, alert2 if
you didn't apply a e.stopPropagation() to the click event;
2) I want to hide all the ul when the mouse is click outside. I did some research, and see other people use mouseup or click on body. But I am not quiet sure how it works.
for question 2:
could be many many ways to do it, you can try blur() //lose focus event trigger.
like what you mentioned mouseout, mouseup, add click event listener to outer area all will work for it as long as u can use method in answer1. i see other ppl have posted many answers already as it can be done in many ways.

Categories