How to add dynamic lists in javascript not jquery - javascript

Am having the data as
var response = '[{"id":1,"name":"Web Demo"},{"id":2,"name":"Audio Countdown"},{"id":3,"name":"The Tab Key"},{"id":4,"name":"Music Sleep Timer"}]';
var obj = JSON.parse(response);
So how I can add the list items dynamically so in future if the list items in the backend increases they should be added directly and how can link dynamic and static elements.
Thanks

Use js appendChild to append each item in your html like this...
var response = [{"id":1,"name":"Web Demo"},{"id":2,"name":"Audio Countdown"},{"id":3,"name":"The Tab Key"},{"id":4,"name":"Music Sleep Timer"}] ;
for (i = 0; i < response.length; i++)
{
var node = document.createElement("LI"); // Create a <li> node
var textnode = document.createTextNode(response[i].name); // Create a text node
node.appendChild(textnode);
document.getElementById("items").appendChild(node); ///append Item
}
<div id="items"></div>

If you want to change your lists according the the changes in the backend, you should periodically test for that via ajax. You can use setInterval and
XMLHttpRequest for these purposes.
When the new data arrives, you should erase your existing list and add new elements to represent the arrived data dynamically.
setInterval(function(){
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (xhttp.readyState == 4 && xhttp.status == 200) {
populateList(xhttp.responseText); //This is your function to create the list
}
};
xhttp.open("GET", "http://www.mybackend.com/list", true);
xhttp.send();
})
And you can use document.createElement function to create a series of elements to represent your data.
function populateList(data) {
var obj = var obj = JSON.parse(response);
document.getElementById('myUl').remove(); //Delete the existing list
var myUi = document.createElement('ul'); //Add new list
obj.forEach(item) {
var listItem = document.createElement('li');
myUi.appendChild(li);
//Then add li details here
}
}
This is just rough code. Your can youse Jquery to get this done very shorter than this. You can even use a JS framework like Angular to automate most of these tasks.

If you are storing dynamic data as like static data, use concat
response.concat(dynamicdata);

Related

XHR request in for loop fires only once

Im making a website for this spa bussiness. It has four horizontal sections with several buttons each, every button should display its own "treatment information" in the div "#container_xhr_info".
To avoid stuffing the HTML I put all the treatment divs in their own html file in a folder, so when making click on a button the XHR request should fetch the button's file and display it inside the container.
Ive added a Click Event to the buttons with a for loop, the event fires the xhr. I also saved the file URLs in an array to put them inside the open() also with a for loop. So far the code works but it displays the 4th URL in the array on every button (the "peeling" one). I havent found a solution to this specific case.
let array_asyncs_facial_location = ["Asyncs/facial/radio.html",
'Asyncs/facial/diamante.html',
'Asyncs/facial/limpieza.html',
'Asyncs/facial/peeling.html',
'Asyncs/facial/acne.html',
'Asyncs/facial/rosacea.html',
'Asyncs/facial/pustulas.html'];
let tratamientos_facial = document.getElementsByClassName('tratamientos_facial');
for(var i = 0; i < tratamientos_facial.length; i++){
tratamientos_facial[i].addEventListener('click', ()=>{
let xhr = new XMLHttpRequest;
let url = array_asyncs_facial_location[i];
xhr.open('GET', url );
xhr.addEventListener('load', ()=>{
if (xhr.status == 200){
let plantilla = xhr.response;
let container_xhr_info = document.querySelector('#container_xhr_info');
container_xhr_info.innerHTML = plantilla;
}
})
xhr.send();
})
}
The variable i that you're relying on to get your URL isn't resolved until the click function fires, at which point it's not the same value as when you set up the listener. There's a better way. Pass through the event argument in your listener and set the url dynamically using element.setAttribute(), then get the value in element.dataset. Setting an attribute like data-url allows us to get it simply with element.dataset.url
let array_asyncs_facial_location = ["Asyncs/facial/radio.html",
'Asyncs/facial/diamante.html',
'Asyncs/facial/limpieza.html',
'Asyncs/facial/peeling.html',
'Asyncs/facial/acne.html',
'Asyncs/facial/rosacea.html',
'Asyncs/facial/pustulas.html'
];
let tratamientos_facial = document.getElementsByClassName('tratamientos_facial');
for (var i = 0; i < tratamientos_facial.length; i++) {
// set the URL as an attribute of the element itself so we can get it later
tratamientos_facial[i].setAttribute('data-url', array_asyncs_facial_location[i]);
tratamientos_facial[i].addEventListener('click', (event) => {
// make sure to pass the event argument through
let xhr = new XMLHttpRequest;
// now we just query the dataset property
let url = event.target.dataset('url');
xhr.open('GET', url);
xhr.addEventListener('load', () => {
if (xhr.status == 200) {
let plantilla = xhr.response;
let container_xhr_info = document.querySelector('#container_xhr_info');
container_xhr_info.innerHTML = plantilla;
}
})
xhr.send();
})
}

