Invoking SPServices in SharePoint Online via App Part - Not Working in Firefox, Chrome, or Safari

Oct 30, 2015 at 4:54 PM
In SharePoint online have an app part built using SPServices to query a calendar in a SharePoint host web. I'm using SPServices GetListItems. This is my only choice because through SPServices the query can include the <QueryOptions> element to specify that SharePoint will expand recurring events - this is not possible in the REST or CSOM (JSOM) methods.

The web part works perfectly in Internet Explorer, but no data is returned at all in Chrome, Firefox, and Safari browsers.

It appears that it works in IE through its "trusted sites" feature, which apparently causes CORS restrictions to be lifted. But there doesn't seem to be a way to do this for the other browsers. CORS is a factor here because the app runs in an app web whose root URL is different than that of the host web.

I have proven this to be the case since if I construct the same query and embed it in the host web via a script editor web part, the query works in all browsers. But in doing so I lose the flexibility of using web part properties to change the calendar list against which I'm running the query (a requested feature from my client).

I've tried as many things as I can think of, notably those covered in Solving cross-domain problems in apps for SharePoint - MSDN , but I'm getting nowhere. it seems that the SharePoint Cross Domain Library (CDL) handles this sort of thing for REST and JSOM calls.

Does anyone know how I could either use the CDL or something else in combination with SPServices?

Here is a sample of the code I'm using:
            $.support.cors = true;
            $().SPServices({
                operation: "GetListItems",
                webURL: <-my-host-web-url->,
                async: false,
                listName: "Calendar",
                CAMLViewFields: "<ViewFields>" +
                        "<FieldRef Name='Title' />" +
                        "<FieldRef Name='EventDate' />" +
                        "<FieldRef Name='EndDate' />" +
                        "<FieldRef Name='Location' />" +
                        "<FieldRef Name='Description' />" +
                        "<FieldRef Name='FileDirRef' />" +
                        "<FieldRef Name='fRecurrence' />" +
                        "<FieldRef Name='RecurrenceData' />" +
                        "<FieldRef Name='RecurrenceID' />" +
                        "<FieldRef Name='fAllDayEvent' />" +
                    "</ViewFields>",
                CAMLQuery: "<Query>" +
                        "<Where>" +
                            "<DateRangesOverlap>" +
                                "<FieldRef Name='EventDate' />" +
                                "<FieldRef Name='EndDate' />" +
                                "<FieldRef Name='RecurrenceID' />" +
                                "<Value Type='DateTime' IncludeTimeValue='TRUE'>" +
                                    "<Month />" +
                                "</Value>" +
                            "</DateRangesOverlap>" +
                        "</Where>" +
                        "<OrderBy>" +
                            "<FieldRef Name='EventDate' />" +
                        "</OrderBy>" +
                    "</Query>",
                CAMLQueryOptions: "<QueryOptions>" +
                        "<CalendarDate>" + <-current-date-UTC-> + "</CalendarDate>" +
                        "<RecurrencePatternXMLVersion>v3</RecurrencePatternXMLVersion>" +
                        "<ExpandRecurrence>TRUE</ExpandRecurrence>" +
                    "</QueryOptions>",
                completefunc: function (xData, Status) {
                    $(xData.responseXML).SPFilterNode("z:row").each(function () {
                        var $node = $(this),
                            fADE = $node.attr("ows_fAllDayEvent") || 0,
                            thisADE = (fADE == 0),
                            thisID = $node.attr("ows_ID"),
                            sepID = thisID.indexOf(';#'),
                            thisStartDate = $node.attr("ows_EventDate"),
                            thisEndDate = $node.attr("ows_EndDate"),
                            thisTitle = $node.attr("ows_Title"),
                            thisRecurrenceID = $node.attr("ows_RecurrenceID"),
                            thisRecurrence = $node.attr("ows_fRecurrence"),
                            thisDesc = $node.attr("ows_Description");
                        if (sepID != -1) thisID = thisID.substring(0, sepID);
                        var thisUrl = "DispForm.aspx?ID=" + thisID,
                            thisClass = thisTitle.replace(" ", "").substr(0, 10).replace(",", "").replace(" ", "") + thisID,
                            thisRD = $node.attr("ows_RecurrenceData");
                        events.push({
                            title: thisTitle,
                            start: $node.attr("ows_EventDate"),
                            end: $node.attr("ows_EndDate"),
                            recurrenceID: thisRecurrenceID,
                            allDay: thisADE,
                            listUrl: $node.attr("ows_FileDirRef"),
                            url: thisUrl,
                            description: $(thisDesc).text()
                        });
                    });
                }
            });