Run function for multiple items in JS - javascript

I have a function that is responsible for updating the values in some <div>, the code looks like this:
file.js
window.onload = function makeRequest() {
var xmlHttp = new XMLHttpRequest();
xmlHttp.onreadystatechange = function() {
if (xmlHttp.readyState == 4 && xmlHttp.status == 200)
calcPreco(xmlHttp.responseText);
}
xmlHttp.open("GET", "_config/buscar_valor.php?id="+document.getElementsByName("cloud")[0].getAttribute("cloudid")+"&periodicidade=monthly", true); // true para asynchronous
xmlHttp.send(null);
}
function calcPreco(preco) {
console.log(preco);
preco = preco.replace(",", ".");
preco -= document.getElementsByName("cloud")[0].getAttribute("desconto");
document.getElementsByClassName("mostrar_valor").textContent = preco;
}
index.php
<div name="cloud" cloudid="1" desconto="5">
<span class="mostrar_valor"></span>
</div>
<div name="cloud" cloudid="2" desconto="10">
<span class="mostrar_valor"></span>
</div>
<div name="cloud" cloudid="3" desconto="15">
<span class="mostrar_valor"></span>
</div>
Note that only the cloudid anddesconto attributes are changed in each <div>, the remainder remains the same.
The script will only do a calculation by searching for the value in "buscar_valor.php", through the cloudid attribute, which is the ID of each plan.
The desconto attribute is the amount it will subtract from the account.
The problem is that it is doing this only for the first <div>, how can I make it work for all <div>?

