0

I am trying to customize a SharePoint 2013 calendar. When tried with jQuery, getting the below error. Any help is appreciated.

    <script src="/sites/it-HongKong/Scripts/jquery-1.7.2.min.js"></script>
<script type="text/javascript">

  _spBodyOnLoadFunctionNames.push('WaitForCalendarToLoad');



function WaitForCalendarToLoad() {


    // we will slightly rewrite this existing function as defined originally in SP.UI.ApplicationPages.Calendar.debug.js
    var pwold$4b= SP.UI.ApplicationPages.CalendarNotify.$4a;
 SP.UI.ApplicationPages.CalendarNotify.$4a = function () {
        pwold$4b();

        test();

    }
}
function test()
{

var divText = $('.ms-acal-sdiv').val();
var b ="CST";
var position = 5;
var txt = [divText.slice(0, position), b, divText.slice(position)].join('');
$(".ms-acal-sdiv").text(txt);
alert(divText);

}</script> 
1

Whenever you see variables or functions in SharePoint JavaScript with weird names like $4a, that's a transpiled or obfuscated item. In general, that means that Microsoft considers the variable or function to be private.

The algorithm for generating these weird identifiers, generates different numbers for the same identifier as the source code changes. So a service pack upgrade, or certainly a major version upgrade is going to change many of these weird identifiers. So if you're going to do customization based on these 'private' variables/functions, you have to be aware that you'll need to retest them, and possibly fix them, when you upgrade SharePoint.

That's the theory. Now in concrete practice, the function:

SP.UI.ApplicationPages.CalendarNotify.$4a

was defined in SharePoint 2010. As of Service Pack 1, it changed to:

SP.UI.ApplicationPages.CalendarNotify.$4b

Ref: Mike Smith's Tech Training Notes SharePoint, PowerShell and .Net!

Also, in 2013 Microsoft introduced Scripts on Demand (SOD). As a result, you need to switch from using _spBodyOnLoadFunctionNames to using SP.SOD.executeOrDelayUntilScriptLoaded to delay execution until the CalendarNotify instance has been initialized.

What you see people do a lot to try to get around this is stuff like:

SP.SOD.executeOrDelayUntilScriptLoaded(function () {
    if (SP.UI.ApplicationPages.CalendarNotify.$4a) {
        var OldCalendarNotify = SP.UI.ApplicationPages.CalendarNotify.$4a;
        SP.UI.ApplicationPages.CalendarNotify.$4a = function () {
            OldCalendarNotify();
            // do your extra stuff here
        }
    }
    if (SP.UI.ApplicationPages.CalendarNotify.$4b) {
        var OldCalendarNotify = SP.UI.ApplicationPages.CalendarNotify.$4b;
        SP.UI.ApplicationPages.CalendarNotify.$4a = function () {
            OldCalendarNotify();
            // do your extra stuff here
        }
    }
}, "SP.UI.ApplicationPages.Calendar.js");

Ref: Getting an error 'CalendarNotify' as null or undefined in the code at SP.UI.ApplicationPages.CalendarNotify line in SharePoint 2013 after migration from 2010

That could probably be refactored to be a bit less messy, but it works. Something like:

SP.SOD.executeOrDelayUntilScriptLoaded(function () {
    function MyNotify(originalNotify) {
        originalNotify();
        // do your extra stuff here
    }

    if (SP.UI.ApplicationPages.CalendarNotify.$4a) {
        MyNotify(SP.UI.ApplicationPages.CalendarNotify.$4a);
    }
    if (SP.UI.ApplicationPages.CalendarNotify.$4b) {
        MyNotify(SP.UI.ApplicationPages.CalendarNotify.$4b);
    }
}, "SP.UI.ApplicationPages.Calendar.js");

That seems a bit nicer, but please note: I do not have access to 2013 to test it as I'm writing this, so I haven't tested this myself and I don't know if $4b is what you need or if it's changed to something else now. It also might depend on what service pack you're up to.

But I've seen examples using the code above as late as 2015, so maybe it hasn't changed in some time. You'll just have to play around with it some and see what works.

Ref: SP.UI.ApplicationPages.CalendarNotify.$4a property not recognized in SharePoint 2013

  • I have tried that. Still, getting the same error. – Jeevana Mar 14 at 19:23
  • My bad, you also need to use SP.SOD.executeOrDelayUntilScriptLoaded to make sure you're code runs after SP.UI.ApplicationPages.Calendar.js gets loaded. I've updated my code to do that, and added a reference. – Joe McShea Mar 14 at 19:30
  • After adding that delay, you no longer need to use _spBodyOnLoadFunctionNames to delay your code. It doesn't work right in 2013 anyway for this particular case. – Joe McShea Mar 14 at 19:31
  • I have tried and it is also not working. Thanks for helping. – Jeevana Mar 14 at 20:53
  • Is it not working in the same way? (i.e. SP.UI.ApplicationPages.CalendarNotify is null). I've taken this about as far as I can without being able to run/test the code. I'll try setup an environment where I can run it and see if I can figure it out. – Joe McShea Mar 15 at 14:15
1

This is the working solution.

 <script src="https://code.jquery.com/jquery-1.12.4.min.js" type="text/javascript"></script>
<script type="text/javascript">
SP.SOD.executeOrDelayUntilScriptLoaded(function () {

    //Week or Day Calendar View
    SP.UI.ApplicationPages.DetailCalendarView.prototype.renderGrids_Old = 
        SP.UI.ApplicationPages.DetailCalendarView.prototype.renderGrids;
    SP.UI.ApplicationPages.DetailCalendarView.prototype.renderGrids = 
        function SP_UI_ApplicationPages_DetailCalendarView$renderGrids($p0) {
        this.renderGrids_Old($p0);

        onCalendarGridsRendered();
    };

    //Month Calendar View
    SP.UI.ApplicationPages.SummaryCalendarView.prototype.renderGrids_Old = 
        SP.UI.ApplicationPages.SummaryCalendarView.prototype.renderGrids;
    SP.UI.ApplicationPages.SummaryCalendarView.prototype.renderGrids = 
        function SP_UI_ApplicationPages_SummaryCalendarView$renderGrids($p0) {
        this.renderGrids_Old($p0);
        onCalendarGridsRendered();
    };
    //Resize Calendar
    SP.UI.ApplicationPages.CalendarStateHandler.prototype.parentResized_Old = 
        SP.UI.ApplicationPages.CalendarStateHandler.prototype.parentResized;
    SP.UI.ApplicationPages.CalendarStateHandler.prototype.parentResized = 
        function SP_UI_ApplicationPages_CalendarStateHandler$parentResized() {
        this.parentResized_Old();

        onCalendarResized();
    };
}, "SP.UI.ApplicationPages.Calendar.js");

function onCalendarGridsRendered(){
    setTimeout(function () { 
        getCalendarEventText();
    }, 100);
}

function onCalendarResized(){
    setTimeout(function () { 
        //Add your functionality here
    }, 100);
}

// hook into the existing SharePoint calendar load function.
function getCalendarEventText(){
    $('.ms-acal-sdiv').each(function(){
        console.log($(this).text());
    });
}
</script>

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.