Download calenderitem to calendar

My first app to SharePoint is now done. Download items from a SharePoint calendar to Outlook. This is done by making a vCal-file, which is just xml and streaming it to the client. Pure javascript. The streaming part is not so easy, but thanks to https://github.com/eligrey/FileSaver.js/ I didn't have to worry about that :)

The script only let's you download your own appointments, but this can easily be removed. You have to call the page with two querystring parameters:
listid: The guid of the list
itemid: The id of the item on the list

Paste the script below to your app and add a reference to filesaver.js

CODE:
'use strict';

var user;
var hostweburl;
var appweburl;
var appContextSite;
var context = SP.ClientContext.get_current();
var hostWebListColl;
var collListItem;
var url = (window.location != window.parent.location)
        ? document.referrer
        : document.location.href;

// This code runs when the DOM is ready and creates a context object which is needed to use the SharePoint object model
$(document).ready(function () {
    appweburl = decodeURIComponent(getParameterByName("SPAppWebUrl"));
    hostweburl = decodeURIComponent(getParameterByName("SPHostUrl"));

    var scriptbase = hostweburl + "/_layouts/15/";

    $.getScript(scriptbase + "SP.Runtime.js",
        function () {
            $.getScript(scriptbase + "SP.js",
                function () { $.getScript(scriptbase + "SP.RequestExecutor.js", execCrossDomainRequest); }
            );
        }
    );
});

function getGuid() {
    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
        var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
        return v.toString(16);
    });
}

function execCrossDomainRequest(){
    context = new SP.ClientContext(appweburl);
    var factory = new SP.ProxyWebRequestExecutorFactory(appweburl);
    context.set_webRequestExecutorFactory(factory);
    appContextSite = new SP.AppContextSite(context, hostweburl);
    var hostWeb = appContextSite.get_web();
    getUserName();

};

function getUserName() {
    user = appContextSite.get_web().get_currentUser();
    context.load(user);
    context.executeQueryAsync(onGetUserSuccess, onFail);
}

function onGetUserSuccess() {
    var listId = getParameterByName('listid', url);
    var itemid = getParameterByName('itemid', url);
    if (listId == '' || itemid == '') {
        // alert('querystring parameters are missing. Both listid og itemid must be given');
        return;
    }

    var oList = appContextSite.get_web().get_lists().getById(listId);

    var camlQuery = new SP.CamlQuery();
    camlQuery.Viewfields = "<FieldRef name='Author'/><FieldRef name='Title'/><FieldRef name='EventDate'/><FieldRef name='EndDate'/><FieldRef name='Comment'/>";
    camlQuery.set_viewXml('<View><Query><Where><Eq><FieldRef Name=\'ID\'/>' +
        '<Value Type=\'Number\'>'+ itemid +'</Value></Eq></Where></Query><RowLimit>1</RowLimit></View>');
    collListItem = oList.getItems(camlQuery);

    context.load(collListItem);
    context.executeQueryAsync(Function.createDelegate(this, onGetItemSuccess), Function.createDelegate(this, onFail));
}

function onGetItemSuccess() {
    var vCal = '';
    var listItemEnumerator = collListItem.getEnumerator();
    if (listItemEnumerator.moveNext()) {
        var oListItem = listItemEnumerator.get_current();

        if (user.get_id() == oListItem.get_item('Author').get_lookupId()) {
            vCal = "BEGIN:VCALENDAR" +
            "\r\nPRODID:-//DTU mode" +
            "\r\nVERSION:2.0" +
            "\r\nMETHOD:PUBLISH" +
            "\r\nBEGIN:VTIMEZONE" +
            "\r\nTZID:Romance Standard Time" +
            "\r\nBEGIN:STANDARD" +
            "\r\nDTSTART:16011028T030000" +
            "\r\nRRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10" +
            "\r\nTZOFFSETFROM:+0200" +
            "\r\nTZOFFSETTO:+0100" +
            "\r\nEND:STANDARD" +
            "\r\nBEGIN:DAYLIGHT" +
            "\r\nDTSTART:16010325T020000" +
            "\r\nRRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=3" +
            "\r\nTZOFFSETFROM:+0100" +
            "\r\nTZOFFSETTO:+0200" +
            "\r\nEND:DAYLIGHT" +
            "\r\nEND:VTIMEZONE" +
            "\r\nBEGIN:VEVENT" +
            "\r\nDTSTART;TZID=\"Romance Standard Time\":" + new Date(oListItem.get_item('EventDate')).toISOString() +
            "\r\nDTSTAMP:{0:yyyyMMddTHHmmss}" + new Date(Date.now()).toISOString() +
            "\r\nDTEND;TZID=\"Romance Standard Time\":" + new Date(oListItem.get_item('EndDate')).toISOString() +
            "\r\nLOCATION: " +
            "\r\nUID:" + getGuid() +
            "\r\nDESCRIPTION:" +
            "\r\nX-ALT-DESC;FMTTYPE=text/html:" +
            "\r\nSUMMARY:" + oListItem.get_item('Comment') +
            "\r\nSTATUS:OOF" +
            "\r\nEND:VEVENT" +
            "\r\nEND:VCALENDAR";

            var blob = new Blob([vCal], {
                type: "text/plain;charset=utf-8;",
            });
            saveAs(blob, "calendar.ics");
        } else {
            alert('You can only download your own appointments');
        }
    }
}

// This function is executed if the above call fails
function onFail(sender, args) {
    alert('Error:' + args.get_message());
}

function getParameterByName(name, url) {
    if (!url) url = window.location.href;
    name = name.replace(/[\[\]]/g, "\\$&");
    var regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"),
        results = regex.exec(url);
    if (!results) return '';
    if (!results[2]) return '';
    return decodeURIComponent(results[2].replace(/\+/g, " "));
}

Sidst opdateret: 21. jun.  2017

Submenu