I have a javascript that reads a xml Phonebook, prints a table and I'd like to make each number clickable so it would launch a Phone App.
<table class="table table-striped table-dark" id="campanie"></table>
function loadXMLDoc() {
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
myFunction(this);
}
};
xmlhttp.open("GET", "campanie-full.xml", true);
xmlhttp.send();
}
function myFunction(xml) {
var i;
var xmlDoc = xml.responseXML;
var table="<thead class=thead-light><tr><th><h5 class=text-dark>Nr.</h5></th><th><h5 class=text-dark>Company</h5></th><th><h5 class=text-dark>Phone 1</h5></th><th><h5 class=text-dark>Phone 2</h5></th></tr></thead>";
var x = xmlDoc.getElementsByTagName("DirectoryEntry");
for (i = 0; i <x.length; i++) {
table += "<tr><td><p>" +
[i+1] + "</p></td><td><p>" +
x[i].getElementsByTagName("Name")[0].childNodes[0].nodeValue +
"</p></td><td><a href=tel:>" +
x[i].getElementsByTagName("Telephone")[0].childNodes[0].nodeValue +
"</a></td><td><a href=tel:>" +
x[i].getElementsByTagName("Telephone")[0].childNodes[0].nodeValue +
"</a></td></tr>";
}
document.getElementById("campanie").innerHTML = table;
}
What should I do in order to have each a href=tel: work properly?
Also, you will see that I put the "Telephone" tag twice, as the Phonebook has more than one phonenumber. As a second question, I'd like to know how to make it read correctly, as the XML file can't be edited in any way. The <Telephone> tag from XML can't be changed to <Telephone1> or <Telephone2>. This question can wait, however.
EDIT: I have added an example XML
<CiscoIPPhoneDirectory>
<DirectoryEntry>
<Name>Doctor Dolittle</Name>
<Telephone>100</Telephone>
<Telephone>+19001234567</Telephone>
</DirectoryEntry>
<DirectoryEntry>
<Name>Tommy Stubbins</Name>
<Telephone>101</Telephone>
</DirectoryEntry>
<DirectoryEntry>
<Name>Chee-Chee</Name>
<Telephone>102</Telephone>
</DirectoryEntry>
<DirectoryEntry>
<Name>Prince Bumpo</Name>
<Telephone>103</Telephone>
</DirectoryEntry>
<DirectoryEntry>
<Name>Polynesia</Name>
<Telephone>104</Telephone>
</DirectoryEntry>
<DirectoryEntry>
<Name>Gub-Gub</Name>
<Telephone>105</Telephone>
</DirectoryEntry>
<DirectoryEntry>
<Name>Jip</Name>
<Telephone>106</Telephone>
</DirectoryEntry>
<DirectoryEntry>
<Name>Dab-Dab</Name>
<Telephone>107</Telephone>
</DirectoryEntry>
You'll need to check the Xml to see whether there are 1 or 2 phone numbers. (You could also make it check for none, if that could ever happen, and not add a row at all). Then you add either the 2nd phone number or an empty cell, depending on what the data says.
Change the function that creates the table contents from the Xml response, like this...
function myFunction(xml) {
var i;
var xmlDoc = xml.responseXML;
var table="<thead class=thead-light>" +
"<tr><th><h5 class=text-dark>Nr.</h5></th>" +
"<th><h5 class=text-dark>Company</h5></th>" +
"<th><h5 class=text-dark>Phone 1</h5></th>" +
"<th><h5 class=text-dark>Phone 2</h5></th>" +
"</tr></thead>";
var x = xmlDoc.getElementsByTagName("DirectoryEntry");
for (i = 0; i <x.length; i++) {
var name = x[i].getElementsByTagName("Name")[0].childNodes[0].nodeValue;
var tel1 = x[i].getElementsByTagName("Telephone")[0].childNodes[0].nodeValue;
var tel2 = "";
// if there are 2 phone numbers, get the value of the 2nd one
if (x[i].getElementsByTagName("Telephone").length === 2) {
// check that it's not an empty node...
if (x[i].getElementsByTagName("Telephone")[1].childNodes) {
tel2 = x[i].getElementsByTagName("Telephone")[1].childNodes[0].nodeValue;
}
}
table += "<tr><td><p>" + [i+1] + "</p></td>" +
"<td><p>" + name + "</p></td>" +
"<td><a href='tel:" + tel1 + "'>" + tel1 + "</a></td>";
// if we don't have a 2nd phone number then add an empty cell
if (tel2 === "") {
table += "<td></td>";
}
// if we do have a 2nd phone number then add it
else {
table += "<td><a href='tel:" + tel2 + "'>" + tel2 + "</a></td>";
}
table += "</tr>";
}
document.getElementById("campanie").innerHTML = table;
}
Related
I have come across a problem while fetching data from an external XML document with JS. I have been following the w3schools tutorial for AJAX XML so far, but I ran into something I couldn't solve. I have a XML that looks like this:
<root>
<document-id>
<author>Tom Riddle</autor>
<title>abzy</title>
<year>1995</year>
</document-id>
<document-id>
<author>Tom Riddle</autor>
<title>abzy</title>
</document-id>
<document-id>
<author>Tom Riddle</autor>
<year>1995</year>
</document-id>
</root>
I want to dynamically access the data inside the XML and create a table while doing so. It works fine for the one DOM Element all documents share, but it gives me an error as soon as I include year or title. I guess it's because the tags are empty in some parts of the tree. Is there a way to ignore empty tags and only write something in the column if there is a value inside? Thank you for your time and knowledge.
THIS IS THE ASSOCIATED HTML
<body>
<header>
<h1>Reading Data from XML Files</h1>
</header>
<main>
<button type="button" onclick="loadDoc()">Get my CD collection</button>
<table id="demo">
</table>
</main>
<script>
function loadDoc() {
const xhttp = new XMLHttpRequest();
xhttp.onload = function() {
myFunction(this);
}
xhttp.open("GET", "books.xml");
xhttp.send();
}
function myFunction(xml) {
const xmlDoc = xml.responseXML;
const x = xmlDoc.getElementsByTagName("document-id");
console.log(x)
let table="<tr><th>Author</th><th>Title</th><th>Year</th></tr>";
for (let i = 0; i <x.length; i++) {
table += "<tr><td>" +
x[i].getElementsByTagName("author")[0].childNodes[0].nodeValue +
"</td><td>" +
x[i].getElementsByTagName("title")[0].childNodes[0].nodeValue +
"</td><td>" +
x[i].getElementsByTagName("year")[0].childNodes[0].nodeValue +
"</tr>";
}
document.getElementById("demo").innerHTML = table;
}
</script>
</body>
Check for existence before you try to access the children.
function getText(node, tag) {
var elem = node.getElementsByTagName(tag);
return elem ? elem.[0].childNodes[0].nodeValue : '';
}
for (let i = 0; i <x.length; i++) {
var cells = ['author', 'title', 'year'].map(function (tag) {
return "<td>" + getText(x[i], tag) + "</td>";
}).join("");
table += "<tr>" + cells + "</tr>");
}
try this with in line solution to check if tag exist in xml
function myFunction(xml) {
const xmlDoc = xml.responseXML;
const x = xmlDoc.getElementsByTagName("document-id");
console.log(x)
let table="<tr><th>Author</th><th>Title</th><th>Year</th></tr>";
for (let i = 0; i <x.length; i++) {
table += "<tr><td>" +
x[i].getElementsByTagName("author")[0].childNodes[0].nodeValue +
"</td><td>" + ((x[i].getElementsByTagName("title")[0] == undefined)?"": x[i].getElementsByTagName("title")[0].childNodes[0].nodeValue ) +
"</td><td>" +
((x[i].getElementsByTagName("year")[0] == undefined)?"": x[i].getElementsByTagName("year")[0].childNodes[0].nodeValue ) +
"</tr>";
}
document.getElementById("demo").innerHTML = table;
}
I'm using two functions to get some data from an API :
The first one request the data for each cycle, the second check if the payment has been done for each cycle.
All the data are placed in a common table. It seems that my issue come from the fact that I use a function in another function. It the that the second function executes itself only after the first one is complete.
https://codepen.io/anon/pen/XQOVVB?editors=1001
var obj, obj2, dbParam,dbParam2, xmlhttp, xmlhttp2, myObj, myObj2, x, y, txt, txt2 = "";
obj = { table: "cycle", limit: 10 };
dbParam = JSON.stringify(obj);
xmlhttp = new XMLHttpRequest();
// Get the value of the inputbox
// KT1 adress for trial KT19www5fiQNAiqTWrugTVLm9FB3th5DzH54
var KT1 = $('#KT1').val();
xmlhttp.onreadystatechange = function() {
obj2 = { table: "cycle2", limit: 100 };
if (this.readyState == 4 && this.status == 200) {
myObj = JSON.parse(this.responseText);
txt += "<table><tr bgcolor=#000000 color=White>"
txt += "<th>Cycle</th>"
//txt += "<th>Reward</th>"
txt += "<th>Paid</th>"
txt += "</tr>"
// Get the data of every cycle using API 1
for (x in myObj) {
// force x to 11 to get the condition PaymentCycle = cycle
x = 11;
cycle = myObj[x].cycle;
//balance = myObj[x].balance/1000000;
//TotalReward = myObj[x].rewards/1000000;
//stakingBalance = myObj[x].staking_balance/1000000;
//Share = balance/stakingBalance*100;
//DelegatorReward = Share*TotalReward/100;
// create line of the table
txt += "<tr>";
txt += "<td width=10% align=center>" + cycle + "</td>";
//txt += "<td width=10% align=center>" + Math.round(DelegatorReward*100)/100 + "</td>";
// here the CYCLE CHANGE CORRECTLY from 106 to 87
console.log("Cycle before function: " + cycle);
//API2 request
dbParam2 = JSON.stringify(obj2);
xmlhttp2 = new XMLHttpRequest();
xmlhttp2.onreadystatechange = function() {
if (this.readyState == 4 && (this.status == 200 || this.status == 0)) {
myObj2 = JSON.parse(this.responseText);
// ERROR HERE - ALWAYS GET THE DATA OF THE LAST CYCLE (87) instead of every cycle check with API1
// It seems that this fonction xmlhttp2 is executed only after xmlhttp is complete giving to cycle the last value of saved for cycle (87)
console.log("Cycle after function: " + cycle);
for (var y = 0; y < 30; y++) {
// Get the Paiement cycle which varies from 106 to 90
Block = myObj2[y].type.operations[0].op_level;
PaiementCycle = Math.round(Block/4096);
PaiementCycle = PaiementCycle - 6;
// If the Data entered in the input box = of the destination adress of API 2 and the cycle of API1 and API2 is the same then
// Here cycle is always = 87 (Last value of the API1 reading (before the function the cycle change from 106 to 87).
// I really don't understand why
if (KT1 == myObj2[y].type.operations[0].destination.tz && PaiementCycle == cycle) {
console.log("Get one");
console.log("Paiement Cycle : " + PaiementCycle);
Paid = "/////////////////" + myObj2[y].type.operations[0].amount/1000000;
console.log("Paid : " + Paid);
txt += "<td width=10% align=center>Paiement :" + Paid + "</td>";
txt += "</tr>";
// All the data saved during this function is saved after the execution or the boucle for(x)
console.log("Txt /////: " + txt);
// document.getElementById("demo2").innerHTML = txt2;
} else {
}//
}
//return txt;
} else {
//console.log("Not Ok");
}
};
xmlhttp2.open("POST", "https://api6.tzscan.io/v3/operations/tz1XynULiFpVVguYbYeopHTkLZFzapvhZQxs?type=Transaction&number=100", true);
xmlhttp2.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xmlhttp2.send("x=" + dbParam2);
}
txt += "</table>";
console.log("Txt 2 : " + txt);
document.getElementById("demo").innerHTML = txt;
}
};
xmlhttp.open("POST", "https://api6.tzscan.io/v3/delegator_rewards_with_details/" + KT1, true);
xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xmlhttp.send("x=" + dbParam);
You can see here my codepen, you can easily see that my function xmlhttp2.onreadystatechange = function() { only executes itself after xmlhttp.onreadystatechange = function() { instead of after getting each data from the JSON file
try to use JavaScript Promises.
A simple Promise is here
I am trying to read data from a xml file and display them in my html file, but when I am trying to display my values I get "undefined" values for all the values.
I am a really new with ajax and xml so excuse my code if its horrible! I will appreciate if someone got a really briefly answer.
Here's my xml file:
<gesmes:Envelope xmlns:gesmes="http://www.gesmes.org/xml/2002-08-01" xmlns="http://www.ecb.int/vocabulary/2002-08-01/eurofxref">
<gesmes:subject>Reference rates</gesmes:subject>
<gesmes:Sender>
<gesmes:name>European Central Bank</gesmes:name>
</gesmes:Sender>
<Cube>
<Cube time="2019-01-25">
<Cube currency="USD" rate="1.1346"/>
<Cube currency="JPY" rate="124.72"/>
<Cube currency="BGN" rate="1.9558"/>
<Cube currency="CZK" rate="25.697"/>
<Cube currency="DKK" rate="7.4664"/>
<Cube currency="GBP" rate="0.86580"/>
....
My javascript code:
function loadDoc() {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
returndata(this);
}
};
xhttp.open("GET", "rates.xml", true);
xhttp.send();
}
function returndata(xml) {
var i;
var xmlDoc = xml.responseXML;
var table="<tr><th>currency</th><th>rates</th></tr>";
var x = xmlDoc.getElementsByTagName("Cube");
for (i = 0; i <x.length; i++) {
table += "<tr><td>" +
x[i].getElementsByTagName("currency")[0] +
"</td><td>" +
x[i].getElementsByTagName("rate")[0] +
"</td></tr>";
}
document.getElementById("demo").innerHTML = table;
}
When I click the button I got the following result:
currency rates
undefined undefined
undefined undefined
undefined undefined
undefined undefined
.....
UPDATE Javascript code(fixed):
function returndata(xml) {
var i;
var xmlDoc = xml.responseXML;
var table="<tr><th>currency</th><th>rates</th></tr>";
var x = xmlDoc.getElementsByTagName("Cube");
for (i = 2; i <x.length; i++) {
table += "<tr><td>" +
x[i].getAttribute("currency") +
"</td><td>" +
x[i].getAttribute("rate") +
"</td></tr>";
}
document.getElementById("demo").innerHTML = table;
}
Okay now it works, thank you very much, i started my variable from the value 2 because when i am trying to have a while loop like (x!=null) my webpage it still loading forever and then breaks down..
i tried that one:
function returndata(xml) {
var i;
var xmlDoc = xml.responseXML;
var table="<tr><th>currency</th><th>rates</th></tr>";
var x = xmlDoc.getElementsByTagName("Cube");
for (i = 0; i <x.length; i++) {
while (x!=null) {
table += "<tr><td>" +
x[i].getAttribute("currency") +
"</td><td>" +
x[i].getAttribute("rate") +
"</td></tr>";
}
}
document.getElementById("demo").innerHTML = table;
}
So in my code I created a table pulling from an XML file that displayed two columns of information about plants. The goal of my program is to be able to hover over the first and print out the other information about that plant and print it in another section to the right of my table. The issue is that I am not gettign any console errors and the hover affect is not printing any information.
window.addEventListener("load", link_events);
var xhr = false;
function link_events() {
xhr = new XMLHttpRequest();
if(xhr) {
xhr.addEventListener("readystatechange", ShowFile);
xhr.open("GET", "plants.xml", true);
xhr.send();
} else {
alert("XHR not supported.");
}
}
function ShowFile() {
var i;
var title;
var cover;
var plant_table = "<table><tr><th>Common Name </th><th>Botanical Name </th></tr>";
if (xhr.readyState == 4) {
if (xhr.status == 200) {
//here we have gotten the file correctly
//loop through it and print out cover and title
var plantlist = xhr.responseXML.getElementsByTagName("PLANT");
//booklist is an array and each element is an object sub i
//so you have to use getElementBy something in order to pull the information
for (i = 0; i < plantlist.length; i++) {
var Common = plantlist[i].getElementsByTagName("COMMON")[0].firstChild.textContent;
var Botanical = plantlist[i].getElementsByTagName("BOTANICAL")[0].firstChild.textContent;
plant_table += "<tr>" +
"<td class =\"plant\">" + Common + "</td>" +
"<td>" + Botanical + "</td>" +
"</tr>";
}
plant_table += "</table>";
document.getElementById("outarea").innerHTML = plant_table;
}
var plants = document.getElementsByClassName("plant");
for (i=0; i < plants.length; i++) {
plants[i].onmouseover = HoverChoice;
}
}
function HoverChoice() {
var input = xhr.responseXML.getElementsByTagName("PLANT");
for (i = 0; i < input.length; i++) {
Common = input[i].getElementsByTagName("COMMON")[0].firstChild.textContent;
var Zone = input[i].getElementsByTagName("ZONE")[0].firstChild.textContent;
var Light = input[i].getElementsByTagName("LIGHT")[0].firstChild.textContent;
var Price = input[i].getElementsByTagName("PRICE")[0].firstChild.textContent;
if (plants == this.innerHTML) {
document.getElementById("inarea").innerHTML =
"<h1>" + Common + "</h1>" + "<br />" + "<br />" +
"Zone: " + Zone + "<br />" +
"Light: " + Light + "<br />" +
"Price: " + Price;
}
}
}
}
you could try using addEventListener method instead and see whether it works?
plants.forEach(function(plant){
plant.addEventListener("onmouseover", HoverChoice);
});
or going with the original loop you made it would be
for (i=0; i < plants.length; i++)
{
plants[i].addEventListener("onmouseover", HoverChoice);
}
I'm not anything professional, a common problem I used to encounter in these kinds of event listening functions was that calling a global function sometimes fails but making the function on the spot inside the event listener would work like addEventListener("onmouseover" , function() { return 0; });
Hi I have an issue with onclick events being writen using innerHTML I have tried doing it two ways and both have not work
the function it needs to call is
function loadnewsstory()
{
alert("123456");
}
at the moment it should show the alert box with 123456 but it is not firing.
the function loading it is the following
function newsstories()
{
document.getElementById("activecontent").innerHTML = "<h1 class='newsheader'>Latest News</h1>";
xmlhttp=new XMLHttpRequest();
xmlhttp.open("POST","test.com?uri=loadnews",false);
xmlhttp.send();
var newsreponse = JSON.parse(xmlhttp.responseText);
var countstories = 0;
for (var i = 0, len = newsreponse.length; i < len; ++i) {
var news = newsreponse[i];
if(i % 2 == 0){
cssclass = "even";
}
else
{
cssclass = "odd";
}
// alert(news.featured_image);
document.getElementById("activecontent").innerHTML += "<div class='news " + cssclass + "'><div class='newstitle'><div class='newstitlecolor'><a href='#' onclick='loadnewsstory();'>" + news.post_title + "</a></div></div><div class='base' style='background: url('" + news.featured_image + "');'><img src='" + news.featured_image + "' style='width:100%; height:100%;' id='news_"+ countstories +"'/></div></div>";
document.getElementById("news_"+countstories).onclick = function(){ loadnewsstory();}
countstories++;
}
}
as you can see I have also ran document.getElementById("news_"+countstories).onclick = function(){ loadnewsstory();} because i read that onclick events could not be written by javascript innerHTML which I know I have been able to do before. If someone else knows of a fix to this issue that would be great. this is for a cordova iphone app
Thanks
EDIT
I have found that this
document.getElementById("activecontent").innerHTML += "<div class='news " + cssclass + "'><a href='javascript:openextlink();'><img src='" + news.featured_image + "' style='width:100%; height:100%;'/></a></div>";
works but it seems to only work on the last news story, am I missing something.
I suspect it's because your request is attempting to read/parse the response from the server too soon here:
xmlhttp.send();
var newsreponse = JSON.parse(xmlhttp.responseText);
Because this is an asyncronus (Ajax) request you need to give the script time to wait for the server to respond. You do this by creating an event handler that waits for the response.
xmlhttp.onreadystatechange=function() { // checks if the state of the request has changed
if (xmlhttp.readyState==4 && xmlhttp.status==200) { // checks that the response is ready
// code to handle the response here
var newsreponse = JSON.parse(xmlhttp.responseText);
// etc.
}
}
Also note that you should create this handler before calling xmlhttp.send();
First of all, appending to innerHTML is usually very bad. If you run the code like something.innerHTML += 'lots of html' in a loop, browser has to update the DOM tree and re-render the page on every iteration. This may greatly slow down the things. Use the buffer string instead.
I also suspect that this might have caused issues with event attachment. Try attaching events after all the divs have been attached to the tree. The code in this case would be something like this:
function newsstories()
{
// Use a variable that would store the newly generated HTML:
var html = "<h1 class='newsheader'>Latest News</h1>";
xmlhttp=new XMLHttpRequest();
xmlhttp.open("POST","test.com?uri=loadnews",false);
xmlhttp.send();
var newsreponse = JSON.parse(xmlhttp.responseText);
for (var i = 0, len = newsreponse.length; i < len; ++i) {
var news = newsreponse[i];
// Notice the 'var' keyword!
if(i % 2 == 0){
var cssclass = "even";
} else {
var cssclass = "odd";
}
// Append to our buffer variable
html += "<div class='news " + cssclass + "'><div class='newstitle'><div class='newstitlecolor'><a href='#' onclick='loadnewsstory();'>" + news.post_title + "</a></div></div><div class='base' style='background: url('" + news.featured_image + "');'><img src='" + news.featured_image + "' style='width:100%; height:100%;' id='news_"+ i +"'/></div></div>";
}
// Now that new html is ready, insert it into the tree
// and attach events
document.getElementById("activecontent").innerHTML = html;
for (var i = 0, len = newsreponse.length; i < len; ++i) {
var img = document.getElementById('news_'+i);
if(img) img.addEventListener('click', loadnewsstory);
}
}
it was due to z-index in my css that this was not working, I have fixed this by removing z-index:-1 and now all works fine, it is interesting that it was due to a css error that this bug come to alight