You have to loop over all cloud elements as:
for(const cloud of Array.from(document.getElementsByName("cloud"))) {
To then retrieve the related preco from the API I would use the new fetch method as that is way more easy to handle:
fetch("_config/buscar_valor.php?id=" + cloud.getAttribute("cloudid")+ "&periodicidade=monthly")
.then(res => res.text())
.then(preco => {
Now the desconto can be applied to preco:
preco -= cloud.getAttribute("desconto");
To get the mostrar_valor insode that cloud, just use querySelector:
const valor = cloud.querySelector(".mostrar_valor");
then you can change the textContent of that element.

Related

xmlHttpRequest issue

I am using Js xmlHttpRequest to display the same menu on different pages of my site. Lately I found out that some functions are not executed when the site is online, like a quiz I made.
I had also tried to use fetch, or put the scripts in different files, but the same thing kept happening.
(The quiz does work when checking locally, where the xml request cannot be satisfied.)
//load the menu
onload = function loadXMLDoc() {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
document.getElementsByTagName('body')[0].innerHTML +=
this.responseText;
}
};
xhttp.open("GET", "mnu.html", true);
xhttp.send();
}
//check the quiz
const checkBtn = document.getElementById('checkBtn')
checkBtn.onclick = function quizCheck() {
//right answers
var score = 0;
if (q1a1.checked) {
score = score + 1;
}
if (q2a1.checked) {
score = score + 1;
}
alert("your score: " + score);
}
<li>
Check the right answer:
<br>
<input type="checkbox" id="q1a1">Right
<br>
<input type="checkbox">Wrong
</li>
<li>
Check the right answer:
<br>
<input type="checkbox" id="q2a1">Right
<br>
<input type="checkbox">Wrong
</li>
<button id="checkBtn">Check</button>
Anybody knows why and/or has some solutions?
The problem is this line which is wrong and that's why js is not working.
document.getElementsByTagName('body')[0].innerHTML += this.responseText;
You can't just add to innerHtml like that.
Instead you should create an html element and add it to body like this:
if (this.readyState == 4 && this.status == 200) {
var p = document.createElement("p");
p.innerText = this.responseText;
document.body.appendChild(p);
}
edit: of course you want to add an html menu instead of just a text inside a <p>, so you will have to add it like this:
var nav = document.createElement('nav');
nav.innerHTML = this.responseText;
document.body.prepend(nav); // always at the top

How to compare JSON data from the same API request?

I'm still learning a lot about web development and javascript, so forgive me if my explanations are not clear.
I have a function to request from an API informations about cryptocurrency (Price, volume etc.) in a JSON file and then i display the price on the web page every 15 seconds.
I want to change the background color of the card where the price is displayed by comparing the actual price and the new one coming from the next request.
here's my javascript :
function requestPrice(url, domLocation){
var req = new XMLHttpRequest();
req.open("GET", url);
req.addEventListener("load", function() {
if (req.status >= 200 && req.status < 400) {
var data = JSON.parse(req.responseText)
domLocation.innerHTML = data.ticker.price + "$";
erreur.innerHTML = "";
} else {
erreur.innerHTML = "Erreur: " + req.status + " " + req.statusText;
}
});
req.addEventListener("error", function () {
erreur.innerHTML = "Erreur";
});
req.send(null);
}
var btcPrice = document.getElementById('boxBTC'), erreur =
document.getElementById('erreur');
setInterval(requestPrice("https://api.cryptonator.com/api/ticker/btc-eur",
btcPrice), 15000);
I was thinking of a simple comparaison between the values and put this code in my loop but i need to stock the actual price somewhere to do the comparison with the new one coming and i'm stuck with that.
if (valueOf(data.ticker.price) <= valueOf(data.ticker.price)){
document.getElementById('overviewcard').style.backgroundColor = red;
} else {
document.getElementById('overviewcard').style.backgroundColor = blue;
}
Or
var overviewcard = getElementById('overviewcard');
if (data.ticker.price <= data.ticker.price){
overviewcard.style.backgroundColor = red;
} else {
overviewcard.style.backgroundColor = blue;
}
here's the html :
<div class="overviewcard">
<span id="boxBTC">...</span>
<span id="erreur"></span>
</div>
Thanks a lot for your help
You can do this in a myriad of ways, but the simplest is to grab the data from the actual HTML DOM element.
var currValue = document.getElementById('boxBTC').innerHTML;
if(valueOf(data.ticker.price) == currValue) {
// do something
}
If you're boxBTC string is formatted too much (eg. if you make "1000" -> "1,000"), then you can always also store a data attribute of the raw value inside the DOM as a data attr.
// assigning the data
document.getElementById('boxBTC').setAttribute('data-val', price);
...
// accessing the data
document.getElementById('boxBTC').getAttribute('data-val');

Getting All Same IDs with Java Script

The java script only get the first id. The 2nd id ignores the code. Are there anyway to make both IDs using the same java script ?
Add Item
List Items
<div id="add_item" class="tabcontent">
<div id="subcatchooser"></div>
<div id="list_item" class="tabcontent">
<div id="subcatchooser"></div>
Java Script here
function showsubcat(str) {
if (str.length == 0) {
document.getElementById("subcatchooser").innerHTML = "";
return;
} else {
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
document.getElementById("subcatchooser").innerHTML = this.responseText;
}
};
xmlhttp.open("GET", "ajax.php?action=showsubcat&parent_id=" + str, true);
xmlhttp.send();
}
}
</script>
That is the main difference between classes and IDs. Classes are designed to be used multiple times, while IDs are designed to be unique. So you can change the divs to look like this:
<div class="subcatchooser"></div>
And then change the JavaScript to look like this:
var elements = document.getElementsByClassName("subcatchooser");
for (var i = 0; i < elements.length; i++) {
elements[i].innerHTML = "";
}

Xhr multiple request javascript

I am using the following script to read the information from an html request.
function runSearch(searchid, fullMovie) {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState == XMLHttpRequest.DONE) {
var fullMovie = JSON.parse(xhr.responseText);
var movie = { title: fullMovie.Title, runtime: fullMovie.Runtime, plot: fullMovie.Plot };
document.getElementById('Title').innerText = movie.title;
document.getElementById('Runtime').innerText = movie.runtime;
document.getElementById('Plot').innerText = movie.plot
}
};
xhr.open('GET', 'http://www.omdbapi.com/?i=' +searchid+ '&plot=short&r=json', true);
xhr.send(null);
}
How can I do to change the searchid from the xhr.open to use the id="searchid" from a div tag?
<div>
<div id="tt0110912">
<h1 id="Title">Title from tt00110912</h1>
<p id="Runtime">Runtime from id</p>
<p id="Plot">Plot from id</p>
</div>
</div>
<br>
<div>
<div id="tt3322364">
<h1 id="Title">Title from tt3322364</h1>
<p id="Runtime">Runtime from id</p>
<p id="Plot">Plot from id`enter code here`</p>
</div>
</div>
Is it possible to run this script several times with different xhr requests? How can i do this if possible?
EDIT: cant make the code work! Theoricaly i need the code to make an xhr request depending on the div id class and fill the information inside that div with the xhr response from that id. Think of a movie database that will show specific movie information from a movie list.
Wrap your code into function and then call it in loop or manually several times with different searchid values.
function runSearch(searchid, fullMovie) {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState == XMLHttpRequest.DONE) {
var fullMovie = JSON.parse(xhr.responseText);
var movie = { title: fullMovie.Title, runtime: fullMovie.Runtime, plot: fullMovie.Plot };
document.getElementById('Title').innerText = movie.title;
document.getElementById('Runtime').innerText = movie.runtime;
document.getElementById('Plot').innerText = movie.plot
}
};
xhr.open('GET', 'http://www.omdbapi.com/?i=' + searchid + '&plot=short&r=json', true);
xhr.send(null);
}
Then call it like this:
runSearch('your search id', fullMovie);
<div id="runSearch('tt0110912', fullMovie)">
JavaScript needs to go in a script element (or an intrinsic event attribute, but they are terrible and should be avoided).
The id attribute is where you put an identifier for an element. It isn't JavaScript and it makes no sense to put JavaScript there.
<script>
runSearch('tt0110912', fullMovie)
</script>
Your HTML is invalid. An id must be unique in a document. You can't reuse the if Title (etc) within the same document. Look at using classes instead.

How to make php/ajax req into OOP

Currently, when a div is clicked, jQuery detects it sends request to fetch data from mysql via Ajax.
What I'm actually fetching is, sub categories for the item clicked and display them in html page.
Now all is done in procedural way, so when another sub level needed to be displayed, I have to copy paste the ajax function. But how do make it into objects so that I don't have to repeat myself?
I just need to know how to bring in OOP into this context..Any help will be greatly appreciated. Thank you.
HTML
<!--append the default top level items starts-->
<div id="default"></div>
<!--append the default top level items ends-->
<hr>
<!--append the default top level items starts-->
<div id="sub"></div>
<!--append the default top level items ends-->
Jquery/AJax
<!--select top level items and append to default id starts-->
$("#clickme").on("click",function()
{
var xmlhttp = getXmlHttp();
xmlhttp.onreadystatechange = function () {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
if (this.responseText !== null) {
var data = JSON.parse(this.responseText);
//console.log(this.responseText);
//console.log(JSON.parse(this.responseText));
for (i = 0; i < data.length; i++)
{
var id=data[i].id;
var name=data[i].item_name;
/*check if sub item exist*/
checkSubExist(id);
/*append to div*/
$("#default").append("name= "+name+", ");
}
}
}
}
xmlhttp.open("GET", "selectTopLevel.php");
xmlhttp.send();
});
<!--select top level items and append to default id ends-->
function checkSubExist(param)
{
//alert(param);
var xmlhttp = getXmlHttp();
xmlhttp.onreadystatechange = function () {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
if (this.responseText !== null) {
var data = JSON.parse(this.responseText);
//console.log(this.responseText);
//console.log(JSON.parse(this.responseText));
for (i = 0; i < data.length; i++)
{
var id=data[i].id;
var name=data[i].item_name;
//alert(name);
$("#sub").append(name+", ");
}
}
}
}
xmlhttp.open("GET", "checkSubExist.php?sub="+param);
xmlhttp.send();
}
I would use $.ajax to wrap the xmlHttpRequest.
If you want a more "OOP" like approach, I would suggest you define some kind of Request Wrapper Objects which you then create upon event binding, naive example:
var RequestWrapperProto = {
getSubnodes: function(){
//handle request
}
//etc
}
var requestWrapper = Object.create(RequestWrapperProto)
$('.sub').on('click', requestWrapper.getSubNodes);

Categories