Oh my god. It's full of code!

jQuery, Apex, and Visualforce – 3 Continuing the madness

So we are back, to continue the calendar project. I know it’s been a while since I wrote, and to be honest my memory is a bit foggy on how exactly I did everything, so please excuse if some things seem a bis disjointed. Please feel free to ask any questions in the comments.

If I recall the last thing we were working on was getting the index page set up, then writing the data fetching components. One thing you may notice about my code is that I include a fair amount of the CSS and javascript in the document instead of linking to it like you would normally see a well developed page do. The reasons for this are simple, if I wanted them to be external, they would probably have to be a static resource. To modify static resources you need to download them, modify them, and upload them again. That is kind of a pain, and in this project, I don’t see any of this code being terribly re-usable, so I simplify my life by including more stuff in the index page than you might normally. It also cuts down on HTTP requests, theoretically increasing page load speed. In the end though, you can structure your code in whatever way makes sense to you.

If you downloaded the calendar project from the first post (which I hope you did) and you are looking at my index file, you are probably seeing a lot of javascript functions, and saying “what the hell is this crap?”. I’m not going to explain in great detail, cause you probably don’t really care, but just to gloss over here is a basic breakdown.

The first part in the onReady function basically says, when the page is loaded, create the calendar. Most of the code there is pretty much straight from the full calendar website. You will notice this line as well

events: “http://fpitesters.force.com/FPIPortal/opscalendarjsonresponder”,

That one is important. That line tells the fullCalendar where to get the JSON data that will be populating the calendar itself. This could be a text file, or a dynamic page. Of course since we want it dynamic and I am awesome, that is a dynamic component that generates JSON on the fly. I’ll show ya how that is built a little later. Next you run into a block of code for handling the loading. That basically says, “if the data is loading, use the lighbox plugin to make a fancy little loading modular window”. Next comes the event renderer. One of the cool features I added to the calendar, is that when you click an event, a neat little draggable popup is created that has info about the event. To do this, I create a hidden div for every event and the data contained for it. This function says, for every event you render (all events in the month) create a new div and make it draggable (anything mentioning drs in my code is for the draggable windows). It assigns the draggable window class, creates the toolbar and appends it to the body.

Next is the event click function. That just says, when a person clicks an event, launch the showmessage function. Lastly there is a call to the updateVisible function. Since our grid supports filtering, I quickly call to the updateVisible to make sure only things that should be visible on load (controlled by checkboxes) is in fact shown. After that are the showMessage and hideMessage functions. Those are simply the functions that control the showing and hiding of the extra info divs that appear when you click an event. There is where you can customize the content of those windows and make them say whatever you want. When the showmessage function is called, it gets a full copy of the even object, so all event info is accessible by using event.datapoint. So anything that is included in your JSON that created the even in the first place is available by using the event object.

After that is a rollover image function. I can’t remember why that is there. It might be useless, a failed and forgotten experiment. I don’t know. It looks like it changes the given image to another given image. Just a simple rollover image changer.

The next function is kind of a biggie, it is the filtering engine. Here is where you can probably really see that I suck at programming. I am sure this is fairly inefficient, violates several programming laws, and may in fact have insulted your mother at some point. It does however at least work. Based on the values below the calender and the status checkboxes it decides what events should be shown. Any events that should not be shown are then hidden using jQuery animations. Same for showing matching events.

The last javascript function is the jump feature. It allows you to enter any date and using the full calender API. Nothing fancy here.

Now we get into the body code for this page. The first part is the loading div, the little light box modular window thing that pops up when data is loading. It has a fancy little ajax loading animation and just adds some polish to the the app. After that is a noticeDiv, you can see it has some of code for the draggable windows, I am not entirely sure why that thing is there, again may be leftover code. I should probably try removing it. Then there is the div where the calendar actually loads. Below that are my form controls for data filtering, refreshing, and jumping to a different date. And that’s it, that is all the code for the main display page. The only other things there are is the components for fetching and returning the data to the calendar.