How to Load CSV to array with object names

I want to be able to store the the data in my CSV files so I can read it easier and serve it to a webpage.
The CSV is in the following format, probname1:"meat1", probename2:"meat2".......
If I paste the data in manual like https://www.w3schools.com/js/tryit.asp?filename=tryjs_array_object
it works,
I also tried setting up my array dirrentely and using MGot90's method from Read CSV headers using Javascript
But I can only ever call 1 full value of each object e.g settings[0], and not call the object by its name e.g settings["ProbeName1"]
I want the following to beable to output meat1 with the following in the CSV file.
updatevalues.csv = probname1:"meat1", probename2:"meat2"
loadData();
function loadData() {
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
parseCSV(this.responseText);
}
};
xmlhttp.open("GET", "js/updatevalues.csv", true);
xmlhttp.send();
}
function parseCSV(string) {
var allTextLines = string;
var settings = [];
var settings = allTextLines.split(",");
document.getElementById("demo1").innerHTML = settings["ProbeName1"];
}`
currently I can only get id=demo1 to output ProbeName1:"meat1" using settings[0].
If I use settings["ProbeName1"] it will display undefined.
This function will convert your csv into a JSON object:
function parseCSV(str) {
var allTextLines = str;
var settings = [];
var settings = allTextLines.split(",");
var results = {};
var name, val, idx;
for (var i = 0; i < settings.length; i++) {
idx = settings[i].indexOf(':');
name = settings[i].substring(0, idx);
val = settings[i].substring(idx+2, settings[i].length-1);
results[name] = val;
}
return results;
}
Working in fiddle: https://jsfiddle.net/p3t7Lv28/
That code strips the quotes off the values by using idx+2, length-1
Why you need that i dont know but may be you can use SheetJS tool.Its for showing the excel on the web.

Append element from XML to div, without jQuery

EDIT: made title more specific to address duplicate question problem.
I have an HTML page that has a button and a div. When the user clicks the button, a function runs an XMLHttpRequest to get a table from an XML file. The table should be inserted into the div.
The AJAX request returns an object Element to my variable. How can I get the content of that variable (i.e., the <table><tr><td>... etc. from the XML file) to insert into the div?
Here's the JavaScript:
function table_loadContent() {
var request;
if (window.XMLHttpRequest) {
request = new XMLHttpRequest();
console.log("HTTPRequest");
} else {
request = new ActiveXObject("Microsoft.XMLHTTP");
console.log("ActiveX");
}
request.open('GET', 'myXMLFile.xml');
request.onreadystatechange = function() {
if ((request.readyState === 4) && (request.status === 200)) {
var newTable = request.responseXML.getElementsByTagName('table');
document.getElementById('myDiv').appendChild(newTable);
}
}
request.send();
}
Variations that I've tried that don't work:
document.getElementById("myDiv").innerHTML = myVar;
document.getElementById("myDiv").appendChild(myVar);
document.getElementById("myDiv").appendChild(myVar[0]);
same as above but using a second variable to hold a .toString() version
tried declaring the XML file as XML and as HTML
var newTable = request.responseXML.getElementById('myTable');
In the next code:
var newTable = request.responseXML.documentElement.getElementsByTagName('table');
The newTable variable is an HTMLCollection, it is not an element.
If you want to append just the first element in the collection you can use:
document.getElementById('myDiv').appendChild(newTable[0]);
If you want to add all the nodes inside the collection you need to iterate in the collection and add to the div each element contained in it:
var newTable = request.responseXML.documentElement.querySelectorAll('table');
var myDiv = document.getElementById('myDiv');
[].forEach.call(newTable, function (table) {
myDiv.appendChild(table)
});
NOTES:
1 - I've used querySelectorAll method because it is a not-live HTMLCollection and can be used to modify the DOM without modifying the collection.
2 - Use the documentElement property of the responseXML to ensure that you are selecting the main document node.
We discovered the solution:
By changing the lines:
var newTable = request.responseXML.getElementsByTagName('table')
document.getElementById('myDiv').appendChild(newTable)
to:
var newTable = request.responseText
document.getElementById('myDiv').innerHTML = newTable
it works as we'd like it to. (Edit frustration: I can't get it to break lines properly)

Properly passing information to a prototype

Only using javascript.
I want to create a prototype called Table that gets all table values such the array that contains all information, how many rows are going to be displayed, the default rows that are going to be displayed, etc.
With AJAX i'm getting the query and parsing to json, then giving to loadTable the jsonArrayList so I can dynamically create the table depending on how many rows the user want to be displayed.
I am not able to give to the prototype the Array (jsonObj.aaData), i guess is not in the scope and ends being undefined, how do i do it correctly?
function loadQuery() {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
//parse to JSON, sends arrayList to loadTable
var jsonObj = JSON.parse(xhttp.responseText);
// function to create the table
//loadTable(jsonObj.aaData);
//does not work
var table_info = new Table(jsonObj.aaData);
}
};
display_number = refreshDropdown();
xhttp.open("GET", "server_processing2.php?iDisplayStart=1&iDisplayLength=" + display_number, true);
xhttp.send();
}
The thing is creating an instance that all functions can see and extract the information from that instance instead of passing parameters from one function to another.
function Table(jsonArrayL){
this.jsonArrayL = jsonArrayL;
this.default_rows = 25;
}

How to properly extract HTML element from Ajax response string with JavaScript?

I am doing a project where I do not use jQuery.
I am trying to load posts from new pages with Ajax, but I don't know how I should extract a specific HTML element or content inside a specific HTML element from the returned string, properly.
Here is how the HTML (for the part I am trying to load new contents into) looks like;
<div id="posts">
<div class="post"> 1 </div>
<div class="post"> 2 </div>
<div class="post"> 3 </div>
<div class="post"> 4 </div>
<div class="post"> 5 </div>
<!--posts-->
</div>
<div id="loadmore">Load More</div>
Here is a sample of how the script I tried looks like (it works);
function load(path) {
var req = new XMLHttpRequest();
req.onreadystatechange = function() {
if (req.readyState == 4 && req.status == 200) {
var resp = req.responseText;
var cont = resp.slice(resp.indexOf('id="posts">') + 11, resp.indexOf("<!--posts-->"));
document.getElementById("posts").innerHTML = document.getElementById("posts").innerHTML + cont;
}
}
req.open("GET", path, true);
req.send();
}
var page = 1;
document.getElementById("loadmore").onclick = function () {
page++;
var pathToLoad = "/page/" + page;
load(pathToLoad);
}
I feel like I am doing it the worst way, and my question is how do I load contents that is inside "#posts" from the new page in a better way?
Thank you!
If i understood what you're looking for, you could create a new element and insert the responseText into that element.
function load(path) {
var req = new XMLHttpRequest();
req.onreadystatechange = function() {
if (req.readyState == 4 && req.status == 200) {
var resp = req.responseText,
d = document.createElement('div');
d.innerHTML = resp; // This way you have a dom node you can easily manipulate or iterate through
for(var i = 0; i < d.getElementsByClassName("post").length; i++){
var el = d.getElementsByClassName("post")[i];
console.log(el.innerHTML);
//Do stuff with the element you need to append.
}
}
}
req.open("GET", path, true);
req.send();
}
Using createElement function you have a Element object, that you can easily use and manipulate for your purposes. Here is the reference for the element object.
https://developer.mozilla.org/en-US/docs/Web/API/Element
It's been almost a month, I was busy with other works, that is why I am late. This project is my favorite though. The big part of the project is also focused on animations, working on that (in JavaScript).
I have learned a lot about "practical JavaScript" in the past month (I was lazy with jQuery before), I made a small library to avoid a lot of repetitions, mostly I will still use native JavaScript 'cause it's cool. My library is a compliment to the JavaScript for my project, not being lazy again - Oh no.
Also never going back to jQuery again or use anything I do not understand hundred percent. Sticking to my rules.
This is what I made after the help from #gmast. It works, and I am satisfied now.
function load(path) {
var rUrl = path.substring(0, path.indexOf(" ")),
rSelector = path.substring(path.indexOf(" ") + 1),
req = new XMLHttpRequest();
req.open("GET", rUrl, true);
req.onreadystatechange = function () {
if (req.readyState == 4 && req.status == 200) {
var nDoc = document.createElement('div'), nElem, length, i;
nDoc.innerHTML = req.responseText;
nElem = nDoc.querySelectorAll(rSelector);
length = nDoc.length;
for (i = 0; i < length; i += 1) {
document.getElementById("posts").appendChild(nElem[i]);
}
}
};
req.send();
}
Then I call it like;
var pageNumber = 1;
document.getElementById("loadmore").addEventListener("click", function () {
pageNumber++;
var pathToLoad = "/page/" + page + " #posts > .post";
load(pathToLoad);
});
Explanation:
The reason I changed getElementsByClassName to querySelectorAll is because I am going to use it for some more things, and the actual code I have to use in the project is more complex with callbacks and a lot of different objects. I would prefer getElementsByClassName as suggested by #gmast, if I did not have to use this function for multiple different things.
Getting the length of the elements out side of the for loop is important, it creates bugs otherwise, because here I am removing one element with every loop. Optionally do not use increment (that is do not use i++, i += 1 etc) to solve the problem.
If you see my comments under #gmast's answer you will see I was talking about getting "[object HTMLDivElement]", that is because innerHTML accepts HTML not objects, and also my point was about the numbers.
I was noob about most part of JavaScript that is connected with the DOM. Now I am better.

Categories

Resources