im at javascript and dom. what i'd like to do with the below codes is when i append a tr and click the 2nd td (last name), the 2nd td value will be changed bold. then when i click the 2nd td value again, it will get back to normal. i've done with changing it bold but i cant make it go back to normal. i know if i add a button with onclick method calling detHandler. but i am not allowed to make a button for that. i need to click that name again to go back to normal. do you guys have any ideas?
<script type="text/javascript">
function appendUser()
{
var fname=prompt("Please enter your First Name");
var lname=prompt("Please enter your Last Name");
var email=prompt("Please enter your Email Address");
var table=document.getElementById("appendable");
var tr=document.createElement("tr");
var td1=document.createElement("td");
var td2=document.createElement("td");
td2.id="p1";
var td3=document.createElement("td");
td1.innerHTML = fname;
td2.innerHTML = lname;
td3.innerHTML = email;
tr.appendChild(td1);
tr.appendChild(td2);
tr.appendChild(td3);
tr.style.color="green";
table.appendChild(tr);
addHandler();
}
function addHandler ()
{
var addH = document.getElementById('p1');
if (addH.addEventListener)
{
addH.addEventListener('click', applyStyle, false);
}
else if (addH.attachEvent)
{
addH.attachEvent('onclick', applyStyle);
}
}
function detHandler ()
{
alert("aa");
var detH = document.getElementById('p1');
if (detH.removeEventListener)
{
detH.removeEventListener('click', applyStyle, false);
detH.style.color="blue";
//detH.style.fontWeight="normal";
}
else if (detH.detachEvent)
{
detH.detachEvent('onclick', applyStyle);
}
}
function applyStyle ()
{
var add = document.getElementById('p1');
add.style.fontWeight="bold";
}
</script>
</head>
<body>
<table id="appendable" width='50%' border='1'><tr><th>First Name</th><th>Last Name</th>
<th>Email Address</th></tr>
</tr></table>
<p><button onclick="appendUser()">Append New Row</button></p>
</body>
</html>'
Just toggle it in the handler
function applyStyle (){
var add = document.getElementById('p1');
var curr = add.style.fontWeight;
add.style.fontWeight = curr != 'bold' ? 'bold' : 'inherit';
}
FIDDLE
It is this line:
if (addH.addEventListener)
In the W3C model, you cannot find out whether an event is registered on an element or not.
You have duplicate IDs in your code (every row will have a cell with id="pq"!)
Consider this solution:
function appendUser()
{
var fname=prompt("Please enter your First Name");
var lname=prompt("Please enter your Last Name");
var email=prompt("Please enter your Email Address");
var table=document.getElementById("appendable");
var tr=document.createElement("tr");
var td1=document.createElement("td");
var td2=document.createElement("td");
var td3=document.createElement("td");
td1.appendChild(document.createTextNode(fname));
td2.appendChild(document.createTextNode(lname));
td2.setAttribute("data-toggleme","true"); // this is how we identify the cell
td3.appendChild(document.createTextNode(email));
tr.appendChild(td1);
tr.appendChild(td2);
tr.appendChild(td3);
tr.style.color="green";
table.appendChild(tr);
}
document.getElementById('appendable').onclick = function(e) {
e = e || window.event;
var t = e.srcElement || e.target;
while( t != this && t.nodeName != "TD") t = t.parentNode;
if( t.getAttribute("data-toggleme")) {
t.style.fontWeight = t.style.fontWeight == "bold" ? "" : "bold";
}
}
Deferring event handlers like this is great for two reasons:
Fewer event handlers! Makes the browser faster not having to keep track of so much.
It is future-proof in that you can add more rows and they will "automatically" be handled correctly
Related
This question already has answers here:
JavaScript closure inside loops – simple practical example
(44 answers)
Closed 3 years ago.
I have the following HTML written. The idea is that I can add items to the list at the top, and then generate a field which includes a name, checkbox, and text field. The text field is to be enabled/disabled depending on the checkbox. In my javascript, the toggle function is assigned to the onclick attribute of the checkbox field, but it only works on the last item on the list. Can anyone tell why this functionality isn't being assigned to all the checkboxes? If you open the resulting html code in a browser, it shows no onclick events for any checkboxes except the last one, so it appears it isn't being added. Does it somehow get removed from the previous one when I assign it to the next? How would I fix it? Thank you.
<!DOCTYPE html>
<html>
<body onload="loadAllSettings()" }>
<script>
var genOptFields = ["genField1", "genField2"];
function loadAllSettings() {
loadSettingsList("genSet", genOptFields);
}
</script>
<h2>Options</h2>
<form>
<fieldset id="genSet">
<legend>General</legend>
</fieldset>
</form>
<script>
function loadSettingsList(parentId, optionalFields) {
var fieldset = document.getElementById(parentId);
for (fieldId of optionalFields) {
var p = document.createElement('p');
p.append(fieldId + ":");
var input = document.createElement('input');
input.type = "text";
input.disabled = true;
input.id = fieldId;
var cb = document.createElement('input');
cb.type = "checkbox";
cb.id = "cb_" + fieldId;
cb.addEventListener("click", function () {
toggleCheck(fieldId);
});
p.appendChild(cb);
p.appendChild(input);
fieldset.appendChild(p);
}
}
function toggleCheck(fieldId) {
document.getElementById(fieldId).disabled = !document.getElementById("cb_" +
fieldId).checked;
}
</script>
</body>
</html>
As explained below, your fieldId reference isnt static. As a result when calling toggle check it was always passing the last value that fieldId contained no matter what (double check this by console.logging your fieldId passed to toggle check)
function loadAllSettings() {
const genOptFields = ["genField1", "genField2"];
loadSettingsList("genSet", genOptFields);
}
function loadSettingsList(parentId, optionalFields) {
const fieldset = document.getElementById(parentId);
optionalFields.forEach(function (fieldId) {
createParagraph(fieldId, fieldset);
});
}
function createParagraph(fieldId, fieldset) {
const p = document.createElement('p');
p.append(fieldId + ":");
createCheckbox(p, fieldId);
createInputField(p, fieldId);
fieldset.appendChild(p);
}
function createInputField(p, fieldId) {
const input = document.createElement('input');
input.type = "text";
input.disabled = true;
input.id = fieldId;
p.appendChild(input);
}
function createCheckbox(p, fieldId) {
const cb = document.createElement('input');
cb.type = "checkbox";
cb.id = "cb_" + fieldId;
//set this attribute to capture value
cb.setAttribute('data-fieldId', fieldId);
cb.addEventListener("click", function () {
//use static data attribute value instead of fieldId var which isnt static
toggleCheck(this.getAttribute('data-fieldId'));
});
p.appendChild(cb);
}
function toggleCheck(fieldId) {
document.getElementById(fieldId).disabled = !document.getElementById("cb_" + fieldId).checked;
}
<!DOCTYPE html>
<html>
<body onload="loadAllSettings()" }>
<h2>Options</h2>
<form>
<fieldset id="genSet">
<legend>General</legend>
</fieldset>
</form>
</body>
</html>
Since you are generating the element using body on-load event, click event become static. That is why element is always pointing to the last child. You can simply achieve your requirement by passing element scope(this) into the click event.
Here is the working solution:
<body onload="loadAllSettings()" }>
<script>
var genOptFields = ["genField1", "genField2"];
function loadAllSettings() {
loadSettingsList("genSet", genOptFields);
}
</script>
<h2>Options</h2>
<form>
<fieldset id="genSet">
<legend>General</legend>
</fieldset>
</form>
<script>
function loadSettingsList(parentId, optionalFields) {
var fieldset = document.getElementById(parentId);
for (fieldId of optionalFields) {
var p = document.createElement('p');
p.append(fieldId + ":");
var input = document.createElement('input');
input.type = "text";
input.disabled = true;
input.id = fieldId;
var cb = document.createElement('input');
cb.type = "checkbox";
cb.id = "cb_" + fieldId;
cb.addEventListener("click", function () {
toggleCheck(this);
});
p.appendChild(cb);
p.appendChild(input);
fieldset.appendChild(p);
}
}
function toggleCheck(ele) {
ele.nextElementSibling.disabled = !ele.checked;
}
</script>
</body>
I created a form dynamically with javascript. Now I have to add validations on the form (only mandatory validations) on click of the button which is also dynamically created. Now the issue I am facing is that whenever I try to add addEventListener on the button exactly after creating it, it is giving me error.
(
function init() {
console.log("div created");
// create a new div element
var newDiv = document.createElement("div");
newDiv.id = "registration_form";
var createForm = document.createElement("form");
newDiv.appendChild(createForm);
var heading = document.createElement("h2");
heading.innerHTML = "Registration Form";
createForm.appendChild(heading);
var linebreak = document.createElement('br');
createForm.appendChild(linebreak);
createElement(createForm, 'label','','','Name: ');
createElement(createForm, 'text', 'dname', '','');
createSpanTag(createForm,'nameError');
breakTag(createForm);breakTag(createForm);
createElement(createForm, 'label','','','Email: ');
createElement(createForm, 'email', 'email', '','');
createSpanTag(createForm,'emailError');
createElement(createForm, 'button','Validate','Validate','');
document.getElementsByTagName('button')[0].addEventListener('click',validate());
document.getElementsByTagName('body')[0].appendChild(newDiv);
}
)();
function createElement(formElement,type,name,value, placeholder) {
if(type=='label'){
var element=document.createElement(type);
if(name!='' && value!=''){
element.setAttribute('name',name);
element.setAttribute('value',value);
}
element.innerHTML=placeholder;
formElement.appendChild(element);
} else {
var element=document.createElement('input');
if(type!=''){
element.setAttribute('type',type);
}
if(name!=''){
element.setAttribute('name',name);
}
if(value!=''){
element.setAttribute('value',value);
}
if(placeholder!=''){
element.setAttribute('placeholder',placeholder);
}
formElement.appendChild(element);
}
}
function breakTag(createForm){
createForm.appendChild(document.createElement('br'));
}
function validate(){
}
function createSpanTag(createForm, id){
var element=document.createElement('span');
element.setAttribute('id',id);
createForm.appendChild(element);
}
The second argument of addEventListener needs to be a function.
Change ...
document.getElementsByTagName('button')[0].addEventListener('click',validate())
to ...
document.getElementsByTagName('button')[0].addEventListener('click',validate);
Since your tag name is input, not button. So use input in parameter of the function getElementsByTagName() and then loop through all nodes and find node with type = button.
Try change this line:
document.getElementsByTagName('button')[0].addEventListener('click',validate());
to:
var nodeList = document.getElementsByTagName("input");
for (var i = 0; i < nodeList.length; i++)
{
if (nodeList[i].getAttribute("type") == "button") {
{
nodeList[i].addEventListener('click',validate);
}
}
I have a script that makes a button in a table every 5 seconds.
I originally had the button made with the onclick attribute which called a function in the script. This however, gave me an error saying that the function didn't exist, and as from what I've seen on here, it has been answered but I don't know how I'd fix it in my situation. I switched it so that Javascript handles for the button click. I added attributes to the button tag to grab when the btnTeamListAction function is called. The console prints the following,
control.js:86 Uncaught TypeError: Cannot set property 'onclick' of null
at window.onload (control.js:86)
JS Snippets:
#button click handler
btnTeamListAction.onclick = function(){
var id = this.getAttribute("data-team-id");
var isRedo = this.getAttribute("data-is-redo");
teamListSelect(id,isRedo);
}
#the function that creates the buttons
function appendTeamTable(id,name,finished){
var finished_txt;
var action_content;
if(finished == 1){
finished_txt = "Yes";
action_content = '<button id="teams-list-action" data-team-id="'+id+'" data-is-redo="1">Retime</button>';
}
else {
finished_txt = "No";
action_content = '<button id="teams-list-action" data-team-id="'+id+'" data-is-redo="0">Time</button>';
}
var tr = document.createElement('tr');
tr.innerHTML ='<td>'+ id +'</td><td>'+ name +'</td><td>'+ finished_txt +'</td><td>'+ action_content +'</td>'
teamTable.appendChild(tr);
var btnTeamListAction = document.getElementById("teams-list-action");
btnTeamListAction.onclick = function(){
console.log("ActionClicked");
var id = this.getAttribute("data-team-id");
var isRedo = this.getAttribute("data-is-redo");
teamListSelect(id,isRedo);
}
}
I've tried browsing this form for this error and have found many related questions but not for this particular case with the button being created by JS itself.
Please ask if you need the full script or HTML, Thanks!
function appendTeamTable(id,name,finished){
var finished_txt;
var action_content= document.createElement("a");
var btn = document.createElement("button");
btn.setAttribute("id","teams-list-action");
btn.setAttribute("data-team-id",id);
if(finished == 1){
finished_txt = "Yes";
var t = document.createTextNode("Retime");
btn.setAttribute("data-is-redo","1");
}
else {
finished_txt = "No";
var t = document.createTextNode("Time");
btn.setAttribute("data-is-redo","0");
}
btn.appendChild(t);
btn.addEventListener("click",function(){
var id = this.getAttribute("data-team-id");
var isRedo = this.getAttribute("data-is-redo");
teamListSelect(id,isRedo);
});
action_content.appendChild(btn);
var tr = document.createElement('tr');
var td = document.createElement('td');
td.appendChild(action_content);
tr.innerHTML ='<td>'+ id +'</td><td>'+ name +'</td><td>'+ finished_txt +'</td>'
tr.appendChild(td);
teamTable.appendChild(tr);}
I looked at the post here and took the idea from the second answer and put a event handler on the table itself instead of the buttons individually. It's works like a charm now. Thanks all three of you for attempting to look through my seriously messed up code! :)
I have a form, and I would like to clear the input field every time I enter the submit (plus) button.
I have tried using this, it does not work. I may be implementing it in the wrong spot.
document.getElementById('add-item').value='';
My Javascript code is below.
window.addEventListener('load', function(){
// Add event listeners
document.getElementById('add-item').addEventListener('click', addItem, false);
document.querySelector('.todo-list').addEventListener('click', toggleCompleted, false);
document.querySelector('.todo-list').addEventListener('click', removeItem, false);
function toggleCompleted(event) {
console.log('=' + event.target.className);
if(event.target.className.indexOf('todo-item') < 0) {
return;
}
console.log(event.target.className.indexOf('completed'));
if(event.target.className.indexOf('completed') > -1) {
console.log(' ' + event.target.className);
event.target.className = event.target.className.replace(' completed', '');
document.getElementById('add-item').value='';
} else {
console.log('-' + event.target.className);
event.target.className += ' completed';
}
}
function addItem() {
var list = document.querySelector('ul.todo-list');
var newItem = document.getElementById('new-item-text').value;
var newListItem = document.createElement('li');
newListItem.className = 'todo-item';
newListItem.innerHTML = newItem + '<span class="remove"></span>';
list.insertBefore(newListItem, document.querySelector('.todo-new'));
}
function removeItem(event) {
if(event.target.className.indexOf('remove') < 0) {
return;
}
var el = event.target.parentNode;
el.parentNode.removeChild(el);
}
});
This is what you need:
document.getElementById('new-item-text').value = "";
regarding your need, you will need to put it at the end of your addItem()
you can refer this simple code:
<html>
<body>
<input type="text" id="test">
<button onclick="func()">remove</button>
<br/>
Value = <span id="val"></span>
<script>
function func(){
alert("clicked");
document.getElementById('val').innerHTML = document.getElementById('test').value;
document.getElementById('test').value = '';
}
</script>
</body>
</html>
Use form reset method to clear inputs in one go.
document.getElementById("myForm").reset();
You can set your textbox value = '' in submit button.
and you can create a ClearFunction and then you can call it everytime you need it.
function cleartextbox() {
$('#name').val("").focus();
$('#selectgender').val("");
$('#telephone').val("");
}
folks!
I've a litte problem, this is the situation:
Tree View
I let the tree on basis of the "lvl" create. That means, Bereich ABC is lvl1, Test1.docx is lvl4 and so on. So it's a "fake" Tree. But i have just this lvl information for every object.
I have to check the checkbox if the parent is clicked. that means, if lvl3 is clicked (for example "Originale") the lvl4 and lvl5 have to be checked also.
Do you understand what i mean? I hope so. But i can't make it working. Do you have any ideas?
$('[class^=lvl]').click(function(){
var keepChecking = true;
var currentElement = $(this);
var clickedLevel = getLevel(currentElement);
var checkValue = currentElement.is(':checked');
while (keepChecking) {
currentElement.attr('checked' , checkValue);
// get next element
currentElement = getNextCheckbox(currentElement);
var currentLevel = getLevel(currentElement);
keepChecking = (currentLevel > clickedLevel);
}
});
function getNextCheckbox(checkbox) {
return checkbox.parent().parent().next().children(":first").children(":first");
}
function getLevel(checkbox) {
var currentClass = checkbox.attr('class');
var currentLvl = currentClass.substring(3, currentClass.length);
return parseInt(currentLvl);
}
<TD class="center">
<INPUT TYPE="checkbox" NAME="" class="lvl[LL_REPTAG=PFADLEVEL /] docCheck" VALUE="[LL_REPTAG=DataId /]">
</TD>
I changed your javascript code to this:
function getNextCheckbox(checkbox) {
return checkbox.parent().parent().next().children(":first").children(":first");
}
function getLevel(checkbox) {
var currentClass = checkbox.attr('class');
if (currentClass){
var currentLvl = currentClass.substring(3, currentClass.length);
return parseInt(currentLvl);
}else{
return false;
}
}
$('[class^=lvl]').click(function(){
var currentElement = $(this);
var clickedLevel = getLevel(currentElement);
var checkValue = currentElement.is(':checked');
nextElement = getNextCheckbox(currentElement);
while ( getLevel(nextElement)>clickedLevel) {
currentElement=nextElement;
currentElement.prop('checked' , checkValue);
nextElement = getNextCheckbox(currentElement);
}
});
You can also play with it here: https://jsfiddle.net/1r73vy7z/1/
Enjoy :)