Populating function's array via JSON - ajax

I am using this timeline plug-in as a base for my own: http://www.jqueryscript.net/other/Create-A-Simple-Vertical-Timeline-with-jQuery-CSS.html
The code I'm trying to change is step 3. Create events for the timeline using Javascript array object.
My code:
(note that #events is my timeline container for all the data)
$(function() {
$.ajax({
url: url,
type: 'get',
dataType: 'json',
async: false,
success: function(data) {
for (i = 0; i < data.timeline.length; i++) {
event = data.timeline[i];
numDate = event.shortdate;
txtTitle = event.longdate;
eventType = event.category;
eventDesc = event.description;
dataInfo = '{ date: new Date(' + numDate + '), type: "' + eventType + '", title: "' + txtTitle + '", description: "' + eventDesc + '" }';
dataArray.push(dataInfo);
}
}
});
$('#events').timeline({
data: dataArray,
height: 800 // in pixel
});
However, this is causing an error in the function that generates the timeline:
TypeError: firstDate is undefined
var tempDate = new Date(firstDate.getTime());
I'm thinking that perhaps something goofy is going on with my dataInfo variable. Any tips would be greatly appreciated!

Your biggest issue is that you're creating an array of strings, but the plugin expects an array of objects (not JSON, but an actual array of objects).
$(function () {
var dataArray = [];
$.ajax({
url: url,
type: 'get',
dataType: 'json',
async: false,
success: function (data) {
for (i = 0; i < data.timeline.length; i++) {
event = data.timeline[i];
dataArray.push({
date: new Date(event.shortdate),
type: event.category,
title: event.longdate,
description: event.description
});
}
}
});
$('#events').timeline({
data: dataArray,
height: 800 // in pixel
});
});
Again, even if the plugin did want JSON (which is a string) as opposed to an array of objects, you weren't providing it with that either--you were proving an array of strings, each of which were an attempt at JSON serializing some data.
Also, if you ever do need to produce JSON, don't do it manually with string concatenation. Create an actual data structure, then JSON.stringify() it.
Finally, you need to ensure that your shortdate property on the returned data is something which Date can use to accurately create the represented date.

Unfortunately the plug-in doesn't look to be all that well documented (as an aside, consider this one perhaps?) but based on just the article & your sample, the issue is likely in your dataInfo as you suspect.
You're not actually providing a valid Date object for the value of the date property; my guess is it should be this:
numDate = new Date(event.shortdate);
...
dataInfo = '{ date:' + numDate + ', type: "' + eventType + '", title: "' + txtTitle + '", description: "' + eventDesc + '" }';
EDIT: Look to JAAulde's answer for the correct way to do this.

Related

Updating a Leaflet Marker With Lan & Long Details From an API Request [duplicate]

This question already has an answer here:
Update geolocation marker instead of adding new one with leaflet api
(1 answer)
Closed 1 year ago.
I'm pulling through the lat & lng data from an API request as below but i'm tring to get the markef to update every time I change the counrty in the dropdown menu (selCountry).
$('#selCountry').on('change', function(){
$.ajax({
url: "php/restCountries.php",
type: 'POST',
dataType: 'json',
data: {
country: $('#selCountry').val()
},
success: function(result) {
console.log('restCountries', result);
if (result.status.name == "ok") {
currencyCode = result.currency.code;
iso2CountryCode = result.data.alpha2Code;
var countryName2 = result.data.name;
countryName = countryName2.replace(/\s+/g, '_');
var latlng = result.data.latlng
$('#countryName').html('<strong> Country: ' + result['data']['nativeName'] + '</strong>');
$('#txtCurrencyCode').html('<strong> Capital City: ' + result['data']['capital'] + '<br> Currency Symbol: '+ result.currency.symbol + '<br> Currency Name: ' + result.currency.name + '<br> Currency Code: ' + result.currency.code + '</strong>');
console.log(result.data.latlng);
I've tried changing the marker details to the latlng info which updates on selecting a new country but the marker does not update. What am I missing?
I have the marker outside the ajax call and if I move it inside the call, the whole map crashes out and does not load.
L.marker([latlng], {icon: redMarker}).bindPopup(result['data']['capital']).addTo(map);
Any advice would be greatly appriciated.
Thank You
Managed to figure out a way to get the request to work. I separated the latlng data out into variables and fed them into the marker statement.
It now adds a marker on each selected country change.
$('#selCountry').on('change', function(){
$.ajax({
url: "php/restCountries.php",
type: 'POST',
dataType: 'json',
data: {
country: $('#selCountry').val()
},
success: function(result) {
console.log('restCountries', result);
if (result.status.name == "ok") {
currencyCode = result.currency.code;
iso2CountryCode = result.data.alpha2Code;
var countryName2 = result.data.name;
countryName = countryName2.replace(/\s+/g, '_');
$('#countryName').html('<strong> Country: ' + result['data']['nativeName'] + '</strong>');
$('#txtCurrencyCode').html('<strong> Capital City: ' + result['data']['capital'] + '<br> Currency Symbol: '+ result.currency.symbol + '<br> Currency Name: ' + result.currency.name + '<br> Currency Code: ' + result.currency.code + '</strong>');
//console.log(result.data.latlng[0]);
var currentLat = result.data.latlng[0]
var currentLng = result.data.latlng[1]
marker = L.marker;
L.marker([currentLat, currentLng], {icon: redMarker}).addTo(map);
};
Happy days!

processing return from ajax call

I'm using the twitter-bootstrap's typeahead to do autocompletion on an input field.
What I have so far:
$(".airportSearch").typeahead({
source: function(typeahead, query) {
$.ajax({
url: url_,
dataType: "json",
data: {
n: 12,
q: typeahead
},
success: function(data) {
var return_list = [], i = data.length;
while(i--) {
return_list[i] = {
type: data[i].type,
id: data[i].iata,
value: data[i].city,
returnvalue: data[i].type == 'city' ? data[i].city + ' [' + data[i].iata + ']' :
data[i].city + ' (' + data[i].iata + ')'
};
}
}
});
}
});
example of output:
[{"type":"airport","city":"Quebec","airport":"Quebec","iata":"YQB","country":"Canada","locationId":"airport_YQB"},
{"type":"airport","city":"Queenstown","airport":"Queenstown","iata":"ZQN","country":"New Zealand","locationId":"airport_ZQN"},
{"type":"city","city":"Setif","airport":"All Airports","iata":"QSF","country":"Algeria","locationId":"DZ_city_QSF"},
{"type":"airport","city":"Setif","airport":"Setif","iata":"QSF","country":"Algeria","locationId":"airport_QSF"},
{"type":"airport","city":"QachaS Nek","airport":"QachaS Nek","iata":"UNE","country":"Lesotho","locationId":"airport_UNE"},
{"type":"airport","city":"Qaisumah","airport":"Qaisumah","iata":"AQI","country":"Saudi Arabia","locationId":"airport_AQI"}]
I have logged the return_list variable that I create and have confirmed that it is the expected list of objects I have created. I want to populate the autocomplete options with the returnvalue strings in the list of objects.
Could anyone tell me how, or point me to somewhere that tells me how?
Try this:
$(".airportSearch").typeahead({
source: function(typeahead, process) {
return $.ajax({ // return ajax result
url: url_,
dataType: "json",
data: {
n: 12,
q: typeahead
},
success: function(data) {
var return_list = [], i = data.length, data_vals = []; // add data_vals array for typeahead
while(i--) {
return_list[i] = {
type: data[i].type,
id: data[i].iata,
value: data[i].city,
returnvalue: data[i].type == 'city' ? data[i].city + ' [' + data[i].iata + ']' :
data[i].city + ' (' + data[i].iata + ')'
};
data_vals.push(return_list[i].returnvalue); // populate the needed values
}
return process(data_vals); // and return to typeahead
}
});
}
});
Normally I would populate the data_vals for typeahead only but you did it your way for your reason I guess.
Hope it helps.

CFWheels Pagination using AJAX

I've searched the entire Internet, all of it, and cannot find an answer to this.
I'm using the ColdFusion CFWheels Framework to query a database. The query is done via AJAX like this:
var id = $("#ship-id").val();
$.ajax({
type: "POST",
url: "/my-controller/my-method?format=json",
data: {shipId: id},
dataType: "json",
success: function(response) {
var resultHtml = '';
$.each(response, function(i, value) {
resultHtml += '<tr><td>' + value.FIRSTNAME + ' ' + value.LASTNAME + '</td></tr>';
});
$("#my-table").html(resultHtml);
}
});
I need to paginate that result set. In CFWheels you normally do that by setting the handle, page, perPage and order values in the query like this:
var order = model("order").findAll(
select="id, firstname, lastname, email",
where="orderid IN (#ValueList(orders.id)#)",
handle="ordersQuery",
page=params.page,
perPage=5,
order="lastname"
);
Then you just put this line in your view:
<cfoutput>#paginationLinks(handle="ordersQuery")#</cfoutput>
But... how in the heck can you get pagination to work with an AJAX call?
I think that something along these lines might be your answer (notice I removed the url and added those params to data ...
$.ajax({
type: "POST",
data: {
shipId: id,
controller: myController,
action: myAction,
page: params.page,
},
dataType: "json",
success: function(response) {
var resultHtml = '';
$.each(response, function(i, value) {
resultHtml += '<tr><td>' + value.FIRSTNAME + ' ' + value.LASTNAME + '</td></tr>';
});
$("#my-table").html(resultHtml);
}
});

Insert json data into text input

I have a function that adds a new patient to the database, gets the json data back and then adds the new patient to the select menu. That works fine. I need to add that data into the corresponding text inputs i.e., input#patient_id, input#patient_firstname, etc. which should occur in the .ajax complete, but nothing happens.
Would appreciate any help!!
Ajax
$('#newpatient').click(function() {
var patientadd = $('#patientaddform').serializeArray();
$.ajax({
url: 'adam.php',
type: "POST",
data: patientadd,
dataType: 'json',
success: function(data){
var html = '';
var len = data.length;
for (var i = 0; i< len; i++) {
html += '<option selected="selected" value="' + data[i].patient_id + '">' + data[i].patient_firstname + ' ' + data[i].patient_lastname + ' : ' + data[i].patient_dob + '</option>';
}
alert(html);
$('#patientselect').prepend(html);
$('#patientselect').selectmenu('refresh', true);
},
complete: function (data) {
for(var id in data) {
$('input#' + id).val( data[id] );
}
}
});
});
json data returned
[{"patient_id":"22","patient_firstname":"","patient_lastname":"","patient_dob":"0000-00-00"}]
the corresponding text input fields are input#patient_id, input#patient_firstname, etc, that is why I'm trying to add the 'input#' to the id in the ajax complete and then add that val to the text input.
The params for the complete call back are jqXHR and textStatus. Not data. See http://api.jquery.com/jQuery.ajax/ for the correct definition of complete(jqXHR, textStatus)
Your json data is an array of objects, so you have to add take the first element of the array like this:
for(var id in data[0]) {
$('input#' + id).val( data[0][id] );
}
Or you have to adapt the server response.
Also consider #techfoobar's answer:
The params for the complete call back are jqXHR and textStatus. Not data. See http://api.jquery.com/jQuery.ajax/ for the correct definition of complete(jqXHR, textStatus)

Synchronised Ajax requests with JQuery in a loop

I have the following situation: I need to make synchronized Ajax requests within a loop and display the returned result after each iteration in a div-element (appended on top with the previous results at the bottom). The response time of each request can be different but the order in which it should be displayed should be the same as issued. Here is an example with 3 requests. Lets say request "A" needs 3 seconds, "B" needs 1 second and "C" needs 5 seconds. The order I want to display the result is A, B, C as the requests were issued but the code I use shows the results in B, A, C.
Here is the code (JQuery Ajax request):
$(document).ready(function(){
var json = document.getElementById("hCategories").value;
var categories = eval( '(' + json + ')' );
for(curCat in categories) {
curCatKey = categories[curCat]['grKey'];
$.ajax({
type: "POST",
url: "get_results.php",
data: "category=" + escape(curCatKey) +
"&search=" + escape($("#hQuery").val()),
timeout: 8000,
async: false,
success: function(data) {
$("#content").append(data);
}
});
});
I thought it would work with "async:false" but then it waits until every Ajax call is finished and presents the results after the loop. I hope some of you can point out some different solutions, I am pretty much stuck.
Thanks in advance,
Cheers Chris
EDIT: Thanks for all the possible solutions, I will try these now one by one and come back with that one that fits my problem.
I have two solution proposals for this problem:
Populate generated divs
You could generate divs with ids in the loop and populate them when the request finishes:
$(document).ready(function() {
var json = document.getElementById("hCategories").value;
var categories = eval('(' + json + ')');
for (curCat in categories) {
(function(curCat) {
var curCatKey = categories[curCat]['grKey'];
$('#content').append('<div id="category-"' + escape(curCat) + '/>');
$.ajax({
type: "POST",
url: "get_results.php",
data: "category=" + escape(curCatKey) + "&search=" + escape($("#hQuery").val()),
success: function(data) {
$("#category-" + escape(curCat)).html(data);
}
});
})(curCat);
}
});
Or use a deferred
You can store jqXHR objects in an array and use a deferred to call the success functions in order, when all calls have finished.
$(document).ready(function() {
var json = document.getElementById("hCategories").value;
var categories = eval('(' + json + ')');
var requests;
for (curCat in categories) {
var curCatKey = categories[curCat]['grKey'];
requests.push($.ajax({
type: "POST",
url: "get_results.php",
data: "category=" + escape(curCatKey) + "&search=" + escape($("#hQuery").val())
}));
}
$.when.apply(requests).done(function() {
for (i in requests) {
requests[i].success(function(data) {
$("#content").append(data);
});
}
});
});
The first method has the advantage that it populates the containers continuously. I have not tested either of these function, but the logic should work the way I described it.
This would do the trick
var results = [];
var idx = 0;
for(curCat in categories) {
curCatKey = categories[curCat]['grKey'];
(function( i ) {
$.ajax({
type: "POST",
url: "get_results.php",
data: "category=" + escape(curCatKey) +
"&search=" + escape($("#hQuery").val()),
timeout: 8000,
async: false,
success: function(data) {
results[i] = data;
if (i == idx - 1) { // last one
for (var j=0; j < results.length; j++) {
$("#content").append(results[j]);
}
}
}
});
})(idx++);
I think something like this is what you're looking for. Might need some tweaking, I'm a little rusty on Deferred. Read up on it though, mighty powerful
deferred = $.Deferred()
for(curCat in categories) {
deferred.pipe(
function(resp){
postData = {} // set up your data...
return $.post("get_results.php", {data: postData, timeout: 8000})
.done(function(content){ $("#content").append(content) })
})
)
}
// Trigger the whole chain of requests
deferred.resolve()

Resources