@progress/kendo-ui
Version:
This package is part of the [Kendo UI for jQuery](http://www.telerik.com/kendo-ui) suite.
1,270 lines (1,037 loc) • 192 kB
JavaScript
module.exports =
/******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId])
/******/ return installedModules[moduleId].exports;
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ exports: {},
/******/ id: moduleId,
/******/ loaded: false
/******/ };
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/ // Flag the module as loaded
/******/ module.loaded = true;
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "";
/******/ // Load entry module and return exports
/******/ return __webpack_require__(0);
/******/ })
/************************************************************************/
/******/ ({
/***/ 0:
/***/ (function(module, exports, __webpack_require__) {
module.exports = __webpack_require__(1291);
/***/ }),
/***/ 3:
/***/ (function(module, exports) {
module.exports = function() { throw new Error("define cannot be used indirect"); };
/***/ }),
/***/ 1010:
/***/ (function(module, exports) {
module.exports = require("./kendo.dropdownlist");
/***/ }),
/***/ 1012:
/***/ (function(module, exports) {
module.exports = require("./kendo.multiselect");
/***/ }),
/***/ 1143:
/***/ (function(module, exports) {
module.exports = require("./kendo.window");
/***/ }),
/***/ 1193:
/***/ (function(module, exports) {
module.exports = require("./kendo.pdf");
/***/ }),
/***/ 1197:
/***/ (function(module, exports) {
module.exports = require("./kendo.datetimepicker");
/***/ }),
/***/ 1198:
/***/ (function(module, exports) {
module.exports = require("./kendo.editable");
/***/ }),
/***/ 1208:
/***/ (function(module, exports) {
module.exports = require("./kendo.pane");
/***/ }),
/***/ 1291:
/***/ (function(module, exports, __webpack_require__) {
var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;(function(f, define){
!(__WEBPACK_AMD_DEFINE_ARRAY__ = [ __webpack_require__(1010), __webpack_require__(1198), __webpack_require__(1012), __webpack_require__(1143), __webpack_require__(1197), __webpack_require__(1293), __webpack_require__(1294), __webpack_require__(1292), __webpack_require__(1295), __webpack_require__(1296), __webpack_require__(1297), __webpack_require__(1298), __webpack_require__(1208), __webpack_require__(1193), __webpack_require__(1299) ], __WEBPACK_AMD_DEFINE_FACTORY__ = (f), __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ? (__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
})(function(){
var __meta__ = { // jshint ignore:line
id: "scheduler",
name: "Scheduler",
category: "web",
description: "The Scheduler is an event calendar.",
depends: [ "dropdownlist", "editable", "multiselect", "window", "datepicker", "datetimepicker", "scheduler.recurrence", "scheduler.view" ],
features: [ {
id: "scheduler-dayview",
name: "Scheduler Day View",
description: "Scheduler Day View",
depends: [ "scheduler.dayview" ]
}, {
id: "scheduler-agendaview",
name: "Scheduler Agenda View",
description: "Scheduler Agenda View",
depends: [ "scheduler.agendaview" ]
}, {
id: "scheduler-monthview",
name: "Scheduler Month View",
description: "Scheduler Month View",
depends: [ "scheduler.monthview" ]
}, {
id: "scheduler-timelineview",
name: "Scheduler Timeline View",
description: "Scheduler Timeline View",
depends: [ "scheduler.timelineview" ]
}, {
id: "scheduler-mobile",
name: "Scheduler adaptive rendering",
description: "Support for adaptive rendering",
depends: [ "dialog", "pane", "switch" ]
}, {
id: "scheduler-pdf-export",
name: "PDF export",
description: "Export the scheduler events as PDF",
depends: [ "pdf", "drawing" ]
}, {
id: "scheduler-timezones",
name: "Timezones",
description: "Allow selecting timezones different than Etc/UTC",
depends: [ "timezones" ]
}]
};
/*jshint eqnull: true */
(function($, undefined) {
var kendo = window.kendo,
date = kendo.date,
MS_PER_DAY = date.MS_PER_DAY,
getDate = date.getDate,
getMilliseconds = kendo.date.getMilliseconds,
recurrence = kendo.recurrence,
keys = $.extend({F10: 121}, kendo.keys),
ui = kendo.ui,
Widget = ui.Widget,
DataBoundWidget = ui.DataBoundWidget,
STRING = "string",
Popup = ui.Popup,
Calendar = ui.Calendar,
DataSource = kendo.data.DataSource,
isPlainObject = $.isPlainObject,
extend = $.extend,
proxy = $.proxy,
toString = Object.prototype.toString,
isArray = $.isArray,
NS = ".kendoScheduler",
CLICK = "click",
MOUSEDOWN = "mousedown",
TOUCHSTART = kendo.support.pointers ? "pointerdown" : "touchstart",
TOUCHMOVE = kendo.support.pointers ? "pointermove" : "touchmove",
TOUCHEND = kendo.support.pointers ? "pointerup" : "touchend",
MOUSEMOVE = kendo.support.mousemove,
CHANGE = "change",
PROGRESS = "progress",
ERROR = "error",
CANCEL = "cancel",
REMOVE = "remove",
RESET = "resetSeries",
SAVE = "save",
ADD = "add",
EDIT = "edit",
FOCUSEDSTATE = "k-state-focused",
EXPANDEDSTATE = "k-state-expanded",
VIEWSSELECTOR = ".k-scheduler-views",
INVERSECOLORCLASS = "k-event-inverse",
valueStartEndBoundRegex = /(?:value:start|value:end)(?:,|$)/,
TODAY = getDate(new Date()),
EXCEPTION_SEPARATOR = ",",
OLD_EXCEPTION_SEPARATOR_REGEXP = /\;/g,
RECURRENCE_EXCEPTION = "recurrenceException",
DELETECONFIRM = "Are you sure you want to delete this event?",
DELETERECURRING = "Do you want to delete only this event occurrence or the whole series?",
EDITRECURRING = "Do you want to edit only this event occurrence or the whole series?",
DELETERECURRINGCONFIRM = "Are you sure you want to delete this event occurrence?",
RESETSERIESCONFIRM = "Are you sure you want to reset the whole series?",
DELETESERIESCONFIRM = "Are you sure you want to delete the whole series?",
COMMANDBUTTONTMPL = '<a class="k-button #=className#" #=attr# href="\\#">#=text#</a>',
VIEWBUTTONTEMPLATE = kendo.template('<li class="k-current-view" data-#=ns#name="#=view#"><a role="button" href="\\#" class="k-link">${views[view].title}</a></li>'),
TOOLBARTEMPLATE = kendo.template('<div class="k-floatwrap k-header k-scheduler-toolbar">' +
'# if (pdf) { #' +
'<ul class="k-reset k-scheduler-tools">' +
'<li><a role="button" href="\\#" class="k-button k-pdf"><span class="k-icon k-i-file-pdf"></span>${messages.pdf}</a></li>' +
'</ul>' +
'# } #' +
'<ul class="k-reset k-scheduler-navigation">' +
'<li class="k-state-default k-header k-nav-today"><a role="button" href="\\#" class="k-link" title="${messages.today}">${messages.today}</a></li>' +
'<li class="k-state-default k-header k-nav-prev"><a role="button" href="\\#" class="k-link" title="${messages.previous}" aria-label="${messages.previous}"><span class="k-icon k-i-arrow-60-left" style="pointer-events: none"></span></a></li>' +
'<li class="k-state-default k-header k-nav-next"><a role="button" href="\\#" class="k-link" title="${messages.next}" aria-label="${messages.next}"><span class="k-icon k-i-arrow-60-right" style="pointer-events: none"></span></a></li>' +
'<li class="k-state-default k-nav-current">' +
'<a role="button" href="\\#" class="k-link">' +
'<span class="k-icon k-i-calendar"></span>' +
'<span class="k-sm-date-format" data-#=ns#bind="text: formattedShortDate"></span>' +
'<span class="k-lg-date-format" data-#=ns#bind="text: formattedDate"></span>' +
'</a>' +
'</li>' +
'</ul>' +
'#if(viewsCount === 1){#' +
'<a role="button" data-#=ns#name="#=view#" href="\\#" class="k-link k-scheduler-refresh">' +
'<span class="k-icon k-i-reload"></span>' +
'</a>' +
'#}else{#' +
'<ul class="k-reset k-header k-scheduler-views">' +
'#for(var view in views){#' +
'<li class="k-state-default k-view-#= view.toLowerCase() #" data-#=ns#name="#=view#"><a role="button" href="\\#" class="k-link">${views[view].title}</a></li>' +
'#}#' +
'</ul>' +
'#}#' +
'</div>'),
MOBILETOOLBARTEMPLATE = kendo.template('<div class="k-header k-scheduler-toolbar">' +
'<ul class="k-reset k-scheduler-tools">' +
'# if (pdf) { #' +
'<li><a role="button" href="\\#" class="k-button k-pdf"><span class="k-icon k-i-file-pdf"></span></a></li>' +
'# } #' +
'<li><a role="button" href="\\#" class="k-button k-nav-calendar"><span class="k-icon k-i-calendar"></span></a></li>' +
"# if (editable) { #" +
'<li><a role="button" href="\\#" class="k-button k-create-event"><span class="k-icon k-i-plus"></span></a></li>' +
"# } #" +
'</ul>' +
'#if(viewsCount === 1){#' +
'<a role="button" data-#=ns#name="#=view#" href="\\#" class="k-link k-scheduler-refresh">' +
'<span class="k-icon k-i-reload"></span>' +
'</a>' +
'#}else{#' +
'<select class="k-scheduler-mobile-views">' +
'#for(var view in views){#' +
'<option class="k-state-default k-view-#= view.toLowerCase() #" value="#=view#">${views[view].title}</option>' +
'#}#' +
'</select>' +
'#}#' +
'</div>'+
'<div class="k-header k-scheduler-toolbar">' +
'<ul class="k-reset k-header k-scheduler-navigation">' +
'<li class="k-state-default k-nav-prev"><a role="button" href="\\#" class="k-link"><span class="k-icon k-i-arrow-chevron-left"></span></a></li>' +
'<li class="k-state-default k-nav-current">' +
'<span class="k-m-date-format" data-#=ns#bind="text: formattedMobileDate"></span>' +
'<span class="k-y-date-format" data-#=ns#bind="text: formattedYear"></span>' +
'</li>' +
'<li class="k-state-default k-nav-next"><a role="button" href="\\#" class="k-link"><span class="k-icon k-i-arrow-chevron-right"></span></a></li>' +
'</ul>' +
'</div>'),
MOBILEDATERANGEEDITOR = function(container, options) {
var attr = { name: options.field, title: options.title };
var isAllDay = options.model.isAllDay;
var dateTimeValidate = kendo.attr("validate") + "='" + (!isAllDay) + "'";
var dateValidate = kendo.attr("validate") + "='" + isAllDay + "'";
appendTimezoneAttr(attr, options);
appendValidDateValidator(attr, options);
appendDateCompareValidator(attr, options);
$('<input type="datetime-local" required ' + kendo.attr("type") + '="datetime-local" ' + kendo.attr("bind") + '="value:' + options.field +', invisible:isAllDay" ' + dateTimeValidate + '/>')
.attr(attr)
.appendTo(container);
$('<input type="date" required ' + kendo.attr("type") + '="date" ' + kendo.attr("bind") + '="value:' + options.field +',visible:isAllDay" ' +
dateValidate + '/>')
.attr(attr).appendTo(container);
$('<span ' + kendo.attr("for") + '="' + options.field + '" class="k-invalid-msg"/>').hide().appendTo(container);
},
DATERANGEEDITOR = function(container, options) {
var attr = { name: options.field, title: options.title },
isAllDay = options.model.isAllDay,
dateTimeValidate = kendo.attr("validate") + "='" + (!isAllDay) + "' ",
dateValidate = kendo.attr("validate") + "='" + isAllDay + "' ";
appendTimezoneAttr(attr, options);
appendValidDateValidator(attr, options);
appendDateCompareValidator(attr, options);
$('<input type="text" required ' + kendo.attr("type") + '="date"' + ' ' + kendo.attr("role") + '="datetimepicker" ' + kendo.attr("bind") + '="value:' + options.field +',invisible:isAllDay" ' +
dateTimeValidate + '/>')
.attr(attr).appendTo(container);
$('<input type="text" required ' + kendo.attr("type") + '="date"' + ' ' + kendo.attr("role") + '="datepicker" ' + kendo.attr("bind") + '="value:' + options.field +',visible:isAllDay" ' +
dateValidate + '/>')
.attr(attr).appendTo(container);
$('<span ' + kendo.attr("bind") + '="text: ' + options.field + 'Timezone"></span>').appendTo(container);
if (options.field === "end") {
$('<span ' + kendo.attr("bind") + '="text: startTimezone, invisible: endTimezone"></span>').appendTo(container);
}
$('<span ' + kendo.attr("for") + '="' + options.field + '" class="k-invalid-msg"/>').hide().appendTo(container);
},
RECURRENCEEDITOR = function(container, options) {
$('<div ' + kendo.attr("bind") + '="value:' + options.field +'" />')
.attr({
name: options.field
})
.appendTo(container)
.kendoRecurrenceEditor({
start: options.model.start,
timezone: options.timezone,
messages: options.messages
});
},
MOBILERECURRENCEEDITOR = function(container, options) {
$('<div ' + kendo.attr("bind") + '="value:' + options.field +'" />')
.attr({
name: options.field
})
.appendTo(container)
.kendoMobileRecurrenceEditor({
start: options.model.start,
timezone: options.timezone,
messages: options.messages,
pane: options.pane,
value: options.model[options.field]
});
},
MOBILEISALLDAYEDITOR = function (container, options) {
$('<input type="checkbox" data-role="switch"' + kendo.attr("bind") + '="value:' + options.field +'" />').appendTo(container);
},
MOBILETIMEZONEPOPUP = function(container, options) {
var text = timezoneButtonText(options.model, options.messages.noTimezone);
$('<span class="k-timezone-label"></span>').text(text).appendTo(container);
$('<span class="k-icon k-i-arrow-chevron-right"></span>').appendTo(container);
container.closest("li.k-item label").click(options.click);
},
TIMEZONEPOPUP = function(container, options) {
$('<a href="#" class="k-button" data-bind="invisible:isAllDay">' + options.messages.timezoneEditorButton + '</a>').click(options.click).appendTo(container);
},
MOBILETIMEZONEEDITOR = function(container, options) {
$('<div class="k-mobiletimezoneeditor" ' + kendo.attr("bind") + '="value:' + options.field +'" />')
.attr({
name: options.field
})
.appendTo(container)
.kendoMobileTimezoneEditor({
optionLabel: options.noTimezone
});
},
TIMEZONEEDITOR = function(container, options) {
var visible = options.visible || options.visible === undefined;
$('<div ' + kendo.attr("bind") + '="value:' + options.field +'" />')
.attr({ name: options.field })
.toggle(visible)
.appendTo(container)
.kendoTimezoneEditor({
optionLabel: options.noTimezone,
title: options.title
});
};
function timezoneButtonText(model, message) {
message = message || "";
if (model.startTimezone) {
message = model.startTimezone;
if (model.endTimezone) {
message += " | " + model.endTimezone;
}
}
return message;
}
function appendTimezoneAttr(attrs, options) {
var timezone = options.timezone;
if (timezone) {
attrs[kendo.attr("timezone")] = timezone;
}
}
function appendValidDateValidator(attrs, options) {
var validationRules = options.model.fields[options.field].validation;
if (validationRules) {
var validDateRule = validationRules.validDateValidator;
if (validDateRule && isPlainObject(validDateRule) && validDateRule.message) {
attrs[kendo.attr("validDate-msg")] = validDateRule.message;
}
}
}
function appendDateCompareValidator(attrs, options) {
var validationRules = options.model.fields[options.field].validation;
if (validationRules) {
var dateCompareRule = validationRules.dateCompare;
if (dateCompareRule && isPlainObject(dateCompareRule) && dateCompareRule.message) {
attrs[kendo.attr("dateCompare-msg")] = dateCompareRule.message;
}
}
}
function wrapDataAccess(originalFunction, timezone) {
return function(data) {
data = originalFunction(data);
convertData(data, "apply", timezone);
return data || [];
};
}
function wrapDataSerialization(originalFunction, timezone) {
return function(data) {
if (data) {
if (toString.call(data) !== "[object Array]" && !(data instanceof kendo.data.ObservableArray)) {
data = [data];
}
}
convertData(data, "remove", timezone, true);
data = originalFunction(data);
return data || [];
};
}
function convertData(data, method, timezone, removeUid) {
var event,
idx,
length;
data = data || [];
for (idx = 0, length = data.length; idx < length; idx++) {
event = data[idx];
if (removeUid) {
if (event.startTimezone || event.endTimezone) {
if (timezone) {
event.start = kendo.timezone.convert(event.start, event.startTimezone || event.endTimezone, timezone);
event.end = kendo.timezone.convert(event.end, event.endTimezone || event.startTimezone, timezone);
event.start = kendo.timezone[method](event.start, timezone);
event.end = kendo.timezone[method](event.end, timezone);
} else {
event.start = kendo.timezone[method](event.start, event.startTimezone || event.endTimezone);
event.end = kendo.timezone[method](event.end, event.endTimezone || event.startTimezone);
}
} else if (timezone) {
event.start = kendo.timezone[method](event.start, timezone);
event.end = kendo.timezone[method](event.end, timezone);
}
} else {
if (event.startTimezone || event.endTimezone) {
event.start = kendo.timezone[method](event.start, event.startTimezone || event.endTimezone);
event.end = kendo.timezone[method](event.end, event.endTimezone || event.startTimezone);
if (timezone) {
event.start = kendo.timezone.convert(event.start, event.startTimezone || event.endTimezone, timezone);
event.end = kendo.timezone.convert(event.end, event.endTimezone || event.startTimezone, timezone);
}
} else if (timezone) {
event.start = kendo.timezone[method](event.start, timezone);
event.end = kendo.timezone[method](event.end, timezone);
}
}
if (removeUid) {
delete event.uid;
}
}
return data;
}
function getOccurrenceByUid(data, uid) {
var length = data.length,
idx = 0,
event;
for (; idx < length; idx++) {
event = data[idx];
if (event.uid === uid) {
return event;
}
}
}
var SchedulerDataReader = kendo.Class.extend({
init: function(schema, reader) {
var timezone = schema.timezone;
this.reader = reader;
if (reader.model) {
this.model = reader.model;
}
this.timezone = timezone;
this.data = wrapDataAccess($.proxy(this.data, this), timezone);
this.serialize = wrapDataSerialization($.proxy(this.serialize, this), timezone);
},
errors: function(data) {
return this.reader.errors(data);
},
parse: function(data) {
return this.reader.parse(data);
},
data: function(data) {
return this.reader.data(data);
},
total: function(data) {
return this.reader.total(data);
},
groups: function(data) {
return this.reader.groups(data);
},
aggregates: function(data) {
return this.reader.aggregates(data);
},
serialize: function(data) {
return this.reader.serialize(data);
}
});
function applyZone(date, fromZone, toZone) {
if (toZone) {
date = kendo.timezone.convert(date, fromZone, toZone);
} else {
date = kendo.timezone.remove(date, fromZone);
}
return date;
}
function validDateValidator(input) {
if ((input.filter("[name=start]").length && input.filter("[title=Start]").length) ||
(input.filter("[name=end]").length && input.filter("[title=End]").length)) {
var date;
var picker = kendo.widgetInstance(input, kendo.ui);
if (picker) {
date = kendo.parseDate(input.val(), picker.options.format);
return !!date && picker.value();
} else {
date = kendo.parseDate(input.val());
return !!date;
}
}
return true;
}
function dateCompareValidator(input) {
if (input.filter("[name=end]").length) {
var container = input.closest(".k-scheduler-edit-form");
var startInput = container.find("[name=start]:visible");
var endInput = container.find("[name=end]:visible");
if (endInput[0] && startInput[0]) {
var start, end;
var startPicker = kendo.widgetInstance(startInput, kendo.ui);
var endPicker = kendo.widgetInstance(endInput, kendo.ui);
var editable = container.data("kendoEditable");
var model = editable ? editable.options.model : null;
if (startPicker && endPicker) {
start = startPicker.value();
end = endPicker.value();
} else {
start = kendo.parseDate(startInput.val());
end = kendo.parseDate(endInput.val());
}
if (start && end) {
if (model) {
var timezone = startInput.attr(kendo.attr("timezone"));
var startTimezone = model.startTimezone;
var endTimezone = model.endTimezone;
startTimezone = startTimezone || endTimezone;
endTimezone = endTimezone || startTimezone;
if (startTimezone) {
start = applyZone(start, startTimezone, timezone);
end = applyZone(end, endTimezone, timezone);
}
}
return start <= end;
}
}
}
return true;
}
var SchedulerEvent = kendo.data.Model.define({
init: function(value) {
var that = this;
kendo.data.Model.fn.init.call(that, value);
that._defaultId = that.defaults[that.idField];
},
_time: function(field) {
var date = this[field];
var fieldTime = "_" + field + "Time";
if (this[fieldTime]) {
return this[fieldTime] - kendo.date.toUtcTime(kendo.date.getDate(date));
}
return getMilliseconds(date);
},
_date: function(field) {
var fieldTime = "_" + field + "Time";
if (this[fieldTime]) {
return this[fieldTime] - this._time(field);
}
return kendo.date.getDate(this[field]);
},
clone: function(options, updateUid) {
var uid = this.uid,
event = new this.constructor($.extend({}, this.toJSON(), options));
if (!updateUid) {
event.uid = uid;
}
return event;
},
duration: function() {
var end = this.end;
var start = this.start;
var offset = (end.getTimezoneOffset() - start.getTimezoneOffset()) * kendo.date.MS_PER_MINUTE;
return end - start - offset;
},
expand: function(start, end, zone) {
return recurrence ? recurrence.expand(this, start, end, zone) : [this];
},
update: function(eventInfo) {
for (var field in eventInfo) {
this.set(field, eventInfo[field]);
}
if (this._startTime) {
this.set("_startTime", kendo.date.toUtcTime(this.start));
}
if (this._endTime) {
this.set("_endTime", kendo.date.toUtcTime(this.end));
}
},
isMultiDay: function() {
return this.isAllDay || this.duration() >= kendo.date.MS_PER_DAY;
},
isException: function() {
return !this.isNew() && this.recurrenceId;
},
isOccurrence: function() {
return this.isNew() && this.recurrenceId;
},
isRecurring: function() {
return !!(this.recurrenceRule || this.recurrenceId);
},
isRecurrenceHead: function() {
return !!(this.id && this.recurrenceRule);
},
toOccurrence: function(options) {
options = $.extend(options, {
recurrenceException: null,
recurrenceRule: null,
recurrenceId: this.id || this.recurrenceId
});
options[this.idField] = this.defaults[this.idField];
return this.clone(options, true);
},
toJSON: function() {
var obj = kendo.data.Model.fn.toJSON.call(this);
obj.uid = this.uid;
delete obj._startTime;
delete obj._endTime;
return obj;
},
shouldSerialize: function(field) {
return kendo.data.Model.fn.shouldSerialize.call(this, field) && field !== "_defaultId";
},
set: function(key, value) {
var isAllDay = this.isAllDay || false;
kendo.data.Model.fn.set.call(this, key, value);
if (key == "isAllDay" && value != isAllDay) {
var start = kendo.date.getDate(this.start);
var end = new Date(this.end);
var milliseconds = kendo.date.getMilliseconds(end);
if (milliseconds === 0 && value) {
milliseconds = MS_PER_DAY;
}
this.set("start", start);
if (value === true) {
kendo.date.setTime(end, -milliseconds);
if (end < start) {
end = start;
}
} else {
kendo.date.setTime(end, MS_PER_DAY - milliseconds);
}
this.set("end", end);
}
},
id: "id",
fields: {
id: { type: "number" },
title: { defaultValue: "", type: "string" },
start: { type: "date", validation: { required: true, validDate: { value: validDateValidator } } },
startTimezone: { type: "string" },
end: { type: "date", validation: { required: true, validDate: { value: validDateValidator }, dateCompare: { value: dateCompareValidator } } },
endTimezone: { type: "string" },
recurrenceRule: { defaultValue: "", type: "string" },
recurrenceException: { defaultValue: "", type: "string" },
isAllDay: { type: "boolean", defaultValue: false },
description: { type: "string" }
}
});
var SchedulerDataSource = DataSource.extend({
init: function(options) {
DataSource.fn.init.call(this, extend(true, {}, {
schema: {
modelBase: SchedulerEvent,
model: SchedulerEvent
}
}, options));
this.reader = new SchedulerDataReader(this.options.schema, this.reader);
},
expand: function(start, end) {
var data = this.view(),
filter = {},
endOffset;
if (start && end) {
endOffset = end.getTimezoneOffset();
end = new Date(end.getTime() + MS_PER_DAY - 1);
if(end.getTimezoneOffset() !== endOffset){
end = kendo.timezone.apply(end, endOffset);
}
filter = {
logic: "or",
filters: [
{
logic: "and",
filters: [
{ field: "start", operator: "gte", value: start },
{ field: "end", operator: "gte", value: start },
{ field: "start", operator: "lte", value: end }
]
},
{
logic: "and",
filters: [
{ field: "start", operator: "lte", value: new Date(start.getTime() + MS_PER_DAY - 1) },
{ field: "end", operator: "gte", value: start }
]
}
]
};
data = new kendo.data.Query(expandAll(data, start, end, this.reader.timezone)).filter(filter).toArray();
}
return data;
},
cancelChanges: function(model) {
if (model && model.isOccurrence()) {
this._removeExceptionDate(model);
}
DataSource.fn.cancelChanges.call(this, model);
},
insert: function(index, model) {
if (!model) {
return;
}
if (!(model instanceof SchedulerEvent)) {
var eventInfo = model;
model = this._createNewModel();
model.accept(eventInfo);
}
if ((!this._pushCreated && model.isRecurrenceHead()) || model.recurrenceId) {
model = model.recurrenceId ? model : model.toOccurrence();
this._addExceptionDate(model);
}
return DataSource.fn.insert.call(this, index, model);
},
pushCreate: function(items) {
this._pushCreated = true;
DataSource.fn.pushCreate.call(this, items);
this._pushCreated = false;
},
remove: function(model) {
if (model.isRecurrenceHead()) {
this._removeExceptions(model);
} else if (model.isRecurring()) {
this._addExceptionDate(model);
}
return DataSource.fn.remove.call(this, model);
},
_removeExceptions: function(model) {
var data = this.data().slice(0),
item = data.shift(),
id = model.id;
while(item) {
if (item.recurrenceId === id) {
DataSource.fn.remove.call(this, item);
}
item = data.shift();
}
model.set(RECURRENCE_EXCEPTION, "");
},
_removeExceptionDate: function(model) {
if (model.recurrenceId) {
var head = this.get(model.recurrenceId);
if (head) {
var start = model.defaults.start;
var replaceRegExp = new RegExp("(\\" + EXCEPTION_SEPARATOR + "?)" + recurrence.toExceptionString(start, this.reader.timezone));
var recurrenceException = (head.recurrenceException || "").replace(OLD_EXCEPTION_SEPARATOR_REGEXP, EXCEPTION_SEPARATOR).replace(/\,$/, "");
if(replaceRegExp.test(recurrenceException)){
head.set(RECURRENCE_EXCEPTION, recurrenceException.replace(replaceRegExp, ""));
}else{
start = model.start;
replaceRegExp = new RegExp("(\\" + EXCEPTION_SEPARATOR + "?)" + recurrence.toExceptionString(start, this.reader.timezone));
head.set(RECURRENCE_EXCEPTION, recurrenceException.replace(replaceRegExp, ""));
}
}
}
},
_addExceptionDate: function(model) {
var start = model.start;
var zone = this.reader.timezone;
var head = this.get(model.recurrenceId);
var recurrenceException = (head.recurrenceException || "").replace(OLD_EXCEPTION_SEPARATOR_REGEXP, EXCEPTION_SEPARATOR).replace(/\,$/, "");
if (!recurrence.isException(recurrenceException, start, zone)) {
var newException = recurrence.toExceptionString(start, zone);
model.defaults.start = start;
head.set(RECURRENCE_EXCEPTION, recurrenceException + (recurrenceException && newException ? EXCEPTION_SEPARATOR : "") + newException);
}
}
});
function expandAll(events, start, end, zone) {
var length = events.length,
data = [],
idx = 0;
for (; idx < length; idx++) {
data = data.concat(events[idx].expand(start, end, zone));
}
return data;
}
SchedulerDataSource.create = function(options) {
if (isArray(options) || options instanceof kendo.data.ObservableArray) {
options = { data: options };
}
var dataSource = options || {},
data = dataSource.data;
dataSource.data = data;
if (!(dataSource instanceof SchedulerDataSource) && dataSource instanceof kendo.data.DataSource) {
throw new Error("Incorrect DataSource type. Only SchedulerDataSource instances are supported");
}
return dataSource instanceof SchedulerDataSource ? dataSource : new SchedulerDataSource(dataSource);
};
extend(true, kendo.data, {
SchedulerDataSource: SchedulerDataSource,
SchedulerDataReader: SchedulerDataReader,
SchedulerEvent: SchedulerEvent
});
var defaultCommands = {
update: {
text: "Save",
className: "k-primary k-scheduler-update"
},
canceledit: {
text: "Cancel",
className: "k-scheduler-cancel"
},
destroy: {
text: "Delete",
imageClass: "k-i-close",
className: "k-primary k-scheduler-delete",
iconClass: "k-icon"
}
};
function trimOptions(options) {
delete options.name;
delete options.prefix;
delete options.remove;
delete options.edit;
delete options.add;
delete options.navigate;
return options;
}
/*
function fieldType(field) {
field = field != null ? field : "";
return field.type || $.type(field) || "string";
}
*/
function createValidationAttributes(model, field) {
var modelField = (model.fields || model)[field];
var specialRules = ["url", "email", "number", "date", "boolean"];
var validation = modelField ? modelField.validation : {};
// var type = fieldType(modelField);
var datatype = kendo.attr("type");
var inArray = $.inArray;
var ruleName;
var rule;
var attr = {};
for (ruleName in validation) {
rule = validation[ruleName];
if (inArray(ruleName, specialRules) >= 0) {
attr[datatype] = ruleName;
} else if (!kendo.isFunction(rule)) {
attr[ruleName] = isPlainObject(rule) ? (rule.value || ruleName) : rule;
}
attr[kendo.attr(ruleName + "-msg")] = rule.message;
}
return attr;
}
function dropDownResourceEditor(resource, model) {
var attr = createValidationAttributes(model, resource.field);
return function(container) {
$(kendo.format('<select data-{0}bind="value:{1}" title="' + model.title + '">', kendo.ns, resource.field))
.appendTo(container)
.attr(attr)
.kendoDropDownList({
dataTextField: resource.dataTextField,
dataValueField: resource.dataValueField,
dataSource: resource.dataSource,
valuePrimitive: resource.valuePrimitive,
optionLabel: "None",
template: kendo.format('<span class="k-scheduler-mark" style="background-color:#= data.{0}?{0}:"none" #"></span>#={1}#', resource.dataColorField, resource.dataTextField)
});
};
}
function dropDownResourceEditorMobile(resource, model) {
var attr = createValidationAttributes(model, resource.field);
return function(container) {
var options = "";
var view = resource.dataSource.view();
for (var idx = 0, length = view.length; idx < length; idx++) {
options += kendo.format('<option value="{0}">{1}</option>',
kendo.getter(resource.dataValueField)(view[idx]),
kendo.getter(resource.dataTextField)(view[idx])
);
}
$(kendo.format('<select data-{0}bind="value:{1}">{2}</select>',
kendo.ns,
resource.field,
options,
resource.valuePrimitive
))
.appendTo(container)
.attr(attr);
};
}
function descriptionEditor(options) {
var attr = createValidationAttributes(options.model, options.field);
return function(container, model) {
$('<textarea name="description" class="k-textbox" title="' + model.title + '"/>').attr(attr)
.appendTo(container);
};
}
function multiSelectResourceEditor(resource, model) {
var attr = createValidationAttributes(model, resource.field);
return function(container) {
$(kendo.format('<select data-{0}bind="value:{1}">', kendo.ns, resource.field))
.appendTo(container)
.attr(attr)
.kendoMultiSelect({
dataTextField: resource.dataTextField,
dataValueField: resource.dataValueField,
dataSource: resource.dataSource,
valuePrimitive: resource.valuePrimitive,
itemTemplate: kendo.format('<span class="k-scheduler-mark" style="background-color:#= data.{0}?{0}:"none" #"></span>#={1}#', resource.dataColorField, resource.dataTextField),
tagTemplate: kendo.format('<span class="k-scheduler-mark" style="background-color:#= data.{0}?{0}:"none" #"></span>#={1}#', resource.dataColorField, resource.dataTextField)
});
};
}
function multiSelectResourceEditorMobile(resource, model) {
var attr = createValidationAttributes(model, resource.field);
return function(container) {
var options = "";
var view = resource.dataSource.view();
for (var idx = 0, length = view.length; idx < length; idx++) {
options += kendo.format('<option value="{0}">{1}</option>',
kendo.getter(resource.dataValueField)(view[idx]),
kendo.getter(resource.dataTextField)(view[idx])
);
}
$(kendo.format('<select data-{0}bind="value:{1}" multiple="multiple" data-{0}value-primitive="{3}">{2}</select>',
kendo.ns,
resource.field,
options,
resource.valuePrimitive
))
.appendTo(container)
.attr(attr);
};
}
function moveEventRange(event, distance) {
var duration = event.end.getTime() - event.start.getTime();
var start = new Date(event.start.getTime());
kendo.date.setTime(start, distance);
var end = new Date(start.getTime());
kendo.date.setTime(end, duration, true);
return {
start: start,
end: end
};
}
var editors = {
mobile: {
dateRange: MOBILEDATERANGEEDITOR,
timezonePopUp: MOBILETIMEZONEPOPUP,
timezone: MOBILETIMEZONEEDITOR,
recurrence: MOBILERECURRENCEEDITOR,
description: descriptionEditor,
multipleResources: multiSelectResourceEditorMobile,
resources: dropDownResourceEditorMobile,
isAllDay: MOBILEISALLDAYEDITOR
},
desktop: {
dateRange: DATERANGEEDITOR,
timezonePopUp: TIMEZONEPOPUP,
timezone: TIMEZONEEDITOR,
recurrence: RECURRENCEEDITOR,
description: descriptionEditor,
multipleResources: multiSelectResourceEditor,
resources: dropDownResourceEditor
}
};
var Editor = kendo.Observable.extend({
init: function(element, options) {
kendo.Observable.fn.init.call(this);
this.element = element;
this.options = extend(true, {}, this.options, options);
this.createButton = this.options.createButton;
this.toggleDateValidationHandler = proxy(this._toggleDateValidation, this);
},
_toggleDateValidation: function(e) {
if (e.field == "isAllDay") {
var container = this.container,
isAllDay = this.editable.options.model.isAllDay,
bindAttribute = kendo.attr("bind"),
element, isDateTimeInput, shouldValidate;
container.find("[" + bindAttribute+ "*=end],[" + bindAttribute + "*=start]").each(function() {
element = $(this);
if (valueStartEndBoundRegex.test(element.attr(bindAttribute))) {
isDateTimeInput = element.is("[" + kendo.attr("role") + "=datetimepicker],[type*=datetime]");
shouldValidate = isAllDay !== isDateTimeInput;
element.attr(kendo.attr("validate"), shouldValidate);
}
});
}
},
fields: function(editors, model) {
var that = this;
var messages = that.options.messages;
var timezone = that.options.timezone;
var click = function(e) {
e.preventDefault();
that._initTimezoneEditor(model, this);
};
var fields = [
{ field: "title", title: messages.editor.title /*, format: field.format, editor: field.editor, values: field.values*/ },
{ field: "start", title: messages.editor.start, editor: editors.dateRange, timezone: timezone },
{ field: "end", title: messages.editor.end, editor: editors.dateRange, timezone: timezone },
{ field: "isAllDay", title: messages.editor.allDayEvent, editor: editors.isAllDay }
];
if (kendo.timezone.windows_zones) {
fields.push({ field: "timezone", title: messages.editor.timezone, editor: editors.timezonePopUp, click: click, messages: messages.editor, model: model });
fields.push({ field: "startTimezone", title: messages.editor.startTimezone, editor: editors.timezone, noTimezone: messages.editor.noTimezone });
fields.push({ field: "endTimezone", title: messages.editor.endTimezone, editor: editors.timezone, noTimezone: messages.editor.noTimezone });
}
if (!model.recurrenceId) {
fields.push({ field: "recurrenceRule", title: messages.editor.repeat, editor: editors.recurrence, timezone: timezone, messages: messages.recurrenceEditor, pane: this.pane });
}
if ("description" in model) {
fields.push({ field: "description", title: messages.editor.description, editor: editors.description({model: model, field: "description"}) });
}
for (var resourceIndex = 0; resourceIndex < this.options.resources.length; resourceIndex++) {
var resource = this.options.resources[resourceIndex];
fields.push({
field: resource.field,
title: resource.title,
editor: resource.multiple? editors.multipleResources(resource, model) : editors.resources(resource, model)
});
}
return fields;
},
end: function() {
return this.editable.end();
},
_buildDesktopEditTemplate: function(model, fields, editableFields) {
var messages = this.options.messages;
var settings = extend({}, kendo.Template, this.options.templateSettings);
var paramName = settings.paramName;
var html = "";
for (var idx = 0, length = fields.length; idx < length; idx++) {
var field = fields[idx];
if (field.field === "startTimezone") {
html += '<div class="k-popup-edit-form k-scheduler-edit-form k-scheduler-timezones" style="display:none">';
html += '<div class="k-edit-form-container">';
html += '<div class="k-edit-label"></div>';
html += '<div class="k-edit-field"><label class="k-check"><input class="k-timezone-toggle" type="checkbox" />' + messages.editor.separateTimezones + '</label></div>';
}
html += '<div class="k-edit-label"><label for="' + field.field + '">' + (field.title || field.field || "") + '</label></div>';
if ((!model.editable || model.editable(field.field))) {
editableFields.push(field);
html += '<div ' + kendo.attr("container-for") + '="' + field.field + '" class="k-edit-field"></div>';
} else {
var tmpl = "#:";
if (field.field) {
field = kendo.expr(field.field, paramName);