Friday, February 15, 2013

Fixing the Calendar with Javascript

This is about fixing Microsoft products with Javascript, the duct tape of the internet. What follows is a script written because someone needed to print a calendar, and Microsoft's custom Calendar Javascript generates a table, totally unrelated to any element of event handling, then sets inline values for each programatically-generated event item, which therefore cannot have their positioning overriden for print by any kind of @media command.

Needless to say, this causes the type of screaming that results in a new throat and an expense account at the state-run liquor outlet, as well as a strong interest in the opium trade, however! We must press on.

What follows is a script that will realign event cells in a more or less default calendar webpart so that they are well-spaced for printing after the fact. Possibly the difficulty of positioning these is related to having used a CSS Reset early in styling the site, possibly it is not, either way we're hand-writing margins in the backend now.

The function of this script is to align Sharepoint's calendar rows before printing to a landscaped piece of paper out of IE7 or IE8, so, ie, a hack job that in an ideal world, so different from our own, goes nicely with an @media -print CSS command. Only some of the @media -print stuff will work - table cell backgrounds, for example, will never show up or change colour, no matter how many !important tags you use.



This is that script. It makes things look ugly, but aligns them properly when you go to print something from IE7 or IE8.

function printCal(){
$('div[class|="ms-acal-item"]').each(function(index)
    {
       var styletag=$(this).attr('style');
       var stylestemp=styletag.split(';');
       var styles={};
       var c='';
       for (var x in stylestemp) {
         c=stylestemp[x].split(':');
         styles[$.trim(c[0])]=$.trim(c[1]);
       }

var boxTop = parseInt(styles.top.substring(0,styles.top.length-2));
var moduloTop = (boxTop%23)-10; // this groups things nicely in descending rows. Row 5 is at the top.
var interval = ((boxTop-(moduloTop+10))/23)-3;
var newTop = boxTop + (interval *6) ;
if (moduloTop == 5) {
var newTop = newTop + 18; // this part is where I lost patience with doing even lightweight math.
}
else if (moduloTop == 4) {
var newTop = newTop -15;
}
else if (moduloTop == 3) {
var newTop = newTop - 30
}
else if (moduloTop == 2) {
var newTop = newTop - 50
}
else if (moduloTop == 1) {
var newTop = newTop - 70
};
$(this).css('top',newTop);
    });
}

Notes:
- The default row height is 23.
- The default interval between grouped events in rows is 68, IE: Row 1 will be 23n +68px high to begin with.

This script does, in fact, work. Problematically, it does not seem to run on the various event handlers I have been attempting to call, because it seems that IE handles javascript much more poorly than Chrome. Triggering .click(); events in Sharepoint has proven to be a challenge. A hard challenge. Full of loathing.
IE runs Calendar.js after everything, and it is insidiously difficult to get your own scripts to run last, even if you do make use of our dear companion (Dear Leader) SP.UI.ApplicationPages.CalendarNotify.$4b; .

Having taken a copy of calendar.js off the Sharepoint hive and read through it to see if there is a more appropriate event kicker around, I now speak the seven languages of the damned which will summon forth the Great Old Ones from beyond the sky. No no, I lie, it was too much to parse and I closed it. Event handlers, buttons for incorporating this and launching window.print(); after it runs, all that is forthcoming.

4 comments:

  1. I took this script and plugged it into a CEWP in SharePoint 2010 (along with the proper jquery references and javascript tags) and it doesn't do anything. Am I missing something, or do I have to also create a print.css and remove/exclude something?

    ReplyDelete
  2. Oho! I had no idea anyone was reading this. There is a followup problem:
    IE will retrigger Sharepoint's default layout JS instantly after you trigger your script. So even if you put in a button to trigger it, it simply won't show up properly.

    I have not actually been able to override the default JS handling in IE to date, partly because I got assigned other projects, and partly due to crippling depression at the state of the world. I should post an update with my current CSS and the print-order guidelines to get a good Calendar out. I have that much. Thanks for commenting.

    ReplyDelete
  3. Alex,

    That'd be fabulous. I just got finished making an enterprise level calendar in SP 2010, and you wouldn't imagine the hell I've had to endure with the SP 2010 calendar's oddities.

    I'll be watching this closely. Thanks!

    ReplyDelete
  4. Thanks Alex.
    We fixed a related alignment issue in SharePoint 2010/2013 Print-Views.
    Checkout my (German) Blog Post at http://2sicgeeks.wordpress.com/2013/12/23/sharepoint-2010-2013-kalender-monatsansichten-drucken-2/

    ReplyDelete