Checking for calendar double-booking in SP 2013

Feb 15 at 1:14 PM
Edited Feb 16 at 8:01 AM
Hi. I'm checking for calendar double-booking in SP 2013. Here's a snippit of the code I'm using inside inside a script editor:

function PreSaveAction() {

var doublebook =false;

$().SPServices({
webUrl: "xxx",
operation: "GetListItems",
async: true,
listName: "xxx",
CAMLQuery: "<Query><Where><Eq><FieldRef Name='EventDate' IncludeTimeValue='TRUE' /><Value Type='DateTime' IncludeTimeValue='TRUE'>2016-02-04T12:00:00Z</Value></Eq></Where></Query>",
completefunc: function (xData, Status) {
  $(xData.responseXML).SPFilterNode("z:row").each(function() {
    doublebook =true;
  });
}
});

if (doublebook ==true) {
return false;
} else {
return true;
}

}

When I'm debugging, the:

if (doublebook ==true) {
return false;
} else {
return true;
}

is getting executed before the $(xData.responseXML).SPFilterNode("z:row").each(function() { part of the code and is always returning a false.

What could the problem be?

Thanks.

Mark
Feb 17 at 7:05 PM
I think the return statements need to be inside the completefunc: function. Or maybe try asynch false. Or have the return statements inside a .done block after converting the GetListItems pull to a deferred promise.
Coordinator
Feb 24 at 2:50 PM
Yes, you're making the cal asynchronously, but then you're not waiting for it to finish.

You have two basic options. Do the call asynchronously and do all the processing in the completefunc:
function PreSaveAction() {

    var doublebook = false;

    $().SPServices({
        webUrl: "xxx",
        operation: "GetListItems",
        async: false,
        listName: "xxx",
        CAMLQuery: "<Query><Where><Eq><FieldRef Name='EventDate' IncludeTimeValue='TRUE' /><Value Type='DateTime' IncludeTimeValue='TRUE'>2016-02-04T12:00:00Z</Value></Eq></Where></Query>",
        completefunc: function(xData, Status) {
            $(xData.responseXML).SPFilterNode("z:row").each(function() {
                doublebook = true;
            });

            if (doublebook == true) {
                return false;
            } else {
                return true;
            }
        }
    });

}
Or use a promise and act when it is complete:
function PreSaveAction() {

    var doublebook = false;
    var doublebooked = $.Deferred();

    var p = $().SPServices({
        webUrl: "xxx",
        operation: "GetListItems",
        async: true,
        listName: "xxx",
        CAMLQuery: "<Query><Where><Eq><FieldRef Name='EventDate' IncludeTimeValue='TRUE' /><Value Type='DateTime' IncludeTimeValue='TRUE'>2016-02-04T12:00:00Z</Value></Eq></Where></Query>",
        completefunc: function(xData, Status) {

        }
    });

    p.then(function() {

        $(p.responseXML).SPFilterNode("z:row").each(function() {
            doublebook = true;
        });

        if (doublebook == true) {
            doublebooked.resolveWith(false);
        } else {
            doublebooked.resolveWith(true);
        }

    });

    return doublebooked.promise();

}
Since you are in the PreSaveAction, I'm not sure the latter will work, because the calling function need to understand that it is getting a promise back.

M.