Removing certain elements from a selector binded to the body - javascript

I have a click event binded to the body element but I don't want it to fire for when the user clicks on certain elements, that being when the element has an attribute of data-dropdown-target, however what I have tried isn't working, it always fires.
CodePen: http://codepen.io/anon/pen/ORQkrb
HTML:
<body>
<div class="foo">foo</div>
<div class="bar" data-dropdown-target="something">bar</div>
<div class="moo">moo</div>
</body>
CSS:
.foo, .bar, .moo {
padding: 10px;
margin: 5px;
}
.foo {
background-color: gray;
}
.bar {
background-color: teal;
}
.moo {
background-color: green;
}
JS:
$('body').not('[data-dropdown-target]').on('click', function(e) {
console.log('Hi!');
});
I assume this is because it is trying to remove body elements that have this attribute, rather than it's children - correct?
How do I go about stopping it from firing on children elements that have this attribute - do I have to loop through everything, as I would like to avoid that because of performance reasons, especially since it's on the body.

Actually your code try to bind event click on every <body> without data-dropdown-target attribute.
This could solve your problem :
$('body').on('click', function(e) {
if($(e.target).data('dropdown-target') || $(e.target).parents('[data-dropdown-target]').length !== 0) return false;
console.log('Hi!');
});
.foo, .bar, .moo {
padding: 10px;
margin: 5px;
}
.foo {
background-color: gray;
}
.bar {
background-color: teal;
}
.moo {
background-color: green;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<body>
<div class="foo">foo</div>
<div class="bar" data-dropdown-target="something">bar</div>
<div data-dropdown-target="something">
<div class="moo">moo</div>
</div>
</body>

The not selector just remove the body element if it has [data-dropdown-target] attribute.
Remove elements from the set of matched elements.
$('body').on('click', function(e) {
console.log('Hi!');
});
$('[data-dropdown-target]').on('click',function(e){
return false;
});

Related

href link not working with innerHTML script with "onmouseover change text" and onmouseout

My goal is to have text change onmouseover from "hello" (without a link) to "Google" and provide an 'href' on the resulting "Google" text, and then revert to "hello" onmouseout without a link.
The code below works in changing the text from "hello" to "Google" but,
the link on "Google" does not work (even though I can right-click on "Google" and open the link on another tab)
the text does not change back to "hello" onmouseout.
Thanks for your help in advance!
Here is my code:
<style>
.container {
margin-top: 6vw;
margin-left: 40%;
margin-right: 40%;
}
</style>
<div class="container">
<h1>
<div class="hello" id="hello1" onmouseover="changeText()" onmouseout="changeText(this,'Hello.')">Hello.</div>
</h1>
</div>
<script>
function changeText() {
if (document.getElementById("hello1")) {
a = document.getElementById("hello1")
a.innerHTML = 'Google'
}
}
</script>
try this way onmouseout="this.innerHTML='Hello.';"
function changeText() {
if (document.getElementById("hello1")) {
a = document.getElementById("hello1")
a.innerHTML = 'Google'
}
}
.container {
margin-top: 6vw;
margin-left: 40%;
margin-right: 40%;
}
<div class="container">
<h1>
<div class="hello" id="hello1" onmouseover="changeText()" onmouseout="this.innerHTML='Hello.';">Hello.</div>
</h1>
</div>
By changing a class of a parent tag, any and all child tags can be affected via CSS. Having the HTML ready when the page loads and then hiding it is better than constantly creating and destroying HTML for trivial effects.
The events "mouseenter" and "mouselrave" are handled by a property event handler and an event listener. Either one is sufficient, but avoid using attribute event handlers:
<div onmouselame="lameAttributeEventHandler()">...</div>
Details are commented in the example below
// Reference the <header>
const hdr = document.querySelector('.title');
/* This is a property event handler
// Whenever the mouse enters within the borders of
// the <header>:
// '.google' class is added
// '.hello' class is removed
*/
hdr.onmouseenter = function(event) {
this.classList.add('google');
this.classList.remove('hello');
};
/* This is an even listener
// Whenever the mouse exits the <header> the
// opposite behavior of the previous handler
// happens
*/
hdr.addEventListener("mouseleave", function(event) {
this.classList.add('hello');
this.classList.remove('google');
});
.title {
height: 50px;
margin-top: 3vh;
border: 3px solid black;
text-align: center;
}
h1 {
margin: auto 0;
}
.hello span {
display: inline-block;
}
.hello a {
display: none;
}
.google a {
display: inline-block;
}
.google span {
display: none;
}
<header class="title hello">
<h1>
<span>Hello</span>
Google
</h1>
</header>
You can try this, May it help u to solve the problem
<!DOCTYPE html>
<head>
<title>change text on mouse over and change back on mouse out
</title>
<style>
#box {
float: left;
width: 150px;
height: 150px;
margin-left: 20px;
margin-top: 20px;
padding: 15px;
border: 5px solid black;
}
</style>
</head>
<html>
<body>
<div id="box" onmouseover="changeText('Yes, this is Onmouseover Text')" onmouseout="changeback('any thing')" >
<div id="text-display" >
any thing
</div>
</div>
<script type="text/javascript">
function changeText(text)
{
var display = document.getElementById('text-display');
display.innerHTML = "";
display.innerHTML = text;
}
function changeback(text)
{
var display = document.getElementById('text-display');
display.innerHTML = "";
display.innerHTML = text;
}
</script>
</body>
</html>

