Modifying innerHTML in nested get() jQuery - javascript

I'm currently using the jQuery get method to read a table in another page which has a list with files to download and links to others similar webpages.
$.get(filename_page2, function(response, status){
var data = $("<div>" + response + "</div>");
var target_element = data.find(target_element_type_page2 + '#' + target_element_id_page2)[0];
var container = document.getElementById(element_change_content_page1);
if (typeof target_element !== "undefined"){
var rows = target_element.rows;
for (var i = 1, n = rows.length; i < n; i++) {
var table = rows[i].cells[1].getElementsByTagName("TABLE")[0];
var isFolder = table.getAttribute("CType") == "Folder";
var elem = table.rows[0].cells[0];
var text = elem.innerText || elem.textContent;
var link = elem.getElementsByTagName("A")[0].getAttribute("href");
if (!isFolder) {
container.innerHTML += "<li class=\"mainfolderfile\">" + "<a class=\"filelink\" href=\"" + link + "\">" + text + "</a></li>";
} else {
container.innerHTML += "<li class=\"folderlist\">" + "<a class=\"folderlink\" onclick=\"open_submenu(this)\" href=\"#\">" + text + "</a><ul></ul></li>";
var elem_page1 = container.getElementsByTagName("li");
var container_page1 = elem_page1[elem_page1.length - 1].getElementsByTagName("ul")[0];
create_subfolder(container_page1, link);
}
}
} else {
container.innerHTML += "<li class=\"mainfolderfile\">" + "<a class=\"filelink\" href=\"" + "#" + "\">" + "Error..." + "</a></li>";
}
}, page2_datatype);
This is working fine, and all the folders and files are being listed. But when I try to do the same thing with the folders (calling the create_subfolder function) and create sublists with their subfolders and files, I'm getting a weird behavior.
function create_subfolder(container2, link1) {
$.get(link1, function(response, status){
var data = $("<div>" + response + "</div>");
var target_element = data.find("table" + "#" + "onetidDoclibViewTbl0")[0];
if (typeof target_element !== "undefined"){
var rows = target_element.rows;
for (var i = 1, n = rows.length; i < n; i++) {
var table = rows[i].cells[1].getElementsByTagName("TABLE")[0];
var elem = table.rows[0].cells[0];
var text = elem.innerText || elem.textContent;
var link2 = elem.getElementsByTagName("A")[0].getAttribute("href");
//nothing is changed in the webpage. The modifications in the html don't appear
container2.innerHTML += "<li>" + text + "</li>";
}
}
alert(container2.innerHTML); // Print the html with all the modifications
}, "html");
}
The second get(), inside the create_subfolder() function are not changing anything in the webpage, so no sublist is created. But, when I call the alert() function at the end of the get() function, it prints the code with all the modifications it should have made in the html at the second get callback. I believe the problem is related with the asynchronous behavior of the get function but I don't know exactly why. Any guess?

Related

How to modularize code while creating HTML elements in JavaScript?

I am writing a piece of code to basically call in the top money earner and the top five money earners in a given data set. While writing the code, I realized that there were a couple of spots where I was rewriting the code, basically copying and pasting it. While that works, I wanted to throw the duplicate portion of the code and call it from a function. However, that is not working and I don't exactly know why. Here is the code that is duplicated:
for (let i = 0; i < len; i++) {
html +=
'<li class="top">' +
'<h2>' +
topSalaries[i][8] +
'</h2>' +
'<h3>' +
topSalaries[i][11] +
'</h3>';
}
container.innerHTML = '<ul id = "topSalaries">' + html + '</ul>';
Here is the function I made to be called. However, when I call it, it's not working as expected, where the information shows up on the webpage. I'm using VS Code and am running this on live server so when I save, the webpage automatically updates.
function createHtmlElements(len, html) {
for (i = 0; i < len; i++) {
html +=
'<li class="top">' +
'<h2>' +
topFiveSalaries[i][8] +
'</h2>' +
'<h3>' +
topFiveSalaries[i][11] +
'</h3>' +
'</li>';
}
return html
}
function getTopSalaries(boston, container) {
const people = boston.data;
const len = 5; // only want top five
let topFiveSalaries = sortPeople(people).slice(0,len);
// create the list elements
html = createHtmlElements(len, html);
container.innerHTML = '<ul id = topSalaries">' + html + '</ul>';
}
For one thing topFiveSalaries is going to be undefined in the function createHtmlElements you've created, you must pass it to the function
Ok. So, Thanks Dave for the help. It looks like I also was missing a piece in that I needed to pass the array into the function as well. This is what I wrote and how I called it.
function getTopSalaries(boston, container) {
const people = boston.data;
const len = 5; // only want top five
var topFiveSalaries = sortPeople(people).slice(0,len);
let html = '';
// create the list elements
html = createHtmlElements(len, html, topFiveSalaries);
container.innerHTML = '<ul id = topSalaries">' + html + '</ul>';
}
function getTopEarner(boston, container){
const people = boston.data;
const len = 1;
let highEarner = sortPeople(people).slice(0,len);
var html = '';
// create the list elements
createHtmlElements(len, html, highEarner);
container.innerHTML = '<ul id = topSalaries">' + html + '</ul>';
}
// sort people by income in descending order
function sortPeople(people) {
people.sort(function(a, b) {
return b[11] - a[11];
})
return people
}
function createHtmlElements(len, html, array) {
for (i = 0; i < len; i++) {
html +=
'<li class="top">' +
'<h2>' +
array[i][8] +
'</h2>' +
'<h3>' +
array[i][11] +
'</h3>' +
'</li>';
}
return html
}