Now lets talk about getting the data into the calendar. Fullcalender uses JSON (javascript simple object notation). If you aren’t familiar with it, take XML make it a lot simpler, and that’s JSON. Just a data interchange format. So the question is, how do we take salesforce data, and turn it into JSON for the calendar? Sounds kinda crazy right? Well actually it isn’t too bad. The method I have devised is fairly straight forward. Have a web service that actually creates the JSON. It queries the requested salesforce objects, pulls the requested fields, and converts the data into JSON. Then you have another visual force page that invokes that webservice, passing the required info, and simple prints the generated JSON on the screen.

So lets start working on our back end component that will actually create the JSON for us. I’ll preface this by saying there is in fact a full blown JSON component that you can download and use to translate SF data into JSON. However, in my experience it didn’t work quite right. It did not generate valid JSON, didn’t know how to handle boolean values, and in general just didn’t agree with the way FullCalendar wanted things done. So I use it to do a bulk of the work, but then do some post formatting, you’ll see what I mean.

Make a new class, call it getJsonEvents. Copy the code from the download and put it in there. I won’t post here cause it’s kinda long and crummy to look at. Again, I’ll just kinda walk you through my code roughly and explain how it is working.

First off we import the JSON object and have this weird {get;set} command in there. Not sure what that does, but it’s important. Next create the getEvents method. It doesn’t take any parameters directly because all the info it needs will be passed into the URL of the calling page. So we take all the url parameters (the start date and end date, and save them into a map. Oh yeah, forgot to mention fullCalender when it requests data, only requests the data for the view you are currently seeing. So it contacts the page you specify in the “events:” attribute and passes two parameters; start and end. Those are the starting date, and ending date in unix epoch time format (number of seconds since 1970 or something like that). So you click March in fullCalender, it contacts your JSON responder page and passes the two times stamps. The receiving page takes those times stamps and passes them into this function we are writing now. Make sense? So anyway, the next few lines are some conversions to get that unix timestamp format turned into a valid salesforce date we can filter against. Again, my code for that probably isn’t terribly efficient (3 lines per conversion with an intermediary variable) but it works.

Moving on we run in my records query. This query basically fetches the data we want from salesforce using the start and end dates we created comparing them to the start and end dates on the objects. Then we create a new list that we will store the JSON values in. Loop over the result set, and being populating our JSON string. Every line you see that looks like this

cjson.putOpt('"allDay"', new JSONObject.value(c.All_Day__c));

is just adding another key-value pair to the JSON string. Don’t let it confuse you, its just taking a value from the query, and sticking it into the JSON string. c is the reference to this row in the query that we are looping over, and the JSONObject.value() is just some magical function that puts the data in the string. I dunno, its a little weird, and seems over engineered to me, but I didn’t write that component (I did write my own query to JSON parser which I’ll probably post later, I like it better personally). So anyway, we populate our JSON string and pack it all up. There are some debugging lines for…. helping to debug, you can remove them if you want. There is also some handling for if no records are returned for a given query (no events for a provided timespan), nothing fancy there. Some error handling in case stuff blows up (ugly hackish error handling, but it does the job).

Then we break into the last function, that does some of the extra parsing I was talking about and actually returns the data. I don’t really know why class is composed of two methods to be honest. Seems to me it could be just one, but I tried consolidating them before and things went to hell. While I did create this process, I build on a framework I found elsewhere, and the two method/function style is the way they had working so I’ve stuck with it. Anywho, you’ll see some replace statements that make the JSON valid (at least for fullcalendar) and then simple returns it. That’s it, that is the whole back end component. Now you just make another apex page, call it whatever you want (make sure it is the same name as the events: attribute in your full calendar config) and put this code in it.

<apex:page controller="getJsonEvents"  action="{!getEvents}"
contentType="application/x-JavaScript; charset=utf-8" showHeader="false" standardStylesheets="false" sidebar="false">
{!result}
</apex:page>

We just have to set up security for these two new things. Under the listing of apex pages, click security next to your new page. Add all the profiles to the enabled profiles area. Probably overkill, but I don’t need to hide this app from anyone, so it doesn’t bother me, You can refine your security as required. Go to sites and find your Salesforce site.Hit public access settings. Make sure your class and visual force pages are listed under “enabled Apex class access” and “enabled visualforce page access” respectively. Also make sure the account your site is using has access to events and any related data. With all that adjusted, you should now be able to access your JSON responder page. Your calendar may even be working at this point as well. Now we just need some extra polish and finishing touches.

You now have an Apex page that can be called, given a start and end time in unix epoch time format, and it will return event data in a JSON string. It probably won’t load now though due to security issues. Next time we’ll talk about Salesforce site security and how to adjust it.

EDIT: New download link http://xerointeractive.com/calendar.zip

19 responses

  1. ssirikon

    Hello,

    This article is really great! I have been looking to work with a calendar that can pull data on to calendar from Salesforce custom objects. This article is a wonderful resource to me. I tried looking for downloading the project as a whole but, I did not find the link to it. Can you please share? I couldn’t find the custom controller class ‘getJsonEvents’ etc.

    July 29, 2010 at 11:53 am

  2. Oh sure, hang on. I’ll rehost it somewhere.

    July 30, 2010 at 4:54 pm

  3. Anonymous

    Thank you! I have downloaded the files. Have to go through them. I will get back to you if I have more questions. :)Thanks again!!

    July 31, 2010 at 3:23 pm

  4. TonyE

    I’m interested in this calendar also as we are having questions about how to track multiple resources on various projects. I tried to download the code from the link above, but I receive an IP Address error. I’ve also had another programmer attempt to download it and received the same issue. Would you be able to email me the zip file to review?

    August 6, 2010 at 1:37 pm

  5. Tony, I have emailed you the files. sorry for all the problems guys, I can’t seem to find a reliable file host. If anyone else wants them, please feel free to email me and I’ll get back to you very soon. Trust me, my email volume isn’t terribly high haha.

    August 6, 2010 at 4:52 pm

  6. Andrew

    Question.

    This works just fine when published out to sites, however when viewing the page within SF example:https://cs3.salesforce.com/apex/%5Bmypage%5D it doesn’t seem to be calling the responder page(events: “Training_CalendarJsonResponder”,) any ideas?

    October 1, 2010 at 5:22 pm

    • Hmm, could be any number of things. The first thing I would check is security, make sure the running user has access to all required resources. Not sure if that even makes sense, but I know sites run under one profile, and if running within the Salesforce instance it runs under the running user, I think.

      The other thing, maybe check for any relative paths. See if maybe a reference got broke somewhere. I’d crack open firebug and the javascript error console and try to pick it apart that way.

      October 1, 2010 at 5:26 pm

      • Andrew

        Ok. so it seems if you have development mode set in your profile the inline IDE prevents the responder from being called. fought that for 2 hours.

        Thanks for your help
        Andrew

        October 1, 2010 at 7:46 pm

  7. Wow I would not have guessed Andrew, that’s pretty amazing. Glad you figured it out. Nice find, hopefully you save someone else a ton of time/debugging.

    October 1, 2010 at 7:48 pm

  8. Kevin

    Hi,
    This is great work!! I am interested in the calendar but I am unable to download the files.
    Would you be able to mail it to me.

    Regatds

    November 19, 2010 at 11:34 pm

  9. sreekumar

    please email me the files too..

    February 21, 2011 at 8:31 pm

    • Yup, I’ll get them too you shortly.

      February 21, 2011 at 8:42 pm

  10. Vishal

    hey, a wonderful article.
    specially for a i-hate-programming kinda programmer!
    i m working on a college project related to this calendar.
    but i m unable to download the files.
    can u kindly mail me the files.
    thanks!

    April 14, 2011 at 10:18 am

  11. Okay everyone, got the calendar hosted at a new place. Use http://xerointeractive.com/calendar.zip
    hopefully that works for ya.

    April 14, 2011 at 4:35 pm

  12. Anonymous

    hey, the download doesn’t have any of the class files you talk about in the post. Can you post them too please?

    June 28, 2011 at 7:20 pm

    • Ah sorry about that. The download on the project page has been updated. Let me know if I forgot anything else XD

      June 28, 2011 at 7:32 pm

  13. Anonymous

    got it. thnx!

    June 29, 2011 at 6:03 am

  14. Sony

    hey, I wanted to write a piece of code in my controller which takes start date, end date and the name from the VF page using jquery and store it in my Custom object and makes the time slot for that time “Block”. How can I achieve this, please let me know. Thanx. 🙂

    July 24, 2011 at 5:30 am

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s