Reputation: 2665
If you go into your SO profile and click on 'days visited', you see a handy jQuery datepicker with the days you've visited the site shaded a luscious green. I'm trying my hand at something similar, and started by picking apart SO's implementation. I'm stuck on figuring out how they were able to format and return the visited dates in the specific JSON format they used. Here's a copy of mine (you can find similar by inspecting the source of that page):
var visited = {2009:{5:{28:1,29:1},6:{3:1,4:1,5:1,7:1,8:1,9:1,10:1,11:1,12:1,13:1,14:1,15:1,16:1,17:1,19:1,20:1,21:1,22:1,23:1,24:1,25:1,27:1,29:1,30:1},7:{1:1,2:1,3:1,4:1,5:1,6:1,7:1,8:1,9:1,10:1,11:1,12:1,13:1,14:1,15:1,16:1,18:1,20:1,21:1,22:1,23:1,24:1,26:1,27:1,28:1,29:1,30:1,31:1},8:{2:1,3:1,4:1,5:1,6:1,7:1,11:1,12:1,13:1,17:1,20:1,24:1,25:1,27:1,28:1},9:{9:1,10:1,15:1,23:1,24:1},10:{1:1,5:1,7:1,8:1,9:1,12:1,13:1,20:1,21:1,22:1,27:1,28:1,30:1},11:{5:1,9:1,10:1,16:1,17:1,24:1,25:1,26:1,30:1},12:{2:1,7:1,8:1,9:1,11:1,12:1,13:1,14:1,15:1,16:1,17:1,18:1,21:1,22:1,23:1,28:1,30:1}},2010:{1:{5:1,8:1,11:1,12:1,13:1,14:1,15:1,18:1,19:1,20:1,21:1,26:1,27:1,28:1},2:{3:1,10:1,17:1,22:1,23:1,26:1},3:{1:1,2:1,3:1,5:1,8:1},4:{8:1,9:1,13:1,19:1,20:1,21:1,22:1,26:1,28:1,29:1},5:{3:1,4:1,5:1,6:1,7:1,11:1,12:1,17:1,28:1},6:{2:1,4:1,7:1,8:1,9:1,10:1,14:1,15:1,16:1,17:1,18:1,21:1,23:1,25:1},7:{7:1,8:1,9:1,12:1,21:1,22:1,23:1,28:1,29:1},8:{2:1,3:1,4:1,5:1,9:1,10:1,11:1,16:1,17:1,18:1,19:1,20:1,25:1,26:1,29:1,30:1,31:1},9:{1:1,8:1},10:{6:1,11:1,15:1,21:1,26:1,27:1,28:1},11:{3:1,4:1,8:1,11:1,15:1,16:1,17:1,19:1,20:1,21:1,23:1,30:1},12:{1:1,2:1,13:1,14:1,15:1,16:1,17:1,20:1,22:1,23:1,28:1}},2011:{1:{3:1,5:1,6:1,7:1,12:1,14:1,18:1,20:1,21:1,25:1,26:1,27:1,28:1,31:1},2:{1:1,2:1,3:1,6:1,7:1,8:1,9:1,10:1,11:1}}};
It's basically an array: [year][month][day]. I'm failing to send back data in that format though and was wondering if anyone (perhaps one of the SO crew) had any insight.
Hope no one thinks I'm ripping off SO with this question. I'm truly just curious how they did it.
EDIT: To clarify, I'm asking what the controller action might look like if I had a grip of .NET DateTime objects and wanted to return JSON in the format mentioned.
My test controller method looks like:
[HttpPost]
public JsonResult GetDates(int id)
{
var model = BaseRepository.FindById(id);
testDates = new DateTime[] { DateTime.Today, DateTime.Today.AddDays(1) };
return Json(testDates);
}
And when I call it via AJAX with:
$.ajax({
type: 'POST',
url: '<%= Url.Action("ClosedDates", "Venue", new { id = Model.Id }) %>',
dataType: 'json',
success: function (data) { alert(data); }
});
The alert shows me the expected list of dates, but in .NET date format. I'm not sure if I should be massaging the data in the controller, or in the callback on the client.
EDIT 2
Ok, so maybe the use of that array will help make more sense of this. Again, riffing off SO's implementation (note how the beforeShowDay function parses the array for the current date being evaluated):
var visited = { 2009: { 5: { 28: 1, 29: 1 }, 6: { 3: 1, 4: 1, 5: 1, 7: 1, 8: 1, 9: 1, 10: 1, 11: 1, 12: 1, 13: 1, 14: 1, 15: 1, 16: 1, 17: 1, 19: 1, 20: 1, 21: 1, 22: 1, 23: 1, 24: 1, 25: 1, 27: 1, 29: 1, 30: 1 }, 7: { 1: 1, 2: 1, 3: 1, 4: 1, 5: 1, 6: 1, 7: 1, 8: 1, 9: 1, 10: 1, 11: 1, 12: 1, 13: 1, 14: 1, 15: 1, 16: 1, 18: 1, 20: 1, 21: 1, 22: 1, 23: 1, 24: 1, 26: 1, 27: 1, 28: 1, 29: 1, 30: 1, 31: 1 }, 8: { 2: 1, 3: 1, 4: 1, 5: 1, 6: 1, 7: 1, 11: 1, 12: 1, 13: 1, 17: 1, 20: 1, 24: 1, 25: 1, 27: 1, 28: 1 }, 9: { 9: 1, 10: 1, 15: 1, 23: 1, 24: 1 }, 10: { 1: 1, 5: 1, 7: 1, 8: 1, 9: 1, 12: 1, 13: 1, 20: 1, 21: 1, 22: 1, 27: 1, 28: 1, 30: 1 }, 11: { 5: 1, 9: 1, 10: 1, 16: 1, 17: 1, 24: 1, 25: 1, 26: 1, 30: 1 }, 12: { 2: 1, 7: 1, 8: 1, 9: 1, 11: 1, 12: 1, 13: 1, 14: 1, 15: 1, 16: 1, 17: 1, 18: 1, 21: 1, 22: 1, 23: 1, 28: 1, 30: 1} }, 2010: { 1: { 5: 1, 8: 1, 11: 1, 12: 1, 13: 1, 14: 1, 15: 1, 18: 1, 19: 1, 20: 1, 21: 1, 26: 1, 27: 1, 28: 1 }, 2: { 3: 1, 10: 1, 17: 1, 22: 1, 23: 1, 26: 1 }, 3: { 1: 1, 2: 1, 3: 1, 5: 1, 8: 1 }, 4: { 8: 1, 9: 1, 13: 1, 19: 1, 20: 1, 21: 1, 22: 1, 26: 1, 28: 1, 29: 1 }, 5: { 3: 1, 4: 1, 5: 1, 6: 1, 7: 1, 11: 1, 12: 1, 17: 1, 28: 1 }, 6: { 2: 1, 4: 1, 7: 1, 8: 1, 9: 1, 10: 1, 14: 1, 15: 1, 16: 1, 17: 1, 18: 1, 21: 1, 23: 1, 25: 1 }, 7: { 7: 1, 8: 1, 9: 1, 12: 1, 21: 1, 22: 1, 23: 1, 28: 1, 29: 1 }, 8: { 2: 1, 3: 1, 4: 1, 5: 1, 9: 1, 10: 1, 11: 1, 16: 1, 17: 1, 18: 1, 19: 1, 20: 1, 25: 1, 26: 1, 29: 1, 30: 1, 31: 1 }, 9: { 1: 1, 8: 1 }, 10: { 6: 1, 11: 1, 15: 1, 21: 1, 26: 1, 27: 1, 28: 1 }, 11: { 3: 1, 4: 1, 8: 1, 11: 1, 15: 1, 16: 1, 17: 1, 19: 1, 20: 1, 21: 1, 23: 1, 30: 1 }, 12: { 1: 1, 2: 1, 13: 1, 14: 1, 15: 1, 16: 1, 17: 1, 20: 1, 22: 1, 23: 1, 28: 1} }, 2011: { 1: { 3: 1, 5: 1, 6: 1, 7: 1, 12: 1, 14: 1, 18: 1, 20: 1, 21: 1, 25: 1, 26: 1, 27: 1, 28: 1, 31: 1 }, 2: { 1: 1, 2: 1, 3: 1, 6: 1, 7: 1, 8: 1, 9: 1, 10: 1, 11: 1}} };
$('#calendar').datepicker({
beforeShowDay: function (date) {
var y = date.getFullYear();
var m = date.getMonth() + 1;
var d = date.getDate();
var hasVisited = visited[y] && visited[y][m] && visited[y][m][d];
return [false, (hasVisited ? 'ui-state-active' : ''), (y + '-' + m + '-' + d)];
}
});
Upvotes: 1
Views: 266
Reputation: 2665
So, I used the eval method @alexl indicated, and came up with the following (I'd be open to improvement as this feels pretty dirty):
$(document).ready(function () {
$.ajax({
type: 'POST',
url: 'myurl',
data: {id: 1},
dataType: 'json',
success: function (data) {
var dates = new Array();
// eval each of the dates coming from the server
for(var i = 0; i < data.length; i++) {
dates[i] = eval('new' + data[i].replace(/\//g, ' '));
}
$('#calendar').datepicker({
beforeShowDay: function (date) {
var isBooked = false;
// look for the current datepicker date in the array
for(var i = 0; i < dates.length; i++) {
if (dates[i].valueOf() == date.valueOf())
{
isBooked = true;
break;
}
}
return [false, (isBooked ? 'ui-state-active' : ''), (date.valueOf)];
}
});
}
});
});
Upvotes: 0
Reputation: 6851
When you send a Datetime in JSON, it is parse in this format:
\/Date(1297250340000)\/
you can parse your datetime in javascript with this code:
var date = eval('new' + oData.replace(/\//g, ' '));
Where oData is your date returned by your controller in JSON.
Hope it helps
Upvotes: 0
Reputation: 3856
From my experience if you don't need to handle dates on the client like Date datatype then it's easier to send it to the client as a string.
So - convert you array of dates as DateTime to array of dates as string in format you need and send them to the client as json.
Upvotes: 0
Reputation: 861
I would create a model to cater to that call. You will have a little bit more processing on the client side, but it will be more OO and you can use JS dot notations to access each object level.
Ajax Call (I am using Razor, but you want to pass ID as a data element):
$.ajax({
type: 'POST',
url: '@Url.Action("ClosedDates", "Venue")',
data: {id: 1},
dataType: 'json',
success: function (data) { console.log({data: data}); }
});
Model:
public class DateListModel
{
public int Month { get; set; }
public List<string> Days { get; set; }
}
public class DateModel
{
public int Year { get; set; }
public List<DateListModel> DateList { get; set; }
}
Controller (with test data):
[HttpPost]
public JsonResult ClosedDates(int id)
{
var dateList2009 = new List<DateListModel> {
new DateListModel{Month =5, Days = new List<string>{"28", "29"}},
new DateListModel{Month = 6, Days = new List<string>{"3", "49", "5"}},
};
var dateList2010 = new List<DateListModel>{
new DateListModel{Month = new DateTime(2010,1,1).Month, Days = new List<string>{"5", "8", "11"}},
new DateListModel{Month = new DateTime(2010,2,1).Month, Days = new List<string>{"3", "10", "11"}},
};
var data = new List<DateModel>{
new DateModel{ Year = 2009, DateList = dateList2009},
new DateModel{ Year = 2010, DateList = dateList2010}
};
return Json(data);
}
Upvotes: 1