This question already has an answer here:
Why onchange function not called when checkbox changed using checked property
(1 answer)
Closed 2 years ago.
I tried to check a checkbox with js and detect the change, but the event onchange not detect the change, while that is visually changing. (sorry for by bad english, i'm french)
Here is an example:
document.querySelector("#checkbox").onchange = (e) => {
let checked = e.target.checked;
if (checked) {
console.log("checked !");
} else {
console.log("unchecked...");
}
}
document.querySelector("#buttonOn").onclick = (e) => {
document.querySelector("#checkbox").checked = true;
}
document.querySelector("#buttonOff").onclick = (e) => {
document.querySelector("#checkbox").checked = false;
}
<button id="buttonOn">On</button>
<button id="buttonOff">Off</button>
<input type="checkbox" name="" id="checkbox">
You need to trigger event while you click buttons
document.querySelector("#checkbox").onchange = (e) => {
let checked = e.target.checked;
if (checked) {
console.log("checked !");
} else {
console.log("unchecked...");
}
}
// Create new change event
var event = new Event('change');
document.querySelector("#buttonOn").onclick = (e) => {
document.querySelector("#checkbox").checked = true;
// Trigger onchange
document.querySelector("#checkbox").dispatchEvent(event);
}
document.querySelector("#buttonOff").onclick = (e) => {
document.querySelector("#checkbox").checked = false;
// Trigger onchange
document.querySelector("#checkbox").dispatchEvent(event);
}
<button id="buttonOn">On</button>
<button id="buttonOff">Off</button>
<input type="checkbox" name="" id="checkbox">
Related
I have created a checkbox directly in javascript, and binded a click event the following way :
let checkBox = document.createElement('input');
checkBox.onclick = (e) => {
console.log("click", e);
};
Now I would like to convert this element to plain html, while keeping the associated event. I now I can call checkBox.outerHTML to get the associated html, but the event would disappear.
Is there a way to do the same thing without removing the attached event ?
I don't know why would you need such an approach when you simply can append that element where ever you want. Yet, it is still simple to just fix it the way it is.
Instead of assigning an event, you should assign an attribute like this:
const checkBox = document.createElement('input');
checkBox.setAttribute("onclick", "cbxClicked(event)");
function cbxClicked(e) {
console.log("click", e);
};
console.log(checkBox.outerHTML); // <input onclick="cbxClicked(event)">
Tested well on chrome.
The recommended way is this
window.addEventListner("load",function() {
document.getElementById("checkboxContainer")
.addEventListener("click",function(e) {
const tgt = e.target;
if (tgt.type && tgt.type==="checkbox") {
console.log("click",tgt)
}
});
});
Now you can create your checkboxes before or after load
window.addEventListener("load", function() {
const container = document.getElementById("checkboxContainer");
container.addEventListener("click", function(e) {
const tgt = e.target;
if (tgt.type && tgt.type === "checkbox") {
console.log("click", tgt)
}
});
const inp = document.createElement("input")
inp.type = "checkbox";
inp.value = "dynamic";
container.appendChild(inp);
});
<div id="checkboxContainer">
<input type="checkbox" value="static" />
</div>
I have a problem with my "CheckCheck" function. The following part of the code should generate a to-do task. The input tag dynamically created in JS provides an option to set the priority to the given task. There is an option to set the task to "normal" or "priotity". However, the code sets the fisk task to "on" and after continues with the imposed "priority" and "normal" but inversely. How to prevent this from happening?
The code:
let tasklist = [];
function Apply() {
const Tasktask = document.querySelector(".task-form");
const Taskdate = document.querySelector(".date");
const Taskpriority = document.querySelector(".check-box");
function Prevent() {
if (Tasktask.value.length === 0 || Taskdate.value === "") {
alert("Fields cannot be empty!");
} else {
Pushed();
render();
clear();
}
}
Prevent();
function Pushed() {
let newTasks = new Tasks(Tasktask.value, Taskdate.value, Taskpriority.value);
tasklist.push(newTasks);
updateLocalStorage();
}
function render() {
CheckCheck();
insertTd();
}
function CheckCheck() {
if (Taskpriority.checked === true) {
Taskpriority.value = "priority"
} else {
Taskpriority.value = "normal"
}
}
function clear() {
Tasktask.value = "";
Taskdate.value = "";
Taskpriority.checked = false;
}
function insertTd() {
checkLocalStorage();
const parent2 = document.querySelector(".table-body");
parent2.innerHTML = "";
tasklist.forEach((item) => {
const table = `<tr>
<td>${item.task}</td>
<td>${item.date}</td>
<td>${item.priority}</td>
<td><a class="delete">delete</a></td>
</tr>`;
parent2.insertAdjacentHTML("afterbegin", table);
});
}
function deleteItem() {
const Table = document.querySelector("table").addEventListener("click", (e) => {
const currentTarget = e.target.parentNode.parentNode.childNodes[1];
if (e.target.innerHTML == "delete") {
if (confirm(`Are you sure you want to delete ${currentTarget.innerText}?`))
deleteTask(findTask(tasklist, currentTarget.innerText));
}
if (e.target.classList.contains("status-button")) {
findTask(tasklist, currentTarget.innerText);
}
updateLocalStorage();
insertTd();
});
}
deleteItem();
function deleteTask(currentTask) {
tasklist.splice(currentTask, currentTask + 1);
}
function findTask(taskArray, task) {
if (taskArray.length === 0 || taskArray === null) {
return;
}
for (let item of taskArray)
if (item.task === task) {
return taskArray.indexOf(item);
}
}
}
The other thing which is not working as intended is the confirm prompt. The more tasks I add, the more confirm prompts I get. I.e. for 1 task it is only one confirm window, for 3 tasks - 3 windows etc. Why is that?
I also attach below a JSFiddle link how better understanding.
Link
Thanks in advance for answers.
You don't get the state of a checkbox by reading its value but its checked property. Try document.querySelector('.check-box').checked
You keep reusing the same buttons and add an event listener to them each time. Either clone them every time, or add the listener once right after creating them.
Simple illustration of the problems here
document.querySelector('#readstates').addEventListener('click', e => {
e.preventDefault();
const disp = `Checked\n 1: ${chk1.checked}, 2: ${chk2.checked} \n`
+ `Value\n 1: ${chk1.value}, 2: ${chk2.value}`;
alert(disp);
});
const spawnBut = document.createElement('button');
spawnBut.id = 'spawned';
spawnBut.textContent = 'Spawned';
document.querySelector('#spawnDirty').addEventListener('click', e => {
const previous = document.querySelector('form #spawned');
if (previous) previous.remove();
document.querySelector('#spawnHere').append(spawnBut);
spawnBut.addEventListener('click', e => {
e.preventDefault();
alert('click!');
});
});
document.querySelector('#spawnClone').addEventListener('click', e => {
const previous = document.querySelector('form #spawned');
if (previous) previous.remove();
const nSpawnBut = spawnBut.cloneNode(true);
document.querySelector('#spawnHere').append(nSpawnBut);
nSpawnBut.addEventListener('click', e => {
e.preventDefault();
alert('click!');
});
});
<form>
<p class="inputs">
<label for="chk1">chk1:</label> <input type="checkbox" id="chk1" />
<label for="chk2">chk2:</label> <input type="checkbox" id="chk2" value="mycheckedvalue" />
<button id="readstates">Read chks</button>
</p>
<p class="button-spawners">
Try spamming those then click below:
<button type="button" id="spawnDirty"
title="Each time you click this one, the button below is respawned and a new handler is attached">
Spawn button
</button>
<button type="button" id="spawnClone"
title="This one will spawn a clone each time, so the click handler is attached only once">
Spawn button clone
</button>
</p>
<p id="spawnHere">
New button will spawn here
</p>
</form>
I have:
<label><input type="checkbox" name="all"> text</label>
<label><input type="checkbox" name="js-frameworks"> text</label>
const all = document.getElementsByName('all')[0];
const jsFrameworks = document.getElementsByName('js-frameworks')[0];
this.addEventListener("change", function() {
if (all.checked) {
jsFrameworks.parentNode.className = 'readonly';
}
});
I thought that when I deselect the checkbox the class 'readonly' will be removed as the code executes only when I tick the checkbox giving the if condition is true. I can't seem to escape the if condition, so to kind of toggle between the click and unclick. How can I do that?
Thanks
Change it this way:
this.addEventListener("change", function() {
if (all.checked) {
jsFrameworks.parentNode.className = 'readonly';
} else {
jsFrameworks.parentNode.className = '';
}
});
This way you are removing the class when unchecked.
UPDATE:
Or you could save the classes that your element may have before:
let classesBefore = jsFrameworks.parentNode.className;
this.addEventListener("change", function() {
if (all.checked) {
jsFrameworks.parentNode.className = classesBefore + ' readonly';
} else {
jsFrameworks.parentNode.className = classesBefore;
}
});
Try this.
const all = document.getElementsByName("all")[0];
const jsFrameworks = document.getElementsByName("js-frameworks")[0];
this.addEventListener("change", function() {
if (all.checked) {
jsFrameworks.parentNode.classList.add("readonly");
} else if (!all.checked) {
jsFrameworks.parentNode.classList.remove("readonly");
}
});
Try this
this.addEventListener("click", function() {
this.parentNode.toggle('readonly');
}
I am changing state of check boxes with following code:
document.getElementById('checkall').onclick = function(){
inputs = VARIABLE.querySelectorAll('input[type=checkbox]');
for(i=0; i<inputs.length; i++)
inputs[i].checked = true;
}
This section work fine.
and i am creating checkboxes with(these codes call on for):
mainFrameInput = document.createElement("input"); mainFrameInput.className = "item"; mainFrameInput.style.display='none'; mainFrameInput.setAttribute('type', 'checkbox'); mainFrameInput.setAttribute('id', GnId);
this section work fine too
At this time i want to have a function which run when check boxes changed because it can change on several way.
I am creating check boxes with JavaScript and want to handle onchange with JavaScript NOT JQUERY.
I tested CHECKBOX_VARIABLE.onchange = function{} but it does not call when i change with above code and just CHECKBOX_VARIABLE.onclick work when i click on each checkbox.
I found solution and posted as answer.
one way to do this is by using the native onchange attribute and give it a function
<select id="mySelect" onchange="alert('change')">
<option value="Audi">Audi</option>
<option value="BMW">BMW</option>
<option value="Mercedes">Mercedes</option>
<option value="Volvo">Volvo</option>
</select>
here's a fiddle showing this
https://jsfiddle.net/r4aj8zh2/
You can do this like that:
HTML:
<button id="checkall">check all</button><br>
a: <input type="checkbox" name="a" value="a"><br>
b: <input type="checkbox" name="b" value="b"><br>
c: <input type="checkbox" name="c" value="c">
JavaScript:
var inputs = document.querySelectorAll('input[type=checkbox]');
document.getElementById('checkall').onclick = function(){
for(var i=0; i<inputs.length; i++) {
inputs[i].checked = true;
}
somethingChanged();
}
for(var i=0; i<inputs.length; i++) {
inputs[i].addEventListener('change', somethingChanged);
}
function somethingChanged(evt) {
if (evt) {
console.log(evt.srcElement.name, 'changed');
}
else {
console.log('all changed');
}
}
Fiddle: https://jsfiddle.net/1m3rcvw9/
Explanation: When I tried it I could reproduce your problem - the change listener was not called when clicking the check-all button. So my idea is to just call the function manually after a click occurs on check-all. You can even distinguish between single checkbox clicks and check-all clicks by checking if there is a event-parameter.
EDIT: If you dynamically add <input> tags then just add the somethingChanged change listener right after creation of new elements and update the inputs variable by reselecting all checkboxes:
mainFrameInput = document.createElement("input");
mainFrameInput.addEventListener('change', somethingChanged);
// ... insert the element into DOM here
inputs = document.querySelectorAll('input[type=checkbox]');
You can addEventListener to these checkboxes
// Get all checkbox. Use more specific selector using name or class
var getAllCheckBox = document.querySelector('input[type=checkbox]');
// Adding event listener change to each checkbox
getAllCheckBox.addEventListener('change', function (event) {
if (getAllCheckBox.checked) {
// do something if checked
} else {
// do something else otherwise
}
});
Add event listener to element when element is created. Make sure the D is lower case d at .getElementById VARIABLE = document.getElementById('#div-id');
mainFrameInput = document.createElement("input");
mainFrameInput.addEventListener("change", function() {
// do stuff
})
FINALLY I RESOLVED THE ISSUE:
first of all i developed a function:
function fireEvent(element,event){
if (document.createEventObject){
var evt = document.createEventObject();
return element.fireEvent('on'+event,evt)
}
else{
var evt = document.createEvent("HTMLEvents");
evt.initEvent(event, true, true ); // event type,bubbling,cancelable
return !element.dispatchEvent(evt);
}
}
and called that when changed state of check box:
fireEvent(inputs[i],'change');
and added on change event when creating check boxes:
mainFrameInput.onchange = function(){
if (this.checked)
{
console.log('checked');
}
else
{
console.log('un checked');
}
}
I think it is more easy just define a onchange function into the input element like this:
const wrapperElement = document.querySelector('.wrapper')
const fruits = ['apple', 'orange', 'banana']
fruits.forEach(f => {
const item = document.createElement('div')
item.className = 'item'
const fruit = document.createElement('input')
fruit.type = 'checkbox'
fruit.id = f
fruit.onchange = handleOnChange
const label = document.createElement('label')
label.className = 'checkbox-label'
label.setAttribute('for', f)
label.textContent = f
item.append(fruit)
item.append(label)
wrapperElement.append(item)
})
function handleOnChange(e) {
const element = e.srcElement
element.parentElement.classList.toggle('checked')
}
.item.checked {
background: red;
}
<div class="wrapper"></div>
I am seeing how I can make an Are You Human checkbox, but I am having a problem (Code At The End). I am trying to make it see if it is clicked until it is clicked. I tried onclick, but that is not working.
window.onload = function() {
var input = document.getElementById('ruhuman');
function check() {
if (input.checked) {
ruhuman.checked = true;
if (event.originalEvent === undefined) {
ruhuman.human = false;
} else {
ruhuman.human = true;
}
}
alert(ruhuman.human);
alert(ruhuman.checked);
}
input.onchange = check;
check();
}
<input type="checkbox" id="ruhuman" class="ruhuman" onclick="check()" required="required">
<label>R U Human?</label>
Edit: Thanks for your help! Finished product at http://ruhuman.github.io/.
To the people that answered I can put your github for your help!
originalEvent is JQuery, not JavaScript. A workaround is to test screenX and screenY -- if it's a human, these will have some value based on the checkbox position. Also, you can remove the onclick from your html and tie your click event like this:
document.getElementById ("ruhuman").addEventListener("click", function(e){
if (this.checked) {
ruhuman.checked = true;
if (e.screenX && e.screenY) {
ruhuman.human = true;
} else {
ruhuman.human = false;
}
}
console.log(ruhuman.human);
console.log(ruhuman.checked);
});
JS Fiddle Demo
This works: https://jsfiddle.net/rz4pmp5L/3/
var input = document.getElementById('ruhuman');
var ruhuman =
{
checked: false
};
function check()
{
if (input.checked)
{
ruhuman.checked = true;
}
alert(ruhuman.checked);
}
input.onchange = check;
check();
The problem was (at least) that ruhuman was not defined at all.