When the button is clicked I would like my text to change every 3 secs. I am using setInterval I can see the numbers changing in console.log but the text isn't changing and i don't know why.
What I've tried:
setInterval(function() {
var quote = jokesArray[jokeNum];
console.log(jokeTxt.innerHTML = quote);
}
setInterval(function() {
if (jokeTxt.innerHTML !== "") {
jokeTxt.innerHTML = "";
jokeNum++;
jokeTxt.innerHTML = jokesArray[jokeNum];
}
setInterval(function() {
var quote = jokesArray[Math.floor(Math.random() % 586) + 1];
console.log(jokeTxt.innerHTML = quote);
Full Script:
function main() {
var myApi = "https://api.icndb.com/jokes/random";
var xhttp = new XMLHttpRequest();
var jokesArray = [];
var randomIndex = Math.random();
var randomizer = (randomIndex % 586) + 1;
var jokeNum = Math.floor(randomizer);
var jokeTxt = document.getElementById("jokeTxt");
xhttp.onreadystatechange = function () {
if (xhttp.readyState == XMLHttpRequest.DONE) {
var jokesJSON = JSON.parse(xhttp.responseText);
var jokes = jokesJSON.value.joke;
for (var i = 0; i < jokes.length; i++) {
jokesArray.push(jokes);
}
//allJokes = jokesArray[jokeNum];
setInterval(function() {
var quote = jokesArray[Math.floor(Math.random() % 586) + 1];
console.log(jokeTxt.innerHTML = quote);
},3000);
}
}
xhttp.open("GET", myApi, true);
xhttp.send();
}
var myBtn = document.getElementById("btn");
myBtn.onclick = main;
The API you're using only returns a single joke at a time, rather than an array of multiple jokes. In your code, you're treating var jokes as though it's an array of many jokes, but this is actually just a string - i.e., one joke. Iterating over this variable means you're looping over the string and performing an action for each character in the joke.
The API also returns a random joke from their database, so instead of building a local array and selecting a random element, you could just send multiple requests to the API and get a new (random) joke each time. Here's a modification of your code that does this:
var jokeTxt = document.getElementById("jokeTxt");
function getJoke() {
var myApi = "https://api.icndb.com/jokes/random";
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (xhttp.readyState == XMLHttpRequest.DONE) {
var jokesJSON = JSON.parse(xhttp.responseText);
var joke = jokesJSON.value.joke;
jokeTxt.innerHTML = joke;
}
}
xhttp.open("GET", myApi, true);
xhttp.send();
}
function startJokes() {
// get the first joke right away...
getJoke();
// ...then get a new joke every 3 seconds
setInterval(function() {
getJoke();
}, 3000);
}
var myBtn = document.getElementById("btn");
myBtn.onclick = startJokes;
<button id="btn">Start the Jokes!</button>
<div id="jokeTxt"><div>
Related
So I'm trying to get a list of JSON objects and then loop through its elements via fori loop, creating <li> and <a> elements.
Everything works smoothly except when I try to add an onclick function to the in each iteration. I'm trying to pass the json object to the onclick function, but all tags have are showing the last json object.
What I need is for every <a> to show its corresponding json object when clicked.
Please see the code:
var url = "https://restcountries.eu/rest/v2/all"
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var countries = JSON.parse(xhttp.responseText)
var ul = document.getElementById('countries')
for (var i = 0; i < countries.length; i++) { //start iteration
var li = document.createElement("LI")
var img = document.createElement("IMG")
var a = document.createElement("A")
var textNode = document.createTextNode(countries[i].name)
img.setAttribute("src", countries[i].flag)
ul.appendChild(li)
li.appendChild(a)
a.appendChild(img)
a.appendChild(textNode);
a.setAttribute("title", countries[i].name)
var country = countries[i]
a.onclick = function(){ CountryClicked(country)} //pass the current JSON to the onclick function of the current <a> Node, this isn't working correctly.
}
}
}
xhttp.open('GET', url, true);
xhttp.send();
function CountryClicked(country){
var div = document.getElementById("parent-country-container")
var h1 = document.createElement("h1")
// div.appendChild(h1)
h1.appendChild(document.createTextNode(country.name + " Clicked"))
div.innerHTML = ""
div.appendChild(h1)
}
Thank you for your time.
It is neccesary to use a closures function to be able to send the right country.
function CountryClicked(el) {
alert(el.name);
}
var countries = [{'flag':'xx',name:'name'}, {'flag':'xx',name:'text 2'}];
var ul = document.getElementById('countries')
for (var i = 0; i < countries.length; i++) { //start iteration
var li = document.createElement("LI")
var img = document.createElement("IMG")
var a = document.createElement("A")
var textNode = document.createTextNode(countries[i].name)
img.setAttribute("src", countries[i].flag)
ul.appendChild(li)
li.appendChild(a)
a.appendChild(img)
a.appendChild(textNode);
a.setAttribute("title", countries[i].name)
var country = countries[i];
a.onclick = (function(country){
return function(){ CountryClicked(country); }
})(country);
}
<ul id="countries"></ul>
I have a script in HTML page head that declares a function to make a get requests for JSON data and passes it to element’s innerHTML.
function called on page load.
Script in head correctly gets JSON data and populates elements innerHTML.
I would like to cross-fade loop between the 2 bits of JSON data.
Script in body tries to get element’s innerHTML and create array to use as input to cross fade loop.
Element’s innerHTML variable comes back empty.
The cross-fade loop script works if strings are declared in array.
Fiddle here
How can I get the JSON values into the text cycle?
<script>
var intervalID = window.setInterval(insertText, 2000);
function insertText(){
const Http = new XMLHttpRequest();
const url = "https://api.kraken.com/0/public/Ticker?pair=XXBTZUSD";
Http.open("GET", url);
Http.send();
Http.onreadystatechange=(e)=>{
const price = Http.responseText
const priceJson = JSON.parse(price);
var priceJsonBtc = priceJson.result.XXBTZUSD.c[0];
var btc = parseFloat(priceJsonBtc)
var btcp = btc.toFixed(2)
console.log(btcp);
document.getElementById("priceUsd").innerHTML = "$" + btcp + " USD";
const usdp = btcp
}
const HttpGbp = new XMLHttpRequest();
const urlGbp = "https://api.kraken.com/0/public/Ticker?pair=XXBTZGBP";
HttpGbp.open("GET", urlGbp);
HttpGbp.send();
HttpGbp.onreadystatechange=(e)=>{
const priceGbp = HttpGbp.responseText
const priceJsonGbp = JSON.parse(priceGbp);
var priceJsonBtcGbp = priceJsonGbp.result.XXBTZGBP.c[0];
var btcGbp = parseFloat(priceJsonBtcGbp)
var btcpGbp = btcGbp.toFixed(2)
console.log(btcpGbp);
document.getElementById("priceGbp").innerHTML = "£" + btcpGbp + " GBP";
const gbpp = btcpGbp
}
}
</script>
</head>
<body onload=insertText()>
<h1 id="priceUsd"></h1>
<h1 id="priceGbp"></h1>
<h1 id="changer">£ GBP</h1>
<script>
var usd = document.getElementById("priceUsd").innerHTML;
var gbp = document.getElementById("priceGbp").innerHTML;
/* This does not work */
/* var words = [usd, gbp]; */
/* This does work */
var words = ["£ GBP", "$ USD"];
var i = 0;
var text = "BTC";
function _getChangedText() {
i = (i + 1) % words.length;
return text.replace(/BTC/, words[i]);
}
function _changeText() {
var txt = _getChangedText();
var d = document.getElementById("changer")
d.className = "fadeOut";
setTimeout(function(){
d.className = "";
document.getElementById("changer").innerHTML = txt;
}, 900);
}
setInterval("_changeText()", 1000);
</script>
</body>
Resolved with setInterval to delay pulling HTML elements before they had been updated:
var intervalID = window.setInterval(updateText, 1500);
function updateText() {
var usd = document.getElementById("price").innerHTML
var gbp = document.getElementById("priceGbp").innerHTML
words = [usd, gbp]
}
var i = 0;
var text = "BTC";
function _getChangedText() {
i = (i + 1) % words.length;
return text.replace(/BTC/, words[i]);
}
function _changeText() {
var txt = _getChangedText();
var d = document.getElementById("changer")
d.className = "fadeOut";
setTimeout(function(){
d.className = "";
document.getElementById("changer").innerHTML = txt;
}, 800);
}setInterval("_changeText()", 3000)
i tried to run a script for developing an add-on. Somehow, the first run will return undefined and only the second run will obtain the result i desire. I searched through and realised it might be something related with hoisting. Any ideas on this? Thanks.
var array1=[];
var array2=[];
var arrayPDS=[];
var arrayPD=[];
var suggPD;
function handleClick(state) {
var suggPD = Request({
url: "http://google.com/complete/search?output=toolbar&q=" + primarydomain,
overrideMimeType: "application/xml; charset=latin1",
onComplete: suggPDparse,
}).get();
function suggPDparse(response) {
var {Cc, Ci} = require("chrome");
var parser = Cc["#mozilla.org/xmlextras/domparser;1"].createInstance(Ci.nsIDOMParser);
var xml = parser.parseFromString(response.text, "application/xml");
var pds;
var pd = xml.getElementsByTagName("suggestion");
for (i=1;i<pd.length;i++){
pds = pd[i].getAttribute("data");
array1.push(pds);
arrayPDS = array1[0];
}
function loadXMLDoc(filename, callback){
var req = new XMLHttpRequest();
req.open("GET",filename,true);
req.onreadystatechange = function(){
if(req.readyState === 4){
callback(req.responseXML);
}
}
req.send();
}
loadXMLDoc(self.data.url("pd.xml"), function(xmlDoc){
if (xmlDoc.documentElement.nodeName=="parsererror"){
console.log(xmlDoc.documentElement.childNodes[0].nodeValue);
return(null);
}
var x = xmlDoc.getElementsByTagName("Row");
for (i=0; i<x.length; i++){
var a=x[i];
getV=(a.getElementsByTagName("Field_0")[0].childNodes[0].nodeValue);
array2.push(getV);
}
arrayPD = array2;
});
}
console.log("arrayPD: " + arrayPD);
console.log("arrayPDS: " + arrayPDS);
}
The result for first click will return:
arrayPD:
arrayPDS:
The result for second click will return:
arrayPD:abcd
arrayPDS:abcd
I need some help on an assignment that I need to do. Basically the question is a number guessing game. We're assigned a number in the interval [0,1023] based on our student number and we have 11 guesses to get the right number. I know I have to use a binary search to get the number, my only problem is connecting to the server and getting a result.
We're given this:
A sample request looks as follows:
http://142.132.145.50/A3Server/NumberGuess?snum=1234567&callback=processResult&guess=800
And also given that the request returns the following parameters:
1: A code to determine if your guess is equal, less than or greater than the number
2: Message string
3: Number of guesses made by my application
This is what I've tried so far, just as a test to get the server request working. All I get in return is "object HTMLHeadingElement"
window.onload = function() {
newGuess();
}
function newGuess() {
var url = "http://142.132.145.50/A3Server/NumberGuess?snum=3057267&callback=processResult&guess=600";
var newScriptElement = document.createElement("script");
newScriptElement.setAttribute("src", url);
newScriptElement.setAttribute("id", "jsonp");
var oldScriptElement = document.getElementById("jsonp");
var head=document.getElementsByTagName("head")[0];
if (oldScriptElement == null) {
head.appendChild(newScriptElement);
} else {
head.replaceChild(newScriptElement, oldScriptElement);
}
}
function processResult(code,message,guesses) {
var code = document.getElementById("code");
var message = document.getElementById("message");
var guesses = document.getElementById("guesses");
code.innerHTML = code;
message.innerHTML = message;
guesses.innerHTML = guesses;
}
EDIT: Current state of my code.
window.onload = function() {
min = 0;
max = 1023;
mid = 0;
setInterval(newGuess,1000);
};
function newGuess() {
mid = Math.floor((max-min)/2);
var url = "http://142.132.145.50/A3Server/NumberGuess?snum=3057267&callback=processResult&guess="+mid;
var newScriptElement = document.createElement("script");
newScriptElement.setAttribute("src", url);
newScriptElement.setAttribute("id", "jsonp");
var oldScriptElement = document.getElementById("jsonp");
var head=document.getElementsByTagName("head")[0];
if (oldScriptElement == null) {
head.appendChild(newScriptElement);
} else {
head.replaceChild(newScriptElement, oldScriptElement);
}
}
function processResult(codeJ,messageJ,guessesJ) {
code = document.getElementById("code");
message = document.getElementById("message");
guesses = document.getElementById("guesses");
code.innerHTML = codeJ;
message.innerHTML = messageJ;
guesses.innerHTML = guessesJ;
if(codeJ == 0){
return;
}else if(codeJ == -1){
min = mid + 1;
}else if(codeJ == 1){
max = mid -1;
}
console.log(mid);
}
Check your variable-names. You are overwriting the function-patameters.
Something like
code.innerHTML = code;
message.innerHTML = message;
guesses.innerHTML = guesses;
just CAN'T work, you should see the problem yourself...
I'm trying to make an image slider that changes the image 'displayMain' every few seconds. My problem is that when I call the displayMain function in setInterval, I continuously get a 'cannot read property 0 of undefined' error. Even when I use the hardcoded value of jsonData[i].name, I receive the same error. The value gets passed in displayThumbs just fine, however. Does anyone know why I can't retain the values in displayMain but can do so in displayThumbs?
window.addEventListener('load', function () {
var mainDiv = document.getElementById('main');
var descDiv = document.getElementById('main-description');
var gallery = document.querySelector('#main-img');
var ul = document.querySelector('ul');
var li;
var i = 0;
var displayThumbs;
var thumbName;
var current = 0;
var images = [];
function displayMain () {
var data = images[i];
gallery.src = 'img/' + data[0];
descDiv.innerHTML = '<h2>' + data[1] + '</h2>';
}
function displayThumbs () {
for (i = 0; i < images.length; i += 1) {
var data = jsonData[i].name.replace('.jpg', '_thumb.jpg');
// thumbnails use dom to make img tag
li = document.createElement('li');
thumbs[i] = document.createElement('img');
var createThumbNail = thumbs[i].src = 'img/' + data;
thumbs[i].setAttribute('alt', data);
thumbs[i].addEventListener('click', function() {
alert(createThumbNail);
});
ul.appendChild(thumbs[i]);
}
}
// success handler should be called
var getImages = function () {
// create the XHR object
xhr = new XMLHttpRequest();
// prepare the request
xhr.addEventListener('readystatechange', function () {
if (xhr.readyState === 4 && xhr.status == 200) {
// good request ...
jsonData = JSON.parse(xhr.responseText);
for (var i = 0; i < jsonData.length; i += 1) {
var data = [];
data.push(jsonData[i].name);
data.push(jsonData[i].description);
images.push(data);
}
displayMain();
displayThumbs();
setInterval(displayMain, 1000);
}
else {
// error
}
});
xhr.open('GET', 'data/imagedata.json', true);
xhr.send(null);
};
// setInterval(getImages, 2000);
getImages();
// displayThumbs();
});
Your problem is that your displayMain uses whatever value i is at the time, and i never gets incremented, so it'll be equal to images.length after the for loop in displayThumbs. displayThumbs increments it itself, so you won't ever go beyond the end of the array.
In your comment, you mentioned that you want to cycle through the images. This should work a bit better:
function displayMain () {
var data;
// wrap around to the first image
if (i >= images.length) {
i = 0;
}
data = images[i];
gallery.src = 'img/' + data[0];
descDiv.innerHTML = '<h2>' + data[1] + '</h2>';
i++;
}
Personally, I would use a private i, just in case another function reuses the same variable:
function displayMain () {
var data;
// wrap around to the first image
if (displayMain.i >= images.length || isNaN(displayMain.i)) {
displayMain.i = 0;
}
data = images[displayMain.i];
gallery.src = 'img/' + data[0];
descDiv.innerHTML = '<h2>' + data[1] + '</h2>';
// move to the next image
displayMain.i++;
}
This attaches a variable named i to the function displayMain. It will update this variable each time it is called, and no other function will use the same i variable.