javascript array varaible on jquery - javascript

I am a rookie on web design. I have a problem like this:
<script type="text/javascript">
var searchIDs = new Array();
<% searches.forEach(function (search) { %>
searchIDs.push('<%= search._id%>');
console.log('<%= search._id%>');
<% }) %>
</script>
...
<script>
for (var i = 0; i < searchIDs.length; i++) {
$.get('../../tCounter', { search: searchIDs[i]}, function(data){
console.log(data.c);
$("#" + searchIDs[i]).append("<b>" + data.c + "</b>");
});
}
</script>
On this code, I have some divs which their ids have been generated by searchID. I want to reach different html components by search IDs. Problem here, I can get true data with get and see it with console.log(data.c); but I cant reach correct component to write the data. It always appends on same div. I am waiting for your suggestions,
Thanks.

The problem is the internal function runs async. The loop is finished and i is at the highest value when they run.
The easiest way around this is using jquery's $.each() like this
$.each(searchIDs, function(i, id) {
$.get('../../tCounter', {
search: id
}, function(data) {
console.log(data.c);
$("#" + id).append("<b>" + data.c + "</b>");
});
});

Related

Array not being filled when the HTML page loads

I am working on a project using Google Apps Script coupled with HTML and JS. I am fairly new to programming, so bear with me if this is a simple question.
Basically, in my JS file I have a function that calls a function contained in the Google Apps Script (from now on, GAS) file using this method; the GAS function populates an array with values retrieved from a Google Sheets and returns the array. This array is then used by the JS file to populate a drop down list in the HTML file.
The issue is that the dropdown list is not populated at all; if I reload the page with the Google Chrome console on, I see that the array is empty; however, if I click on the empty array, the values are shown, as if it is not populated on page load. See the picture below to have a better understanding of what I mean:
Google Chrome Console screenshot
Below you'll find the relevant snippets of code that handle the differente functions:
JS:
$(function() {
var cities = [];
function onSuccess(elem, array) {
var i = 0;
for (item in elem) {
array.push(elem[i])
i++;
};
return array
};
google.script.run.withSuccessHandler(onSuccess).withUserObject(cities).populate();
//Create the dropdown menu for the cities
for (city in cities) {
var element = $("#city1").append("<option value=" + cities[city].toLowerCase() + ">" + cities[city] + "</option>");
console.log(city);
};
[...]
});
HTML:
<select id="city1" name="city" placeholder="City"><option id="citydummy">City</option></select>
Google Apps Script:
function populate() {
var db = SpreadsheetApp.openById('SHEETID');
var check = true;
var array = [];
for (var i = 2; i < db.getLastRow(); i++) {
db.getActiveSheet().getRange(i, "1").getValue()
array.push(db.getActiveSheet().getRange(i, "1").getValue())
}
return array;
}
Many thanks in advance for anyone who will contribute!
How about the following modification for JS? HTML and GAS are not modified. Data obtained at populate() is directly sent to onSuccess(), and imported the data to the list.
JS :
$(function() {
google.script.run.withSuccessHandler(onSuccess).populate();
});
function onSuccess(cities) {
for (city in cities) {
var element = $("#city1").append("<option value=" + cities[city].toLowerCase() + ">" + cities[city] + "</option>");
console.log(city);
};
};
If I misunderstand your situation, I'm sorry.

How do I set an attribute to a dynamically created button?

