FullCalendar: events not rendering initially from function call (AJAX) - javascript

I've configured my FullCalendar to pull its events from an AJAX request, but they don't render on the calendar when the page is first loaded.
$(document).ready(function() {
sh1client = new Array();
sh2client = new Array();
$('#sh1_cal').fullCalendar({
height: 1000,
minTime:'9:00am',
maxTime:'5:00pm',
editable: false,
events: function(start, end, callback) {
$.ajax({
type: 'GET',
url: 'http://localhost:8080/getEvents',
dataType: 'json',
success: function(reply) {
console.log(reply.first);
callback(reply.first);
}
});
}
});
$("#sh1_cal").fullCalendar('addEventSource', sh1client); // these are the clientside arrays
});
And on the server,
app.get('/getEvents', function(req, res){
console.log('Server: passing events...');
var arrays = {first: sh1, second: sh2}
var pack = JSON.stringify(arrays)
res.writeHead(200, {'Access-Control-Allow-Origin' : '*', 'Content-Type': 'application/json'});
res.end(pack);
});
Is there any reason these events wouldn't initially load? Everything seems to be being passed through alright, but it's like the callback isn't working or something.
EDIT: Here is another approach I tried
events: {
url: 'http://localhost:8080/getEvents',
type: 'GET',
error: function() {
alert('there was an error while fetching events!');
},
success: function(reply) {
console.log(reply);
//callback(reply.first);
},
color: 'yellow', // a non-ajax option
textColor: 'black' // a non-ajax option
}
EDIT: JavaScript console shows this as being POSTed to the page as soon as it loads (this is the first object in an array:
[Object]
allDay: "false"
end: "1392129000"
id: "phil#google.com"
room: "Sh1"
start: "1392127200"
title: "Phil - Google"
__proto__: Object
length: 1
__proto__: Array[0]

Instead of using your own ajax call, have you tried using fullcalendars?
http://arshaw.com/fullcalendar/docs/event_data/events_json_feed/
Fullcalendar defaults the dataType as JSON and caching to false.
Combined some of your code with code from doc:
$('#calendar').fullCalendar({
events: {
url: 'http://localhost:8080/getEvents',
type: 'GET',
error: function() {
alert('there was an error while fetching events!');
},
success: function(reply) {
console.log(reply.first);
callback(reply.first);
},
color: 'yellow', // a non-ajax option
textColor: 'black' // a non-ajax option
}
});
You can try just getting your JSON string cutting and pasting in and see if you can render without ajax call
events: [
{
end: 1392129000,
id: "phil#google.com",
room: "Sh1",
start: 1392127200,
title: "Phil - Google"
}]
You can also process the response:
$('#myCalendar').fullCalendar({
...
eventSources : [{
url: 'myUrl',
type: 'GET',
},
success: function(replyObject) {
var results = [];
var reply= replyObject.Results[0];
for(var index in reply) {
results.push(reply[index]);
}
return results;
}
}]
...

Related

How to properly code Javascript / Ajax for use with Chart.js

I have a controller action in my MVC project that creates a json record with the components needed. This is working. The issue I am having is bringing it into a chart.js canvas. This will be a pie chart that shows all the related countries with a count of each. Json has this info. Originally this was setup to use google visualization but I want to use chart.js. I just started using it. Creating charts with static data is no issue but I am pulling the info from a SQL table and creating a json to read from.
I have tried using the same structure and calling the data: data[] but it doesn't work I have also tried data: getData, which is a var for the ajax function. I am getting the data per the council on refresh.
Here is my controller Action
public ActionResult CustomersByCountry()
{
CustomerEntities _context = new CustomerEntities();
var customerByCountry = (from c in _context.Addresses
group c by c.Country into g
orderby g.Count() descending
select new
{
Country = g.Key,
CountCustomer = g.Count()
}).ToList();
return Json(new { result = customerByCountry }, JsonRequestBehavior.AllowGet);
}
And here is the JavaScript/ajax - which is nested in a document.ready function with the rest of the charts.
EDIT - changed Ajax - Still not working
OrdersByCountry()
function OrdersByCountry() {
$.ajax({
url: '/admin/CustomersByCountry',
method: "GET",
dataType: "json",
error: function (_, err) {
console.log(_, err)
},
success: function (data) {
console.log (data);
var customer = $("#customerByCountryPieChart").get(0).getContext("2d");
console.log(customer)
var cpieChart = new Chart(customer, {
type: 'pie',
data: data,
options: {
responsive: true,
title: {
display: true,
text: "Customers By Country",
}
}
});
}
});
};
Edit - The now working code is below.
I changed it to get states instead of country, just to clear up possible confusion. It made more sense to me to get States rather than Country at this point. This is working - meaning displaying the graph, I still need to work on the labels etc.
OrdersByStates()
function OrdersByStates() {
$.ajax({
url: '#Url.Action("CustomersByStates", "Admin")',
data: JSON,
contentType: "application/json; charset=utf-8",
method: "get",
dataType: "json",
error: function (_, err) {
console.log(_, err)
},
success: function (response) {
console.log(response);
var jsonresult = response
var labels = jsonresult.result.map(function (e) {
return e.State;
});
var data = jsonresult.result.map(function (e) {
return e.CountCustomer;
});;
var ctx = document.getElementById("CustomerByStatePieChart").getContext("2d");
var cpieChart = new Chart(ctx, {
type: 'pie',
data:
{
datasets: [
{
backgroundColor: ["#46BFBD", "#F7464A"],
hoverBackgroundColor: ["#5AD3D1", "#FF5A5E"],
label: "Orders",
data: data,
}]
},
options: {
responsive: true,
title: {
display: true,
text: "Customers By Country",
}
}
});
}
});
};
});
try:
var cpieChart = new Chart(customer, {
type: 'pie',
data: data.result,
options: {
responsive: true,
title: {
display: true,
text: "Customers By Country",
}
}
});
the response from the server "data" var on your request is {result: LIST}