How to make jquery scrolling effect work on multiple element/classes?

I'm trying to make a very light script for multiple classes class"demo" that can work on my onScrollDown responsive animation.
I don't really understand about writing arrays. but, I believe that if I use document.getElementsByClassName("demo")[i] , i < 0 and some function(i) I can implement it for individual classes. Because I use getBoundingClientRect() instead of fixed value.
So, how can I write it correctly using i as arrays?
Thank you..
Here is my working script :
<script>
var e = document.getElementById("demo");
var rect = e.getBoundingClientRect();
var x = rect.top;
$(window).bind('scroll', function () {
if ($(window).scrollTop() > x-300) {
$('#demo').addClass('animate');
} else {
$('#demo').removeClass('animate');
}
});
</script>
*work only for a single element.
Here is what I'm trying to do, that not working yet
<script>
var e = document.getElementsClassName("test")[i];
var rect = e.getBoundingClientRect();
var x = rect.top;
var i;
for (i = 0; i < e.length; i++) {
$(window).bind('scroll', function (i) {
if ($(window).scrollTop() > x-300) {
$e.addClass('animate');
} else {
$e.removeClass('animate');
}
});
}
</script>
CSS :
<style>
.test {
background:#345;
color:#FFF;
height:2em;
padding:.5em;
top:50px;
margin-top: 100px;
width:100%;
}
.animate {
width: 60px;
}
</style>
HTML
<div style="color: red; margin-bottom: 400px;">(Top!)</div>
<div class="test" id="demo">Menu</div>
<div class="test" id="demo">Menu</div>
<div class="test" id="demo">Menu</div>
<div style="color: red; margin-top: 400px;">(Bottom!)</div>
Okay so I've achieved what you're trying to do. Here are the changes I made:
Used the JQuery each function. This will loop all of the demo elements every time a scroll is detected. There are other ways of looping the elements but because you've already imported JQuery we may as well use it's functions.
Changed #demo to .demo. In other words, I've changed id to class. id should only be used when working with elements that are completely unique. In this case, there are multiple demos so we use class instead.
Final code (as you scroll each element will turn red showing that the animate class has been added:
$(window).on('scroll', function() {
$('.demo').each(function(i, obj) {
var rect = obj.getBoundingClientRect();
var x = rect.top;
if ($(window).scrollTop() > x - 300) {
$(obj).addClass('animate');
} else {
$(obj).removeClass('animate');
}
});
});
.body {
height: 200vh;
background-color: #f1f1f1;
}
.demo {
height: 200px;
width: 100%;
background-color: #f9f9f9;
}
.demo.animate {
background-color: #ff0000;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="body">
<div class="demo"></div>
<div class="demo"></div>
<div class="demo"></div>
<div class="demo"></div>
</div>
There are few notes in regards to your code:
In jQuery you can get elements offset by using .offset() function.
you should not use the same id more than once per page.
.bind() has been deprecated since jQuery 3.0. Use .on() instead.
To toggle class you can use .toggleClass(className, state). State is used to determine if you want to remove or add the class.
See this example:
$(window).on('scroll', function() {
jQuery(".test").each(function() {
let isTop = $(window).scrollTop() > jQuery(this).offset().top - 300;
jQuery(this).toggleClass('animate', isTop);
});
});
.test {
background: #345;
color: #FFF;
height: 2em;
padding: .5em;
top: 50px;
margin-top: 100px;
width: 100%;
}
.animate {
width: 60px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div style="color: red; margin-bottom: 400px;">(Top!)</div>
<div class="test">Menu</div>
<div class="test">Menu</div>
<div class="test">Menu</div>
<div style="color: red; margin-top: 400px;">(Bottom!)</div>

How to change content of div on hover using JQuery/Javascript

I'm trying to change the contents of a div when it's hovered over using JQuery. I've seen answers on stack overflow, but I can't seem to get it working.
I've tried
$( "imgDiv" ).mouseover(
function() {
$("tdiv").textContent = "hovering";
},
function() {
$("tdiv").textContent = 'title';
}
);
I've also replaced "mouseover" with "hover". I've used a variable and the actual div in place of "imgDiv".
This is what my code looks like:
imgDiv = document.getElementById('imgDiv');
tDiv = document.getElementById('titleDiv');
$( "imgDiv" ).mouseover(
function() {
$("tdiv").textContent = "hovering";
}, function() {
$("tdiv").textContent = 'title';
}
);
body {
background: white;
padding: 20px;
font-family: Helvetica;
}
#imgDiv {
width: 100px;
height: 100px;
background-color: pink;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="imgDiv">
<div id=titleDiv>title</div>
</div>
You can use jQuery's .hover() function along with the .text() function to do what you want. Also, no need for document.getElementById:
$("#imgDiv").hover(
function() {
$("#titleDiv").text("hovering");
},
function() {
$("#titleDiv").text('title');
}
);
body {
background: white;
padding: 20px;
font-family: Helvetica;
}
#imgDiv {
width: 100px;
height: 100px;
background-color: pink;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="imgDiv">
<div id="titleDiv">title</div>
</div>
You can target the div with jQuery, and store it's original value. On mouseout, you can restore it. Also using mouseenter reduces the number of times the logic processes as mouseover will fire for every mouse move over the element.
var $titleDiv = $('#titleDiv');
$("#imgDiv")
.on('mouseenter', function() {
$titleDiv.data('originalText', $titleDiv.text());
$titleDiv.text('hovering');
})
.on('mouseout', function() {
$titleDiv.text($titleDiv.data('originalText'));
});
body {
background: white;
padding: 20px;
font-family: Helvetica;
}
#imgDiv {
width: 100px;
height: 100px;
background-color: pink;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="imgDiv">
<div id="titleDiv">title</div>
</div>
First of all, replace $("imgDiv") with $("#imgDiv") to get the element with id (#) imgDiv.
Then $("tdiv") doesn't exist, you probably mean $("div") to select a <div>tag in your DOM.
And finally, $("tdiv").textContent doesn't exist. You can try $("div").html() or $("div").text() to get the <div> tag content
--
Quick reminder : jQuery documentation on selectors
$("div") will select the <div> tags
$(".element") will select tags with class="element"
$("#element") will select tags with id="element"
You need to try like this
$( "#imgDiv" ).mouseover(function() {
$("#titleDiv").text("hovering");
}).mouseleave( function() {
$("#titleDiv").text('title');
});
body {
background: white;
padding: 20px;
font-family: Helvetica;
}
#imgDiv {
width: 100px;
height: 100px;
background-color: pink;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="imgDiv">
<div id=titleDiv>title</div>
</div>
Easy solution,
var s = document.getElementsByTagName('div');
function out() {
s[0].innerHTML = 'hello';
}
function ibn() {
s[0].innerHTML = 'Myname';
}
<div onmouseout = 'out()' onmouseenter = 'ibn()'> Myname </div>
You cannot call reference a dom with pure Javascript and them manipulate it with jQuery - it will not work.
Try this:
$( "#imgDiv" ).mouseover(function() {
$("#titleDiv").text("hovering");
});
The titleDiv id has to be referenced in your code using "#", then the id name.
Also, use $("#name_of_id").text("your content") instead of .textContent()

:hover select target only, not parents with same class

How do I make this only fire :hover for the target element (ignoring the parents)?
Assume this is recursive design of object inside object, therefore with the same classes and an autogenerated id.
.group:hover {
background-color: red;
}
.group {
border: 1px solid black;
width: 100px;
padding: 20px;
}
<div id="g1" class="group">aaaa
<div id="g2" class="group">bbbb
<div id="g3" class="group">cccc
</div>
</div>
</div>
Since you tagged the question with javascript you can achieve this using it. The key is to use .stopProgagation() which will stop events from "falling through" down to your other elements.
See example below:
document.querySelectorAll(".group").forEach(elem => {
elem.addEventListener('mouseover', function(e) {
e.stopPropagation();
this.classList.add('group-hover');
});
elem.addEventListener('mouseout', function(e) {
this.classList.remove('group-hover');
});
});
.group-hover {
background-color: red;
}
.group {
border: 1px solid black;
width: 100px;
padding: 20px;
}
<div id="g1" class="group">aaaa
<div id="g2" class="group">bbbb
<div id="g3" class="group">cccc
</div>
</div>
</div>
Alternatively, you could intead use e.target to get the target of the event if you wish not to use stopPropagation():
document.querySelectorAll(".group").forEach(elem => {
elem.addEventListener('mouseover', e => e.target.classList.add('group-hover'));
elem.addEventListener('mouseout', e => e.target.classList.remove('group-hover'));
});
.group-hover {
background-color: red;
}
.group {
border: 1px solid black;
width: 100px;
padding: 20px;
}
<div id="g1" class="group">aaaa
<div id="g2" class="group">bbbb
<div id="g3" class="group">cccc
</div>
</div>
</div>
Only with JS, and using events delegate for simpler way
const All_g = document.querySelector('#g1');
All_g.onmouseover = function(event) {
let target = event.target;
target.style.background = 'red';
};
All_g.onmouseout = function(event) {
let target = event.target;
target.style.background = '';
};
.group {
border: 1px solid black;
width: 100px;
padding: 20px;
}
<div id="g1" class="group">aaaa
<div id="g2" class="group">bbbb
<div id="g3" class="group">cccc
</div>
</div>
</div>
some explanations :=> https://javascript.info/mousemove-mouseover-mouseout-mouseenter-mouseleave
You can do it in the following way:
var elements = document.getElementsByClassName('group');
var lastElement = null;
elements.each(element =>{
lastElement = element;
});
lastElement.on('hover', function(){
//do anything you wish with element
})
Approach 1
Register hover event to toggle class and use event.stopPropagation();
https://developer.mozilla.org/en-US/docs/Web/API/Event/stopPropagation
The bubbles read-only property of the Event interface indicates
whether the event bubbles up through the DOM or not.
https://developer.mozilla.org/en-US/docs/Web/API/Event/bubbles
Approach 2
Mouseenter event - By design it does not bubble - so don't have to perform event.stopPropagation()
Though similar to mouseover, it differs in that it doesn't bubble and
that it isn't sent to any descendants when the pointer is moved from
one of its descendants' physical space to its own physical space.
https://developer.mozilla.org/en-US/docs/Web/API/Element/mouseenter_event

Stop event bubbling - onclick listener

Why clicking on parent div element does the job, but clicking on the child div text Click Me! returns undefined and the page doesn't load in iframe? I used event.stopPropagation to stop bubbling but it is still the same. What is the correct way to do that, when addEvenLisneter is preferred over inline onclick ?
var panel = document.getElementsByClassName('panel');
var iframe = document.getElementById('frame');
[].forEach.call(panel, function(each) {
each.addEventListener('click', linkClick);
});
function linkClick ( event ) {
event.stopPropagation();
event.preventDefault();
iframe.src = event.target.dataset.url;
}
.panel {
padding: 20px;
margin: 10px;
border: 1px solid yellow;
}
.panel div {
display: inline;
}
<div class="panel" data-url="https://www.w3schools.com/jsref/event_preventdefault.asp">
<div>Click Me!</div>
</div>
<iframe id="frame"></iframe>
When I console.log(event) bubble property is still set to true.
If you prevented the click event from bubbling from the inner div, then it would never reach the one to which you bound the event handler and your function would not fire at all.
The problem here is that event.target matches the element that was actually clicked on. You want event.currentTarget if you want to get the element that the event handler was bound to.
var panel = document.getElementsByClassName('panel');
var iframe = document.getElementById('frame');
[].forEach.call(panel, function(each) {
each.addEventListener('click', linkClick);
});
function linkClick ( event ) {
event.stopPropagation();
event.preventDefault();
iframe.src = event.currentTarget.dataset.url;
}
.panel {
padding: 20px;
margin: 10px;
border: 1px solid yellow;
}
.panel div {
display: inline;
}
<div class="panel" data-url="https://www.w3schools.com/jsref/event_preventdefault.asp">
<div>Click Me!</div>
</div>
<iframe id="frame"></iframe>
Well, I am not actually solving the problem as a such, more like a workaround.
Maybe you could try using a button instead, as this is slightly more valid HTML.
I modified the CSS a bit, so it matches your example.
<!DOCTYPE html>
<html>
<style>
.panel {
padding: 20px;
margin: 10px;
border: 1px solid yellow;
display:block;
width:100%;
text-align:left
}
</style>
<body>
<button class="panel" data-url="https://www.w3schools.com/jsref/event_preventdefault.asp" type="button">Click Me!</button>
<iframe id="frame"></iframe>
</body>
<script>
var panel = document.getElementsByClassName('panel');
var iframe = document.getElementById('frame');
[].forEach.call(panel, function(each) {
each.addEventListener('click', linkClick);
});
function linkClick ( event ) {
event.stopPropagation();
event.preventDefault();
iframe.src = event.target.dataset.url;
}
</script>
</html>

Categories