Dynamically added element function call not working - javascript

I have a problem with function call, when element is dynamically added.
Here is the link to code pen example. Function call - onclick - is from this button:
<button id="btnFocus" class="btnFocus" onclick="focusToDIV($(this))">Focus to DIV</button>
Function focusToDIV:
var focusToDIV = function(btnReference){
btnReference.parent().find("#div3").focus();
}
First element which contains this button is statically added. All the other elements can be added with button 'Add new'. With statically added element function focusToDIV gets called and div3 receives focus.
With dynamically added elements btnReference is not defined, that is why this error is thrown:
Uncaught TypeError: Cannot read property 'parent' of undefined
How to make this function work (put focus on div3 with click on btnFocus) with dynamically added elements? Why is btnReference not defined, if element is added dynamically to DOM?
var focusToDIV = function(btnReference){
btnReference.parent().find("#div3").focus();
}
var addNew = function(){
$("#divMain").append("<div class='divContainer' class='divContainer'> <div id='divInner' class='divInner'>" +
"<div id='div2' class='div2'> <div id='div3' class='div3' contentEditable='true'></div>" +
"</div></div> <button id='btnFocus' class='btnFocus' onclick='focusToDIV($(this))'>Focus to DIV</button> </div>");
}
.divMain{
height: 100vh;
width: 100vw;
}
.divContainer{
position: relative;
display: inline-block;
left: 20%;
top: 10%;
}
.divInner{
width: 300px;
height: 300px;
border: 1px solid black;
}
.div2{
position: relative;
left: 20px;
top: 20px;
width: 200px;
height: 100px;
border: 1px solid blue;
}
.btnFocus{
position: absolute;
top: 305px;
}
.div3{
position: relative;
left: 10%;
top: 10%;
width: 150px;
height: 80px;
border: 1px solid red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="divMain" class="divMain">
<button id="btnAdd" onclick="addNew()">Add new</button>
<div class="divContainer" class="divContainer">
<div id="divInner" class="divInner" >
<div id="div2" class="div2">
<div id="div3" class="div3" contentEditable="true"></div>
</div>
</div>
<button id="btnFocus" class="btnFocus" onclick="focusToDIV($(this))">Focus to DIV</button>
</div><!-- divContainer -->
</div><!-- divMain -->

You need to change the onclick method from focusToDIV() to focusToDIV($(this)).
As the element wasn't passed btnReference is undefined and you were calling a method on that undefined variable.
var addNew = function(){
$("#divMain").append("<div class='divContainer' class='divContainer'> <div id='divInner' class='divInner'>" +
"<div id='div2' class='div2'> <div id='div3' class='div3' contentEditable='true'></div>" +
"</div></div> <button id='btnFocus' class='btnFocus' onclick='focusToDIV($(this))'>Focus to DIV</button> </div>");
}

Related

Why does mouseDown event not propagate in React?

I have a simple React component with two squares which are in the same absolute position. The blue square covers the red square.
function App() {
return (
<div className="App">
<div>
<div
style={{
position: "absolute",
backgroundColor: "red",
width: 100,
height: 100
}}
onMouseDown={() => console.log("Red!")}
/>
<div
style={{
position: "absolute",
backgroundColor: "blue",
width: 100,
height: 100
}}
onMouseDown={() => console.log("Blue!")}
/>
</div>
</div>
);
}
ReactDOM.render(<App />, document.getElementById("root"));
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
When attaching event listeners to the react components, only the component on top catches the event and it does not reach the red square. Why is that the case? Is this default behavior? I thought event propagation is only stopped using event.stopPropagation()? When using vanilla javascript, both squares catch the event though.
function clickRed() {
console.log("Red!");
}
function clickBlue() {
console.log("Blue!");
}
<div id="root">
<div style="position: absolute; background-color: red; min-width: 100px; min-height: 100px;" onmousedown="clickRed();" />
<div style="position: absolute; background-color: blue; min-width: 100px; min-height: 100px;" onmousedown="clickBlue();"/>
</div>
This isn't a React thing, it's how events work in the DOM. The issue is that events propagate through the DOM tree, from innermost children to outermost ancestors of those children. But your elements are siblings, they don't have a parent/child relationship. So whichever one is above the other in the z-order will be the one that receives the event (which then propagates to that element's parent, not its siblings).
When using vanilla javascript, both squares catch the event though.
Not with the DOM structure you've defined in your question. Here it is with straight HTML and inline event handlers:
<div class="App">
<div>
<div
style="
position: absolute;
background-color: red;
width: 100px;
height: 100px;
"
onmousedown='console.log("Red!")'
></div>
<div
style="
position: absolute;
background-color: blue;
width: 100px;
height: 100px;
"
onmousedown='console.log("Blue!")'
></div>
</div>
</div>
Or with JavaScript using the DOM directly:
const app = document.createElement("div");
app.innerHTML = `
<div>
<div
style="
position: absolute;
background-color: red;
width: 100px;
height: 100px;
"
class="red"
></div>
<div
style="
position: absolute;
background-color: blue;
width: 100px;
height: 100px;
"
class="blue"
></div>
</div>
`;
app.querySelector(".red").addEventListener("mousedown", () => console.log("Red!"));
app.querySelector(".blue").addEventListener("mousedown", () => console.log("Blue!"));
document.getElementById("root").appendChild(app);
<div id="root"></div>
Re your edit adding this example:
function clickRed() {
console.log("Red!");
}
function clickBlue() {
console.log("Blue!");
}
<div id="root">
<div style="position: absolute; background-color: red; min-width: 100px; min-height: 100px;" onmousedown="clickRed();" />
<div style="position: absolute; background-color: blue; min-width: 100px; min-height: 100px;" onmousedown="clickBlue();"/>
</div>
The HTML there is incorrect. In HTML, <div/> is exactly the same thing as <div> — it's just a start tag. As a result, your div elements are nested (blue is inside red). The HTML equivalent to JSX <div/> is <div></div>:
function clickRed() {
console.log("Red!");
}
function clickBlue() {
console.log("Blue!");
}
<div id="root">
<!-- Scroll right in the stack snippet to see the difference at the end ⇒ ⇒ ⇩⇩⇩⇩⇩⇩⇩ -->
<div style="position: absolute; background-color: red; min-width: 100px; min-height: 100px;" onmousedown="clickRed();" ></div>
<div style="position: absolute; background-color: blue; min-width: 100px; min-height: 100px;" onmousedown="clickBlue();"></div>
</div>