I'm not sure why this isn't XML information isn't printing to the screen

I have written this code which is supposed to print the information from the xml file into a list for each faculty member. I want to eventually place all of these into a table, but need to know how to print them to the screen first.
function init() {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function () {
if (this.readyState == 4 && this.status == 200) {
console.log(this.responseXML);
var faculty = this.responseXML.getElementsByTagName("faculty");
var strOut = "<ul>";
for (i = 0; i < faculty.length; i++) {
var name = faculty[i].getElementsByTagName("name")[0].innerHTML;
var title = faculty[i].getElementsByTagName("title")[0].innerHTML;
var office = faculty[i].getElementsByTagName("office")[0].innerHTML;
var phone = faculty[i].getElementsByTagName("phone")[0].innerHTML;
var email = faculty[i].getElementsByTagName("email")[0].innerHTML;
strOut += "<li><a href = " + name + title + "</a></li>";
}
strOut += "<ul>";
document.getElementById("output").innerHTML = strOut;
}
};
xhttp.open("GET", "faculty.xml", true);
xhttp.send();
}
window.onload = init;
Here is the XML file:
<facultyInfo>
<faculty>
<name>Prof A</name>
<title>Professor and Program Coordinator</title>
<office>CI 555</office>
<phone>(999-999-9999</phone>
<email>ProfA#school.edu</email>
</faculty>
<faculty>
<name>Prof B</name>
<title>Visiting Professor</title>
<office>CI 333</office>
<phone>999-999-9999</phone>
<email>ProfB#school.edu</email>
</faculty>
</facultyInfo>
This line:
strOut += "<li><a href = " + name + title + "</a></li>";
... is both malformed and probably not what you intended. Between the missing quotes for the href attribute, missing the ">" to close off the <a> start, and not putting any text in between <a></a>, this results in a link tag where the link destination (href) is set, but the actual text to show to the user is not set. I don't see any links in your XML (maybe that is for the future), so for now you probably want something like this:
strOut += '<li>' + name + ', ' + title + '</li>';
Here is a quick demo with your XML input:
<div id="output"></div>
<script>
var xmlString = '<facultyInfo> <faculty> <name>Prof A</name> <title>Professor and Program Coordinator</title> <office>CI 555</office> <phone>(999-999-9999</phone> <email>ProfA#school.edu</email> </faculty> <faculty> <name>Prof B</name> <title>Visiting Professor</title> <office>CI 333</office> <phone>999-999-9999</phone> <email>ProfB#school.edu</email> </faculty> </facultyInfo>';
var xmlDoc = (new DOMParser()).parseFromString(xmlString,'text/xml');
// var faculty = this.responseXML.getElementsByTagName("faculty");
var faculty = xmlDoc.getElementsByTagName("faculty");
var strOut = "<ul>";
for (i = 0; i < faculty.length; i++){
var name = faculty[i].getElementsByTagName("name")[0].innerHTML;
var title = faculty[i].getElementsByTagName("title")[0].innerHTML;
var office = faculty[i].getElementsByTagName("office")[0].innerHTML;
var phone = faculty[i].getElementsByTagName("phone")[0].innerHTML;
var email = faculty[i].getElementsByTagName("email")[0].innerHTML;
strOut += '<li>' + name + ', ' + title + '</li>';
}
strOut += "<ul>";
document.getElementById("output").innerHTML = strOut;
</script>

Can't addEventListener('click', ...) to a div created programmatically

I parse the result of XMLHttprequest() into a JSON object, then for each node of that object I create a div to store the informations.
Finally I add each div as innerHTML of a parent div.
Here the relevant part
xhr.onreadystatechange = function() {//Call a function when the state changes.
if(xhr.readyState == 4 && xhr.status == 200) {
var response = JSON.parse(xhr.responseText);
var html="";
var linksDiv = document.getElementById('links');
if (response.error != true){
for (var i=0; i< response.links.length; i++){
var l = response.links[i];
var curId = l.id;
var curLink = l.link;
var curCreated = l.created_at;
var curOrigin = l.origin;
html = "<div id=\"link"+curId+"\" >"+
"<label><b>Id </b></label><label>"+curId+"</label> </br>"+
"<label><b>Link </b></label><label>"+curLink+"</label> </br>"+
"<label><b>Created </b></label><label>"+curCreated+"</label> </br>"+
"<label><b>Origin </b></label><label>"+curOrigin+"</label> </br></br>"+
"</div>";
linksDiv.innerHTML += html;
var curDiv = document.getElementById('link'+curId);
console.log("curDiv is"+'link'+curId);
curDiv.addEventListener('click', function(){
curDiv.style.background="gray";
getLink(curId);
});
}
}
}
}
unfortunately
curDiv.addEventListener('click', function(){
curDiv.style.background="gray";
getLink(curId);
});
doesn't work.
I already tried to make sure that the div exist (the console.log("curDiv is"+'link'+curId); works just fine)
and even used different ways like curdDiv.onmouseover = function(){curDiv.style.background="gray";}
If i put curDiv.style.background="gray"; outside the addEventListener() every div's background gets correctly changed.
If i put onmouseover="this.style.background='gray';" as inline property of the div tag when i generate it, it works as well, but i don't want javascript in the html since I will transform this page in a Chrome Extension and javascript must be separated
Please don't get confused from the mouseover tries, I need onclick behavior, but was just testing different thing to see if they worked.
I looked for a long time on SO for an answer, as you can see from my tries, but couldn't find something that worked for me. Probably there is something that I don't get.
Ps.
Let me know if you need a sample JSON data to test the function.
I think you should use
html = document.createElement('div');
html.id = 'link' + curId;
html.innerHTML = "<label><b>Id </b></label><label>" + curId
+ "</label> </br><label><b>Link </b></label><label>" + curLink
+ "</label> </br><label><b>Created </b></label><label>" + curCreated
+ "</label> </br><label><b>Origin </b></label><label>" + curOrigin
+ "</label> </br></br>";
html.addEventListener('click', function(){
this.style.background="gray";
getLink(this.id);
});
linksDiv.appendChild(html);
instead of
html = "<div id=\"link"+curId+"\" >"+
"<label><b>Id </b></label><label>"+curId+"</label> </br>"+
"<label><b>Link </b></label><label>"+curLink+"</label> </br>"+
"<label><b>Created </b></label><label>"+curCreated+"</label> </br>"+
"<label><b>Origin </b></label><label>"+curOrigin+"</label> </br></br>"+
"</div>";
linksDiv.innerHTML += html;
var curDiv = document.getElementById('link'+curId);
console.log("curDiv is"+'link'+curId);
curDiv.addEventListener('click', function(){
curDiv.style.background="gray";
getLink(curId);
});
Check this working code. make delay so that event will attached to element.
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<script type="text/javascript">
function populateLink() {
var html = "";
var linksDiv = document.getElementById('links');
for (var i = 0; i < 10; i++) {
var l = 'l-' + i;
var curId = i;
var curLink = 'l.link-' + i;
var curCreated = 'l.created_at_' + 1;
var curOrigin = 'l.origin_' + i;
html = "<div id=\"link" + curId + "\" >" +
"<label><b>Id </b></label><label>" + curId + "</label> </br>" +
"<label><b>Link </b></label><label>" + curLink + "</label> </br>" +
"<label><b>Created </b></label><label>" + curCreated + "</label> </br>" +
"<label><b>Origin </b></label><label>" + curOrigin + "</label> </br></br>" +
"</div>";
linksDiv.innerHTML += html;
//var curDiv = document.getElementById('link' + curId)
//curDiv.addEventListener('click', function () {
// this.style.background = "gray";
// getLink(this.id);
//});
attachEvent(curId);
}
}
function attachEvent(curId) {
setTimeout(function () {
var curDiv = document.getElementById('link' + curId)
curDiv.addEventListener('click', function () {
this.style.background = "gray";
//getLink(this.id);
});
}, 100);
}
window.onload = populateLink;
</script>
</head>
<body>
<div id="links"></div>
</body>
</html>

Assistance with JSON changing page contents dynamically

I am working on a website and I am looking to make the recipes pages dynamic. I created a JSON test database, created a JS file that retrieves values from the JSON file and displays them in appropriate divs on the page.
What i want to do is be able to choose the respectful JSON for each recipe and display it on the same page when a user clicks a link in the sidebar without having to create a ton of blank HTML pages with the same divs.
Below is my code. Hoping someone can help guide me thanks!
(function() {
'use strict';
var url = 'my json url';
$.getJSON(url, function(json) {
//store json data into variable
var data = (json);
//store data in empty string
var title = '';
var image = '';
var directions = '';
var prep = '';
var cook = '';
var serve = '';
//retrieve values from dataArray
$.each(data[0], function (i, item) {
title += '<h1>' + item.recipeName + '</h1>';
image += '<img src="' + item.imageURL + '">';
directions += '<p>' + item.directions + '</p>';
prep += '<strong>' + item.prepTime + '</strong>';
cook += '<strong>' + item.cookTime + '</strong>';
serve += '<strong>' + item.servInfo + '</strong>';
});
//append results to div
$('#recipeTitle').html(title);
$('#recipeImage').html(image);
$('#recipeDirections').html(directions);
$('#recipePrep').html(prep);
$('#recipeCook').html(cook);
$('#recipeServes').html(serve);
var ul = $('<ul class="nav nav-stacked">').appendTo('#recipeIngredients');
$.each(data[0][0].ingredients, function(i, item) {
ul.append($(document.createElement('li')).text(item));
});
});
})();
new code`(function() {
function callback(json){
//store json data into variable
var data = (json);
//store data in empty string
var title = '';
var image = '';
var directions = '';
var prep = '';
var cook = '';
var serve = '';
//retrieve values from dataArray
$.each(data[0], function (i, item) {
title += '<h1>' + item.recipeName + '</h1>';
image += '<img src="' + item.imageURL + '">';
directions += '<p>' + item.directions + '</p>';
prep += '<strong>' + item.prepTime + '</strong>';
cook += '<strong>' + item.cookTime + '</strong>';
serve += '<strong>' + item.servInfo + '</strong>';
});
//append results to div
$('#recipeTitle').html(title);
$('#recipeImage').html(image);
$('#recipeDirections').html(directions);
$('#recipePrep').html(prep);
$('#recipeCook').html(cook);
$('#recipeServes').html(serve);
var ul = $('<ul class="nav nav-stacked">').appendTo('#recipeIngredients');
$.each(data[0][0].ingredients, function(i, item) {
ul.append($(document.createElement('li')).text(item));
});
}
$('#pasta').click(function(){
$('#recipeIngredients').empty();
//get the url from click coresponding to the item
$.getJSON(url,callback);
});
//intially load the recipies with the URL
var url = '';
$.getJSON(url,callback);
})();`
to achieve code reusability , try calling the $.getJSON() with a reusable function (callback) on click of the link in the sidebar
(function() {
function callback(json){
//store json data into variable
var data = (json);
//store data in empty string
var title = '';
var image = '';
var directions = '';
var prep = '';
var cook = '';
var serve = '';
.... //rest of the code
...
$.each(data[0][0].ingredients, function(i, item) {
ul.append($(document.createElement('li')).text(item));
});
}
$('.sidebarLink').click(function(){
$('#recipeIngredients').empty()
//get the url from click coresponding to the item
$.getJSON(url,callback);
});
//intially load the recipies with the URL
var url = 'my json url';
$.getJSON(url,callback);
})();

Get text and id from an li element on click with pure JS

I've been stuck with this for several days and I can't solve it.
I've done it with jQuery with no problem, but I need it in pure JS.
This is how my list is generated.
function get_friends(items){
if(items != undefined){
if (items.length != 0){
var html_friends_list = "";
for(var count = 0; count < items.length; count++){
if(items[count].subscription == "both"){
var display_name = Strophe.getNodeFromJid(items[count].jid);
html_friends_list = html_friends_list + "<li style='font-size:19px' id='open_chat-" + items[count].jid + "'>" + "<a href='chat-js/index.html'>" + display_name + "<span class='block-list-label' id='" + items[count].jid + "_unread_messages" + "'>0</span><span class='block-list-label' id='" + items[count].jid + "_change_status" + "'></span></a></li>";
}
}
document.getElementById("friends-list").innerHTML = html_friends_list;
As a said I want to save the value of the text and the id of any li element clicked.
Regards
you haven't specified whether this is for a specific list or just any li on your page. The below will log the id and innerHTML components of any li on the page. Perhaps you may need to update the querySelector for your particular use case.
var list = document.querySelectorAll('li');
Array.prototype.slice.call(list).forEach(function(listItem){
listItem.addEventListener('click', function(e){
console.log(this.id);
console.log(this.innerHTML);
});
});
Here's a JSFiddle which I think demonstrates what you are trying to achieve.
Jsfiddle
Combination of james' answer and working example.
function get_friends(items) {
if (items != undefined) {
if (items.length != 0) {
var html_friends_list = "<ul>";
for (var count = 0; count < items.length; count++) {
if (items[count].subscription == "both") {
html_friends_list = html_friends_list + "<li id='open_chat-" + items[count].jid + "'>"+ items[count].display_name +"</li>";
}
}
html_friends_list = html_friends_list + '</ul>'
document.getElementById("friends-list").innerHTML = html_friends_list;
}
}
}
Note: you should trigger prototype after your dom element created.

Categories

Resources