Bootstrap-table : multiple tables , one function

I am on an custom ajax implementation for bootstrap-table (the documentation : http://bootstrap-table.wenzhixin.net.cn/documentation/) :
For some reason, I would like to have multiple bootstrap Tables (let's call them searchTable1 , searchTable2,etc). Each of these table will be set on a custom date range (30 last days, 60 last days,etc).
I would like to pass a parameter (like the table Jquery selector or any data-myCustomDataAttribute parameter) . How can I do that ? (I tried using call but bootstrap already call it on the ajaxCallback function so It seems I cannot use it here).
It will look like stupid to make x functions that are exactly the same except for two fields depending on the table. Does someone has an idea to do that ?
Here is my code :
$('#searchTable').bootstrapTable({
columns: [{
field: 'product',
title: 'Produit'
} , {
field: 'language',
title: 'Langue'
}, {
field: 'comment',
title: 'Commentaire'
}],
showRefresh: true,
ajax: provideFeedbacksList,
cache: false,
dataField: 'feedbacks',
totalField: 'total_size',
search: false,
sidePagination: 'server',
pagination: true
});
The ajax provider :
// I only used this example : http://issues.wenzhixin.net.cn/bootstrap-table/index.html#options/custom-ajax.html
function provideFeedbacksList(params) {
let tableData = params.data;
let serverCall = {};
// add limits and offset provided by bootstrap table
serverCall["page_offset"] = tableData.offset;
serverCall["page_size"] = tableData.limit;
// retrieve the date range for this table :
// will be easy If something like this was possible : params.jquerySelector.attr("date-range-start")
// will be easy If something like this was possible : params.jquerySelector.attr("date-range-end")
let json = JSON.stringify(serverCall);
$.ajax({
url: baseUri + "/feedbacks",
type: "POST",
dataType: "json",
contentType: "application/json; charset=utf-8",
data: json,
success: function (reponse) {
params.success(reponse);
},
error: function (er) {
params.error(er);
}
});
}
Bonus, the call stack :
Finally found my answer , I have to wrapper it as a function to enable bootstrap table to pass also its data:
Self solved my issue :
js:
function callbacker(test){
console.log(test);
return function (params) {
console.log(params);
console.log(test);
let tableData = params.data;
let serverCall = {};
// add limits and offset provided by bootstrap table
serverCall["page_offset"] = tableData.offset;
serverCall["page_size"] = tableData.limit;
let json = JSON.stringify(serverCall);
$.ajax({
url: baseUri + "/feedbacks",
type: "POST",
dataType: "json",
contentType: "application/json; charset=utf-8",
data: json,
success: function (reponse) {
params.success(reponse);
},
error: function (er) {
params.error(er);
}
});
}
}
html:
$('#searchTable').bootstrapTable({
columns: [{
field: 'product',
title: 'Produit'
} , {
field: 'language',
title: 'Langue'
}, {
field: 'comment',
title: 'Commentaire'
}],
showRefresh: true,
ajax: callbacker("whatEverValueYouWant"),
cache: false,
dataField: 'feedbacks',
totalField: 'total_size',
search: false,
sidePagination: 'server',
pagination: true
});

FullCalendar.js - "there was an error while fetching events"

I'm using FullCalendar.js to display Google Calendar events from multiple sources. It's been working OK up until today. For some reason FullCalendar started popping up the "there was an error while fetching events" error message and all the events are obviously gone. Here is a jsfiddle.
http://jsfiddle.net/mlk4343/1wko0z1j/1/
$(document).ready(function() {
$('#calendar').fullCalendar({
header: {
left: 'prev,next today',
center: 'title',
right: 'month,agendaWeek,agendaDay'
},
contentHeight: 600,
eventMouseover: function(calEvent, jsEvent) {
var tooltip = '<div class="tooltipevent">' + calEvent.title + '</div>';
$("body").append(tooltip);
$(this).mouseover(function(e) {
$(this).css('z-index', 10000);
$('.tooltipevent').fadeIn('500');
$('.tooltipevent').fadeTo('10', 1.9);
}).mousemove(function(e) {
$('.tooltipevent').css('top', e.pageY + 10);
$('.tooltipevent').css('left', e.pageX + 20);
});
},
eventMouseout: function(calEvent, jsEvent) {
$(this).css('z-index', 8);
$('.tooltipevent').remove();
},
eventSources: [
{
// Adele H
url: 'https://www.google.com/calendar/feeds/sonomaschools.org_u030vtntt1tp7gjn8cnqrr9nsk%40group.calendar.google.com/public/basic',
type: 'POST',
error: function() {
alert('there was an error while fetching events!');
},
color: 'yellow', // a non-ajax option
textColor: 'black' // a non-ajax option
},
{
// Altimira
url: 'https://www.google.com/calendar/feeds/sonomaschools.org_e6j3ejc40g02v4sdo0n3cakgag%40group.calendar.google.com/public/basic',
type: 'POST',
error: function() {
alert('there was an error while fetching events!');
},
color: 'red', // a non-ajax option
textColor: 'white' // a non-ajax option
},
{
// Charter
url: 'https://www.google.com/calendar/feeds/sonomacharterschool.org_0p2f56g5tg8pgugi1okiih2fkg%40group.calendar.google.com/public/basic',
type: 'POST',
error: function() {
alert('there was an error while fetching events!');
},
color: 'LightSalmon', // a non-ajax option
textColor: 'black' // a non-ajax option
},
{// Dunbar
url: 'https://www.google.com/calendar/feeds/sonomaschools.org_4tmsks5b9s70k6armb6jkvo9p0%40group.calendar.google.com/public/basic',
type: 'POST',
error: function() {
alert('there was an error while fetching events!');
},
color: 'green', // a non-ajax option
textColor: 'white' // a non-ajax option
},
{// El Verano
url: 'https://www.google.com/calendar/feeds/pv2hfl7brn6dj8ia3mqksp9fl0%40group.calendar.google.com/public/basic',
type: 'POST',
error: function() {
alert('there was an error while fetching events!');
},
color: 'LightBlue', // a non-ajax option
textColor: 'black' // a non-ajax option
},
{ // Flowery
url: 'https://www.google.com/calendar/feeds/sonomaschools.org_v0a2nmtu4jrca90lui62tccbd4%40group.calendar.google.com/public/basic',
type: 'POST',
error: function() {
alert('there was an error while fetching events!');
},
color: 'blue', // a non-ajax option
textColor: 'white' // a non-ajax option
},
{ // Prestwood
url:'https://www.google.com/calendar/feeds/sonomaschools.org_25rjgf4pu3vsa5i7r7itnqkigs%40group.calendar.google.com/public/basic',
type: 'POST',
error: function() {
alert('there was an error while fetching events!');
},
color: 'purple', // a non-ajax option
textColor: 'white' // a non-ajax option
},
{ // Sassarini
url: 'https://www.google.com/calendar/feeds/sonomaschools.org_18a25r5mrc084gn4ekegadpfm8%40group.calendar.google.com/public/basic',
type: 'POST',
error: function() {
alert('there was an error while fetching events!');
},
color: 'Aqua ', // a non-ajax option
textColor: 'black' // a non-ajax option
},
{ // SVHS
url: 'https://www.google.com/calendar/feeds/sonomaschools.org_h450occacktra5errgbhsrv3k4%40group.calendar.google.com/public/basic',
type: 'POST',
error: function() {
alert('there was an error while fetching events!');
},
color: 'Chartreuse', // a non-ajax option
textColor: 'black' // a non-ajax option
},
{ // SVUSD
url: 'https://www.google.com/calendar/feeds/sonomaschools.org_2i1596pg2fokba99kvatqn45bk%40group.calendar.google.com/public/basic',
type: 'POST',
error: function() {
alert('there was an error while fetching events!');
},
color: 'MediumVioletRed', // a non-ajax option
textColor: 'white' // a non-ajax option
},
]
});
});
The events show OK on Google Calendar.
I tried the other solutions, which got me close to a fix but not entirely there. The results were fetching the entire set of calendar events and not a set number in a certain date-range.
What I discovered was that the names of the Parameters have also changed in the new API.
See: https://developers.google.com/google-apps/calendar/v3/reference/events/list
My fix involves adding the new APIv3 parameters to the data variable. Also the date-format for timeMin and timeMax are RFC3339/ATOM and not ISO 8601 (which Moment.js outputs by default) so I have added a format string to produce RFC3339 formatted dates.
Use the APIv3 URL format in your HTML/PHP file:
https://www.googleapis.com/calendar/v3/calendars/CALENDAR-ID/events?key=API-KEY
Update your gcal.js to the following code. This is based on the fixes posted by user4263042 and Stephen (Thanks guys!)
(function(factory) {
if (typeof define === 'function' && define.amd) {
define([ 'jquery' ], factory);
}
else {
factory(jQuery);
}
})(function($) {
var fc = $.fullCalendar;
var applyAll = fc.applyAll;
fc.sourceNormalizers.push(function(sourceOptions) {
if (sourceOptions.dataType == 'gcal' ||
sourceOptions.dataType === undefined &&
(sourceOptions.url || '').match(/^(http|https):\/\/www.googleapis.com\/calendar\/v3\/calendars/)) {
sourceOptions.dataType = 'gcal';
if (sourceOptions.editable === undefined) {
sourceOptions.editable = false;
}
}
});
fc.sourceFetchers.push(function(sourceOptions, start, end, timezone) {
if (sourceOptions.dataType == 'gcal') {
return transformOptions(sourceOptions, start, end, timezone);
}
});
function transformOptions(sourceOptions, start, end, timezone) {
var success = sourceOptions.success;
var data = $.extend({}, sourceOptions.data || {}, {
'singleEvents' : true,
'maxResults': 250,
'timeMin': start.format('YYYY-MM-DD[T]HH:mm:ssZ'),
'timeMax': end.format('YYYY-MM-DD[T]HH:mm:ssZ'),
});
return $.extend({}, sourceOptions, {
url: sourceOptions.url + '&callback=?',
dataType: 'jsonp',
data: data,
success: function(data) {
var events = [];
if (data.items) {
$.each(data.items, function(i, entry) {
events.push({
id: entry.id,
title: entry.summary,
start: entry.start.dateTime || entry.start.date,
end: entry.end.dateTime || entry.end.date,
url: entry.htmlLink,
location: entry.location,
description: entry.description || '',
});
});
}
var args = [events].concat(Array.prototype.slice.call(arguments, 1));
var res = applyAll(success, this, args);
if ($.isArray(res)) {
return res;
}
return events;
}
});
}
// legacy
fc.gcalFeed = function(url, sourceOptions) {
return $.extend({}, sourceOptions, { url: url, dataType: 'gcal' });
};
});
Here's the fix everyone:
https://github.com/jonnyhweiss/fullcalendar/commit/520022a4da81ded61f3a1cc7020df4df54726fbc?diff=split
It requires editing of gcal.js and gcal.html to get the demo's working; from those demos you should be able to fix your own broken calendars, hopefully ; )
Please note:
Requires Full-Calendar 2.2.0
I quickly discovered it will not work on Full Calendar 1.x.x, or if it will, I'm not code savvy enough to figure it out. Full Calendar 2.2.0 adds moment.js as a dependent JS link, which is not a part of Full Calendar 1.x.x, so copy and pasting what is available on the link above into your Full Calendar 1.x.x files will not work.
Happy coding and fixing your Google Calendars!
I believe I have the solution.
After a little digging I found a this page, but written as is, the code failed to work correctly. BUT after a little modification, see below, I now have things in working order again.
To use the new piece of code one needs to change the source URL for ones calendar to the form:
https://www.googleapis.com/calendar/v3/calendars/CALENDAR-ID/events?key=API-KEY
Insert your own calendar id and public API key into the URL as indicated. Your API-KEY can be obtained by setting up a project inside your Google Developers Console and then creating a public access API browser key.
Here is the actual code one needs to use in place of ones in the current gcal.js file.
(function(factory) {
if (typeof define === 'function' && define.amd) {
define([ 'jquery' ], factory);
} else {
factory(jQuery);
}
})
(function($) {
var fc = $.fullCalendar;
var applyAll = fc.applyAll;
fc.sourceNormalizers.push(function(sourceOptions) {
if (sourceOptions.dataType == 'gcalv3'
|| (sourceOptions.dataType === undefined
&& (sourceOptions.url || '').match(/^(http|https):\/\/www.googleapis.com\/calendar\/v3\/calendars\//))) {
sourceOptions.dataType = 'gcalv3';
if (sourceOptions.editable === undefined) {
sourceOptions.editable = false;
}
}
});
fc.sourceFetchers.push(function(sourceOptions, start, end, timezone) {
if (sourceOptions.dataType == 'gcalv3') {
return transformOptionsV3(sourceOptions, start, end, timezone);
}
});
function transformOptionsV3(sourceOptions, start, end, timezone) {
var success = sourceOptions.success;
var data = $.extend({}, sourceOptions.data || {}, {
singleevents: true,
'max-results': 9999
});
return $.extend({}, sourceOptions, {
url: sourceOptions.url,
dataType: 'json',
data: data,
startParam: 'start-min',
endParam: 'start-max',
success: function(data) {
var events = [];
if (data.items) {
$.each(data.items, function(i, entry) {
events.push({
id: entry.id,
title: entry.summary || '', // must allow default to blank, if it's not set it doesn't exist in the json and will error here
start: entry.start.dateTime || entry.start.date,
end: entry.end.dateTime || entry.start.date, // because end.date may be the next day, cause a '2-all-day' event, we use start.date here.
url: entry.htmlLink,
location: entry.location || '', // must allow default to blank, if it's not set it doesn't exist in the json and will error here
description: entry.description || '' // must allow default to blank, if it's not set it doesn't exist in the json and will error here
});
});
}
var args = [events].concat(Array.prototype.slice.call(arguments, 1));
var res = applyAll(success, this, args);
if ($.isArray(res)) {
return res;
}
return events;
}
});
}
});
To fix comment out the Google Holiday feed if you are using it. That fixed it for us. Evidently they are having feed issues. That is the only feed from Google I use, so other Google feeds may be impacted also.
Version 2 of the API was deprecated today.

Loop displaying undefined and I can't see where I've set it wrong

I'm looping through data from a .net web service through jsonp. Similar code works elsewhere but I can't see where i've gone wrong here.
The data is retreived through:
if (pageId === 'alerts') {
var Username = localStorage.getItem("Username");
var SessionKey = localStorage.getItem("SessionID");
console.log(Username);
console.log(SessionKey);
$.mobile.loading( 'show', { theme: "b", text: "Loading", textonly: false});
$.ajax({
crossDomain: true,
contentType: "application/json; charset=utf-8",
url: "http://redacted/GetData.asmx/GetLostAnimals",
data: {Username: Username, SessionKey: SessionKey },
dataType: "jsonp",
success: myAlerts
});
}
var lostSelectedPet = 0;
function myAlerts(data)
{
$("#alertsListMissingPets").empty();
$.mobile.loading( 'hide', { theme: "b", text: "Loading", textonly: false});
$.each(data, function(index) {
console.log(data[index].LostDate)
$("#alertsListMissingPets").append(" <li>"+ data[index].AnimalKey + " <span class=\"ui-li-count\">12</span></li>");
});
$("#alertsListMissingPets").listview('refresh');
}
$(document).on('click', '#alertsListMissingPets li a', function(){
localStorage.setItem("lostSelectedPet", $(this).attr('data-custom'));
editingId = $(this).attr('data-custom');
});
The json returned is like:
callback(
{
AnimalKey: "f152e1c6baca181d9f3ca1f18c91cc41f23fc122545d9c8bff9f4cb2ea449874",
LostDate: "11/06/2014 16:14:19",
FoundDate: "",
LostKey: "7560733274a7ca2ec43a85fcb9abd345fdc876acffac2b75ace7946035122fbd",
Resp: "OK"
}
)
However, this returns - It shows 5 items but theres only one result, the json above is the full response.
You are not looping over an array, you are looping over an object. You have 5 keys in the object, hence why there is 5 rows in the output.
Change the response to be an array.
callback(
[{ //<-- added [
AnimalKey: "f152e1c6baca181d9f3ca1f18c91cc41f23fc122545d9c8bff9f4cb2ea449874",
LostDate: "11/06/2014 16:14:19",
FoundDate: "",
LostKey: "7560733274a7ca2ec43a85fcb9abd345fdc876acffac2b75ace7946035122fbd",
Resp: "OK"
}] //<-- added ]
)

Highscore with jQuery.ajax: How to Initialize / Scope Issue

I'm quite a newbie concerning JS, so this may be a stupid question...
I try to do a Highscore Master/Detail chart (see sample http://jsfiddle.net/VhqaQ/). The data array should be filled with a jQuery.ajax call:
$(function () {
var masterChart,
detailChart,
data=[],
chatter=[],
indizies=[];
$(document).ready(function() {
$.ajax({
url: 'index.php',
data: 'type=1363435001',
dataType: 'json',
success: function(json) {
data = json.range;
scatter = json.scatter;
indizies = json.indizies;
},
error: function (xhr, status, error) {
alert('Status: ' + status +' Error: ' + error);
}
});
// create the master chart
function createMaster() {
masterChart = new Highcharts.Chart({
.......
series: [{
type: 'columnrange',
name: 'Intervall',
pointInterval: 1,
pointStart: 0,
data: data
}],
});
}
........
createMaster();
});
});
But like this the chart stays empty. Is this a scope issue for the data array? Or is data not initialized yet when new Highcharts.Chart( ...) is called?
I tested the ajax part - data is filled properly. So this is not the issue...
Maybe I should put the ajax call somewhere else?
Call createMaster() in the callback of your $.ajax call and pass it the data.
You are currently assuming that at initialization of the ajax call that the data has been returned, which most likely not the case. Placing the function call inside of the callback ensure that your data is present.
$.ajax({
url: 'index.php',
data: 'type=1363435001',
dataType: 'json',
success: function(json) {
data = json.range;
scatter = json.scatter;
indizies = json.indizies;
createMaster(data);
},
error: function (xhr, status, error) {
alert('Status: ' + status +' Error: ' + error);
}
});
// create the master chart
function createMaster(data) {
masterChart = new Highcharts.Chart({
.......
series: [{
type: 'columnrange',
name: 'Intervall',
pointInterval: 1,
pointStart: 0,
data: data
}],
});
}

Categories