getting the difference between the top of a container a clicked element

I am trying to create a container that has children inside it all with the same class.
I'm trying to get the difference between the clicked div and the top of the container then animate that clicked div to the top of the container.
I have gotten mixed results.. when it worked it would animate then reanimate the position of the container back to its original position.
Can anyone give me some insight into why this is not functioning correctly?
Code below.
<style>
#contact-list-scroller {
position: absolute;
left: 0px;
top: 0px;
right: 0px;
bottom: 0px;
background: Silver;
overflow:scroll;
width: 200px;
}
#contact-list-scroller div {
background: white;
width: 150px;
height: 150px;
border: 1px solid Gray;
}
</style>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div style="position:relative; width:150px; height:100vh;">
<div id="contact-list-scroller">
<div class="test" id="contact_8965">stuff1</div>
<div class="test" id="contact_8966">stuff2</div>
<div class="test" id="contact_8967">stuff3</div>
<div class="test" id="contact_8968">stuff4</div>
<div class="test" id="contact_8969">stuff5</div>
<div class="test"></div>
<div class="test"></div>
<div class="test"></div>
<div class="test"></div>
<div class="test"></div>
</div>
</div>
<script>
$('.test').click(function(){
var contactTopPosition = $(this).offsetTop;
var containerTop = $('#contact-list-scroller').scrollTop();
var heightDifference = containerTop - contactTopPosition;
console.log(contactTopPosition + ' contactTop');
console.log(containerTop + ' containerTop');
console.log(heightDifference + ' heightDifference');
//$("#contact-list-scroller").scrollTop(contactTopPosition);
$("#contact-list-scroller").animate({scrollTop: heightDifference,
complete: $(this).unbind()
});
});
</script>
Is there a reason for giving every <div> inside of the container class="test"? If every child is a div, and has the same class, you can just use the cascading part of CCS, to target them. I also noticed you have a $(this).unbind() after the transition - you want each element to only be clickable once?
I've put together a snippet, assuming there's no specific need for the same class on all children, and commented out the unbind(). It uses element.position().top to find the visible distance between the element and its parent's top, then adds the parent's current scroll value.
$('#contact-list-scroller > div').click(function() {
var contactTopPosition = $(this).position().top;
var contactList = $(this).parent();
console.log(contactTopPosition + ' contactTop');
contactList.animate({
scrollTop: contactList.scrollTop() + contactTopPosition
//, complete: $(this).unbind() // Stops the function from running again after the first click, is that waht you want?
});
});
#contact-list-scroller {
position: absolute;
left: 0px;
top: 0px;
right: 0px;
bottom: 0px;
background: Silver;
overflow: scroll;
width: 200px;
}
#contact-list-scroller div {
background: white;
width: 150px;
height: 150px;
border: 1px solid Gray;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div style="position:relative; width:150px; height:100vh;">
<div id="contact-list-scroller">
<div id="contact_8965">stuff1</div>
<div id="contact_8966">stuff2</div>
<div id="contact_8967">stuff3</div>
<div id="contact_8968">stuff4</div>
<div id="contact_8969">stuff5</div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
</div>

