Events conflict check in SharePoint Calendar (recurring events too)

I want to share with you my solution how to prevent events overlapping in Out-Of-The-Box SharePoint Calendar.

As you know you can easly create client or server-side validator for simple (non-recurring) events. But for recurring events we have to check a lot more different options depends on what type of recurring events we have (daily, weekly, monthly, …), repetition pattern, how many repetition we want (date range) etc.

2017-12-29_0856

I have decided for server-side solution with web service which is called from JavaScript event function on Save button in New/Edit Form of SharePoint Calendar.

In web service we have two functions:

  • SejneSobe_PreveriPrekrivanje which is called when we want to add simple (non-recurring) event and we want to check conflict with other events (recurring or non-recurring)
  • SejneSobe_PreveriPrekrivanjePonavljajoce which is called when we want to add recurring event and we want to check conflict with other events (recurring or non-recurring)

2017-12-29_0931

You can see content of both function on my GitHub (link at the end of this blog post).

Then we have to modify New and Edit Form of our SharePoint Calendar list template where we have to include custom JS script files:

  • SejneSobe_NewForm.js in New Form of SharePoint Calendar
  • SejneSobe_EditForm.js in Edit Form of SharePoint Calendar

In both we have to remember original save button click handler for later use and we have to set new one (in my case) named CheckOverload().

var originalSaveButtonClickHandler = function () {
};

$(document).ready(function () {
    var saveButton = $("[name$='diidIOSaveItem']");
    if (saveButton.length > 0) {
        originalSaveButtonClickHandler = saveButton[0].onclick;
    }
    $(saveButton).attr("onClick", "CheckOverload()");
});

In CheckOverload function we have to firstly check if we want to add recurrence or non-recurrence event. If is recurrence event, we call SejneSobe_PreveriPrekrivanjePonavljajoce function from web service otherwise we call SejneSobe_PreveriPrekrivanje.

