Iteration through ajax data is working time to time - javascript

I wrote small calculator on python, using flask framework. I created forms in template, in which I gather specific data with Javascript and using .getJSON, I achieve working ajax. Here's code. (Using jQuery as well)
$(document).ready(function() {
$(function() {
$('.btn#population').bind('click', function() {//Only one button.
$( ".faction" ).each(function(x) {//Loops through many forms, which all are class .faction
var totals = [];//For late r use. Store gathered data.
$.getJSON('/_population', {//Parse data to python.
faction: $(this).attr('id'),
houses: $(this).find('input[name="houses"]').val(),
level: $(this).find(':radio:checked').val(),
space: $(this).find('.space').prop( "checked" ),
senate: $(this).find('.senate').prop( "checked" )
},
function(data) {//Receive data. give it to next functions.
$.merge(totals, data.result);
/*$.each(data, function(i, item){
item.forEach(function(number){
//console.log(number);
totals.push(number);
});
}); This is commented, due experiments.*/
});
console.log(totals);
$(this).find('input[name="total"]').each(function(i,val) {//Search for fields in forms, wich will store resoults. (Doesn't used for data gathering in this global function.)
$(this).val();//Here I'll itter througt totals and change values of inputs.
});
});
return false;
});
});
});
Forms are consisted of various inputs, but it's not important. /_population route has python script, which returns basic json array, consisting only numbers, usually, 3 or 4, like [0,0,0,0] or [120,140,300].
My aim is to put each of item of an returned array and put it in input fields in template. As you can see in code, it loops through many forms, and returned array items will goes to some of them. For now, I'm stuck at point, where console shows me very weird behaviour, sometimes it makes proper arrays, sometimes not.
Here's the example of Firefox console output.
Array [ ] functions.js:23
Array [ ] functions.js:23
Array [ ] functions.js:23
Array [ 40, 120, 300, 0 ] functions.js:23
Array [ 72, 540, 0, 0 ] functions.js:23
Array [ 30, 210, 100 ] functions.js:23
Array [ ] functions.js:23
Array [ ] functions.js:23
Array [ ] functions.js:23
Array [ 40, 120, 300, 0 ] functions.js:23
Array [ 72, 540, 0, 0 ] functions.js:23
Array [ 30, 210, 100 ] functions.js:23
(It's irregular at random manner.)
What would be a problem, why it's so and how to fix it?

You could store all the ajax calls in an array and use $.when to get a callback when everything is done and then iterate over the elements and set the value.
It's hard to test this, but something close to this should work.
$(function() {
$('#population').on('click', function(e) {
e.preventDefault();
var xhr = [];
$( ".faction" ).each(function(i, el) {
xhr.push(
$.getJSON('/_population', {
faction : el.id,
houses : $(el).find('input[name="houses"]').val(),
level : $(el).find(':radio:checked').val(),
space : $(el).find('.space').is( ":checked" ),
senate : $(el).find('.senate').is( ":checked" )
})
);
});
$.when.apply(undefined, xhr).done(function() {
var arg = [].slice.call(arguments);
$(this).find('input[name="total"]').val(function(i,val) {
return arg[i].responseText;
});
});
});
});

I'm sorry, but as it always happens to me, I thought pretty simple fix to problem. As #lan mentioned, getJSON is asynchronus, I thought, that then I should do all fucntions, while I have response, not after I get it. Here's my modified script. Commentaries included.
$(document).ready(function() {
$(function() {
$('.btn#population').bind('click', function() {
$( ".faction" ).each(function(x) {
//Here will answers be shown.
var answers = $(this).find('input[name="total"]');
$.getJSON('/_population', {
faction: $(this).attr('id'),
houses: $(this).find('input[name="houses"]').val(),
level: $(this).find(':radio:checked').val(),
space: $(this).find('.space').prop( "checked" ),
senate: $(this).find('.senate').prop( "checked" )
},
function(data) {
//Gathered data is stored directly in response function.
var totals = [];
//I guess ,can be done by merge too, but for now, I'll leave it like that.
$.each(data, function(i, item){
item.forEach(function(number){
totals.push(number);
});
});
//Here previously gathered answer input fields are used for purpose.
answers.each(function(y,val) {
$(this).val(totals[y]);
});
});
});
return false;
});
});
});

Related

How to display data from server in pie chart?

I want to display data in pie chart. Data is retrieved from server in JSON format i.e. single int value and I want to display it using pie chart. Suppose that data is 66, then i want to show that 66% full in pie chart.
I have retrieved data but not able to find the function in javascript to accept data
For Ex. :
$(function(){
$("#doughnutChart").drawDoughnutChart([
{ title: "Full", value: 66, color: "#FC4349" },
{ title: "Empty", value: 34, color: "#6DBCDB" },
]);
});`
Then instead of already defined values in above function i want to accept value from server and display in pie chart.
in index.html I added statement
<script>
$(document).ready(function(){
$("button").click(function(){
$.getJSON('http://api.thingspeak.com/channels/79448/feed/last.json?callback=?', function(data){
$("div").append(data.field1 + " ");
});
**var x=data.field1;**
});
});
</script>
This is my index.js file :
$("#doughnutChart").drawDoughnutChart( dataFromServer);
`$(function(){
`$("#doughnutChart").drawDoughnutChart([
{ title:"Full" value: dataFromServer.y1, color: "#FC4349" },
{ title: "Empty" value: dataFromServer.y2, color: "#6DBCDB" },
]);
});`
`var formattedData = [];`
// "dataFromServer" contains an array of differently-formatted objects
for ( var i = 0; i < dataFromServer.length; i++ ){
formattedData.push({
value: dataFromServer[i].y,
});
}
$("#doughnutChart").drawDoughnutChart( formattedData );
So please tell me is this way i should write in index.js file???
dataFromServer.y1=x; Please suggest me the correct way.
This depends upon the form of your data. A;; you're going to do is use variables instead of literals. For instance, if your data is an array of objects with a title, value, and color, you could just call:
// "dataFromServer" is an array of appropriately formatted objects
$("#doughnutChart").drawDoughnutChart( dataFromServer);
If, on the other hand, you have a complex object you need to map out, you could do it explicitly like so:
// "dataFromServer" contains all of the right data, but in different locations
$("#doughnutChart").drawDoughnutChart([
{ title: dataFromServer.x1, value: dataFromServer.y1, color: dataFromServer.z1 },
{ title: dataFromServer.x2, value: dataFromServer.y2, color: dataFromServer.z2 },
]);
Most likely you will have an array of differently formatted object, which you will want to turn into an array of objects formatted in this manner, in which case you would want to loop through the objects from the server and create a new variable from them:
// formattedData is the array that will be passed into the chart
var formattedData = [];
// "dataFromServer" contains an array of differently-formatted objects
for ( var i = 0; i < dataFromServer.length; i++ ){
formattedData.push({ title: dataFromServer[i].x,
value: dataFromServer[i].y,
color: dataFromServer[i].z });
}
$("#doughnutChart").drawDoughnutChart( formattedData );
Addendum:
Upon comment clarification, I am adding the following. Assuming the Title and Color values are static (i.e. not coming from the database), you may simply insert the integer "values" into the code directly, like so:
// "mySanFranciscoDataValue" is the single integer you're trying to insert
// into the chart. Simply reference it directly, whether it's a
// variable or a function. Presumably you will have two of them,
// one for each city, so I've included a "myNewYorkDataValue" too.
$("#doughnutChart").drawDoughnutChart([
{ title: "San Francisco", value: mySanFranciscoDataValue, color: "#FC4349" },
{ title: "New York", value: myNewYorkDataValue, color: "#6DBCDB" },
]);

Jquery: Autocomplete with label

I am trying to learn website development.
While learning autocomplete feature of jquery, I tried to put in the labels.
function autocomplete (data) {
var data = data.toString();
var availableTags = data.split(',');
var autocompleteData = [];
for (var i = 0; i < availableTags.length; i++){
autocompleteData[i] = {};
autocompleteData[i].label = i.toString();
autocompleteData[i].value = availableTags[i];
}
$("#tags").autocomplete({
source: autocompleteData,
select: function (event, ui) {
printautocomplete(event, ui)
}
});
};
The autocomplete[i].value is a valid string.
autocompleteData[0]
Object {label: 0, value: "Peter"}
However, I do not see any suggestions.
What is wrong with the way I am using the API?
The API says:
"Array: An array can be used for local data. There are two supported formats:
An array of strings: [ "Choice1", "Choice2" ]
OR An array of objects with label and value properties: [ { label: "Choice1", value: "value1" }, ... ]
The label property is displayed in the suggestion menu. The value will be inserted into the input element when a user selects an item. If just one property is specified, it will be used for both, e.g., if you provide only value properties, the value will also be used as the label. "
Thank you.
$('#sidebarSearch').autocomplete(
{
source: function(query, result)
{
var query = $('#sidebarSearch').val ();
$.ajax(
{
url:"sidebarSearchFetch.php",
method:"POST",
data:{query:query},
dataType:"json",
success:function(data)
{
result($.map(data, function(item)
{
return {
label: item.name,
value: item.usrId
};
}));
}
})
},
appendTo: "#sidebar-form"
});
I am skeptical of line 2 in your code (var data = String()data;) I would use: var data = data.toString();
But if you are sure that the autocompleteData elements do indeed have valid strings, then my best guess would be that perhaps you forgot to give the '#tags' id to your html entry field element.
Finally, if this is not it, to troubleshoot, I would try removing the select: option from the object you are passing to autocomplete() in the line that begins: $("#tags").autocomplete(... so that only the source options is passed.
Another thing to check out is when the code is being run. It is possible that a document.ready() function is needed to ensure that that when the autocomplete feature is added to the DOM element with the id '#tags', that the element has already been created.
The autocomplete works fine. Instead of completing "value", it completes "label".
So when I type in "1", it suggests "1", "10", "11", etc.
Autocomplete applying value not label to textbox answers how to change to to by-value.

Create array of selected items in a list and display their JSON data

I'm trying to perform what seems like a simple task and display <li>'s for each item in a JSON object. Then, when I click each displayed item, get additional JSON info from all the selected items, and create an array that is stored in a variable for use later.
Here is my JSON. Nothing crazy, simple array of data.
[
{
"subCategory": "Foo",
"total": 100,
"converted": 25,
"revenue": 500
},
{
"subCategory": "Bar",
"total": 100,
"converted": 25,
"revenue": 1000
}
]
With my JS (using jQuery), I'm getting and displaying each item correctly, but I'm not getting the data that I want when i select an item that is getting displayed. In the following JS, I realize I'm not doing much beyond adding the class to the li displayed, but I'm stuck on how to go about getting the data for each selected item and over write the variables below.
(function(){
$('.bubbles').on('click', 'li', function(){
$(this).toggleClass('selected');
});
$.getJSON('data.json', function(data) {
$.each(data,function(i, value){
// Display bubbles
$('.marketingBubbles').append("<li class='"+ value.leads + " "+ value.status + " "+ value.lift + "'>");
// Get data and create arrays
var totalArray = [value.total], // Get values from all totals
convertedArray = [value.converted], // Get all values from converted
revenueArray = [value.revenue]
// Add up numbers in arrays
var totalConverted = eval(convertedArray.join('+')), // Sum of all converted leads
totalLeads = eval(totalArray.join('+')), // Sum of all total leads
totalRevenue = eval(indicatorRevenue.join('+')) // Sum of all revenue
});
});
})();
HTML
<ul class="marketingBubbles"></ul>
Eventually, i would like to take the values within an array, no matter how many times it is changed, perform some simple math operations with the data and display in various divs on the screen.
Any help would be appreciated.
Thank you!

Grouping / counting in javascript using underscore.js

I am new to javascript (and to Stack Overflow) and I've encountered a problem I can't seem to solve. I am trying to generate a simple pie chart that shows the number of Projects for each value of Technology in my data. This is the kind of data I am working with:
[Project1, Java]
[Project2, Excel]
[Project3, SAS]
[Project4, Java]
The pie ratio in the example above would be 2:1:1.
The first part of my code loads the data and pushes it to an array, "techArray", that contains [project, tech]. This part works ok - I've verified it in a simplified version of the code.
I then want to group the array "techArray" and count the instances of each tech. To do so I'm using the Underscore library, as follows:
var chartData = [];
var techData = _.groupBy(techArray, 'tech');
_.each(techData, function(row) {
var techCount = row.length;
chartData = push( {
name: row[0].tech,
y: techCount
});
});
The script then renders the chartData array using highcharts. Again, I have verified that this section works using a simplified (ungrouped) version.
There must be an issue with the grouping/counting step outlined above because I am seeing no output, but I simply can't find where. I am basing my solution on the following worked example: Worked example.
If anyone can spot the error in what I've written, or propose another way of grouping the array, I'd be very grateful. This seems like it should be a simpler task than it's proving to be.
countBy could be used instead of groupBy:
var techArray = [
{ project: 'Project1', tech: 'Java'},
{ project: 'Project2', tech: 'Excel'},
{ project: 'Project3', tech: 'SAS'},
{ project: 'Project4', tech: 'Java'},
];
var counts = _.countBy(techArray,'tech');
This will return an object with the tech as properties and their value as the count:
{ Java: 2, Excel: 1, SAS: 1 }
To get the data in the form for highcharts use map instead of each:
var data = _.map(counts, function(value, key){
return {
name: key,
y: value
};
});
This should work
var techArray = [['Project1','Java'], ['Project2', 'excel'], ['Project3', 'Java']];
var chartData = [];
var techData = _.groupBy(techArray, function(item) {
return item[1];
});
_.each(techData, function(value, key) {
var techCount = value.length;
chartData.push({
name: key,
y: techCount
});
});
_.groupBy needs to either get a property name, or a function that returns the value being grouped. There is no tech property of an array, so you cant group by it. But, as our techArray is an array of tuples, we can pass a function _.groupBy that returns the value that we want to groupBy, namely the second item in each tuple.
chartData now looks like this:
[{
name: 'Java',
y: 2
}, {
name: 'excel',
y: 1
}]

Create JSON from jQuery each loop

All the questions I have dug through in the boards aren't really answering a question I have. So I will ask the experts here. First off, thank you very much for reading on. I really appreciate what Stackoverflow is all about, hopefully I can contribute now that I am a member.
I want to dynamically create a JSON object based off variables set from another JSON object from with a jQuery each loop. I think my syntax and probably my knowledge of this stuff is a little off.
I would like to end up with the following JSON structure:
{
desktop:{
title:300,
rev:200
}
}
Where "desktop" is a value from another JSON object not in this loop, I can call that no problem, in fact it is actually the name value I set on the other JSON object. I am looping through an array in the object called columns but want to set a separate object containing all the widths because the columns are adjustable and accessible via another frame that I will push it to, I want to retain those widths.
I was trying to do this from within the loop:
var colWidths = {};
$.each(columns, function(i) {
colWidths.desktop.title = columns[i].width;
});
I can alert columns[i].width successfully. The issue I have is creating and accessing this. Everything I seem to be doing seems right but this is not the case. Maybe its me or my setup? Could you please show me how to code this properly? OR I could create a Javascript Object if this is not possible. Thanks in advance!
Welcome to Stackoverflow. You did not write any error messages you got, so I assume the following.
// prepare the object correctly first
var colWidths = {
desktop: {
title: 0
}
};
// then ADDING each value with += instead of =
// (because in your code you will just have the last value)
$.each(columns, function(i) {
colWidths.desktop.title += columns[i].width;
});
EDIT
var grid = {
"name": "desktop",
"columns": [
{
"id": "icons",
"width": 50},
{
"id": "title",
"width": 200},
{
"id": "name",
"width": 300},
{
"id": "revision",
"width": 400}
]
};
var columns = grid.columns;
var gridName = grid.name;
var colWidths = {};
// CHANGE HERE
colWidths[gridName] = {};
$.each(columns, function(c) {
var col = columns[c];
var colname = col.id;
var colwidth = col.width;
// CHANGE HERE
var thisGrid = colWidths[gridName];
if(!thisGrid[colname]) thisGrid[colname] = 0;
thisGrid[colname] += colwidth;
});
//alert(colWidths.desktop.title);​
document.write(JSON.stringify(colWidths));
// RESULT:
// {"desktop":{"icons":50,"title":200,"name":300,"revision":400}}

Categories

Resources