Only target parent with event.target? - javascript

HTML:
<div onclick="doSomething()" id="parent">
<div id="child"></div>
</div>
CSS:
#parent {
background-color: blue;
width: 100%;
height: 100px;
}
#child {
background-color: green;
width: 50%;
height: inherit;
}
.myClass {
background-color: red !important;
}
JS:
function doSomething() {
event.target.className = ('myClass');
}
As you can see in this JSFIDDLE, upon clicking the child, instead of applying the class to the parent which triggers the function, it applies it to the child. I want to know how to avoid this and apply it to the parent no matter where I click inside of it. I am trying to avoid using the document.getElement(s)ByClass/Id method.Any help?

You can refer to the element that handles the event with currentTarget.
Identifies the current target for the event, as the event traverses the DOM. It always refers to the element the event handler has been attached to as opposed to event.target which identifies the element on which the event occurred.
However, instead of relying on the browser to provide a global event object, I would pass it to the function:
onclick="doSomething(event)"
You can also refer to the element the handler is bound to with this:
onclick="doSomething(event, this)"
Of course please consider to not use inline event handlers.

Just reference the target in your javascript call:
function doSomething(target) {
target.className = ('myClass');
}
#parent {
background-color: blue;
width: 100%;
height: 100px;
}
#child {
background-color: green;
width: 50%;
height: inherit;
}
.myClass {
background-color: red !important;
}
<div onclick="doSomething(this)" id="parent">
<div id="child"></div>
</div>

To get the immediate parent element of the clicked element you can use the 'path' array of the event. Path provides an array which includes every element in ascending order from the element you clicked to the top of the DOM.
Having trouble working out the exact browser support for this though.
var children = document.querySelectorAll('[id^="child-"]'),
clickEvent = function(event) {
console.log(event.path[0]); //prints clicked child element
console.log(event.path[1]); //prints parent
event.path[1].classList.toggle('row'); //toggles row or column mode of parent
event.path[0].classList.toggle('selected'); //toggles color of child
};
children.forEach(function(child) {
child.addEventListener('click', clickEvent);
});
<div id="parent">
<div id="child-1">Child One</div>
<div id="child-2">Child Two</div>
<div id="child-3">Child Three</div>
<div id="child-4">Child Four</div>
<div id="child-5">Child Five</div>
</div>

Related

How to make an entire div clickable except a deep level child div?

