I am going to fetch a json file from jsonbin when clicking a button, but it is not working, your help is appreciated.
<button id="runxhr">RUN XHR</button>
<div id="main"></div>
js file is here:
function runXHR() {
let xhr = new XMLHttpRequest();
addListeners(xhr);
xhr.open(
"GET",
"https://api.jsonbin.io/v3/b/62b4395c449a1f3821167058/",
true
);
xhr.setRequestHeader("X-Bin-Meta", "false");
xhr.send();
return xhr.responseText;
}
function addListeners(xhr) {
xhr.addEventListener("loadend", display(xhr));
}
function display(jsonstring) {
let main = document.getElementById("main");
json = JSON.parse(jsonstring);
main.innerHTML = json[0]["name"];
}
const buttnRun = document.getElementById("runxhr");
buttnRun.addEventListener("click", () => {
runXHR();
});
JSONBin author here. You are doing several things wrong in the above example so I just refactored your code in general. Here's how you could fetch the JSON and print the body on click of a button.
To enhance it further, I have replaced your div tag with a pre tag, and I am using JSON.stringify() to pretty print the JSON to make it readable.
let btn = document.getElementById('runxhr');
btn.addEventListener('click', () => {
let req = new XMLHttpRequest();
req.onreadystatechange = () => {
if (req.readyState == XMLHttpRequest.DONE) {
document.getElementById('main').innerText = JSON.stringify(JSON.parse(req.responseText), null, 2);
}
};
req.open("GET", "https://api.jsonbin.io/v3/b/62b4395c449a1f3821167058/", true);
req.setRequestHeader("X-Bin-Meta", false);
req.send();
})
<button id="runxhr">Run XHR</button>
<pre id="main"></pre>
Related
I've run into issues trying to write a XMLHttpRequest loadmore function over $.ajax and unsure what i'm missing.
Below is my function which is based on a working $.ajax version I have used before. With jQuery version I use a data object, but I can't get this to work it XMLHttpRequest. I've tried including it with FormData, but I don't think it's the right way to go.
Data Object example from jQuery version which adds WP specific data relating to post type, action to link with PHP function etc:
data = {
action: "loadmore",
query: WP.posts, // that's how we get params from wp_localize_script() function
page: WP.current_page
};
const xhr = new XMLHttpRequest();
const el = document.getElementById("loadmore");
if (el) {
el.addEventListener("click", e => {
e.preventDefault();
el.value = this.value;
xhr.onload = function() {
const button = this;
if (xhr.status === 200) {
document.getElementById("response").innerHTML = xhr.responseText;
if (data) {
WP.current_page++;
if (WP.current_page == WP.max_page) button.remove(); // if last page, remove the button
} else {
button.remove(); // if no data, remove the button as well
}
} else {
console.log(xhr.status);
console.log(xhr.response);
console.log(xhr.responseText);
}
};
xhr.open("POST", WP.ajax, true);
// const formData = new FormData(el);
const data = new FormData();
data.append("action", "loadmore");
data.append("query", WP.posts);
data.append("page", WP.current_page);
xhr.send(data);
});
}
Here is an example of working jQuery function. Innocence I'm wanting the same results but with XMLHttpRequest... Any help/direction would be appreciated :)
jQuery(function($) {
$("#loadmore").click(function() {
var button = $(this),
data = {
action: "loadmore",
query: WP.posts,
page: WP.current_page
};
$.ajax({
url: WP.ajaxurl,
data: data,
type: "POST",
beforeSend: function(xhr) {
button.text("Loading...");
},
success: function(data) {
if (data) {
button
.text("More posts")
.prev()
.before(data);
WP.current_page++;
if (WP.current_page == WP.max_page) button.remove();
} else {
button.remove();
}
}
});
});
});
So I worked out the solution. If anyone is interested here it is:
As you can't use a data object like you can for $.ajax, appending to formData achieves the same results, then add data const in send.
const data = new FormData();
data.append("action", "loadmore");
data.append("query", WP.posts);
data.append("page", WP.current_page);
xhr.send(data);
const xhr = new XMLHttpRequest();
const el = document.getElementById("loadmore");
el.addEventListener("click", e => {
e.preventDefault();
el.value = this.value;
const data = new FormData();
data.append("action", "loadmore");
data.append("query", WP.posts);
data.append("page", WP.current_page);
xhr.onload = function() {
if (xhr.status === 200) {
document.getElementById("response").innerHTML = xhr.responseText;
console.log(xhr.responseText);
WP.current_page++;
} else {
console.log(xhr.status);
console.log(xhr.response);
console.log(xhr.responseText);
}
};
xhr.open("POST", WP.ajax, true);
xhr.send(data);
});
If there is a better way of doing this please let me know.
I'm very new to JavaScript and have been looking for a solution for a while with no success. I'm trying to use the Last.fm API to retrieve the currently playing track on my account. This is what I have so far:
<html>
<body>
<p>this is an experiment!</p>
<script type="text/javascript">
const request = new XMLHttpRequest();
request.open('GET', 'http://ws.audioscrobbler.com/2.0/?method=user.getrecenttracks&user='+[MY_USERNAME]+'&api_key='+[MY_API_KEY]+'&format=json');
request.send();
request.onload = () => {
if (request.status === 200) {
console.log("Success");
var song = JSON.parse(request.response).recenttracks.track[0].name;
console.log(song);
}
};
request.onerror = () => {
console.log("error")
};
</script>
</body>
</html>
and I get an error in the console when I open the file in my browser. Any help is appreciated :)
Update: everything worked when I gave it the direct URL, e.g. I took out the +s and put the API key directly in.
I checked your code with the test-account and it works fine. So probably you get the empty result, let's add some checks:
request.onload = () => {
if (request.status === 200) {
// look at the response
console.log(request.response);
const recenttracks = JSON.parse(request.response).recenttracks;
if (!recenttracks.track || !recenttracks.track.length) {
console.log('track is empty');
return;
}
const song = recenttracks.track[0].name;
console.log(song);
}
};
It looks like you should use onreadystatechange to catch the response instead of onload.
Example:
request.onreadystatechange = function() {
if (this.status == 200) {
console.log(this.responseText);
}
};
You can read more about XMLHttp Requests here:
https://www.w3schools.com/xml/ajax_xmlhttprequest_send.asp
I'm trying to program a Client, that can record audio data and then send it to a server.
I don't have much experience in front-end development. I was told to use React and so I'm trying to use ReactMediaRecorder (https://github.com/avasthaathraya/react-media-recorder).
render () {
return (
<ReactMediaRecorder
audio
whenStopped={blobUrl=>this.setState({audio: blobUrl })}
render={({startRecording, stopRecording, mediaBlob }) => (
<div>
<button id="recorder" className="button" onClick={startRecording}>Start Recording</button>
<button className="button" onClick={() => {stopRecording();this.upload()}}>Stop Recording</button>
<audio id="player" src={mediaBlob} controls />
</div>
)}
/>
)
}
upload() {
console.log("upload was called with blob " + this.state.audio)
//if (false) {
if (this.state.audio != null) {
console.log("got here, type of audio is " + this.state.audio)
var xhr = new XMLHttpRequest();
var filename = new Date().toISOString();
xhr.onload = function (e) {
if (this.readyState === 4) {
console.log("Server returned: ", e.target.responseText);
}
};
var fd = new FormData();
fd.append("audio_data", this.state.audio, filename);
xhr.open("POST", "http://127.0.0.1:3000", true);
xhr.send(fd);
}
}
At first it seemed very straightforward. But I don't get why I can't send the mediaBlob. The formData.append says, that this.state.audio is not of type Blob. So I checked it's type in the console log, and found out it is of type stringContent. I tried to create a Blob from that by using new Blob() but failed. I also fail to find information of this type.
Does somebody know what to do?
Ok I finally got it. The mistake was, that mediaBlob is actually not blob, but a blob Url. So first we need to load it and then we can send it. I changed my upload function to:
upload(mediaBlob) {
if (this.state.audio != null) {
//load blob
var xhr_get_audio = new XMLHttpRequest();
xhr_get_audio.open('GET', mediaBlob, true);
xhr_get_audio.responseType = 'blob';
xhr_get_audio.onload = function(e) {
if (this.status == 200) {
var blob = this.response;
//send the blob to the server
var xhr_send = new XMLHttpRequest();
var filename = new Date().toISOString();
xhr_get_audio.onload = function (e) {
if (this.readyState === 4) {
console.log("Server returned: ", e.target.responseText);
}
};
var fd = new FormData();
fd.append("audio_data",blob, filename);
xhr_send.open("POST", "http://localhost/uploadAudio",
true);
xhr_send.send(fd);
}
};
xhr_get_audio.send();
}
}
Now it works fine.
I am working with a JSON file that I have, and I am linking it in my JavaScript.
I am trying to get it requested through AJAX to show up on my console.log, but I am just getting null for my readystatechange function. What am I doing wrong?
Also to better clarify I am doing this for my course and ideally what my goal is; I have a json file that I created (myjson.com), I have that URL its in my JavaScript, and I am trying to get that json url to update to my JavaScript so when I do a console.log it shows up the values of the objects from the json. Here's my code:
<div id="btn1"> Update </div>
<div id="output"></div>
<script>
var output = document.getElementById("output");
document.getElementById("btn1").onclick = function () {
var a = newXMLHttpRequest();
a.onreadystatechange = function () {
}
a.open("GET", "https://api.myjson.com/bins/z79bt", true);
a.send();
};
</script>
UPDATE
Code from the comment:
var output = document.getElementById("output");
document.getElementById("btn1").onclick = function () {
var a = new XMLHttpRequest();
a.onreadystatechange = function () {
if(this.readyState == 4) {
var myObj = this.responseText;
}
console.log(a);
}
a.open("GET", "api.myjson.com/bins/z79bt";, true);
a.send();
};
Two issues:
you're missing a space in newXMLHttpRequest
you're not doing anything inside the state change callback
(third: you're also not populating the output div)
See the live example here:
var output = document.getElementById("output");
document.getElementById("btn1").onclick = function () {
var a = new XMLHttpRequest();
a.onreadystatechange = function () {
if(a.readyState === XMLHttpRequest.DONE && a.status === 200) {
console.log(a.responseText);
output.textContent = a.responseText;
}
}
a.open("GET", "https://api.myjson.com/bins/z79bt", true);
a.send();
};
<div id="btn1"> Update </div>
<div id="output"></div>
UPDATE
Fixed code from the comment:
var output = document.getElementById("output");
document.getElementById("btn1").onclick = function () {
var a = new XMLHttpRequest();
a.onreadystatechange = function () {
if(this.readyState == 4) {
var myObj = this.responseText;
console.log(myObj);
}
}
a.open("GET", "https://api.myjson.com/bins/z79bt", true);
a.send();
};
<div id="btn1"> Update </div>
<div id="output"></div>
I am trying to append the contents of a .html file to the body of my main page. Basically, I am trying to make a reusable chunk of html that I can load into any page with a simple JavaScript function.
Here is the content of my nav bar, the content I want to reuse:
<div id = "navbar">
<div class = "Tab">
<h1>Home</h1>
</div>
<div class = "Tab">
<h1>Contact</h1>
</div
</div>
That is in a file called navbar.html
Now in my main index.html I want to import it by doing something like this:
<head>
<script src = "importHTML.js" type = "text/javascript"></script>
</head>
<body>
<script type = "text/javascript">
importHTML("navbar.html");
</script>
</body>
That should take care of importing the html in navbar.html.
The content of importHTML.js is this:
function importHTML(url_) {
var request = new XMLHttpRequest();
request.addEventListener("load", function(event_) {
//This is the problem line of code
//How do I get the contents of my response to act like an element?
document.body.appendChild(this.responseText);
}, false);
xmlhttprequest.open("POST", url_, true);
xmlhttprequest.send(null);
}
So, I guess my question is pretty simple: How do I convert that response text to an HTML element so I can append all of it to the body?
Ajax HTML Injection
jQuery $.get() and JavaScript XMLHttpRequest()
This is a demonstration of 2 ways to inject, include, import, etc. There's 3 pages:
index.html
It has 2 links and 2 divs
data1.html
It's data will be imported to index.html by $.get()
data2.html
It's data will be imported to index.html by XMLHttpRequest()
I added jQuery to show the difference in complexity, but they do the same thing. The live demo is at the end of this mess.
jQuery $.get() Setup
HTML on index.html
div#data1 is the element that'll have the HTML of data1.html appended to it.
<h3 id="import1">
Import data1.html by jQuery<code>$.get()</code>
</h3>
<div id="data1"></div>
jQuery on index.html
$('#import1').on('click', function(e) {
e.preventDefault();
$.get('data1.html', function(data) {
$("#data1").html(data);
});
});
JavaScript XMLHttpRequest() Setup
HTML on index.html
div[data-x] is the element that'll have the HTML of data2.html appended to it.
<h3 id="import2">
<a href="">
Import data2.html by JavaScript<code>XMLHttpRequest()</code>
</a></h3>
<div data-x="data2.html"></div>
javaScript on index.html
function xhr() {
var tags, i, clone, file, xhttp;
tags = document.getElementsByTagName("*");
for (i = 0; i < tags.length; i++) {
if (tags[i].getAttribute("data-x")) {
clone = tags[i].cloneNode(false);
file = tags[i].getAttribute("data-x");
xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (xhttp.readyState == 4 && xhttp.status == 200) {
clone.removeAttribute("data-x");
clone.innerHTML = xhttp.responseText;
tags[i].parentNode.replaceChild(clone, tags[i]);
xhr();
}
}
xhttp.open("GET", file, true);
xhttp.send();
return;
}
}
}
document.getElementById('import2').addEventListener('click', function(e) {
e.preventDefault();
xhr();
}, false);
README.md
Plunker
Note: This demo relies on user interaction via anchor links. This of course is probably not exactly what you need. You probably want it automatically loaded, so the following modifications are needed:
jQuery
$(function() {
$.get('data1.html', function(data) {
$("#data1").html(data);
});
});
JavaScript
(function xhr() {
xhr();
var tags, i, clone, file, xhttp;
tags = document.getElementsByTagName("*");
for (i = 0; i < tags.length; i++) {
if (tags[i].getAttribute("data-x")) {
clone = tags[i].cloneNode(false);
file = tags[i].getAttribute("data-x");
xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (xhttp.readyState == 4 && xhttp.status == 200) {
clone.removeAttribute("data-x");
clone.innerHTML = xhttp.responseText;
tags[i].parentNode.replaceChild(clone, tags[i]);
xhr();
}
}
xhttp.open("GET", file, true);
xhttp.send();
return;
}
}
})();
Interestingly there is an upcoming W3C draft for HTML imports
https://www.w3.org/TR/html-imports/
Until then we can append the required markup to the DOM using Javascript.
JQuery approach
$(document).ready(function(){
$( "body" ).load( "navbar.html" );
});
Js haven't native method for this task, but you can use jquery method load
${element}.load('./template.html');
Or, create element-container, and use innerHTML prop
request.addEventListener("load", function(event_) {
//This is the problem line of code
//How do I get the contents of my response to act like an element?
var container = document.createElement("div");
container.innerHTML = this.responseText;
document.body.appendChild(container);
}, false);
UPD
Convert string to DOM.
function strToDom(str) {
var tempEl = document.createElement('div');
tempEl.innerHTML = str;
return tempEl.children[0];
}
NOTE: string element should be one root element, that wraps others
<div> ... </div>
not
<div></div><div></div>
The importHTML.js file will look like this :
function importHTML(url_) {
var request = new XMLHttpRequest();
request.addEventListener("load", function(event_) {
var iDiv = document.createElement('div');
iDiv.innerHTML = this.responseText;
document.getElementsByTagName('body')[0].appendChild(iDiv);
}, false);
request.open("POST", url_, true);
request.send(null);
}
I assume you can create a div and then modify the div.innerHTML to have the content of the response:
function importHTML(url_) {
var request = new XMLHttpRequest();
request.addEventListener("load", function(event_) {
var myDiv = document.createElement("div")
myDiv.innerHTML = this.responseText
document.body.appendChild(myDiv);
}, false);
xmlhttprequest.open("POST", url_, true);
xmlhttprequest.send(null);
}
you need a reference to DOM to know where to innest your loaded page. in your case you could think about appending it to body like this:
function importHTML(url_) {
var request = new XMLHttpRequest();
request.addEventListener("load", function(event_) {
document.body.innerHTML += this.responseText
}, false);
xmlhttprequest.open("POST", url_, true);
xmlhttprequest.send(null);
}