I am cloning a div using jQuery and find that events on cloned elements do not work although they work on the original elements. How can I go about this? Note how the answer in the question states that...
"This is how jQuery's clone() method is able to copy a node with its
event listeners, for example"
let add = document.getElementsByClassName("add"),
rem = document.getElementsByClassName("rem"),
container = document.getElementsByClassName('container')[0];
for (let i = 0; i < add.length; i++) {
add[i].addEventListener("click", () => {
$(".cloneable").clone(true, true).appendTo(".container");
});
}
for (let i = 0; i < rem.length; i++) {
rem[i].addEventListener("click", () => {
if (container.childElementCount > 1) {
$(".cloneable:last").remove();
}
});
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container">
<div class="cloneable">
<div>
<a class="btn btn-primary add" role="button">Add cell</a>
<a class="btn btn-primary rem" role="button">Remove cell</a>
</div>
<iframe src="index.php"></iframe>
</div>
</div>
ETA: This code clones all elements named ".cloneable", so on second click it creates TWO clones, and so on. You should clone with $('.cloneable:first') or similar.
The issue seems to arise from you binding javascript native events. Using jQuery Events solves your problem.
let add = document.getElementsByClassName("add"),
rem = document.getElementsByClassName("rem"),
container = document.getElementsByClassName('container')[0];
for (let i = 0; i < add.length; i++) {
$(add[i]).on("click", () => {
$(".cloneable:first").clone(true, true).appendTo(".container");
});
}
for (let i = 0; i < rem.length; i++) {
$(rem[i]).on("click", () => {
if (container.childElementCount > 1) {
$(".cloneable:last").remove();
}
});
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container">
<div class="cloneable">
<div>
<a class="btn btn-primary add" role="button">Add cell</a>
<a class="btn btn-primary rem" role="button">Remove cell</a>
</div>
<iframe src="index.php"></iframe>
</div>
</div>
Related
I have an image which is an arrow for sorting the list. When i click it has to change to other image which is downward of the same image. But it doesn't stay that way after clicking. . I need if else statement here because i will need the reverse list with new image after first click.
It's not all of my Javascript. I tried to copy the parts which are related to my question. I hope it is an understandable example.
const sorting = document.querySelector('#sortingIcon');
let arr = [];
sorting.addEventListener('click', (event) => {
if (sorting.src = "images/Group74.png") {
sorting.src = "images/Group90.png";
const items = document.getElementsByTagName('li');
for (let i = 0; i < items.length; i++) {
console.log(items[i])
arr.push(items[i].firstChild.value);
}
arr.sort();
for (let i = 0; i < items.length; i++) {
items[i].firstChild.value = arr[i];
}
}
})
<div class="box">
<div id="yellow"></div>
<h1>To-do list</h1>
<img id="sortingIcon" src="images/Group74.png" alt="sorting">
<div id="inputBox">
<input class="input" type="text" name="input1">
<img class="clear" src="images/Group77.png" alt="">
</div>
<button id="plus_button">
<div id="flex">
<div id="plus">+</div>
<div id="enter">Добавить </div>
</div>
</button>
</div>
How can i make it stay that way?
I want to show div content on button click .and thee is 3 different button following 3 different content. I tried this logic and it made my code lengthy. how to simplify is code using loop or condition?
function replace1(){
document.getElementById("con1").style.visibility="visible";
document.getElementById("con2").style.visibility="hidden";
document.getElementById("con3").style.visibility="hidden";
document.getElementById("con4").style.visibility="hidden";
document.getElementById("con5").style.visibility="hidden";
document.getElementById("con6").style.visibility="hidden";
}
function replace2(){
document.getElementById("con1").style.visibility="hidden";
document.getElementById("con2").style.visibility="visible";
document.getElementById("con3").style.visibility="hidden";
document.getElementById("con4").style.visibility="hidden";
document.getElementById("con5").style.visibility="hidden";
document.getElementById("con6").style.visibility="hidden";
}
function replace3(){
document.getElementById("con1").style.visibility="hidden";
document.getElementById("con2").style.visibility="hidden";
document.getElementById("con3").style.visibility="visible";
document.getElementById("con4").style.visibility="hidden";
document.getElementById("con5").style.visibility="hidden";
document.getElementById("con6").style.visibility="hidden";
}
enter image description here
.active-button {
background: red;
}
<button class="replace-button" onclick="replace(1, this)"></button>
<button class="replace-button" onclick="replace(2, this)"></button>
<button class="replace-button" onclick="replace(3, this)"></button>
function replace(visibleIndex, _this) {
const buttons = document.querySelectorAll('.replace-button');
buttons.forEach(button => button.classList.remove("active-button"));
_this.classList.add("active-button");
for(let i = 1; i < 7; i++) {
let element = document.getElementById("con" + i)
i === visibleIndex ? element.style.visibility = "visible" : element.style.visibility = "hidden";
}
}
Use a class - add class="con" to each element - also use hidden instead of visibility since the hidden divs still will take up space
const toggle = id => cons
.forEach(con => con.hidden = con.id !== id);
Here is a version that will change the colour of the button too.
You will need to use hidden or display:none to have the divs stay in one place
window.addEventListener('DOMContentLoaded', function() {
const cons = document.querySelectorAll('.con');
const buts = document.querySelectorAll('.toggle');
const toggle = id => cons
.forEach(con => con.hidden = con.id !== id);
document.getElementById('nav').addEventListener('click', function(e) {
const tgt = e.target.closest('button');
if (tgt.classList.contains('toggle')) {
toggle(tgt.dataset.id)
buts.forEach(but => but.classList.remove('active'));
tgt.classList.add('active');
}
})
})
.active {
background-color: green;
}
<nav id="nav">
<button type="button" class="toggle" data-id="con1">Con 1</button>
<button type="button" class="toggle" data-id="con2">Con 2</button>
<button type="button" class="toggle" data-id="con3">Con 3</button>
</nav>
<div id="con1" class="con" hidden>
<h1>Con 1</h1>
</div>
<div id="con2" class="con"hidden>
<h1>Con 2</h1>
</div>
<div id="con3" class="con" hidden>
<h1>Con 3</h1>
</div>
I'm trying to loop through divs and set the content of a div inside the outer div. I tried this.
Here is the HTML div's I want to loop through and I want to set the content of div with class content-detail with the value for its attribute data-form data.
//the javascript code I used is this
$(function($) {
for (var i of $(".item .content-detail")) {
var container = document.querySelector($(i)[0]);
var formData = $(i).attr("data-formdata");
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.2.3/jquery.min.js"></script>
<div class="item">
<div class="down-div"> </div>
<div class="detail">
<h4>Detail</h4>
<div id="div_" class="content-detail" data-formdata="my Item">
</div>
<div class="text-center">
<button class="btn btn-blue center"> SET !</button>
</div>
</div>
</div>
<div class="item">
<div class="down-div"> </div>
<div class="detail">
<h4>Detail</h4>
<div id="div_" class="content-detail" data-formdata="my Item">
</div>
<div class="text-center">
<button class="btn btn-blue center"> SET !</button>
</div>
</div>
</div>
But am stuck at this point var container = document.querySelector($(i)[0]);
I don't know how to get the jquery selector of that current div to a variable.
This may need some tweaks, but it should be close...
$(function ($) {
$(".item .content-detail").each(function(index, element) {
element.text($(element).attr("data-formdata"))
})
});
Take a look at the .each() method
$(function($) {
for (var i of $(".item .content-detail")) {
//var container = document.querySelector($(i)[0]);
var container = i;
var formData = $(i).attr("data-formdata");
}
});
I just needed the element
If you want to set the content of each DIV, you don't need a for loop. The .text() method takes a callback function, and it will be called on each element that matches the selector. The returned value is used as the new content.
$(".item .content-detail").text(function() {
return $(this).data("formdata");
});
This works.
$(function($) {
$(".item .content-detail").text(function(){
return $(this).attr("data-formdata");
})
});
Can you not just use JS like this:
[UPDATED]
function test() {
var divs = document.getElementsByTagName("div");
for (var i = 0; i < divs.length; i++) {
var divsSub = divs[i].getElementById("div_").querySelectorAll(".content-detail");;
for (var iS = 0; iS < divsSub.length; iS++) {
var x = divsSub[iS].getAttribute("data-formdata");
divsSub[iS].innerHTML = x;
}
}
}
I have the following function which I have used for hiding and showing respective pages based on different button clicks. Now I am using JQuery and I want to be able to do the same thing but just with JQuery. There must be something wrong the way I am translating it cause it doesn't work.
function showPages() {
var aBtnShowPages = document.getElementsByClassName("btnShowPage");
// this is an array
for (var i = 0; i < aBtnShowPages.length; i++) {
aBtnShowPages[i].addEventListener("click", function () {
//console.log( "WORKS" );
// Hide the pages
var aPages = document.getElementsByClassName("page");
for (var j = 0; j < aPages.length; j++) {
aPages[j].style.display = "none";
}
var sDataAttribute = this.getAttribute("data-showThisPage");
//console.log( sDataAttribute );
document.getElementById(sDataAttribute).style.display = "flex";
});
}
}
JQuery version:
function showPages() {
let $aBtnShowPages = $(".btnShowPage");
// this is an array
for (let i = 0; i < $aBtnShowPages.length; i++) {
$aBtnShowPages[i].click(function () {
//console.log("WORKS");
// Hide the pages
let $aPages = $('.page');
for (let j = 0; j < $aPages.length; j++) {
$aPages[j].hide();
}
let $sDataAttribute = $(this).attr("data-showThisPage");
//console.log( $sDataAttribute );
$(sDataAttribute).show();
});
}
}
This shows how to toggle between those with "false" and those with "true" values. Pretty verbose and could simply be one function using .toggle(true) instead.
I put some fake markup in place since you provided none.
$(function() {
$(".btnShowPage").on("click", function() {
let $aPages = $('.page');
$aPages.hide();
$aPages.filter(function() {
return $(this).data("showThisPage") == true;
}).show();
}).trigger('click'); // set initial state ;
$(".btnHidePage").on("click", function() {
let $aPages = $('.page');
$aPages.show();
$aPages.filter(function() {
return $(this).data("showThisPage") == true;
}).hide();
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="page" data-show-this-page="true">showme1</div>
<div class="page" data-show-this-page="true">showme2</div>
<div class="page" data-show-this-page="true">showme3</div>
<div class="page" data-show-this-page="false">showme4</div>
<div class="page" data-show-this-page="true">showme5</div>
<div class="page" data-show-this-page="true">showme6</div>
<button id="showem" class="btnShowPage" type="button">showem</button>
<button id="hideem" class="btnHidePage" type="button">hideem</button>
Just show those with true set.
$(function() {
$(".btnShowPage").on("click", function() {
// just show those with true set
$('.page').each(function(index) {
let showme = $(this).data("showThisPage") == true;
$(this).toggle(showme);
});
}).trigger('click'); // set initial state ;
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="page" data-show-this-page="true">showme1</div>
<div class="page" data-show-this-page="true">showme2</div>
<div class="page" data-show-this-page="true">showme3</div>
<div class="page" data-show-this-page="false">showme4</div>
<div class="page" data-show-this-page="true">showme5</div>
<div class="page" data-show-this-page="true">showme6</div>
<button id="showem" class="btnShowPage" type="button">showem</button>
Show just a targeted element and hiding/showing all:
$(function() {
$(".btnShowPage").on("click", function() {
// just show those with the target
let showTarget = $(this).data("target");
switch (showTarget) {
case -1:
$('.page').hide();
break;
case "all":
$('.page').show();
break;
default:
$('.page').eq(showTarget).toggle(true);
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="page">showme0</div>
<div class="page">showme1</div>
<div class="page">showme2</div>
<div class="page">showme3</div>
<div class="page">showme4</div>
<div class="page">showme5</div>
<div class="page">showme6</div>
<button id="showem" class="btnShowPage" type="button" data-target="all">showem all</button>
<button id="showem" class="btnShowPage" type="button" data-target="1">showem 1</button>
<button id="showem" class="btnShowPage" type="button" data-target="2">showem 2</button>
<button id="showem" class="btnShowPage" type="button" data-target="5">showem 5</button>
<button id="showem" class="btnShowPage" type="button" data-target="-1">hide all</button>
I am working on a tic tac toe game, which is almost complete. The only thing I am left wondering about is if it is possible to add an event handler for onclick from my .js file instead of directly calling it from an HTML attribute. Here is the bit of HTML that uses the onclick:
<div id="left">
<div id="board">
<div id="one" onclick="playerMove(this)">
</div>
<div id="two" onclick="playerMove(this)">
</div>
<div id="three" onclick="playerMove(this)">
</div>
<div id="four" onclick="playerMove(this)">
</div>
<div id="five" onclick="playerMove(this)">
</div>
<div id="six" onclick="playerMove(this)">
</div>
<div id="seven" onclick="playerMove(this)">
</div>
<div id="eight" onclick="playerMove(this)">
</div>
<div id="nine" onclick="playerMove(this)">
</div>
</div>
</div>
Any thoughts on the matter would be greatly appreciated.
If you use jQuery something like this should work:
$(document).ready(function() {
$('#board div').click(playerMove);
});
In plain javascript (no cross platform libraries), event handlers can be added via javascript code with addEventListener (modern browsers) or attachEvent (older versions of IE).
Here's a simple function that adds an event handler in a cross browser fashion:
// add event cross browser
function addEvent(elem, event, fn) {
if (elem.addEventListener) {
elem.addEventListener(event, fn, false);
} else {
elem.attachEvent("on" + event, function() {
// set the this pointer same as addEventListener when fn is called
return(fn.call(elem, window.event));
});
}
}
Example usage (called after the page DOM has loaded):
addEvent(document.getElementById("one"), 'click', playerMove);
Or, to install event handlers for all the board divs, you could do this:
var divs = document.getElementById("board").children;
for (var i = 0, len = divs.length; i < len; i++) {
// element nodes only
if (divs[i].nodeType === 1) {
addEvent(divs[i], 'click', playerMove);
}
}
You should really consider using jQuery for this. If you were using jQuery, this would have been as simple as:
$('#board > div').click(playerMove);
In case you want to stick with vanilla JS, you can do:
var items = document.getElementById('board').children;
for(x in items) {
items[x].onclick = function() {
playerMove(items[x]);
};
}
Use this:
document.getElementById('element_id').onclick = function(){ playerMove(this); };
For each Div, change 'element_id' with 'one', 'two', ...
Try:
document.getElementById('one').onclick();
For binding the event handler in js file:
var board = document.getElementById('board'),
divs = board.getElementsByTagName('div'),
i, len = divs.length;
for (i = 0; i < len; i++) {
divs[i].onclick = function() {
playerMove(this);
};
}
Your answer is in following 5 lines. Try it :) If someone copies/converts my code in new post or my post to j-query, That is welcome with no problem.
var yourDivID = document.getElementById('your_Div_ID');
yourDivID.addEventListener('click', function (){ playerMove(this); }, false);
function playerMove(divElement)
{
alert(divElement.id);
}
I have tried to put complete demo Here on jsfiddle.net, You can click any div out of nine to check its event if link does not work, then you can check the following code (working for me WIN7 and FireFox)
<html>
<head>
<title> Add Events Dynamically </title>
<script type="text/javascript">
function add_DivClick_Events() {
var nodes = document.getElementById('board').childNodes;
for (var i = 0; i < nodes.length; i++) {
if (i % 2 == 1) {
nodes[i].addEventListener('click', function () {
playerMove(this);
}, false);
}
}
}
function playerMove(divElement)
{
alert(divElement.id);
}
</script>
<style type="text/css">
#board div
{
width:20px;
height:20px;
border:2px solid;
}
</style>
</head>
<body onload='add_DivClick_Events()'>
<div id="left">
<div id="board">
<div id="one">
</div>
<div id="two">
</div>
<div id="three">
</div>
<div id="four">
</div>
<div id="five">
</div>
<div id="six">
</div>
<div id="seven">
</div>
<div id="eight">
</div>
<div id="nine">
</div>
</div>
</div>
</body>
</html>