I want to make an entire div clickable except a child div. This child div is not an immediate child of the div, rather it is in a few level deeper. I would like to dynamically exclude this child div by just passing div id or class name.
I tried to solve it with jQuery ".not()" and ".children()" methods, which works. But its static in a sense that I need to know in which level the div is and need to align the methods accordingly. However, I want something dynamic which will take only the div's class name or id, and find it from the DOM tree and exclude it from the new DOM object chain so that the jQuery ".click" and ".hover" function can be applied on the entire div except that particular div.
I have created a dummy example of my problem. In the example, I want to make the entire div (i.e., id = main1) hyperlinked except the "#d3" div.
Here is my JSFiddle: JSFiddle
Example Code:
HTML:
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>
Untitled Document
</title>
</meta>
</head>
<body>
<div class="center border divmain1" id="main1">
<a href="https://www.google.ca" style="display: block">
link
</a>
<p>
Main
</p>
<div class="border-thin divd1" id="d1">
<p>
d1
</p>
</div>
<div class="border-thin divd2" id="d2">
<p>
d2
</p>
<div class="border-thin divd3" id="d3">
<p>
d3
</p>
<div class="border-thin divd4" id="d4">
d4
</div>
<div class="border-thin divd5" id="d5">
d5
</div>
</div>
</div>
</div>
</body>
</html>
CSS:
.border {
border: 5px solid RosyBrown;
}
.border-thin {
border: 2px solid RosyBrown;
}
.divmain1 {
width: 90%;
margin: 0 auto 0 auto;
overflow: hidden;
}
.divd1 {
width: 30%;
float: left;
}
.divd2 {
width: 60%;
float: right;
margin: 0 0 0 3.5%;
}
.divd3 {
margin: auto;
width: 90%;
}
.divd4 {
width: 30%;
}
.divd5 {
width: 30%;
}
jQuery:
// find elements
var main1 = $("#main1")
var d3 = $("#d3")
// handle click and hover pointer
main1.on("click", function(){
window.open('https://www.google.ca');
});
main1.hover(function(){
$(this).css("cursor", "pointer");
});
Could anyone please help me on how to make an entire div clickable and dynamically exclude a child div?
The key thing here is to pass the event object so you can check what is the element actually receiving the click.
Since #d3 contains both #d4 and #d5 I'm assuming you don't want those elements to fire either.
If that's the case, you can use Node.contains() to check if the element is a descendant of your target element.
The Node.contains() method returns a Boolean value indicating whether
a node is a descendant of a given node, i.e. the node itself, one of
its direct children, [...]
If you just want to prevent the action for the element #d3 itself, you don't need to d3.contains and just if (e.target != d3) should do.
// find elements
var main1 = $("#main1")
var d3 = $("#d3").get(0) // Get the HTMLElement
// handle click and hover pointer
main1.on("click", function(e) {
if (!d3.contains(e.target)) {
console.log("I'll open a window");
} else {
console.log("I'm " + e.target.id + " and won't open a window")
}
});
main1.hover(function() {
$(this).css("cursor", "pointer");
});
.border {
border: 5px solid RosyBrown;
}
.border-thin {
border: 2px solid RosyBrown;
}
.divmain1 {
width: 90%;
margin: 0 auto 0 auto;
overflow: hidden;
}
.divd1 {
width: 30%;
float: left;
}
.divd2 {
width: 60%;
float: right;
margin: 0 0 0 3.5%;
}
.divd3 {
margin: auto;
width: 90%;
}
.divd4 {
width: 30%;
}
.divd5 {
width: 30%;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="center border divmain1" id="main1">
link
<p>
Main
</p>
<div class="border-thin divd1" id="d1">
<p>d1</p>
</div>
<div class="border-thin divd2" id="d2">
<p>d2</p>
<div class="border-thin divd3" id="d3">
<p>d3</p>
<div class="border-thin divd4" id="d4">d4</div>
<div class="border-thin divd5" id="d5">d5</div>
</div>
</div>
</div>
</body>
</html>
In your jQuery you can run
event.stopPropagation();
within a click event for the div child you don't want to trigger the initial function.
use cancelBubble
for example, to disable your root event on "#d5" div
$('#d5').on('click', function(e){
// stop the event from bubbling.
e.cancelBubble=true
});
I am not much of a fan of jQuery but I can tell you that this can be done with pure JavaScript. All you have to do is to implement an event listener to the top level div and see if the clicked element or it's parent has the targeted class.
Let's take this HTML markup for an example where we will trigger an alert "Target Locked" when someone clicked anything inside divd4 else "General Action"
function HasSelfClassOrParent(element, classname) {
if (element.classList && element.classList.contains(classname))
return true;
return element.parentNode && HasSelfClassOrParent(element.parentNode, classname);
}
let divd2 = document.querySelector(".divd2")
let target = 'divd4'
divd2.addEventListener("click", function(event) {
let isTargetOrChild = HasSelfClassOrParent(event.target, target)
if (isTargetOrChild) {
alert("Target Locked")
} else {
alert("General Action")
}
})
.border {
border: 5px solid RosyBrown;
}
.border-thin {
border: 2px solid RosyBrown;
padding: 20px;
margin-bottom: 10px
}
.divd4{
background: #64B448;
color: #fff;
cursor: pointer;
}
<p>Click on div four and see what happens</p>
<div class="border-thin divd2" id="d2">
<p>I am Div 2</p>
<div class="border-thin divd3" id="d3">
<p>I am Div 3</p>
<div class="border-thin divd4" id="d4">
<p>I am a simple paragraph inside div four</p>
<p>I am a another paragraph inside div four</p>
</div>
<div class="border-thin divd5" id="d5">
I am Div 5
</div>
</div>
</div>

JQuery how to append on the same place

so in a project i need to append a few elements with jquery. I am using the .append() function, an it works fine, but what i need to really do is append the elements in the same place every time, and not one after the other.
as you can see i need the secon element (yellow one) - and the next ones - to be appended but every time on the same place, not dependent on the before elements positions.
sorry for bad english.
As #darklightcode mentioned, you should solve this by using CSS.
Add position: relative rule to the Parent element. Then, add position: absolute to Child elements, that you are appending to. The easiest way would be to give each element, that you are adding the same class, that has this rule: position: absolute.
You won't need to specify z-index for each added element, because by default the last added will be visible on top of all other elements.
It can look like this:
HTML:
<div class="parent">
<div class="child green"></div>
<div class="child yellow"></div>
<div class="child red"></div>
</div>
CSS:
.parent {
position: relative;
}
.child {
width: 100px;
height: 100px;
position: absolute;
}
.green {
background: green;
}
.yellow {
background: yellow;
}
.red {
background: red;
}

Why closest() find first itself element before travesing tree

I looking for why closest() find first itself element before traversing tree.
For example: I would like fadeOut the parent div element when i click on children element, but the children element is too a div and so is the children who fadeOut
$(document).on("click", ".close", function() {
$(this).closest("div").fadeOut();
});
.feed {
width: 200px;
height: 200px;
background: red;
position: relative;
}
.close {
position: absolute;
top: 0;
right: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="feed">
<div class="close">
X
</div>
</div>
Why is itself element who fadeOut and no the parent div element?
I know parent() get the parent element, but closest() is supposed traversing elements tree.
Have you a concrete cases, where get itself is useful?
It's because the .closest() method traverses the DOM beginning with the current element. You may want the .parents() method instead since it will begin with the parent element.
$(this).parents("div").fadeOut();
It's worth noting that the .parents() method returns zero or more elements whereas .closest() will return zero or one element. Therefore you might want to chain .first() after the .parents() method in order to get the first match:
$(this).parents("div").first().fadeOut();
$(document).on("click", ".close", function() {
$(this).parents("div").first().fadeOut();
});
.feed {
width: 200px;
height: 200px;
background: red;
position: relative;
}
.close {
position: absolute;
top: 0;
right: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="feed">
<div class="close">
X
</div>
</div>
Alternatively, you could also just exclude the parent by selecting the parent element and then using .closest() like:
$(this).parent().closest("div").fadeOut();
However, it would be much better just to select the closest .feed element rather than any div:
$(this).closest(".feed").fadeOut();
$(document).on("click", ".close", function() {
$(this).closest(".feed").fadeOut();
});
.feed {
width: 200px;
height: 200px;
background: red;
position: relative;
}
.close {
position: absolute;
top: 0;
right: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="feed">
<div class="close">
X
</div>
</div>
As has been said, closest() begins with the current element. Your selector is vague enough that it stops there.
It may be safer (and more widely useful) to target a specific container class rather than the immediate ancestor div.
$(this).closest(".feed").fadeOut()
You must be more specific, closest() is used when you are not sure what element exactly will receive click (div itself, label inside, image or smth. else) but you want have always same action, so closest can point exactly same element (contrary to parent approach)
$(document).on("click",".close",function(){
$(this).closest(".feed").fadeOut()
});
.feed{
width:200px;
height:200px;
background:red;
position:relative;
}
.close{
position:absolute;
top:0;
right:0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="feed">
<div class="close">
X
</div>
1
</div>
<br>
<div class="feed close">
<div class="close">
X
</div>
2
</div>

How to get top level object under the mouse function?

Title says it all. I've got child div's with absolute positions inside a relative parent div, and would like to know whether the mouse is over a child or a parent div at a "random" point in time.
Hypothetically, I'd like to call the .mouseover method and perform a .hasclass test on the highest level object to see if it has the child class or not. However, .mouseover is an event handler, thus not something I could just call to get the relevant information.
Example HTML below:
$(document).ready(function() {
$(".child").draggable();
setTimeout(doSomething, 31415);
});
var doSomething = function() {
// Edit content based on what is underneath the mouse
}
.parent {
width: 100%;
height: 1000px;
position: relative;
background: #f0f0f0;
}
.child {
width: 300px;
height: 100px;
position: absolute;
background: #cccccc;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<link rel="stylesheet" href="http://code.jquery.com/ui/1.11.4/themes/ui-lightness/jquery-ui.css">
<script src="http://code.jquery.com/ui/1.11.4/jquery-ui.min.js"></script>
<div class="parent">
<div class="child"></div>
<div class="child"></div>
</div>
Getting an element from a position is what the document.elementFromPoint function was designed to do:
document.elementFromPoint(mousePosition.x, mousePosition.y);
To get the current mouse position, attach a listener to mousemove (as far as I know there is no native method to extract mouse coordinates without a mouse event). Here's an example fiddle showing this: https://jsfiddle.net/xsLwt8Ld/
If I understood correctly, you want to know if at any given time, the mouse is over the child or directly over the parent. You could achieve it by using the :hover pseudoclass
Create a function that checks if there is any .child that has the :hover class:
If there is, that means that the mouse is over a .child (and you have the element) and there's no need to check the parent.
If there isn't, then check if there is any .parent element that also has the class that you created:
If there is: the mouse is over a .parent but not over a .child;
If there is not: the mouse i not over a .parent or a .child.
The code to achieve this is simple:
function checkMouseOver() {
if ($(".child:hover").length) {
// mouse over a .child
} else if ($(".parent:hover").length) {
// mouse over a .parent (but not over .child)
} else {
// mouse not over a .parent or .child;
}
}
A simple working demo:
$(".child").draggable();
// Edit content based on what is underneath the mouse
function checkMouseOver() {
if ($(".child:hover").length) {
alert("You were over " + $(".child:hover").text());
} else if ($(".parent:hover").length) {
alert("You were over " + $(".parent:hover").attr("id"));
} else {
alert("You are not over a .parent or .child");
}
}
.parent {
width: 100%;
height: 1000px;
position: relative;
background: #f0f0f0;
}
.child {
width: 300px;
height: 100px;
position: absolute;
background: #cccccc;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<link rel="stylesheet" href="http://code.jquery.com/ui/1.11.4/themes/ui-lightness/jquery-ui.css">
<script src="http://code.jquery.com/ui/1.11.4/jquery-ui.min.js"></script>
<button onclick="checkMouseOver()">Check where the mouse is</button>
<div class="parent" id="parent1">
<div class="child">Child 1</div>
<div class="child">Child 2</div>
</div>
<div class="parent" id="parent2">
<div class="child">Child 3</div>
<div class="child">Child 4</div>
</div>
(Click on the page and press tab until you get into the button, then mouse over the different elements and press Enter to trigger the funtion)

Javascript - Make the whole div clicable

I have a parent div element, and within it a child div element. Now there is a click handler for the child div, it brings a drop down(like a menu).
Requirement - Is to bring the dropdown on click of the parent div also.
Note - on click of parent div, and firing childdiv.click() won't work, infinite loop.
Cannot do a stoppropagation, functionality for bringing the dropdown won't work.
$(document).ready(function(){
$("#child").click(function(){
$("ul").slideUp();
})
$("#parent").click(function(){
$("#child").trigger("click");
})
})
#parent {
padding: 50px;
background: red;
}
#child {
height: 50px;
background: green;
color: white;
}
li {
background: rgba(0,0,255,0.3);
border: 2px solid black;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="parent">Parent
<div id="child">
Child
<ul id="menu" class="hide">
<li>menu1</li>
<li>menu2</li>
</ul>
</div>
</div>
Try this adding the parent onclick event handler and then use event.stopPropagation to stop event bubbling.
$("#child").click(function(e){
e.stopPropagation();
$("ul").slideToggle();
});
$("#parent").click(function(e){
$("#child").trigger("click");
});
CHECK FIDDLE is this what you want? Not sure what you want to do next. Adding your code would have been much easier to help.

Categories

Resources