First and foremost, hello. I'm a college student and not a very experienced coder, so forgive me if I end up saying something really dumb.
Either way, I have a school project in which I have to create a functional website using Node.js, where people are able to log in and buy stuff.
Most of the stuff already works, but I am having trouble with a very specific thing which I simply cannot get to work, yet is essential to the project itself.
I import data from a mySql database into the website using AJAX, that data contains products that people can buy. Then, those products are appended to the HTML page itself, and dynamically create two buttons for each product that is appended, one which says "Buy Now" and the other which says "Learn More".
Now, those buttons are supposed to be somehow associated to the values of the database, but I have no idea how to do this.
$(document).ready(function () {
$(function () {
$.ajax({
type: 'POST',
url: 'http://localhost:3000/getPacotes',
success: function (data) {
console.log(data);
for (var i = 0; i < data.length; i++) {
var pacoteSet1 = "<div class='col-md-4 pacotes'>";
var pacoteSet2 = "<input id=btnPac"+
i + " type='button' name='comprar' value='Comprar Pacote'>";
var pacoteSet3 = "</div>";
var idPacote = data[i].idPacote;
var nomePacote = data[i].Nome_Pacote;
$("#pacotes").append(pacoteSet1 +
"<h1>" + nomePacote + "</h1>" +
"<h1>" + nomePacote + "</h1>" +
"<h3>" + precoPacote + "euros/mes </h3>" +
pacoteSet2 +
pacoteSet3);
}
}
});
});
});
My teacher told me to give an attr to the buttons I create, and that's what I was pretty much trying to do now, but I dont know how to do that, I mean, if the buttons were static it would be pretty easy, but since the buttons are not there when the document is created, I dont know if this will work
$("#btnPac" + i).attr({"id": idPacote,
"nome": nomePacote,
"preco": precoPacote,
});
Anyway, Hopefully, I didn't sound too dumb and thanks in advance
TL:DR how do I give an attribute to a dynamically created button
You just need to change your jquery function like below:
$(document).find("#btnPac" + i).attr({"id": idPacote,
"nome": nomePacote,
"preco": precoPacote
});
This should be your solution.
You can do that while creating the html for button element. By using string concatenation, which you are already using while setting the ID:
var pacoteSet2 = "<input id=btnPac"+ i + " nome='" + nomePacote + "' preco='" + precoPacote + "' type='button' name='comprar' value='Comprar Pacote'>";
Overloading the HTML with attributes is a bad idea in my opinion. You could create the Elements in JS, bind the data to it, and then append the button to the dom. Thats quite easy with jquery:
var button=$("<button>Show More</button>");//create
button.on("click",showMore.bind({name:"test"}));//add listener
$(document.body).append(button);//append
function showMore(){
alert(this.name);
}
You can create a new input tag and set these attributes then append to your div with this code:
$('<input/>', {
id: 'btnPac' + i,
nome: nomePacote ,
preco: precoPacote ,
type: 'button'
}).appendTo("#pacotes");
You can do the same for your others (h1, h3)

Elements prepended using jQuery .get() while looping through array are loaded in different order on page refresh