function CheckOverload() {
    var ponavljajociDogodek = $('input[id$="RecurrenceField"]').prop('checked');
    if (ponavljajociDogodek) {
        var context = new SP.ClientContext.get_current();
        var web = context.get_web();
        context.load(web);
        context.executeQueryAsync(function () {
            var _zacDatum = moment(new Date(0001, 0, 1, 0, 0, 0, 0));
            var _konDatum = moment(new Date(0001, 0, 1, 0, 0, 0, 0));

            var _dateHoursInputs = $('select[id$="DateTimeFieldDateHours"]');
            if (_dateHoursInputs.length >= 2) {
                var _zacUra = parseInt(_dateHoursInputs.eq(0).val());
                if (_dateHoursInputs.eq(0).val().indexOf("PM") >= 0) {
                    _zacUra += 12;
                }
                _zacDatum = _zacDatum.add(_zacUra, 'hours');

                var _konUra = parseInt(_dateHoursInputs.eq(1).val());
                if (_dateHoursInputs.eq(1).val().indexOf("PM") >= 0) {
                    _konUra += 12;
                }
                _konDatum = _konDatum.add(_konUra, 'hours');
            }
            else {
                _zacDatum = _zacDatum.add(0, 'hours');
                _konDatum = _konDatum.add(24, 'hours');
            }

            var _dateMinutesInputs = $('select[id$="DateTimeFieldDateMinutes"]');
            if (_dateMinutesInputs.length >= 2) {
                var _zacMinuta = parseInt(_dateMinutesInputs.eq(0).val());
                _zacDatum = _zacDatum.add(_zacMinuta, 'minutes');

                var _konMinuta = parseInt(_dateMinutesInputs.eq(1).val());
                _konDatum = _konDatum.add(_konMinuta, 'minutes');
            }

            var _datumOd = moment($('input[id$="windowStart_windowStartDate"]').val(), 'D.M.YYYY');
            var _datumDo = moment($('input[id$="windowEnd_windowEndDate"]').val(), 'D.M.YYYY');

            $.ajax({
                url: "/_vti_bin/{web-service-path}/{web-service-name}.svc/SejneSobe_PreveriPrekrivanjePonavljajoce",
                data: JSON.stringify({
                    siteUrl: web.get_url(),
                    listGuid: _spPageContextInfo.pageListId,
                    uraOd: _zacDatum.format("HH:mm"),
                    uraDo: _konDatum.format("HH:mm"),
                    tipPonovitve: $('input[name$="RecurrencePatternType"]:checked').val(),
                    dnevnoTipVzorec: $('input[name$="DailyRecurType"]:checked').val(),
                    dnevnoVsakihDni: $('input[id$="daily_dayFrequency"]').val(),
                    tedenskoVsakihTednov: $('input[id$="weekly_weekFrequency"]').val(),
                    dnevi: $('input[name$="weekly_multiDays$0"]:checked').length + "," +
                            $('input[name$="weekly_multiDays$1"]:checked').length + "," +
                            $('input[name$="weekly_multiDays$2"]:checked').length + "," +
                            $('input[name$="weekly_multiDays$3"]:checked').length + "," +
                            $('input[name$="weekly_multiDays$4"]:checked').length + "," +
                            $('input[name$="weekly_multiDays$5"]:checked').length + "," +
                            $('input[name$="weekly_multiDays$6"]:checked').length,
                    mesecnoTipVzorec: $('input[name$="MonthlyRecurType"]:checked').val(),
                    mesecnoDan: $('input[id$="monthly_day"]').val(),
                    mesecnoVsakihMesecev: $('input[id$="monthly_monthFrequency"]').val(),
                    mesecnoKateri: $('select[id$="monthlyByDay_weekOfMonth"]').val(),
                    mesecnoDan2: $('select[id$="monthlyByDay_day"]').val(),
                    mesecnoVsakihMesecev2: $('input[id$="monthlyByDay_monthFrequency"]').val(),
                    letnoTipVzorec: $('input[name$="YearlyRecurType"]:checked').val(),
                    letnoVsakMesec: $('select[id$="yearly_month"]').val(),
                    letnoDan: $('input[id$="yearly_day"]').val(),
                    letnoKateri: $('select[id$="yearlyByDay_weekOfMonth"]').val(),
                    letnoDan2: $('select[id$="yearlyByDay_day"]').val(),
                    letnoVMesecu: $('select[id$="yearlyByDay_month"]').val(),
                    datumOd: _datumOd.format("DD.MM.YYYY"),
                    tipDatumDo: $('input[name$="EndDateRangeType"]:checked').val(),
                    datumDo: _datumDo.format("DD.MM.YYYY"),
                    stPonovitev: $('input[id$="repeatInstances"]').val()
                }),
                type: "POST",
                cache: false,
                dataType: 'json',
                contentType: "application/json; charset=utf-8"
            })
            .done(function (data) {
                if (data.ErrorMessage) {
                    alert(data.ErrorMessage);
                }
                else {
                    console.log(data.Data);
                    if (!data.Data) {
                        originalSaveButtonClickHandler();
                    } else {
                        // izpiši napake
                        ssIzpisiNapakoCas("Končni čas", "End Time");
                    }
                }
            });
        });
    }
    else {
        var _zacDatum;
        var _konDatum;

        $('span#sIzpisiNapakoCas').hide();

        var _dateInputs = $('input[id$="DateTimeFieldDate"]');
        if (_dateInputs.length >= 2) {
            _zacDatum = moment(_dateInputs.eq(0).val(), 'D.M.YYYY');
            _konDatum = moment(_dateInputs.eq(1).val(), 'D.M.YYYY');
        }
        else {
            originalSaveButtonClickHandler();
            return;
        }

        var _dateHoursInputs = $('select[id$="DateTimeFieldDateHours"]');
        if (_dateHoursInputs.length >= 2) {
            var _zacUra = parseInt(_dateHoursInputs.eq(0).val());
            if (_dateHoursInputs.eq(0).val().indexOf("PM") >= 0) {
                _zacUra += 12;
            }
            _zacDatum = _zacDatum.add(_zacUra, 'hours');

            var _konUra = parseInt(_dateHoursInputs.eq(1).val());
            if (_dateHoursInputs.eq(1).val().indexOf("PM") >= 0) {
                _konUra += 12;
            }
            _konDatum = _konDatum.add(_konUra, 'hours');
        }
        else {
            _zacDatum = _zacDatum.add(0, 'hours');
            _konDatum = _konDatum.add(24, 'hours');
        }

        var _dateMinutesInputs = $('select[id$="DateTimeFieldDateMinutes"]');
        if (_dateMinutesInputs.length >= 2) {
            var _zacMinuta = parseInt(_dateMinutesInputs.eq(0).val());
            _zacDatum = _zacDatum.add(_zacMinuta, 'minutes');

            var _konMinuta = parseInt(_dateMinutesInputs.eq(1).val());
            _konDatum = _konDatum.add(_konMinuta, 'minutes');
        }

        var context = new SP.ClientContext.get_current();
        var web = context.get_web();
        context.load(web);
        context.executeQueryAsync(function () {
            $.ajax({
                url: "/_vti_bin/{web-service-path}/{web-service-name}.svc/SejneSobe_PreveriPrekrivanje",
                data: JSON.stringify({
                    SiteUrl: web.get_url(),
                    ListGuid: _spPageContextInfo.pageListId,
                    DatumOd: _zacDatum.format("DD.MM.YYYY HH:mm:ss"),
                    DatumDo: _konDatum.format("DD.MM.YYYY HH:mm:ss")
                }),
                type: "POST",
                cache: false,
                dataType: 'json',
                contentType: "application/json; charset=utf-8"
            })
            .done(function (data) {
                if (data.ErrorMessage) {
                    alert(data.ErrorMessage);
                }
                else {
                    console.log(data.Data);
                    if (!data.Data) {
                        originalSaveButtonClickHandler();
                    } else {
                        // izpiši napake
                        ssIzpisiNapakoCas("Končni čas", "End Time");
                    }
                }
            });
        });
    }
}

If we have conflict with other events in SharePoint Calendar we show simple message to user. If not we call originalSaveButtonClickHandler which take care for OOTB saving of our new event to SharePoint Calendar.

2017-12-29_0926

[ Complete code on GitHub ]

Cheers!
Gašper Rupnik

{End.}

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

Powered by WordPress.com.

Up ↑

%d bloggers like this: