Calling the function on every iteration of for loop in Javascript - javascript

function myFunction(xml) {
var i;
var xmlDoc = xml.responseXML;
var table =
"<tr><th>Title</th><th>Author</th><th>Cover Page</th><th>Ratings</th></tr>";
var x = xmlDoc.getElementsByTagName("best_book");
for (i = 0; i < x.length; i++) {
bookname = x[i].getElementsByTagName("title")[0].childNodes[0].nodeValue;
authorname = x[i].getElementsByTagName("name")[0].childNodes[0].nodeValue;
table +=
"<tr><td class='book'>" +
bookname +
"</td><td class='author'>" +
authorname +
"</td><td>" +
"<img src='" +
x[i].getElementsByTagName("image_url")[0].childNodes[0].nodeValue +
"' height='100px' width='70px'>" +
"</td><td>" +
"<div class='stars' data-rating='1'>" +
"<span class='star'> </span>" +
"<span class='star'> </span>" +
"<span class='star'> </span>" +
"<span class='star'> </span>" +
"<span class='star'> </span>" +
"<input type='button' value='Add Rating' onClick = 'submitRating()'>" +
"</div>" +
"</td></tr>";
console.log(bookname);
}
document.getElementById("result").innerHTML = table;
}
async function submitRating() {
try {
let boo = bookname;
console.log(boo);
let auth = authorname;
console.log(auth);
let rat = 5;
console.log(rat);
let data = JSON.stringify({
author: auth,
book: boo,
rating: rat
});
console.log(data);
let res = await fetch(hostUrl + "api/ratings", {
method: "POST",
body: data,
headers: {
"Content-Type": "application/json"
}
});
console.log(res);
res.json().then(matter => {
console.log(matter);
});
// let myJson = res.json();
// console.log(myJson);
if (res.status == 200) {
console.log("the status is " + res.status);
} else {
console.log("the status is " + res.status);
alert("rating not given");
}
} catch (error) {
console.log("Error:" + error);
}
}
I am trying to call submitRating function on every iteration of for loop,
but I am not getting the correct method for this in JavaScript.
Right now, after running the loop, onclick = submitRating() function only submitting the last value in mongodb.
Can someone help me with this please?

That is because the bookname and authorname retain the last value set by the final iteration of the for loop. In other words, these variables are simply overwritten multiple times until the for loop ends. If you want to store these information on a per-item basis, you can store them in HTML5 data- attributes and retrieve them in the onclick handler.
For example, you can do this:
"<input type='button' value='Add Rating' data-bookname='"+bookname+"' data-authorname='"+authorname+"' onClick='submitRating(this)' />"
And then, in your submitRating method, you can simply read the information using Element.dataset:
async function submitRating(el) {
const bookname = el.dataset.bookname;
const authorname = el.dataset.authorname;
// More logic here
}

Related

Repetitive data when you load a combobox

