/**
* Kendo UI v2016.1.112 (http://www.telerik.com/kendo-ui)
* Copyright 2016 Telerik AD. All rights reserved.
*
* Kendo UI commercial licenses may be obtained at
* http://www.telerik.com/purchase/license-agreement/kendo-ui-complete
* If you do not own a commercial license, this file shall be governed by the trial license terms.
*/
(function (f, define) {
define('util/main', ['kendo.core'], f);
}(function () {
(function () {
var math = Math, kendo = window.kendo, deepExtend = kendo.deepExtend;
var DEG_TO_RAD = math.PI / 180, MAX_NUM = Number.MAX_VALUE, MIN_NUM = -Number.MAX_VALUE, UNDEFINED = 'undefined';
function defined(value) {
return typeof value !== UNDEFINED;
}
function round(value, precision) {
var power = pow(precision);
return math.round(value * power) / power;
}
function pow(p) {
if (p) {
return math.pow(10, p);
} else {
return 1;
}
}
function limitValue(value, min, max) {
return math.max(math.min(value, max), min);
}
function rad(degrees) {
return degrees * DEG_TO_RAD;
}
function deg(radians) {
return radians / DEG_TO_RAD;
}
function isNumber(val) {
return typeof val === 'number' && !isNaN(val);
}
function valueOrDefault(value, defaultValue) {
return defined(value) ? value : defaultValue;
}
function sqr(value) {
return value * value;
}
function objectKey(object) {
var parts = [];
for (var key in object) {
parts.push(key + object[key]);
}
return parts.sort().join('');
}
function hashKey(str) {
var hash = 2166136261;
for (var i = 0; i < str.length; ++i) {
hash += (hash << 1) + (hash << 4) + (hash << 7) + (hash << 8) + (hash << 24);
hash ^= str.charCodeAt(i);
}
return hash >>> 0;
}
function hashObject(object) {
return hashKey(objectKey(object));
}
var now = Date.now;
if (!now) {
now = function () {
return new Date().getTime();
};
}
function arrayLimits(arr) {
var length = arr.length, i, min = MAX_NUM, max = MIN_NUM;
for (i = 0; i < length; i++) {
max = math.max(max, arr[i]);
min = math.min(min, arr[i]);
}
return {
min: min,
max: max
};
}
function arrayMin(arr) {
return arrayLimits(arr).min;
}
function arrayMax(arr) {
return arrayLimits(arr).max;
}
function sparseArrayMin(arr) {
return sparseArrayLimits(arr).min;
}
function sparseArrayMax(arr) {
return sparseArrayLimits(arr).max;
}
function sparseArrayLimits(arr) {
var min = MAX_NUM, max = MIN_NUM;
for (var i = 0, length = arr.length; i < length; i++) {
var n = arr[i];
if (n !== null && isFinite(n)) {
min = math.min(min, n);
max = math.max(max, n);
}
}
return {
min: min === MAX_NUM ? undefined : min,
max: max === MIN_NUM ? undefined : max
};
}
function last(array) {
if (array) {
return array[array.length - 1];
}
}
function append(first, second) {
first.push.apply(first, second);
return first;
}
function renderTemplate(text) {
return kendo.template(text, {
useWithBlock: false,
paramName: 'd'
});
}
function renderAttr(name, value) {
return defined(value) && value !== null ? ' ' + name + '=\'' + value + '\' ' : '';
}
function renderAllAttr(attrs) {
var output = '';
for (var i = 0; i < attrs.length; i++) {
output += renderAttr(attrs[i][0], attrs[i][1]);
}
return output;
}
function renderStyle(attrs) {
var output = '';
for (var i = 0; i < attrs.length; i++) {
var value = attrs[i][1];
if (defined(value)) {
output += attrs[i][0] + ':' + value + ';';
}
}
if (output !== '') {
return output;
}
}
function renderSize(size) {
if (typeof size !== 'string') {
size += 'px';
}
return size;
}
function renderPos(pos) {
var result = [];
if (pos) {
var parts = kendo.toHyphens(pos).split('-');
for (var i = 0; i < parts.length; i++) {
result.push('k-pos-' + parts[i]);
}
}
return result.join(' ');
}
function isTransparent(color) {
return color === '' || color === null || color === 'none' || color === 'transparent' || !defined(color);
}
function arabicToRoman(n) {
var literals = {
1: 'i',
10: 'x',
100: 'c',
2: 'ii',
20: 'xx',
200: 'cc',
3: 'iii',
30: 'xxx',
300: 'ccc',
4: 'iv',
40: 'xl',
400: 'cd',
5: 'v',
50: 'l',
500: 'd',
6: 'vi',
60: 'lx',
600: 'dc',
7: 'vii',
70: 'lxx',
700: 'dcc',
8: 'viii',
80: 'lxxx',
800: 'dccc',
9: 'ix',
90: 'xc',
900: 'cm',
1000: 'm'
};
var values = [
1000,
900,
800,
700,
600,
500,
400,
300,
200,
100,
90,
80,
70,
60,
50,
40,
30,
20,
10,
9,
8,
7,
6,
5,
4,
3,
2,
1
];
var roman = '';
while (n > 0) {
if (n < values[0]) {
values.shift();
} else {
roman += literals[values[0]];
n -= values[0];
}
}
return roman;
}
function romanToArabic(r) {
r = r.toLowerCase();
var digits = {
i: 1,
v: 5,
x: 10,
l: 50,
c: 100,
d: 500,
m: 1000
};
var value = 0, prev = 0;
for (var i = 0; i < r.length; ++i) {
var v = digits[r.charAt(i)];
if (!v) {
return null;
}
value += v;
if (v > prev) {
value -= 2 * prev;
}
prev = v;
}
return value;
}
function memoize(f) {
var cache = Object.create(null);
return function () {
var id = '';
for (var i = arguments.length; --i >= 0;) {
id += ':' + arguments[i];
}
if (id in cache) {
return cache[id];
}
return f.apply(this, arguments);
};
}
function ucs2decode(string) {
var output = [], counter = 0, length = string.length, value, extra;
while (counter < length) {
value = string.charCodeAt(counter++);
if (value >= 55296 && value <= 56319 && counter < length) {
extra = string.charCodeAt(counter++);
if ((extra & 64512) == 56320) {
output.push(((value & 1023) << 10) + (extra & 1023) + 65536);
} else {
output.push(value);
counter--;
}
} else {
output.push(value);
}
}
return output;
}
function ucs2encode(array) {
return array.map(function (value) {
var output = '';
if (value > 65535) {
value -= 65536;
output += String.fromCharCode(value >>> 10 & 1023 | 55296);
value = 56320 | value & 1023;
}
output += String.fromCharCode(value);
return output;
}).join('');
}
deepExtend(kendo, {
util: {
MAX_NUM: MAX_NUM,
MIN_NUM: MIN_NUM,
append: append,
arrayLimits: arrayLimits,
arrayMin: arrayMin,
arrayMax: arrayMax,
defined: defined,
deg: deg,
hashKey: hashKey,
hashObject: hashObject,
isNumber: isNumber,
isTransparent: isTransparent,
last: last,
limitValue: limitValue,
now: now,
objectKey: objectKey,
round: round,
rad: rad,
renderAttr: renderAttr,
renderAllAttr: renderAllAttr,
renderPos: renderPos,
renderSize: renderSize,
renderStyle: renderStyle,
renderTemplate: renderTemplate,
sparseArrayLimits: sparseArrayLimits,
sparseArrayMin: sparseArrayMin,
sparseArrayMax: sparseArrayMax,
sqr: sqr,
valueOrDefault: valueOrDefault,
romanToArabic: romanToArabic,
arabicToRoman: arabicToRoman,
memoize: memoize,
ucs2encode: ucs2encode,
ucs2decode: ucs2decode
}
});
kendo.drawing.util = kendo.util;
kendo.dataviz.util = kendo.util;
}());
return window.kendo;
}, typeof define == 'function' && define.amd ? define : function (a1, a2, a3) {
(a3 || a2)();
}));
(function (f, define) {
define('util/text-metrics', [
'kendo.core',
'util/main'
], f);
}(function () {
(function ($) {
var doc = document, kendo = window.kendo, Class = kendo.Class, util = kendo.util, defined = util.defined;
var LRUCache = Class.extend({
init: function (size) {
this._size = size;
this._length = 0;
this._map = {};
},
put: function (key, value) {
var lru = this, map = lru._map, entry = {
key: key,
value: value
};
map[key] = entry;
if (!lru._head) {
lru._head = lru._tail = entry;
} else {
lru._tail.newer = entry;
entry.older = lru._tail;
lru._tail = entry;
}
if (lru._length >= lru._size) {
map[lru._head.key] = null;
lru._head = lru._head.newer;
lru._head.older = null;
} else {
lru._length++;
}
},
get: function (key) {
var lru = this, entry = lru._map[key];
if (entry) {
if (entry === lru._head && entry !== lru._tail) {
lru._head = entry.newer;
lru._head.older = null;
}
if (entry !== lru._tail) {
if (entry.older) {
entry.older.newer = entry.newer;
entry.newer.older = entry.older;
}
entry.older = lru._tail;
entry.newer = null;
lru._tail.newer = entry;
lru._tail = entry;
}
return entry.value;
}
}
});
var defaultMeasureBox = $('
')[0];
var TextMetrics = Class.extend({
init: function (options) {
this._cache = new LRUCache(1000);
this._initOptions(options);
},
options: { baselineMarkerSize: 1 },
measure: function (text, style, box) {
var styleKey = util.objectKey(style), cacheKey = util.hashKey(text + styleKey), cachedResult = this._cache.get(cacheKey);
if (cachedResult) {
return cachedResult;
}
var size = {
width: 0,
height: 0,
baseline: 0
};
var measureBox = box ? box : defaultMeasureBox;
var baselineMarker = this._baselineMarker().cloneNode(false);
for (var key in style) {
var value = style[key];
if (defined(value)) {
measureBox.style[key] = value;
}
}
$(measureBox).text(text);
measureBox.appendChild(baselineMarker);
doc.body.appendChild(measureBox);
if ((text + '').length) {
size.width = measureBox.offsetWidth - this.options.baselineMarkerSize;
size.height = measureBox.offsetHeight;
size.baseline = baselineMarker.offsetTop + this.options.baselineMarkerSize;
}
if (size.width > 0 && size.height > 0) {
this._cache.put(cacheKey, size);
}
measureBox.parentNode.removeChild(measureBox);
return size;
},
_baselineMarker: function () {
return $('')[0];
}
});
TextMetrics.current = new TextMetrics();
function measureText(text, style, measureBox) {
return TextMetrics.current.measure(text, style, measureBox);
}
kendo.util.TextMetrics = TextMetrics;
kendo.util.LRUCache = LRUCache;
kendo.util.measureText = measureText;
}(window.kendo.jQuery));
}, typeof define == 'function' && define.amd ? define : function (a1, a2, a3) {
(a3 || a2)();
}));
(function (f, define) {
define('util/base64', ['util/main'], f);
}(function () {
(function () {
var kendo = window.kendo, deepExtend = kendo.deepExtend, fromCharCode = String.fromCharCode;
var KEY_STR = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
function encodeBase64(input) {
var output = '';
var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
var i = 0;
input = encodeUTF8(input);
while (i < input.length) {
chr1 = input.charCodeAt(i++);
chr2 = input.charCodeAt(i++);
chr3 = input.charCodeAt(i++);
enc1 = chr1 >> 2;
enc2 = (chr1 & 3) << 4 | chr2 >> 4;
enc3 = (chr2 & 15) << 2 | chr3 >> 6;
enc4 = chr3 & 63;
if (isNaN(chr2)) {
enc3 = enc4 = 64;
} else if (isNaN(chr3)) {
enc4 = 64;
}
output = output + KEY_STR.charAt(enc1) + KEY_STR.charAt(enc2) + KEY_STR.charAt(enc3) + KEY_STR.charAt(enc4);
}
return output;
}
function encodeUTF8(input) {
var output = '';
for (var i = 0; i < input.length; i++) {
var c = input.charCodeAt(i);
if (c < 128) {
output += fromCharCode(c);
} else if (c < 2048) {
output += fromCharCode(192 | c >>> 6);
output += fromCharCode(128 | c & 63);
} else if (c < 65536) {
output += fromCharCode(224 | c >>> 12);
output += fromCharCode(128 | c >>> 6 & 63);
output += fromCharCode(128 | c & 63);
}
}
return output;
}
deepExtend(kendo.util, {
encodeBase64: encodeBase64,
encodeUTF8: encodeUTF8
});
}());
return window.kendo;
}, typeof define == 'function' && define.amd ? define : function (a1, a2, a3) {
(a3 || a2)();
}));
(function (f, define) {
define('mixins/observers', ['kendo.core'], f);
}(function () {
(function ($) {
var math = Math, kendo = window.kendo, deepExtend = kendo.deepExtend, inArray = $.inArray;
var ObserversMixin = {
observers: function () {
this._observers = this._observers || [];
return this._observers;
},
addObserver: function (element) {
if (!this._observers) {
this._observers = [element];
} else {
this._observers.push(element);
}
return this;
},
removeObserver: function (element) {
var observers = this.observers();
var index = inArray(element, observers);
if (index != -1) {
observers.splice(index, 1);
}
return this;
},
trigger: function (methodName, event) {
var observers = this._observers;
var observer;
var idx;
if (observers && !this._suspended) {
for (idx = 0; idx < observers.length; idx++) {
observer = observers[idx];
if (observer[methodName]) {
observer[methodName](event);
}
}
}
return this;
},
optionsChange: function (e) {
this.trigger('optionsChange', e);
},
geometryChange: function (e) {
this.trigger('geometryChange', e);
},
suspend: function () {
this._suspended = (this._suspended || 0) + 1;
return this;
},
resume: function () {
this._suspended = math.max((this._suspended || 0) - 1, 0);
return this;
},
_observerField: function (field, value) {
if (this[field]) {
this[field].removeObserver(this);
}
this[field] = value;
value.addObserver(this);
}
};
deepExtend(kendo, { mixins: { ObserversMixin: ObserversMixin } });
}(window.kendo.jQuery));
return window.kendo;
}, typeof define == 'function' && define.amd ? define : function (a1, a2, a3) {
(a3 || a2)();
}));
(function (f, define) {
define('kendo.scheduler', [
'kendo.dropdownlist',
'kendo.editable',
'kendo.multiselect',
'kendo.window',
'kendo.datetimepicker',
'kendo.scheduler.recurrence',
'kendo.scheduler.view',
'kendo.scheduler.dayview',
'kendo.scheduler.agendaview',
'kendo.scheduler.monthview',
'kendo.scheduler.timelineview',
'kendo.mobile.actionsheet',
'kendo.mobile.pane',
'kendo.pdf'
], f);
}(function () {
var __meta__ = {
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: [
'mobile.actionsheet',
'mobile.pane'
]
},
{
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']
}
]
};
(function ($, undefined) {
var kendo = window.kendo, date = kendo.date, input_support = kendo.support.input, MS_PER_DAY = date.MS_PER_DAY, getDate = date.getDate, getMilliseconds = kendo.date.getMilliseconds, recurrence = kendo.recurrence, keys = 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', CHANGE = 'change', CANCEL = 'cancel', REMOVE = 'remove', SAVE = 'save', ADD = 'add', EDIT = 'edit', valueStartEndBoundRegex = /(?:value:start|value:end)(?:,|$)/, TODAY = getDate(new Date()), 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?', DELETESERIESCONFIRM = 'Are you sure you want to delete the whole series?', COMMANDBUTTONTMPL = '#=text#', VIEWBUTTONTEMPLATE = kendo.template('${views[view].title}'), TOOLBARTEMPLATE = kendo.template(''), MOBILETOOLBARTEMPLATE = kendo.template('' + ''), MOBILEDATERANGEEDITOR = function (container, options) {
var attr = { name: options.field };
var datepicker_role = !input_support.date ? kendo.attr('role') + '="datepicker" ' : '';
var datetimepicker_role = kendo.attr('role') + '="datetimepicker" ';
var isAllDay = options.model.isAllDay;
var dateTimeValidate = kendo.attr('validate') + '=\'' + !isAllDay + '\'';
var dateValidate = kendo.attr('validate') + '=\'' + isAllDay + '\'';
appendTimezoneAttr(attr, options);
appendDateCompareValidator(attr, options);
$('').attr(attr).appendTo(container);
$('').attr(attr).appendTo(container);
$('').hide().appendTo(container);
}, DATERANGEEDITOR = function (container, options) {
var attr = { name: options.field }, isAllDay = options.model.isAllDay, dateTimeValidate = kendo.attr('validate') + '=\'' + !isAllDay + '\' ', dateValidate = kendo.attr('validate') + '=\'' + isAllDay + '\' ';
appendTimezoneAttr(attr, options);
appendDateCompareValidator(attr, options);
$('').attr(attr).appendTo(container);
$('').attr(attr).appendTo(container);
$('').appendTo(container);
if (options.field === 'end') {
$('').appendTo(container);
}
$('').hide().appendTo(container);
}, RECURRENCEEDITOR = function (container, options) {
$('').attr({ name: options.field }).appendTo(container).kendoRecurrenceEditor({
start: options.model.start,
timezone: options.timezone,
messages: options.messages
});
}, MOBILERECURRENCEEDITOR = function (container, options) {
$('').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]
});
}, MOBILETIMEZONEPOPUP = function (container, options) {
var text = timezoneButtonText(options.model, options.messages.noTimezone);
$('' + text + '').click(options.click).appendTo(container);
}, TIMEZONEPOPUP = function (container, options) {
$('' + options.messages.timezoneEditorButton + '').click(options.click).appendTo(container);
}, MOBILETIMEZONEEDITOR = function (container, options) {
$('').attr({ name: options.field }).toggle(options.visible).appendTo(container).kendoMobileTimezoneEditor({ optionLabel: options.noTimezone });
}, TIMEZONEEDITOR = function (container, options) {
$('').attr({ name: options.field }).toggle(options.visible).appendTo(container).kendoTimezoneEditor({ optionLabel: options.noTimezone });
};
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 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 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 }
},
startTimezone: { type: 'string' },
end: {
type: 'date',
validation: {
required: true,
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 = {};
if (start && end) {
end = new Date(end.getTime() + MS_PER_DAY - 1);
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.start;
head.set(RECURRENCE_EXCEPTION, head.recurrenceException.replace(recurrence.toExceptionString(start, this.reader.timezone), ''));
}
}
},
_addExceptionDate: function (model) {
var start = model.start;
var zone = this.reader.timezone;
var head = this.get(model.recurrenceId);
var recurrenceException = head.recurrenceException || '';
if (!recurrence.isException(recurrenceException, start, zone)) {
head.set(RECURRENCE_EXCEPTION, recurrenceException + recurrence.toExceptionString(start, zone));
}
}
});
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-delete',
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 createValidationAttributes(model, field) {
var modelField = (model.fields || model)[field];
var specialRules = [
'url',
'email',
'number',
'date',
'boolean'
];
var validation = modelField ? modelField.validation : {};
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('