JavaScript adding classes on multiple modals

I'm kind of desperate. I'm trying to make the same modal as Behance has when you click on one of the little windows but I can't get my JavaScript to work. I'm not able to show "test2".
function modalActive(){
document.getElementsByClassName("window")[0].classList.add("modalActive")
};
function closeModal(){
document.getElementsByClassName("window")[0].classList.remove("modalActive")
};
.gallery-item {
width: 120px;
height: 120px;
border: 3px solid gray;
float: left;
margin-left: 10px;
}
.window {
display: none;
height: 500px;
width: 500px;
Background-color: gray;
z-index: 100000;
position: absolute;
margin: 0 auto;
}
.modalActive {
display: block !important;
}
<div class="gallery-item">
<button class="button" onclick="modalActive()">derp</button>
</div>
<div class="window">
<button class="close" onclick="closeModal()">×</button>
test1
</div>
<div class="gallery-item">
<button class="button" onclick="modalActive()">derp</button>
</div>
<div class="window">
<button class="close">×</button>
test2 - im not able to see this due to some error in my code/knowledge
</div>
You have to target a specific modal to open when clicking on the buttons. At the moment you are only ever finding the first modal and setting the modalActive class.
I have updated your code below to pass the modal id number when clicking on a button.
function modalActive(id){
document.getElementsByClassName("window-" + id)[0].classList.add("modalActive")
};
function closeModal(){
document.getElementsByClassName("modalActive")[0].classList.remove("modalActive")
};
.gallery-item {
width: 120px;
height: 120px;
border: 3px solid gray;
float: left;
margin-left: 10px;
}
.window {
display: none;
height: 500px;
width: 500px;
Background-color: gray;
z-index: 100000;
position: absolute;
margin: 0 auto;
}
.modalActive {
display: block !important;
}
<div class="gallery-item">
<button class="button" onclick="modalActive(1)">derp</button>
</div>
<div class="window window-1">
<button class="close" onclick="closeModal()">×</button>
test1
</div>
<div class="gallery-item">
<button class="button" onclick="modalActive(2)">derp</button>
</div>
<div class="window window-2">
<button class="close" onclick="closeModal()">×</button>
test2 - im not able to see this due to some error in my code/knowledge
</div>

New to javascript trying to figure this out

So I'm trying to make multiple lights activate on button clicks and I'm not sure what I'm doing wrong here.
I thought I could make this into a function and then pass it the id name but it looks like it's not acting the way I want.
html
<div class="lights">
<div id="red"></div>
<div id="yellow"></div>
<div id="green"></div>
</div>
<div class="button">
<button id="red_button"> Red Button </button>
<button id="yellow_button">Yellow Button </button>
<button id="green_button">Green Button </button>
</div>
css
.lights{
height: 600px;
width: 200px;
background-color: black;
padding-top: 15px;
}
.button{
padding-top: 20px;
}
#red,
#yellow,
#green {
margin: 0 auto;
background-color: black;
border-radius: 50%;
width: 180px;
height: 180px;
margin-top: 10px;
}
#red.active {
background-color: red;
}
#yellow.active {
background-color: yellow;
}
#green.active {
background-color: green;
}
jquery
function click(e) {
$('#red,#yellow,#green').removeClass('active');
$('e').addClass('active');
}
$('#red_button').click(click('#red'));
$('#yellow_button').click(click('#yellow'));
$('#green_button').click(click('#green'));
http://jsfiddle.net/0m9wos1r/1/
A few things. I wouldn't recommend naming your function after an event, although it should still work. The issue with your code is that you're immediately calling the function, and in the function you quoted the parameter. Use this instead:
function click(e) {
$('#red,#yellow,#green').removeClass('active');
$(e).addClass('active');
}
$('#red_button').click(function () {
click('#red')
});
$('#yellow_button').click(function () {
click('#yellow')
});
$('#green_button').click(function () {
click('#green')
});
.lights {
height: 600px;
width: 200px;
background-color: black;
padding-top: 15px;
}
.button {
padding-top: 20px;
}
#red, #yellow, #green {
margin: 0 auto;
background-color: black;
border-radius: 50%;
width: 180px;
height: 180px;
margin-top: 10px;
}
#red.active {
background-color: red;
}
#yellow.active {
background-color: yellow;
}
#green.active {
background-color: green;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="lights">
<div id="red"></div>
<div id="yellow"></div>
<div id="green"></div>
</div>
<div class="button">
<button id="red_button">Red Button</button>
<button id="yellow_button">Yellow Button</button>
<button id="green_button">Green Button</button>
</div>
Fixed: http://jsfiddle.net/0m9wos1r/4/
2 issues you need to fix:
The function call within the click call. Like so, using an anonymous function:
$('#red_button').click(function(){click('#red')});
The selector within the click function. Like so:
$(e).addClass('active');

