Buttons disapper on adding new list items? - javascript

I am creating a list using javascript.After every list item, there are two buttons inserted. But these buttons appear only on last list item.Please help me.
My Code
Here is my function which updates the list using JS`
function updateView() {
fetchFromLocal(); //fetches list from local storage and updates TaskList array
list.innerHTML = ""; //list is var that points to unordered list
var checkbox = document.createElement("input");
checkbox.setAttribute('type', 'checkbox');
var btnUp = document.createElement("input");
btnUp.setAttribute('type', 'button');
btnUp.setAttribute('value', '^');
// console.log(btnUp);
var btnDown = document.createElement("input");
btnDown.setAttribute('type', 'button');
btnDown.setAttribute('value', 'v');
for(var i=0;i<TaskList.length;i++)
{
var TempElem = document.createElement("li");
//console.log(TempElem);
TempElem.appendChild(checkbox);
// console.log("Elem after checkbox " + TempElem.innerHTML);
TempElem.innerHTML += " <span class='listitem'> " + TaskList[i] + "</span>";
// console.log("Elem after tasklist "+ TempElem.innerHTML);
TempElem.appendChild(btnUp);
TempElem.appendChild(btnDown);
console.log("Final Tepelem " + TempElem.innerHTML);
list.appendChild(TempElem);
}
}

Because you are appending the same element so since the same element can not be in more than one place it is moved to the new location. You need to clone them before appending.
https://developer.mozilla.org/en-US/docs/Web/API/Node/cloneNode
TempElem.appendChild(checkbox.cloneNode(true));
You need to do it to the buttons also.

Related

Delete the text when clicked - javascript

I'm writing a code that I can add a list element text and delete it when clicking a certain part in the text, using two functions - add_in() and del_in().
so if I click add button, it should add "Reading (del)"
and when I click the text del, it should delete it.
I looked for getting the id of clicked element here, and used event target.
In add_in(), it adds the list element and I change its content using innerHTML so it contains a p element of (del).
the delNode should start del_in() when clicked.
In del_in(), it has addEventListener to get the id of clicked element and if it's a (del), it deletes.
html
<ol id='interests'>
//should be added here.
</ol>
<input type="text" id='add_int'></input>
<input type="button" value="add" id='add_btt' onclick='add_in();'>
javascript
var idcount = 0;
function add_in() {
nodeId = "new" + idcount;
++idcount;
var interest = document.getElementById('add_int').value;
var newNode = document.createElement("li");
newNode.setAttribute("id", nodeId);
newNode.innerHTML = interest + "<p id='del" + nodeId + "'>(del)</p>";
document.getElementById("interests").appendChild(newNode);
var delNode = document.getElementById('del' + nodeId);
delNode.setAttribute("onclick", "del_in();");
}
function del_in() {
var clickId = "";
document.addEventListener("click", function(e) {
clickId = e.target.id;
});
if (clickId.includes("delnew")) {
var clickEle = document.getElementById(clickId);
clickEle.parentNode.removeChild(clickEle);
}
}
It can add, but can't delete. Nothing happens when clicked.
If I type 'newNode' in console, it says: VM247:1 Uncaught ReferenceError: delNode is not defined. ClickId is not defined either after clicking an element.
Thanks for any help in advance.
Let me know if the code looks too complicated or the question looks too half-assed. I'll edit.
var idcount = 0;
function add_in() {
nodeId = "new" + idcount;
++idcount;
var interest = document.getElementById('add_int').value;
var newNode = document.createElement("li");
newNode.setAttribute("id", nodeId);
newNode.innerHTML = interest + "<p id='del" + nodeId + "'>(del)</p>";
document.getElementById("interests").appendChild(newNode);
var delNode = document.getElementById('del' + nodeId);
delNode.setAttribute("onclick", "del_in(this);");
}
function del_in(e) {
e.parentNode.remove();
}
<ol id='interests'>
//should be added here.
</ol>
<input type="text" id='add_int'></input>
<input type="button" value="add" id='add_btt' onclick='add_in();'>
the easy and simplest way you can try select parent element and change it e.parentNode.remove();

How to fire up a function when clicking on a link and then pass a class from that link

I have this HTML:
<li class="sshjd839djjd blahclass"><a onclick="doSomething()">Blah Blah</a></li>
So when I click my link doSomething() is triggered and I want to grab sshjd839djjd. I have many links with different keys like this one which I need to grab correct data.
I don't know much about Javascript and jQuery but I need it to make admin panel which I would use to manage my data in Firebase, just to explain what I'm doing.
I tried to avoid onClick and use .click but that didn't work.
Can somebody help me a bit please?
So what should go in:
function doSomething() {
// grab class which is actually a child key from Firebase which I already implemented
// do Firebase magic, I will know this once I get that key
}
Keys/classes are added like this:
var resultVetRef = new Firebase("https://myappname.firebaseio.com/data/users");
resultVetRef.on("child_added", function(snapshot) {
var key = snapshot.key();
var data = snapshot.val();
var name = data.name;
var city = data.city;
$("#results").append($("<li class=\"" + key + " blahclass\">" + "<a onClick=\"grabVet()\">" + name + ", " + city + "</a></li>"));
});
add the key as data to the li
var resultVetRef = new Firebase("https://myappname.firebaseio.com/data/users");
resultVetRef.on("child_added", function(snapshot) {
var key = snapshot.key();
var data = snapshot.val();
var name = data.name;
var city = data.city;
$("#results").append($("<li class=\"" + key + " blahclass\" data-key=\""+ key +"\">" + "<a onClick=\"grabVet()\">" + name + ", " + city + "</a></li>"));
});
Then get it like:
<li class="sepcialKey blahclass" data-key="sepcialKey"><a>Blah Blah</a></li>
$('a').click(function(){
alert($(this).closest('li').data('key'));
});
Here is the Demo: https://jsfiddle.net/ffyLgg3s/
Specifically for your example
<li class="sshjd839djjd blahclass"><a>Blah Blah</a></li>
$('a').click(function(){
alert( $(this).closest('li')[0].classList.item(0) );
});
using classList and item method.
or if you want to use your own doSomething
<li class="sshjd839djjd blahclass"><a onclick="doSomething(this)">Blah Blah</a></li>
function doSomething(thisObj)
{
alert($(thisObj).closest("li")[0].classList.item(0));
}
ClassList method gives you an array with all classes of the element.
In your case it will return array ["specialKey", "blahclass"] for your <li> element.
function doSomething() {
// get the firs element of classList array and asign it to a variable
var specialKey = this.parentElement.classList[0]; // "this" keyword is the reference to clicked element, "parentElement" give you "li" element reference
// do Firebase magic, I will know this once I get that key
}
Or modify your append code:
var resultVetRef = new Firebase("https://myappname.firebaseio.com/data/users");
resultVetRef.on("child_added", function (snapshot) {
var key = snapshot.key();
var data = snapshot.val();
var name = data.name;
var city = data.city;
// create li element
var li = $("<li class=\"blahclass\"></li>");
// create a element
var a = $("<a>" + name + ", " + city + "</a>");
a.on("click", function () {
// when a clicked execute "doSomething" passing key as parameter
doSomething(key);
})
// append a to li
li.append(a);
//append li to #results
$("#results").append(li);
});

link a checkbox to an object in Javascript

Suppose I have a table which is populated by filling out a form on a page and clicking the submit button.
The last column of the table is a Completed section with a checkbox on each row. On clicking on the checkbox I want to change the .completed property from false to true on that object.
How can I distinguish which checkbox was clicked and change the property from that row?
this.addRowToTable = function() {
return "<tr id='tableRow'><td>" + this.app + "</td><td>" + this.priority + "</td><td>" + this.date + "</td><td>" + this.additionalNotes + "</td><td>" + "<input type='checkbox' class='checkApp[]' value='" + this.completed + "' />" + "</td></tr>";
};
I have all the checkboxes in the checkApp array, but Im not sure where to go from there?.
This is called when the form is submitted:
function addAppointment() {
if (txtApp.value == "" || txtPriority.value == "" || txtDate.value == "" || {
alert("Please fill all text fields");
} else {
var app = new Appointment(txtApp.value, txtPriority.value, txtDate.value, txtNotes.value, false);
apps.push(app);
localStorage.setItem("apps", JSON.stringify(apps));
clearUI();
}
updateTable();
updateTable() loops through all objects in my array and adds them between table tags:
for (var i = 0; i < apps.length; i++) {
var app = new Appointment(apps[i].app, apps[i].priority, expenses[i].date, apps[i].notes, false);
tblHTML += app.addRowToTable();
}
My Appointment Object:
function Appointment(app, priority, date, notes, completed) {
this.app = app;
this.priority = priority;
this.date = date;
this.additionalNotes = notes;
this.completed = completed;
this.addRowToTable = function { ... };
}
First of all, in HTML, id attributes should be unique. So, make sure table rows have unique IDs. At the moment, all of them have the identical ID of tableRow.
Besides, you should consider using a framework/library such as jQuery for real-world scenarios rather than creating the DOM elements, etc. manually.
Now back to the original problem: if you use the DOM API rather than string concatenation to create the table rows, you can add custom fields to the DOM objects representing the table rows. So, from each table row, you can have a reference back to its corresponding Appointment object:
var row = document.createElement("tr");
row.appointment = this;
Similarly, you can use the DOM API to create the table cells as well as the checkbox:
addTd(row, this.app);
addTd(row, this.priority);
addTd(row, this.date);
addTd(row, this.additionalNotes);
var input = document.createElement("input");
var td = document.createElement("td");
td.appendChild(input);
row.appendChild(td);
input.setAttribute("type", "checkbox");
input.setAttribute("class","checkApp[]"); // Why checkApp[]? checkApp or check-app make more sense
input.setAttribute("value", this.completed);
where addTd is the following function:
function addTd(row, innerHTML) {
var td = document.createElement("td");
td.innerHTML = innerHTML;
row.appendChild(td);
}
Now that you are using the DOM APIs, you can easily attach event listeners to each checkbox object as well.
Then inside the event listener you can get a reference back to the Appointment corresponding to the row you
have changed its checkbox:
var row = document.createElement("tr");
row.appointment = this;
addTd(row, this.app);
addTd(row, this.priority);
addTd(row, this.date);
addTd(row, this.additionalNotes);
var input = document.createElement("input");
var td = document.createElement("td");
td.appendChild(input);
row.appendChild(td);
input.setAttribute("type", "checkbox");
input.setAttribute("class","checkApp[]"); // Why checkApp[]? checkApp or check-app make more sense
input.setAttribute("value", this.completed);
input.addEventListener("change", function(event) {
var row = this.parentNode.parentNode,
appointment = row.appointment;
// change appointment however you like
});

Select menu behaving strangely with AJAX

I have a dropdown whose options get filled dynamically:
function populateDropdown(dropdownNum) {
// invokeWebService uses $.ajax
json = invokeWebService("GET", "/webservice/dropwdownOptions");
optionsHtml = "";
$.each(json, function(count, jsObj) {
optionValue = jsObj.name
optionsHtml+="<option>" + optionValue + "</option>";
});
var dropdownId = "#NRdropdown_" + dropdownNum;
$(dropdownId).html(optionsHtml);
}
function display(blockNum) {
var url = "/webservice/blocks" + blockNum;
var response = invokeWebService("GET", url);
var replacementHtml = "";
var currBlock = "blah";
$.each(response, function(i, block) {
currName = block.name;
var textfield = "<input type='text' id='blockValue" + block.id +
"'>";
var dropdownMenu = "<select id=\"NRdropdown_" + i +
"\"onClick=\"populateDropDown(" + i +
")\"><option>Existing Blocks</option>"
var submitButton = "<input type='submit' value='UPDATE' id='" +
block.id + "'><br><br>";
replacementHtml = currName + textfield + dropdownMenu + submitButton;
});
$("#main").html(replacementHtml);
}
The javascript function "populateDropdown(dropdownNum)":
Makes the ajax request
Parses the json response for the option values into an html string called optionsHtml
Replaces the inner html of the select element with the option values via:
var dropdownSelector = "#NRdropdown_" + dropdownNum;
$(dropdownSelector).html(optionsHtml)
1) When I click on the dropdown arrow, I STILL see "Existing Blocks".
2) After 1 sec I see the first dynamically generated option UNDERNEATH the "Existing Blocks" option, I don't see the other dynamically generated options.
3) Then I click outside the dropdown and see the dropdwon showing the first dynamically generated value.
4) Finally I click the dropdown arrow again and it works as it should with all the dynamically generated values.
How do I make it work so that:
When the page first loads, the dropdown shows "Existing Blocks".
Once I click the dropdown arrow, the dropdown should show all dynamically generated values without the "Existing Blocks" value.
Thanks!
the dropdown listener should be for onmousedown, not onclick

Add items to a list using jquery

I had a quick question that I can't figure out. I am working with this code:
http://jsfiddle.net/spadez/ZTuDJ/32/
// If JS enabled, disable main input
$("#responsibilities").prop('disabled', true);
// $("#responsibilities").addClass("hidden");
// If JS enabled then add fields
$("#resp").append('<input placeholder="Add responsibility" id="resp_input" ></input><input type="button" value="Add" id="add"> ');
// Add items to input field
var eachline='';
$("#add").click(function(){
var lines = $('#resp_input').val().split('\n');
var lines2 = $('#responsibilities').val().split('\n');
if(lines2.length>10)return false;
for(var i = 0;i < lines.length;i++){
if(lines[i]!='' && i+lines2.length<11){
eachline += lines[i] + '\n';
}
}
$('#responsibilities').text($("<div>" + eachline + "</div>").text() );
$('#resp_input').val('');
});
The idea is that you type something in the responsibility field and it gets inserted into a text area. What I also want to do is that when an item is inserted into the text area it also prints it out above it in a list format like this:
<li>inserted item 1</li> <li>inserted item 2</li>
I'm really new to javascript but this was my best stab at it based on information found online:
$("#resp").append('<li> +eachline </li> ')
$('#responsibilities').text($("<div>" + eachline + "</div>").text() ).before("<li>"+lines+"</li>");
Demo ---> http://jsfiddle.net/ZTuDJ/34/
http://jsfiddle.net/pjdicke/ZTuDJ/35/
You will need to create a <ul> then add this below
$('#responsibilities').text( $("<div>" + eachline + "</div>").text() );
// add this line after above
$('<li>' + lines + '</li>').appendTo('#list');
I already fixed that for you in your previous question.
Jquery adding items to a list without reloading page
http://jsfiddle.net/blackjim/VrGau/15/
var $responsibilityInput = $('#responsibilityInput'),
$responsibilityList = $('#responsibilityList'),
$inputButton = $('#addResp'),
rCounter = 0;
var addResponsibility = function () {
if(rCounter < 10){
var newVal = $responsibilityList.val()+$responsibilityInput.val();
if(newVal.trim()!==''){
var newLi = $('<li>');
$('ul#respList').append(newLi.text(newVal));
$responsibilityList.val('');
rCounter+=1;
}
}
}
$inputButton.click(addResponsibility);

Categories

Resources