I'm not familiar with Ajax so I'm learning fast. I'd appreciate some help on displaying a variable
rdm = urandom.randint(10,100) //comes from a loop in micropython.
Here's what I've so far. The part of turning ON/OFF a LED is working. I just cannot get the variable to update every 2 seconds.
TIA
<html>
<head>
<title>ESP32-OLED
</title>
<meta charset="utf-8">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.js" type="text/javascript">
</script>
</head>
<body>
<div>
<h4>The ESP32 Update web page without refresh
</h4>
<br>
<p>LED State:
<strong>%s
</strong>
</p>
<p>RDM number:
<span id="rdm">0
</span>
</p>
<p>
<button onclick="window.location.href = '/?led=on'">ON
</button>
</p>
<p>
<button onclick="window.location.href = '/?led=off'">OFF
</button>
</p>
<br>
<a href="http://www.google.com">www.google.com
</a>
</div>
<script>
var txt = "jQuery Works";
var _rdm = rdm;
//wait for the page to fully load
//$(document).ready(function(){
// var txt = "jQuery Works";
// alert(txt)
//}
//);
setInterval(function() {
// Call a function repetatively with 2 Second interval
getData();
}, 2000);
//2000mSeconds update rate
function getData() {
var xhttp = new XMLHttpRequest();
var rdm = document.getElementById("rdm").value;
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
//returns 4 when the server finishes streaming the response
document.getElementById("rdm").innerHTML = _rdm;
//return object whose id property matches the specified string
}
};
xhttp.send();
}
</script>
</body>
</html>```
<!DOCTYPE html>
<html>
<head>
<title>ESP32-OLED
</title>
<meta charset="utf-8">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.js" type="text/javascript">
</script>
</head>
<body>
<div>
<h4>The ESP32 Update web page without refresh
</h4>
<br>
<p>LED State:
<strong>OFF
</strong>
</p>
<p>RDM number:
<span id="rdm">0
</span>
</p>
<p>
<button onclick="window.location.href = '/?led=on'">ON
</button>
</p>
<p>
<button onclick="window.location.href = '/?led=off'">OFF
</button>
</p>
<br>
<a href="http://www.google.com">www.google.com
</a>
</div>
<script>
var asyncGetData = new Promise(getData)
asyncGetData.then(() => {
setTimeout(asyncGetData, 2000)
})
function getData(resolve) {
var xhttp = new XMLHttpRequest();
var rdm = document.getElementById("rdm").value;
alert("Test 123!!");
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
//returns 4 when the server finishes streaming the response
document.getElementById("rdm").innerHTML = rdm;
resolve();
//return object whose id property matches the specified string
}
};
xhttp.send();
}
</script>
</body>
</html>
You should resolve xhr before calling interval/timeout, also you need to call method open
var asyncGetData = new Promise(getData)
function run () {
asyncGetData.then(d => {
console.log(d)
setTimeout(run, 2000)
})
}
run()
function getData(resolve) {
var xhttp = new XMLHttpRequest();
// var rdm = document.getElementById("rdm").value;
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
//returns 4 when the server finishes streaming the response
document.getElementById("rdm").innerHTML = JSON.stringify(JSON.parse(this.responseText), false, 2);
resolve(this.responseText);
//return object whose id property matches the specified string
}
};
// you need to call open with the method an the api url
xhttp.open('GET', 'https://api.github.com/users/octocat')
xhttp.send();
}
<pre id="rdm"></pre>
Related
I am trying to display the data (a bunch of upcoming events) on list.php using JavaScript, I think a for loop is the way to go but am not sure what is wrong with this. The console displays nothing, previously I had my for loop outside of the xhttp.onreadystatechange and it was giving "getData is undeclared" error messages. I am very new to this so apologies if I worded the question wrong or am not clear. I am a beginner coder so please no overly complicated answers!
here is my list.php code:
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script type="text/javascript"></script>
<script>
function getData() {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (xhttp.readyState == 4 && xhttp.status == 200) {
var javaobj = JSON.parse(xhttp.response);
document.getElementById('div1').innerHTML = javaobj.name + " " +
javaobj.date + " " + javaobj.time + " " + javaobj.location + " " + javaobj.organiser;
}
xhttp.open("GET", "events.json", true);
xhttp.send();
//for loop to go split javaobj into array elements
for (i = 0; i < javaobj.length; ++i) {
console.log(javaobj[i].name);
console.log(javaobj[i].date);
console.log(javaobj[i].time);
console.log(javaobj[i].location);
console.log(javaobj[i].organiser);
}
}
}
</script>
</head>
<body>
<input type="button" name="data" onclick="getData()" value="Click to View Events" />
<div id="div1"></div>
</body>
</html>
I'm following a tutorial and I made a button to show some content. However this button doesn't work and I'm at my wits end unable to figure out what could be causing this.
Can someone show why this doesn't work?
const users = document.querySelector('#user');
const getUsers = document.getElementById('getUsers');
getUsers.addEventListener('click', loadUsers);
var loadUsers = () => {
console.log('hello button clicked')
let xhr = new XMLHttpRequest();
xhr.open('GET', 'https://api.github.com/users', true);
xhr.onload = () => {
if (this.status == 200) {
let gusers = this.responseText
console.log(gusers);
}
}
xhr.send()
}
console.log(getUsers)
<h1>USER</h1>
<button id="getUsers">Get Users</button>
<div id="users"></div>
Order of your variable declarations matters in this scenario due to hoisting - move the loadUsers definition above the call.
JavaScript only hoists declarations, not initializations. If a
variable is declared and initialized after using it, the value will be
undefined.
The block-quote above from MDN explains why function declarations can be defined after they are called (reading code from top-to-bottom), but variables that are initialized after they are used would have a value of undefined.
const users = document.querySelector('#user');
const getUsers = document.getElementById('getUsers');
const loadUsers = () => {
console.log('Load users..');
}
getUsers.addEventListener('click', loadUsers);
<head>
<meta charset="UTF-8">
<title>Testing AJAX</title>
</head>
<body>
<h1>USER</h1>
<button id="getUsers">Get Users</button>
<div id="users"></div>
</body>
Or you could keep the function at the bottom but use a function declaration which will be hoisted:
const users = document.querySelector('#user');
const getUsers = document.getElementById('getUsers');
getUsers.addEventListener('click', loadUsers);
function loadUsers() {
console.log('Load users..');
}
<head>
<meta charset="UTF-8">
<title>Testing AJAX</title>
</head>
<body>
<h1>USER</h1>
<button id="getUsers">Get Users</button>
<div id="users"></div>
</body>
In addition to the correct answer have a look at your code that I have refactored below. Hope this helps.
// Get Elements
const usersList = document.querySelector('#usersList');
const usersBtn = document.querySelector('#usersBtn');
// Bind listener to usersButton
usersBtn.addEventListener('click', () => {
// XHR Request function
const xhr = new XMLHttpRequest();
xhr.open('GET','https://api.github.com/users')
xhr.send()
xhr.onload = function() {
if (xhr.status == 200) {
// Convert the response to JSON and assign it to data
const data = JSON.parse(xhr.responseText)
// Loop throug through data
for(let i = 0; i <data.length; i++) {
// Create LI element and append the user name
const listItem = document.createElement('li');
usersList.appendChild(listItem).innerHTML = data[i].login
}
}
}
})
<h1>USERS</h1>
<button id="usersBtn">Get Users</button>
<ul id="usersList"></ul>
I'm trying read a text file and based on the contents of that text file, change the image on a webpage. I tried using the console log to get error messages back, however I'm not getting errors. The contents of the txt file is literally the name of the images I want to show. Below is my javascript and html code.
<!DOCTYPE html>
<html>
<meta charset="utf-8"/>
<script type="text/javascript">
window.onload = function(){
var txtFile = new XMLHttpRequest();
txtFile.open("GET", "../HTML/Images/Bowl.txt", true);
console.log(txtFile);
txtFile.onreadystatechange = function() {
allText = txtFile.responseText;
lines = txtFile.responseText.split("\n"); // Will separate each line into an array
if (lines === 'GDogbowl.png'){
document.getElementById('myImage').src='../HTML/Images/GDogbowl.png'
}
else if (lines === 'YDogbowl.png') {
document.getElementById('myImage').src='../HTML/Images/YDogbowl.png'
}
else {
document.getElementById('myImage').src='../HTML/Images/RDogbowl.png'
}
}
}
</script>
<body>
<table class="centerTable" >
<tr>
<td>
<div class="imgContainer">
<div>
<img id="fullsize" />
<ul id="thumbs">
<img id="myImage" src= "../HTML/Images/RDogbowl.png" style="width:100px">
</ul>
</div>
<div class="imgButton">
<button id="Bowl" >Toggle Color</button>
</div>
</div>
</td>
</table>
</body>
You can't magicly pull data out of an array as if it were a string. To solve the issue, you'll have to loop through the array after you've split the lines. Something like this:
var xhr = new XMLHttpRequest();
var data = null;
xhr.open("GET", "../HTML/Images/Bowl.txt", true);
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200) {
data = xhr.responseText.split('\n');
for(var i=0; i<data.length; i++){
document.getElementById('myImage').src='../HTML/Images/'+data;
}
}
};
xhr.send();
You need to check for txtFile.readyState == 4 and txtFile.status == 200 in your readystatechange handler, and you also need to do txtFile.send().
You also need to reference each URL in the lines array separately. Here's an example with two ways to show the images:
var txtFile = new XMLHttpRequest();
txtFile.open("GET", "../HTML/Images/Bowl.txt", true);
console.log(txtFile);
txtFile.onreadystatechange = function() {
if (txtFile.readyState == 4 && txtFile.status == 200) {
allText = txtFile.responseText;
lines = txtFile.responseText.split("\n"); // Will separate each line into an array
if (lines[0] === 'GDogbowl.png'){
document.getElementById('myImage').src='../HTML/Images/GDogbowl.png'
}
else if (lines[0] === 'YDogbowl.png') {
document.getElementById('myImage').src='../HTML/Images/YDogbowl.png'
}
else {
document.getElementById('myImage').src='../HTML/Images/RDogbowl.png'
}
// if you have several images, you need several image elements:
lines.forEach(function(imgUrl, i) {
var image = document.createElement("img");
img.src = imgUrl;
img.id = "myImage_" + i;
document.body.appendChild(img);
});
}
}
txtFile.send();
split returns an array, where each element contains a line. So use, lines[0] to access the first element, lines[1] to access the second and so on.
If you don't care about handling state changes of your xmlHTTPRequest, then you can use the onload event, rather than onstatechange. ( I think all modern browsers should support this by now)
And as others have alluded in their answers, if you only care about the first line item, and you are sure that the name in the file is always valid, then you can concatenate the strings to achieve your goal without all the if/else cases.
<!DOCTYPE html>
<html>
<meta charset="utf-8"/>
<script type="text/javascript">
window.onload = function(){
var txtFile = new XMLHttpRequest();
txtFile.open("GET", "../HTML/Images/Bowl.txt", true);
console.log(txtFile);
txtFile.onload = function() {
allText = txtFile.responseText;
lines = txtFile.responseText.split("\n"); // Will separate each line into an array
document.getElementById('myImage').src="../HTML/Images/"+lines[0];
</script>
<body>
<table class="centerTable" >
<tr>
<td>
<div class="imgContainer">
<div>
<img id="fullsize" />
<ul id="thumbs">
<img id="myImage" src="../HTML/Images/RDogbowl.png" style="width:100px">
</ul>
</div>
<div class="imgButton">
<button id="Bowl" >Toggle Color</button>
</div>
</div>
</td>
</table>
</body>
While converting a script to not require jQuery, I've discovered that if I load my content (a partial html page with html and javascript) via XMLHttpRequest, the javascript in the partial page does not work. But if I load the partial using jQuery.load, it does work.
I've tried digging through jQuery's load function to see if it's doing anything special and nothing jumped out at me. I've been banging my head against the wall and searching for an answer for a couple of days now to no avail.
What am I doing wrong/how can I make it work like it does when loaded with jQuery.load?
EDIT
I got the XMLHttpRequest method to work by splitting out out my javascript from the html in the fragment and loading the javascript using the suggested technique here: https://stackoverflow.com/a/11695198/362958. However, that still does not provide an explanation of why jQuery.load works. Is jQuery umtimately parsing the HTML and doing the same thing for any scripts it finds within the content it loads?
I've set up a plunker (https://plnkr.co/edit/wE9RuULx251C5ARnUbCh) with the following code that demonstrates the issue. Note: once you load the fragment with jQuery, it will continue to work and you'll have to restart the plunk for the XMLHttpRequest method to fail again.
index.html:
<!DOCTYPE html>
<html>
<head>
<script data-require="jquery#*" data-semver="3.0.0" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.0.0/jquery.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body>
<h3>Buttons</h3>
<div>
<input type="button" value="Load with XMLHttpRequest" onclick="loadXMLDoc('ajaxContentDiv', 'fragmentToLoad.html');"> (Links do not work if loaded this way... Script from fragmentToLoad.html not loaded in DOM?) <br/><br/>
<input type="button" value="Load with JQuery" onclick="jQuery('#ajaxContentDiv').load('fragmentToLoad.html');"> (Links will work if loaded this way)
</div>
<br/>
<br/>
<br/>
<div id="ajaxContentDiv">Content will load here...</div>
</body>
</html>
script.js:
function loadXMLDoc(targetDivName, url) {
var xmlhttp = new XMLHttpRequest();
xmlhttp.open("GET", url, true);
xmlhttp.onreadystatechange = function () {
if (xmlhttp.readyState == XMLHttpRequest.DONE) {
if (xmlhttp.status == 200) {
document.getElementById(targetDivName).innerHTML = xmlhttp.responseText;
}
}
};
xmlhttp.send();
}
fragmentToLoad.html:
<div id="divToBeUpdated">
<span id="stringBox">String here</span>
</div>
<br/>
<h3>Links</h3>
<div>
Link 1<br>
Link 2<br>
Link 3<br>
</div>
<script>
function updateDiv(string){
var stringBox = document.getElementById('stringBox');
stringBox.innerHTML = string;
}
</script>
You can use single .html file, and you are on the correct track by splitting the html content - though you can also split the html content of a single file, rather than requesting two files. #Barmar explains the functionality of jQuery's .load() method at this comment.
script.js
function loadXMLDoc(targetDivName, url) {
var xmlhttp = new XMLHttpRequest();
xmlhttp.open("GET", url, true);
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == XMLHttpRequest.DONE) {
if (xmlhttp.status == 200) {
// create a `div` elemenent, append response to `div` element
// get specific elements by `id`, append `script` element to `document.body`
var content = document.createElement("div");
content.innerHTML = xmlhttp.responseText
var div = content.querySelector("#htmlContent");
var contentScript = content.querySelector("#contentScript");
var script = document.createElement("script");
script.textContent = contentScript.textContent;
document.getElementById(targetDivName).innerHTML = div.innerHTML;
document.body.appendChild(script);
}
}
};
xmlhttp.send();
}
fragmentToLoad.html
<div id="htmlContent">
<div id="divToBeUpdated">
<span id="stringBox">String here</span>
</div>
<br/>
<h3>Links</h3>
<div class="links">
Link 1
<br>
Link 2
<br>
Link 3
<br>
</div>
</div>
<script type="text/javascript" id="contentScript">
function updateDiv(string) {
var stringBox = document.getElementById('stringBox');
stringBox.innerHTML = string;
}
// attach `click` event to `.link a` elements here
var links = document.querySelectorAll(".links a");
for (var i = 0; i < links.length; i++) {
(function(link, i) {
console.log(i)
link.addEventListener("click", function(e) {
e.preventDefault();
updateDiv("Hello World " + i)
})
})(links[i], i)
}
</script>
plnkr https://plnkr.co/edit/7fLtGRSV7WlH2enLbwSW?p=preview
HTML contains two div make different ajax calls to both the divs,where div1 is the result of html form and div2 should be the result of onclick on div1
html
<html lang="en">
<head>
<title>Display Movie Information</title>
<meta charset="utf-8"/>
<script type="text/javascript" src="movies.js"></script>
</head>
<body onload="initialize();">
<tr><td>
<form>
<label>Movie title: <input type="text" id="form-input"/></label>
<input type="button" onclick="sendRequest();" value="Display Info"/>
</form>
<div id="output"> </div></td>
<td><div id="right_panel">Display Dynamic results here</div></td>
</body>
</html>
I have a movies.js file which using ajax gets the result
function initialize () {
}
function sendRequest () {
var xhr = new XMLHttpRequest();
var query = encodeURI(document.getElementById("form-input").value);
xhr.open("GET", "proxy.php?method=/3/search/movie&query=" + query);
xhr.setRequestHeader("Accept","application/json");
xhr.onreadystatechange = function () {
if (this.readyState == 4) {
var json = JSON.parse(this.responseText);
var str = JSON.stringify(json,undefined,2);
//customized code
console.log(json.results.length);
var i=0;
var movie_title,release_date;
var movies = new Array();
while(i<json.results.length)
{
movie_title = json.results[i].title;
release_date = json.results[i].release_date;
movies[i] = "<li>"+movie_title+"<br/>"+release_date+"<br/></li>";
i++;
}
document.getElementById("output").innerHTML = "<ul>" + movies + " </ul>";
}
};
var movie_detail = new XMLHttpRequest();
var movie_credit = new XMLHttpRequest();
xhr.send(null);
}
This code displays the title and the release date of the movies(result of onclick on the button)
Q: I want to make the movie title an hyperlink that could make a call like www.imdb.com/(movie_title) and display the result in the second div tag named "right_panel" using only ajax and javascript and no jquery.