I'm calling EventListener so that when something is typed into the username field, it will list that user's companies for me.
var ent = document.getElementById("username");
ent.addEventListener('change', async () => {
localStorage.clear();
self.empUsuario = new Array();
self.rucEmp = new Array();
var newUser = document.getElementById("username");
$('#empresa').empty();
await fetch(environment.apiPoint + '/empresas?usuario=' + newUser.value, {
method: 'GET',
headers: {
'Content-Type': 'application/json'
}
})
.then(res => res.json())
.then(datos => {
datos.forEach(e => {
self.todasEmpresasUsuario.push({
ruc: e.ruc,
nombEmp: e.nombreCorto
});
});
})
await self.todasEmpresasUsuario().forEach(
function (element) {
self.empUsuario.push(element.nombEmp);
self.rucEmp.push(element.ruc);
}
);
Then I give it a conditional if the user is different from null, that it shows me with the rucEmp, and if not an empty space.
var str = "";
var item = "";
if (newUser.value != '') {
self.cont = 0;
let vacio = '';
for (item of self.empUsuario) {
vacio = "<option value=''>" + ' ' + "</option>"
str += "<option value='" + self.rucEmp[self.cont] + "'>" + item + "</option>"
self.cont++;
}
if (newUser.value == '') {
//str += "";
str += "<option value='" + self.rucEmp[self.cont] + "'>" + item + "</option>"
$('#empresa').empty().append(str);
}
$('#empresa').empty().append(vacio + str);
}
I expected the company lists to appear for each user and not accumulate, but the lists accumulate in the select.

Callback function not defined even though it has been defined right before calling in javascript

I am using for loop get all the data place in a div. I have following code in javascript so far:
<script type="text/javascript">
function callback(){
$.getScript("/frontend/vendor/jquery/jquery.min.js", function() {
$('input').on('change', function(){
var qty = $(this).attr('id');
var price = $('#'+qty+'_price').attr('value');
var subtotal = qty * price;
$('#'+qty+'_total').html('€ '+subtotal);
})
});
}
function checkout(callback){
let eventDate = JSON.parse(localStorage.getItem("events"));
var unique = eventDate.filter(function(itm, i, eventDate) {
return i == eventDate.indexOf(itm);
});
let items = [];
for (var n = 0; n < unique.length; n++){
var eventId = unique[n];
$.ajax({
"url":"/get_my_product/"+ eventId,
"type":"GET",
"dataType":"json",
"contentType":"application/json",
success:function(response){
let party = 'Party name';
let html = "<tr class='product-row'><td class='product-col'><h5 class='product-title'><a>"+party+"</a></h5></td><td class='product-col'><h5 class='product-title'><a>"+response.date+"</a></h5></td><td value='"+response.price+"' id='"+n+"_price'>€ "+response.price+"</td><td><div class='input-group'><input class='vertical-quantity form-control dataqty' id='"+n+"' type='number'><span class='input-group-btn-vertical'></span></div></td><td id='"+n+"_total'>€ "+response.price+"</td></tr>";
$('#data').append(html);
}
})
}
callback && callback();
}
checkout();
</script>
When I am trying to call the function after the loop completion it does not work. What is wrong here?
Change
function checkout(callback){
to
function checkout() {
I think the argument callback to the function checkout "shadows" the previously defined callback function. Then, when you call the function checkout you are passing nothing to the function, and callback will be undefined.
Or, in the last line, pass the function as an argument:
checkout(callback);
Makes no sense to add another version of jQuery to add events. You are not passing the callback to the method so it is always going to be undefined. And you are not waiting for the Ajax calls to complete before calling the callback.
// No reason for loading the JQuery version here
function addMyEvents() {
$('input').on('change', function() {
var qty = $(this).attr('id');
var price = $('#' + qty + '_price').attr('value');
var subtotal = qty * price;
$('#' + qty + '_total').html('€ ' + subtotal);
})
}
function checkout(callback) {
// hold the ajax calls
const myAjaxCalls = []
let eventDate = JSON.parse(localStorage.getItem("events"));
var unique = eventDate.filter(function(itm, i, eventDate) {
return i == eventDate.indexOf(itm);
});
let items = [];
for (var n = 0; n < unique.length; n++) {
var eventId = unique[n];
// push the ajax calls to an array
myAjaxCalls.push($.ajax({
"url": "/get_my_product/" + eventId,
"type": "GET",
"dataType": "json",
"contentType": "application/json",
success: function(response) {
let party = 'Party name';
let html = "<tr class='product-row'><td class='product-col'><h5 class='product-title'><a>" + party + "</a></h5></td><td class='product-col'><h5 class='product-title'><a>" + response.date + "</a></h5></td><td value='" + response.price + "' id='" + n + "_price'>€ " + response.price + "</td><td><div class='input-group'><input class='vertical-quantity form-control dataqty' id='" + n + "' type='number'><span class='input-group-btn-vertical'></span></div></td><td id='" + n + "_total'>€ " + response.price + "</td></tr>";
$('#data').append(html);
}
}))
}
// if we have a callback
if (callback) {
// wait for all the ajax calls to be done
$.when.apply($, myAjaxCalls).done(callback)
}
}
// pass the function to the method.
checkout(addMyEvents);
Now the best part is you do not even need to worry about the callback to bind events. You can just use event delegation and it would work. This way whenever an input is added to the page, it will be picked up.
$(document).on('change', 'input', function() {
var qty = $(this).attr('id');
var price = $('#' + qty + '_price').attr('value');
var subtotal = qty * price;
$('#' + qty + '_total').html('€ ' + subtotal);
})
function checkout() {
let eventDate = JSON.parse(localStorage.getItem("events"));
var unique = eventDate.filter(function(itm, i, eventDate) {
return i == eventDate.indexOf(itm);
});
let items = [];
for (var n = 0; n < unique.length; n++) {
var eventId = unique[n];
$.ajax({
"url": "/get_my_product/" + eventId,
"type": "GET",
"dataType": "json",
"contentType": "application/json",
success: function(response) {
let party = 'Party name';
let html = "<tr class='product-row'><td class='product-col'><h5 class='product-title'><a>" + party + "</a></h5></td><td class='product-col'><h5 class='product-title'><a>" + response.date + "</a></h5></td><td value='" + response.price + "' id='" + n + "_price'>€ " + response.price + "</td><td><div class='input-group'><input class='vertical-quantity form-control dataqty' id='" + n + "' type='number'><span class='input-group-btn-vertical'></span></div></td><td id='" + n + "_total'>€ " + response.price + "</td></tr>";
$('#data').append(html);
}
})
}
}
checkout();

Clear previous results from query

Through the attached code I do a search on youtube based on the username and the results are shown. If I search twice, the results add up. I would like previous results to be deleted. I try with htmlString = card; but it show only one result.Thanks to everyone who wants to help me solve this problem.
var musicCards = [];
jQuery(document).ready(function() {
jQuery("#searchButton").on("click", function() {
var query = jQuery("#queryInput").val();
if (query != "") {
loadYoutubeService(query);
console.log(query + "");
}
});
});
function loadYoutubeService(query) {
gapi.client.load('youtube', 'v3', function() {
gapi.client.setApiKey('ADADADADADA');
search(query);
});
}
function search(query) {
var request = gapi.client.youtube.search.list({
part: 'snippet',
q: query,
type: 'channel',
maxResults: 15
});
request.execute(function(response) {
jQuery.each(response.items, function(i, item) {
if (!item['']) {
var musicCard = {};
musicCard._id = item['snippet']['customUrl'];
musicCard.title = item['snippet']['title'];
musicCard.linkprofilo = item['snippet']['channelId'];
musicCard.url = "https://www.youtube.com/channel/";
musicCard.description = item['snippet']['description'];
musicCard.immagine = item['snippet']['thumbnails']['high']['url'];
musicCards.push(musicCard);
}
});
renderView();
});
}
function renderView() {
var htmlString = "";
musicCards.forEach(function(musicCard, i) {
var card = createCard(musicCard._id, musicCard.title, musicCard.description, musicCard.url,musicCard.immagine, musicCard.linkprofilo);
htmlString += card;
});
jQuery('#youtube-utente').html(htmlString);
}
function createCard(_id, title, description, url, immagine, linkprofilo) {
var card =
'<div class="card">' +
'<div class="info">' +
'<img src="' + immagine + '" alt="' + description + '">' +
'</div>' +
'<div class="content">Clicca per selezionare:' +
'<h3>' + title + '</h3>' +
'<a class="seleziona" href="' + url +linkprofilo+'">'+ url +linkprofilo+'</a>' +
'<p>' + description + '</p>' +
'</div>' +
'</div>';
return card;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.0/jquery.min.js"></script>
Solved using :
request.execute(function(response) {
musicCards.length = 0; // clear array

Filter data obtained through GitHub API

I created this function to obtain GitHub issues:
retrieveEnerpriseIssues: function(repoOrg, repoName, callback) {
let data = null;
// token auth
octokit.authenticate({
type: 'basic',
username: config.githubEnterprise.username,
password: config.githubEnterprise.token
});
async function paginate(method) {
let response = await method({
q: "repo:" + repoOrg + "/" + repoName + " is:issue",
per_page: 100
});
data = response.data.items;
var count = 0;
while (octokit.hasNextPage(response)) {
count++;
console.log(`request n°${count}`);
response = await octokit.getNextPage(response);
data = data.concat(response.data.items);
}
return data;
}
paginate(octokit.search.issues)
.then(data => {
callback(data);
})
.catch(error => {
console.log(error);
});
}
It is called in this function which takes the issues, filters out all of the unwanted keys into json format and puts it in my db.
extractToDb: function() {
let gitIssues = null;
for(var i = 0; i < config.githubEnterprise.orgs.length; i++) {
for(var j = 0; j < config.githubEnterprise.orgs[i].repos.length; j++) {
gitHubService.retrieveEnerpriseIssues(
config.githubEnterprise.orgs[i].owner,
config.githubEnterprise.orgs[i].repos[j].repoName,
function(data, err) {
if(err) {
console.log('err: ', err);
} else {
gitIssues = data;
}
gitIssues = JSON.stringify(gitIssues);
gitIssues = JSON.parse(gitIssues);
let issueFormatForDb = null;
for(var i = 0; i < gitIssues.length; i++) {
issueFormatForDb = gitIssues[i];
const body = '{' +
'"github_id": "' + issueFormatForDb.id + '",' +
'"issue_title": "' + issueFormatForDb.title + '",' +
'"issue_number": "' + issueFormatForDb.number + '",' +
'"issue_url": "' + issueFormatForDb.url + '",' +
'"issue_state": "' + issueFormatForDb.state + '"' +
'}';
console.log('Body: ', body);
getGitHubIssues.postToDb(body);
}
});
}
}
}
I'd like to take this a step further by filtering out any issues where the state is closed. How is this done and should it be handled in my retrieveEnerpriseIssues function or my extractToDb?
Possible solution
I tried this in my extractToDb function:
gitIssues = JSON.parse(gitIssues);
gitIssues = _.where(gitIssues, {state: "open"});
let issueFormatForDb = null;
Is it the best solution or is there a better way?
As #givehug stated:
Better use _.filter, or native filter method like
gitIssues = gitIssues.filter(i => i.state === 'open')
I think .where was deprecated in later versions of lodash github.com/lodash/lodash/wiki/Deprecations. Other than that its perfectly fine.
I just realsied I can filter the state in my paginate function with this:
let response = await method({
q: "repo:" + repoOrg + "/" + repoName + " is:issue" + " label:issue_label" + " state:open",
per_page: 100
});

How do I hyperlink JSON API return values with variable URL addresses?

I have an HTML/CSS search bar where people can type a keyword and, on click, my Open States JSON API code returns New Jersey state bills that match that keyword.
Search Bar Screenshot
Screenshot of a Result
I want the bill titles that are returned to be hyperlinked to their page on the New Jersey state legislature site, but I can only find instructions for how to hyperlink a return with a static site.
Here is my JavaScript code so far (with API key removed):
e.preventDefault();
// console.log($("#billID").val());
var billSearchValue = $("#billID").val();
if(billSearchValue=='')
{
alert("Enter Desired Query Parameters");
} else{
// console.log(billSearchValue);
}
var searchQuery = "&q=" + billSearchValue;
var baseUrl = "http://openstates.org/api/v1/bills/?state=nj";
var apiKey = "";
var apiKeyParam = "&apikey=";
var apiKeyParams = apiKeyParam + apiKey;
var urlJSON = baseUrl + searchQuery + apiKeyParam + apiKey;
// console.log(urlJSON);
$.getJSON(urlJSON, function (data) {
var billsVar = [];
$.each(data, function(key, val) {
billsVar.push(val);
});
for (var i = 0; i < billsVar.length; i++) {
var billList = "<li>Bill <ul class=\"ul-sub\">"
var billTitle = "<li><strong>Bill Title</strong>: " + billsVar[i]['title'] + "</li>";
var billCreatedAt = "<li><strong>Bill Created</strong>: " + billsVar[i]['created_at'] + "</li>";
var billUpdatedAt = "<li><strong>Bill Updated</strong>: " + billsVar[i]['updated_at'] + "</li>";
var billID = "<li><strong>ID</strong>: " + billsVar[i]['id'] + "</li>";
var billChamber = "<li><strong>Bill Chamber</strong>: " + billsVar[i]['chamber'] + "</li>";
var billState = "<li><strong>Bill State (Probably Don't Want/Need This)</strong>: " + billsVar[i]['state'] + "</li>";
var billSession = "<li><strong>Bill Session</strong>: " + billsVar[i]['session'] + "</li>";
var billType = "<li><strong>Bill Type</strong>: " + billsVar[i]['type'] + "</li>";
var billSubjects = "<li><strong>Subjects</strong>: " + billsVar[i]['subjects'] + "</li>";
var billBillID = "<li><strong>Bill ID</strong>: " + billsVar[i]['bill_id'] + "</li>";
var billOutput = billList + billTitle + billCreatedAt + billUpdatedAt + billID + billChamber + billState + billSession + billType + billSubjects + billBillID + "</ul></li>";
$("#jsonlist").append(billOutput);
}
});
})
});
After a bit of research I see that a bill hyperlink is like this:
http://openstates.org/nj/bills/{Bill Session}/{Bill ID}/
I can't test my code because I have no API key, but the solution could be something like:
var billTitle = '<li><strong>Bill Title</strong>: '
+ '<a href="http://openstates.org/nj/bills/' +
billsVar[i]['session'] + '/' + billsVar[i]['bill_id'].split(' ').join('') + '/">'
+ billsVar[i]['title'] + '</a></li>';

Categories