Collision detection support for recurring events

I see from the documentation that collision detection is not supported for recurring events. Is this on your product roadmap? It would be tremendously helpful!

In the event that it is not… Is there an event hook I could use if I felt adventuresome and wanted to attempt to detect collisions using my own logic?

Thanks,
Chris

So far we don’t plan to add the such functionality ( in case of events without end-date , its hardly possible to predict collisions )

You can alter collision_check method in dhtmlxscheduler_collision.js, logic in it check only first date of event for collisions. It possible to use getRecDates methods, to get all occurrences of event, and check them for collisions.

Hi,

I am using my own query to check for collisions onEventSave. When I use the getRecDates method in this function, it only returns the first date. When I have used the same logic in my onEventAdded function, it returns the correct set of dates. Am I missing something? Both functions are pasted below.

        scheduler.attachEvent("onEventSave",
            function(event_id,event_object){
                $("#working_message").show();
                if(event_object.status == 'billed') {
                    alert("You cannot alter an appointment that has already been billed");
                    return false;
                }
                if ((event_object.end_date - event_object.start_date)/60000 < 30) {
                    alert("Appointment must be at least 30 min. long");
                    return false;
                }
                if ((event_object.end_date - event_object.start_date)/3600000 > 24) {
                    alert("Appointment cannot be longer than 24 hours");
                    return false;
                }    
                if (event_object.text.length > 2000) {
                    alert("Description must be 2,000 characters or less.");
                    return false;
                }                    
                <{if $admin == false}> 
                    <{if $account_id == null || $account_id == 0}>
                        alert("You must select a budget code prior to making appointments. Go to Profile tab to make selection.");
                        return false;
                    <{else}>
                        var now = new Date();
                        if (event_object.start_date < now) { 
                            alert("Appointment cannot be in the past.");
                            return false;
                        }
                        if (event_object.start_date > now.setDate(now.getDate()+31)) { 
                            alert("Appointment cannot be made more than 31 days in advance.");
                            return false;
                        }
                    <{/if}>    
                <{else}>
                    var percentDouble = /^((100(\.0{1,2})?)|(\d{0,2}(\.\d{1,2})?))$/i;
                    var event_discount = event_object.discount;
                    if (!percentDouble.test(event_discount)) {
                        alert("Discount must be bewteen 0 and 100, with no more than 2 decimals.");
                        return false;
                    }
                <{/if}>
                var start_dt = convert(event_object.start_date);
                var end_dt = convert(event_object.end_date);
                var rec_dates = '';
                if (event_object.rec_type != null && event_object.rec_type != '') {
                    var temp_rec_dates = scheduler.getRecDates(event_id); //calculates dates and times for each recurring instance of event.
                    var length = temp_rec_dates.length;
                    for (var i = 0; i < length; i++) {
                        rec_dates += '&start[' + i + ']=' + convert(temp_rec_dates[i]['start_date']) + '&end[' + i + ']=' + convert(temp_rec_dates[i]['end_date']);
                    }
                    confirm(rec_dates);
                } 
                $.wiengine.request({
                    handle_only : 1,
                    method : 'POST', 
                    panel_id : '<{insert name="get_panel_id"}>',
                    parameters : '&conflict_check=1&&start_dt=' + start_dt + 
                        '&end_dt=' + end_dt + '&instr=' + event_object.instrument_id + rec_dates,
                    onSuccess: function(response) {
                        if (response == 'email') {
                            alert("Your appointment conflicts with one or more existing appointments. Those conflicts have been emailed to you. Please review the list and adjust/cancel appointments with a conflict before scheduling.");
                            return false;
                        } else if (response == 'conflict') {
                            alert("Your appointment conflicts with an existing appointment. Please select a different time or instrument.");
                            return false;  
                        }
                    }
                });
                if (event_object.rec_type != null && event_object.rec_type != '') {
                    scheduler._roll_back_dates(event_object);
                    length = event_object.event_length;
                }
                $("#working_message").hide();
                return true;
            }
	    );



        scheduler.attachEvent("onEventAdded", 
            function(event_id,event_object) {
                $("#working_message").show();
                var start_dt = convert(event_object.start_date);
                var end_dt = convert(event_object.end_date);
                var rec_type = event_object.rec_type;
                var rec_dates = '';
                if (rec_type != null && rec_type != '') {
                    rec_type = event_object.rec_type.replace('#', '');
                    var temp_rec_dates = scheduler.getRecDates(event_id); //calculates dates and times for each recurring instance of event.
                    var length = temp_rec_dates.length;
                    for (var i = 0; i < length; i++) {
                        rec_dates += '&start[' + i + ']=' + convert(temp_rec_dates[i]['start_date']) + '&end[' + i + ']=' + convert(temp_rec_dates[i]['end_date']);
                    }
                    confirm(rec_dates);
                } 
                var urlparts = $.wiengine.getUrl();
                var data = $.wiengine.removeParam(urlparts.params, '_display');
                data = $.wiengine.removeParam(data, '_hist_id');
                $.ajax({
                    type: "POST",
                    url: urlparts.url_naked+'?'+data+'&_handle_only=1&_panel_id=<{insert name="get_panel_id"}>&_handle_only_display=1',
                    data: '&insert=1&event_id=' + event_id + '&start_dt=' + start_dt + '&end_dt=' + end_dt + 
                        '&text=' + event_object.text + '&instr=' + event_object.instrument_id +
                        '&discount=' + event_object.discount + '&is_assisted=' + event_object.is_assisted +   
                        '&event_length=' + length + '&event_pid=' + event_object.event_pid + 
                        rec_dates + '&rec_type=' + rec_type, 
                    success: function(response) {
                        temp = jQuery.parseJSON(response); //response includes new event_id, cost, and status.
                        scheduler.changeEventId(event_id, temp.new_id);
                        var ev = scheduler.getEvent(temp.new_id);
                       	ev.person_id = <{$person_id}>;
                        ev.name = "<{$name}>";
                        ev.cost = temp.cost;
                        ev.status = temp.status;
                        scheduler.updateEvent(temp.new_id);
                    }
                });
                for (var i = 0; i < sections.length; i++) {
                    if (event_object.instrument_id == sections[i].key) {
                        scheduler.getEvent(event_id).instrument_name = sections[i].label;
                    }
                }
                $("#working_message").hide();
            }
        );