I want to show a subsection of some projects on my webpage. I have an array of project names and some corresponding data in html files, like in the example below. I have a button with some preview-content in it, and if a user clicks on that it opens up the full container with all the project details.
To do this I though to loop through a sliced array in reverse and prepend the code to a div element on my webpage. The content often loads fine, but sometimes when I refresh the page it will display the previews in a different order than as defined in the array. Also, sometimes "previewtitle" and "previewcontent" return undefined, but not all the time. What am I doing wrong here?
I want to prepend the projects dynamically in the same order on every refresh.
var $projectNames = [ "coolprojecthere", "andanotherone", "moreprojects", "lastone" ];
projects/coolprojecthere.html looks like this:
<div id="title">Project title here</div>
<div id="content">Content html here</div>
projects/previews/coolprojecthere.html looks like this:
<div id="title">Project title here</div>
<div id="content">Content text here</div>
I loop through them like this to prepend them:
$projectNames = $projectNames.slice(0, 7);
$.each($projectNames.reverse(), function (index, projectname) {
var previewtitle, previewcontent;
$.get("projects/previews/" + projectname + ".html", function (prevdata) {
previewtitle = $(prevdata).filter('#title').text();
previewcontent = $(prevdata).filter('#content').text();
});
$.get("projects/" + projectname + ".html", function (data) {
var project = "<section id=\"project\" class=\"\"> \
<t>" + previewtitle + "</t><br /> \
<p>" + previewcontent + "</p> \
</div> \
<div class=\"content\"> \
<h5>" + $(data).filter('#title').text() + "</h5> \
<div class=\"content-container\">"
+ $(data).filter('#content').html() +
"</div> \
</div> \
</section>"
$('#main-container').prepend(project);
});
From the jQuery Documentation you must specify async option to be set to false to get a synchronous AJAX request.
$.ajax({ url: 'projects/previews/" + projectname + ".html',
async: false,
dataType: 'json',
success: function(data) {
// your code here
}
});
By default, all requests are sent asynchronously (i.e. this is set to true by default). If you need synchronous requests, set this option to false.
Otherwise, you could also do the jQuery's AJAX setup, and set it in synchronous mode by calling once (above your initial code):
jQuery.ajaxSetup({async:false});
It will perform all your further AJAX calls in synchronous mode. You can continue using jQuery.get(); method as you did before.
Note: Please read Felix Kling's answer, about when synchronous calls might be a bad idea.
Making the Ajax calls synchronous is a bad idea. Instead, you should chain and nest them, so that each one is executed after each other.
Lets organize your code a little more, using promises:
function getPreviewData(projectName) {
return $.get(
"projects/previews/" + projectname + ".html"
).then(function(prevdata) {
return {
title: $(prevdata).filter('#title').text(),
content: $(prevdata).filter('#content').text()
};
);
}
function getProjectHTML(projectName, previewTitle, previewContent) {
return $.get("projects/" + projectname + ".html").then(function (data) {
// ...
});
}
$projectNames = $projectNames.slice(0, 7);
var head = new $.Deferred();
var chain = head.promise();
$.each($projectNames.reverse(), function (index, projectName) {
chain = chain.then(function() {
return getPreviewData(projectName).then(function(previewData) {
return getProjectHTML(projectName, previewData.title, previewData.content);
});
});
});
head.resolve();

Populating select element with external javascript file

Trying to popluate a dropdown box from a list of data from my js file. I've found a few examples out there but not exactly what I'm trying to do. I would like it to show 'DataText' in the drop down itself.
<select id="select" </select>
script
<script type="text/javascript" src="js/data/datafile.js"></script>
Could it not be done as simple as this?
$(document).ready(function()
{
$("#select").append(Mydata);​
});
file format
var Mydata=[{"ID":"00","DataText":"Text1"}, {"ID":"01","DataText":"Text2"}, {"ID":"02","DataText":"Test3"}]
I'd suggest:
$('#select').html(function(){
return $.map(Mydata, function(v) {
return '<option id='+ v.ID +'>'+ v.DataText +'</option>';
}).join('');
});
http://jsfiddle.net/Y8eCy/
You need to loop your data and then insert it into your select, in this case i needed to parse the data.
var Mydata='[{"ID":"00","DataText":"Text1"}, {"ID":"01","DataText":"Text2"}, {"ID":"02","DataText":"Test3"}]';
var data = $.parseJSON(Mydata);
$.each(data, function(k,v){
$('#test').append('<option value="'+v.ID+'">'+v.DataText+'</option>');
});
Working example: jsfiddle
Sure it can be done, but you have to iterate over the data and add what's needed.
$(document).ready(function () {
for (var i = 0, count= Mydata.length; i < count; i++) {
$('<option>').val(Mydata[i].ID).text(Mydata[i].DataText).appendTo("#select");
}
});
This is a quick solution, so add error checking. Also, just in case this isn't a bad paste job, the HTML provided is invalid. The opening select tag needs a >
Demo

How to insert one final item after foreach in jquery?

I am fetching some json and returning it out, creating a new div for each object. I am now trying to add one final div (not from json) that just says something along the lines of 'This could be yours!'.
I have tried to insert
$('section#fans').append('<div class="fan">new div</div>');
or several variations of that (after, appendChild etc) and cannot get it to perform as i wish. Currently it adds one new div but before the foreach kicks in and it doesn't follow the fadeIn delay pattern that for the foreach does.
How can i get it to add the div with the same effect after the foreach. as one final div? As if it belonged to the json, altough it wont be the same template as the previous.
function get_fans(){
$.ajax('http://localhost/facebook_app/selectFans/', {
type : 'get',
dataType: 'json',
success : function (data) {
$.each(data, function(index) {setTimeout(function(){
var first_name = data[index].first_name;
var location = data[index].location;
var imagePath = data[index].image_path;
var d = $('<div class="fan"><img src="http://localhost/uploads/' + imagePath + '" width="170" height="160" />' + first_name + ', ' + location +'</div>');
$('section#fans').append(d);
d.hide();
d.fadeIn('50');
}, 250*(index +1));
});
$('section#fans').append('<div class="fan">new div</div>');
},
});
}
Your "final" insert is done immediately, while the other ones are done after a timeout.
You could replace
$('section#fans').append('<div class="fan">new div</div>');
with
setTimeout(function(){
$('#fans').append('<div class="fan">new div</div>');
}, 250*(data.length +2));
so that the final insert would be done after all others have been done.
A side note : don't use $('section#fans') but $('#fans'). This will be faster as jQuery will use the fast document.getElementById function.

Categories

Resources