change image in a div with any effect like fadein when mouse hovered on another div

The below shown is the format of my html code. In the header div i have a image. Each box(box1, box2, box3) inside the contain div has link inside like(software development(box1), Graphic Designing(box2), and Technical Training(box3). These links when clicked will take me to separate pages which has their own header images. So i have 3 header image for each box and a default header image in the home page.In the home page when ever I hover my mouse in the box1 div the header image should change to the box1 header image with an effect like fadeIn and return my default image on mouse out. Same for box2 and box3. Please help me with doing this with CSS or JS or jQuery. Thank You
<body>
<div class="wrapper">
<div class="out">
<div class="in">
<div id="header"></div>
<div class="contain">
<div class="box1"></div>
<div class="box2"></div>
<div class="box3"></div>
</div>
</div>
</div>
</div>
</body>
css:
.wrapper{
width: 100%
height: auto;
margin: 0px;
}
.out{
margin: auto;
width: 1000px;
height: 730px;
border-top: 5px solid #333333;
}
.in{
width: 900px;
height: 640px;
margin: auto;
margin-top: 25px;
}
#header{
background:url(../img/Untitled-1.jpg);
height: 175px;
width: 900px;
margin: 0px;
}
.contain{
margin: 0px;
width: 900px;
height: 428px;
}
.box1{
height: 360px;
width: 295px;
float: left;
margin: 67px 0px 0px 0px;
position: absolute;
background-color: #e6e7e9;
border-bottom: 4px solid #735d8c;
}
.box2{
height: 360px;
width: 295px;
float: left;
margin: 67px 0px 0px 302px;
position: absolute;
background-color: #e6e7e9;
border-bottom: 4px solid #735d8c;
}
.box3{
height: 360px;
width: 295px;
float: left;
margin: 67px 0px 0px 602px;
position: absolute;
background-color: #e6e7e9;
border-bottom: 4px solid #735d8c;
}
I have a made an BIN
I am placing same image for all the 3 divs like
$('#content,#content2,#content3').mouseover(function(){
$('#header').css('background','url(http://www.google.com/mobile/android/images/android.jpg)')
});
You change with your respective images like
$('#content').mouseover(function(){
$('#header').css('background','url(http://www.google.com/mobile/android/images/android.jpg)')
});
$('#content2').mouseover(function(){
$('#header').css('background','url(http://www.google.com/mobile/android/images/android.jpg)')
});....
jsBin demo
jQuery:
var currPage = 0; // PLAY HERE: set here current page (0 = home)
var $header = $('#header');
var $headerImg = $header.find('img');
$headerImg.eq( currPage ).show().addClass('currentImg');
// clone images to boxes:
var c = 0;
$('.box').each(function( i ){
$(this).prepend( $headerImg.eq(i==currPage? (i+1+c++) : c+i).clone() );
});
$('.box img[class^=headImg]').on('mouseenter mouseleave', function( e ){
var opacity = e.type=='mouseenter' ? 1 : 0 ;
var myClass = $(this).prop('class'); // get class
var $mainImg = $header.find('img.'+myClass);
$headerImg.hide();
$mainImg.stop().fadeTo(300, opacity);
$('.currentImg').stop().fadeTo(600, !opacity);
});
HTML:
<div class="wrapper">
<div class="out">
<div class="in">
<div id="header">
<img class="headImg1" src="home.jpg" alt="" />
<img class="headImg2" src="ONE.jpg" alt="" />
<img class="headImg3" src="TWO.jpg" alt="" />
<img class="headImg4" src="THREE.jpg" alt="" />
</div>
<div class="contain">
<div class="box">
</div>
<div class="box">
</div>
<div class="box">
</div>
</div>
</div>
</div>
</div>
MODIFIED CSS PART:
/*ADDED*/
#header img{
position:absolute;
display:none;
}
.contain{
margin: 0px;
width: 900px;
height: 428px;
}
.box{ /* CHANGED */
height: 360px;
width: 294px;
float: left;
margin: 67px 3px 0px;
position: relative;
background-color: #e6e7e9;
border-bottom: 4px solid #735d8c;
}
/* ADDED */
.box img{
width:100%;
}
See this : http://jsfiddle.net/xTjQT/2/
$('a').mouseover(function() {
var src = $(this).attr('alt');
alert(src);
$('#header img').stop().fadeOut(100, function() {
$(this).attr('src', src);
$(this).fadeIn(100);
});
});
$('a').mouseout(function() {
$('#header img').stop().fadeOut(200, function() {
$(this).attr('src', 'http://jsfiddle.net/img/logo.png');
$(this).fadeIn(100);
});
});

Categories