I made several changes to my onEventSave so it makes more sense now, but getRecDates is still only returning one set of dates (the first)…

        scheduler.attachEvent("onEventSave",
            function(event_id,event_object){
                $("#working_message").show();
                if(event_object.status == 'billed') {
                    alert("You cannot alter an appointment that has already been billed");
                    return false;
                }
                if ((event_object.end_date - event_object.start_date)/60000 < 30) {
                    alert("Appointment must be at least 30 min. long");
                    return false;
                }
                if ((event_object.end_date - event_object.start_date)/3600000 > 24) {
                    alert("Appointment cannot be longer than 24 hours");
                    return false;
                }    
                if (event_object.text.length > 2000) {
                    alert("Description must be 2,000 characters or less.");
                    return false;
                }                    
                <{if $admin == false}> 
                    <{if $account_id == null || $account_id == 0}>
                        alert("You must select a budget code prior to making appointments. Go to Profile tab to make selection.");
                        return false;
                    <{else}>
                        var now = new Date();
                        if (event_object.start_date < now) { 
                            alert("Appointment cannot be in the past.");
                            return false;
                        }
                        if (event_object.start_date > now.setDate(now.getDate()+31)) { 
                            alert("Appointment cannot be made more than 31 days in advance.");
                            return false;
                        }
                    <{/if}>    
                <{else}>
                    var percentDouble = /^((100(\.0{1,2})?)|(\d{0,2}(\.\d{1,2})?))$/i;
                    var event_discount = event_object.discount;
                    if (!percentDouble.test(event_discount)) {
                        alert("Discount must be bewteen 0 and 100, with no more than 2 decimals.");
                        return false;
                    }
                <{/if}>
                var start_dt = convert(event_object.start_date);
                var end_dt = convert(event_object.end_date);
                var rec_dates = '';
                var rec_type = event_object.rec_type;
                if (rec_type != null && rec_type != '') {
                    scheduler._roll_back_dates(event_object);
                    if (event_object.start_date > event_object.end_date) {
                        alert("Recurring end by date must be greater than or equal to start date of event.");
                        return false;
                    }
                    rec_type = event_object.rec_type.replace('#', '');
                    var temp_rec_dates = scheduler.getRecDates(event_id); //calculates dates and times for each recurring instance of event.
                    var length = temp_rec_dates.length;
                    for (var i = 0; i < length; i++) {
                        rec_dates += '&start[' + i + ']=' + convert(temp_rec_dates[i]['start_date']) + '&end[' + i + ']=' + convert(temp_rec_dates[i]['end_date']);
                    }
                    length = event_object.event_length;
                } 
                $.wiengine.request({
                    handle_only : 1,
                    method : 'POST', 
                    panel_id : '<{insert name="get_panel_id"}>',
                    parameters : '&conflict_check=1&&start_dt=' + start_dt + 
                        '&end_dt=' + end_dt + '&instr=' + event_object.instrument_id + 
                        rec_dates + '&rec_type=' + rec_type,
                    onSuccess: function(response) {
                        if (response == 'email') {
                            alert("Your appointment conflicts with one or more existing appointments. Those conflicts have been emailed to you. Please review the list and adjust/cancel appointments with a conflict before scheduling.");
                            return false;
                        } else if (response == 'conflict') {
                            alert("Your appointment conflicts with an existing appointment. Please select a different time or instrument.");
                            return false;  
                        }
                    }
                });
                $("#working_message").hide();
                return true;
            }
	    );

change
scheduler.getRecDates(event_id)
to the
scheduler.getRecDates(event_object)

The problem is , in moment of onEventSave event is not change yet, so all API calls by ID will operate with event as it was before editing, while you need to get info about event how it will be after editing, which is second param of handler - event_obj

getRecDates can accept both event id, and event object as its parameter