jquery - update jquery.sparkline after async data fetch - javascript

Background
i'm using jquery.sparkline to produce Pie Charts. The data for the Pie Chart is contained in an array.
When the page is first loaded a web-service is called (using .ajax) to get the data, the callback specified there takes the received data and updates the array associated with the pie chart.
That same update process is invoked when a dropdown on the screen changes value.
Situation
If I set the .ajax call to asynch=false this all works fine.
If I set the .ajax call to asynch=true the results shown in the pie are always 'one refresh behind'. By this I mean there's no pie initially and then when the dropdown is changed the pie is rendered as it should have been initially.
Code
$.ajax({
type: "GET",
contentType: "application/json; charset=utf-8",
url: requestURL,
async: true ,
success: function (data) { successCallback(data); },
error: function (data) { failureCallback(data); }
});
Help?
Anyone out there recognise this problem ?
Options
I've been looking at variations on the Observer pattern to monitor a change to the array and the (not sure how) persuade the jquery.sparkline object to redraw itself but this seems crazy and I'm sure I must be overlooking something much more straightforward.
Thanks to Gareth and his sample code I was able to see what I was doing wrong (which wasn't anything to do with jquery.sparkline.
I had some functions like this :
function RefreshPieChart(){
//First call managePieDataFetch()
//to kick off the web-service request
managePieDataFetch();
//now reinitialise the jquery.sparkline
//pie charts on the basis that the
//array variable initialised in
//pieDataFetchCallBack() has the newest
//data in it.
//
//.... It hasn't !
}
function managePieDataFetch(){
//invoke the .ajax call and
//provide function pieDataFetchCallBack() as
//a call back function
}
function pieDataFetchCallBack(){
//post process the data
//returned from a successful
//ajax call. Place the results
//into an array variable at
//script scope
}

I'd need to see a more complete example to determine where the problem is, but using async: true works fine for me.
Here's a link to a very simple working example: http://omnipotent.net/jquery.sparkline/ajaxtest.html
The source for the ajax side is here:
http://omnipotent.net/jquery.sparkline/ajax.phps
If your chart is hidden (ie. display: none) at the time .sparkline() is actually called then you may need to call $.sparkline_display_visible() at the point the chart is made visible to force it to be rendered at that point.

Related

asp.net webservice jquery populate textbox

I want to get 3 values from a web service by providing current URL and current user. My webservice accepts 2 parameter URL and user. Web service works fine.
Now I want to put this 3 values in 3 different textboxes using jquery.in txtOrgCity = city, in txtPin = pin, in txtCountry = country
bellow is code for txtOrgCity
$(document).ready(function () {
$('#txtOrgCity').val({
source: function (request, response) {
$.ajax({
url: '../lead_hunter.asmx/GetOrgCity',
method: 'post',
contentType: 'application/json;charset=utf-8',
data: JSON.stringify({ url: "http://srv3.testsrv.com/homepage", user: "testuser#testsrv.com" }),
dataType: 'json',
success: function (data) {
response(data.d);
},
error: function (err) {
alert(err);
}
});
when I run it gives me [object object] in text box.
How do I define to grab City for txtOrgCity, pin for txtOrgPin, country for txtOrgCountry in response(data.d).?
and do I need to duplicate the same code for other 2 text boxes or any better way.?
Given code is just for some txtbox autocomplete and it works perfectly so I just wanted it to modify a bit for my need. $('#txtOrgCity').val was $('#txtOrgCity').autocomplete
Any help would be appreciated.
--
Thanks
I recommend that you open this up in google chrome. Open up your developer tools (press f12) and, open up resources and select the page you are currently working on. Then use the find box to search for your javascript method which fires the ajax and put a break point inside the success part of your ajax call. Now run your code and wait to hit the break point. Now you can see what is inside your data.d object. Do not resume and keep debugging. Open up your console tab and type data.d. you should see an intelicence option box with all the variables inside your data.d object. You should see the variable for city, pin and country in whatever way you named them when you deserialized your data and returned it as json to your ajax call.
If, for example, you write data.d.city in your console it should write out the corresponding value. The same goes for any other json variable your service passed back to the browser.
With that information it is easy enough to use jquery and do what you want with the data. So in the succes part of your ajax call you can write:
$("#txtOrgCity").val(data.d.city);
$("#txtPin").val(data.d.pin);
$("#txtCountry").val(data.d.country);
p.s. im writting on a phone.
For your example you should not write out the same code two more times. Do not call ajax inside a jquery .val(), that is wrong. Make a new function which handles your ajax, call it from the page load or anywhere you need :
function loadData(//put your user parameter in here if you need){
$.ajax({
url: '../lead_hunter.asmx/GetOrgCity',
method: 'post',
contentType: 'application/json;charset=utf-8',
data: JSON.stringify({ url: "http://srv3.testsrv.com/homepage", user: "testuser#testsrv.com" }),
dataType: 'json',
success: function (data) {
$("#txtOrgCity").val(data.d.city);
$("#txtPin").val(data.d.pin);
$("#txtCountry").val(data.d.country);
},
error: function (err) {
//welldone for handling your error message. Many people neglect this. As a developer that is like coding blindly. At the very least you can console.log(err); if you don't want the user to see
alert(err);
}
});
}
Instead of $('#txtOrgCity').val({})
In your .ready function make the AJAX call first.
Store d.OrgCity, d.OrgPin & d.OrgCountry into some local JavaScript variables. In the Ajax call success use these values to deposit into textboxes like
$('#txtOrgCity').val(d.OrgCity)
You are after JSON.stringify(). So where you specify your .val() You want .val(JSON.stringify());

Can't make DataTables work by using jQuery .post()

I am working on a form where a uses chooses a date range in order to display information by using DataTables.
When the user clicks on the button, the dates are sent through jQuery .post() function and it retrieves the info as expected.
Here is the piece of the code related to it:
//Sending the dates range
$.post(url_route, datos, function(data,status){
if(status=='success'){
var response = jQuery.parseJSON(data);
//checking if data were found
if(response.list_events.length === 0){
console.log('No data available');
}
else{
//Let us display the info with DataTables inside div #list_events and
//table #table_id
$('#list_events').html('<table class="table table-striped table-hover" id="table_id"></table>');
$('#list_events table').append('<thead><tr><th>Event</th><th>Type</th><th>Attendance</th><th>Coordinators</th><th>Participants</th><th>Institutes</th><th>Talks</th></tr></thead><tbody></tbody>');
//retrieving the info for each row and append it to the table:
$.each(response.list_events,function(i,item)
{
$('#list_events').find('tbody').append('<tr>');
$('#list_events').find('tbody').append('<td>'+item.Event+'</td>');
$('#list_events').find('tbody').append('<td>'+item.Type+'</td>');
$('#list_events').find('tbody').append('<td>'+item.Attendance+'</td>');
$('#list_events').find('tbody').append('<td>'+item.Coordinator+'</td>');
$('#list_events').find('tbody').append('<td>'+item.Participant+'</td>');
$('#list_events').find('tbody').append('<td>'+item.Institute+'</td>');
$('#list_events').find('tbody').append('<td>'+item.Talk+'</td>');
});//end of each
//initializing DataTables
var table = $('#table_id').DataTable();
}//end of else (info found)
}//end of if success
}//end of post()
So far, the info is displayed in the DataTables but it is not totally working, since only the information is displayed. The DataTables search, next, and previous buttons, as well as the number of results dropdown menu are not shown.
In the console.log I get the following error:
Uncaught TypeError: Cannot read property 'length' of undefined
Any ideas? Can anyone shed some light on this?
Solved
The problem was with the append function.
If I type just one append with only the <tr> like this:
$('#list_events').find('tbody').append('<tr>');
The result in HTML is <tr></tr> That is to say, the tag is closed automatically ... no matter what. So, the solution was to put all the appends in one line like the following:
$('#list_events').find('tbody').append('<tr><td>'+item.Event+'</td><td>'+item.Type+'</td><td>'+item.Attendance+'</td><td>'+item.Coordinator+'</td><td>'+item.Participant+'</td><td>'+item.Institute+'</td><td>'+item.Talk+'</td></tr>');
And that was it ☺
My first thought is that perhaps "response.list_events" is undefined. Certainly your error:
"Uncaught TypeError: Cannot read property 'length' of undefined"
seems to imply that.
My second thought is that I have recently done something similar where I had trouble with the .post method, and found success with the .ajax method.
Try something along these lines:
$.ajax({
type: "POST",
url: url_route,
data: datos,
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function(returned_from_server){
// your function here
}
});
My third thought is that I don't see where you put your closing row tags.
$.each(response.list_events,function(i,item)
{
$('#list_events').find('tbody').append('<tr>');
$('#list_events').find('tbody').append('<td>'+item.Event+'</td>');
$('#list_events').find('tbody').append('<td>'+item.Type+'</td>');
$('#list_events').find('tbody').append('<td>'+item.Attendance+'</td>');
$('#list_events').find('tbody').append('<td>'+item.Coordinator+'</td>');
$('#list_events').find('tbody').append('<td>'+item.Participant+'</td>');
$('#list_events').find('tbody').append('<td>'+item.Institute+'</td>');
$('#list_events').find('tbody').append('<td>'+item.Talk+'</td>');
$('#list_events').find('tbody').append('</tr>'); // <--- I believe you might be missing this!!
});//end of each
Hopefully this was some help.
If you are using a remote source for your data, it is far more elegant and efficient to let DataTables itself render the data for you.
In your example, you fetch the data, build the table, and then turn it into a "DataTable". If it meets the requirements and gets the job done, you've written perfectly fine code and you should read this answer no more!
But DataTables itself is awfully smart about rendering data detached from the DOM and then slotting it all in place. You get the benefit of more efficient updates while simultaneously having cleaner code.
Here's a basic example. Without testing it in your environment, I can't say for sure it will do your job, but I think it should:
var myTable = $('#table_id').DataTable( {
"ajax": {
"url": url_route,
"data": function(customData) {
customData.datos = datos // need some way to have access to datos
}
}
});
And then on click, if you want to retrieve newer data based on whatever has changed (the date range?) you just have to redraw.
myTable.draw();
I can imagine a few ways to get datos in there-- wrap it up in a function that accepts and uses datos. Declare a namespaced or otherwise quasi-global (or actually global if you're that guy!) variable that myTable would have access to at any given point in time... or even just destroy the current table and call the whole DataTable() on it again.

jQuery AJAX inside another AJAX call. Sync and finished issues

I get a list of users with an AJAX call, but within the AJAX I call another AJAX to get some information that I could not get with the first AJAX call.
This is basically the structure I'm using, I've removed some unneccesary code that would just clutter, it is possible that there is some syntax errors here and there.
But the code basically works but there are some issues.
function doAJAX(){
$(".loading").show();
$("#table").hide();
$.ajax({
type: "POST",
url: "#Url.Action("Action", "Controller")",
data: { variable: varVariable},
dataType: "json",
success: function (data) {
$.each(data, function (index, value) {
$.ajax({
type: "POST",
url: "#Url.Action("Action", "Controller")",
data: { variable: value.id},
success: function (data2) {
$.each(data2, function (index2, value2) {
$("#tableBody").append("<tr><td>" + value.test +"</td><td>" + value2.test +"</td></tr>");
});
}
});
});
}
});
}
I hide my table at the start, when the AJAX is complete I want to show it again. Where exactly should I place it? Even if I place it at the end of the first AJAX success function it does not work because it gets executed while the other AJAX is still running.
For some reason my list ends up in an odd order everytime the AJAX runs, my list is sorted by alphabetical order yet with this AJAX it ends up random everytime, sometimes the user Adam is at the start, sometimes in the middle and so on. The list itself is fine and in correct order
I do a lot of mathematics that is probably slowing down the second AJAX call which is probably why it ends up in a weird order
Both of these issues are happening because the two AJAXs aren't running "together" but individually, is there a way to make them sync with each other and is there a good way to be sure that the AJAX is completed and now I can show my table?
Sending ajax request inside a loop doesn't seem like a good idea. Why won't you send one ajax request with array of id's as a data, inside your serverside script just get "WHERE id IN (id_list)" array of user records and return them as json-encoded object, and then output it inside a double loop, first for <tr>, second for a list of fields.
I'm sorry i can't provide code, as i don't know what is being returned from your requests to server.

Show ajax tooltip from an SVG onclick event

I have an SVG with this code for some shapes (its a map)
onclick="top.traeDatos(evt.target.id);"
in the html file I have:
function traeDatos(region){
alert(region);
}
So, I click on a region, I have the alert window with the region name and the variable in the html file. Thats great
Now I want that the click on the map shows a popup with more information i'll get using ajax from multiple databases trough a file called, for example "getDetails.php".
Im new in js and ajax, I know how to make a standard call in ajax to get some information given an id (or name in this case), I know how to change the value of a text field to the text I get trought the ajax call...but I dont understand how to call ajax and show a tooltip from that javascript code in the SVG or the one in html.
Im not sure too of what tolltip to use, but one problem at the time ;)
Can you enlighten me a little.
Thanks!
Here's a start:
function traeDatos(region){
var domn = document.domain;
document.domain = domn;
var detURL = "http://" + domn + "/getDetails.php";
$.ajax({
url: detURL,
type: 'POST',
data: {
region: region
},
cache: false,
success: function(json){
var data = jQuery.parseJSON(json);
//using PHP's json_encode() you can return an array
//in the example below 'info' is an item in the array
$('#insert_place').val(data.info);
}
});
}
Let me know if you have some problem with that.

jQuery Flot Charts + Overwrite xAxis

I get the data via an AJAX request and it looks like this:
[1,3252325],[2,2323]
The second value is the file id called fId
Now I try to get that id and make another ajax call to find out the corresponding name and use it to override the x-axis description.
Everything works fine, but the problem is that everytime it runs, it deletes all existing names. Therefor, at the end, I am left with only one, the last, dataset that has a custom xAxis description.
What I need is that in the end all datasets have their custom new name for the xAxis.
I tried to search the API.txt but couldnt find anything about it. I did also try for hours to move the code around or rewrite it, but after all I am stuck with the same problem.
Thats the part of the code:
function onDataReceived(series) {
//Add data
if (!alreadyFetched[series.label]) {
alreadyFetched[series.label] = true;
fdata.push(series);
//Get ID
var fId = [series.data[0][0]];
//Get names
$.ajax({
url: 'inc/admin.inc.php?action=get&option=filename&id='+fId+'',
method: 'GET',
dataType: 'html',
success: function(response){
$.plot(fplaceholder, fdata,$.extend(true, {}, foptions, {
//Works, but each time it runs, it removes all previous overrides
xaxis:{ticks:[[fId,response]]}
}));
}
});
}
}
$.ajax({
url: dataurl,
method: 'GET',
dataType: 'json',
success: onDataReceived
});
UPDATE:
I am currently using a "hack" to make this work how I want it, but this is probably only working for my specific needs:
I set the xaxis "show decimal numbers" to false. After the plot is built, I start a timeout function to search all xaxis values (ids in my case) and find the corresponding name with a small ajax call.
I am still looking how to do it directly within the flot code though.

Categories

Resources