Ext.ns("Terrasoft.controls.ScheduleItem");
/**
* Calendar item status
* @enum
*/
Terrasoft.controls.ScheduleItem.Status = {
/** New */
NEW: 1,
/** Completed */
DONE: 2,
/** Overdue */
OVERDUE: 3
};
/**
* Abbreviation for {@link Terrasoft.controls.ScheduleItem.Status}
* @member Terrasoft
* @inheritdoc Terrasoft.controls.ScheduleItem.Status
*/
Terrasoft.ScheduleItemStatus = Terrasoft.controls.ScheduleItem.Status;
/**
* Class to work with the schedule.
*/
Ext.define("Terrasoft.controls.ScheduleItem.ScheduleItem", {
alternateClassName: "Terrasoft.ScheduleItem",
extend: "Terrasoft.Component",
/**
* Estimated height of the time slot (em)
* @type {Number}
*/
timeItemHeight: 2.2,
/**
* Estimated height of the multi-day task (px)
* @private
* @type {Number}
*/
multiDayItemHeight: 21,
/**
* View Model collection Id
* @type {Object}
*/
scheduler: null,
/**
* View Model collection Id
* @type {String}
*/
viewModelCollectionItemId: "",
/**
* Item Id
* @type {String}
*/
itemId: null,
/**
* Start date
* @type {Date}
*/
startDate: null,
/**
* End date
* @type {Date}
*/
dueDate: null,
/**
* Title
* @type {String}
*/
title: null,
/**
* Status
* @type {Terrasoft.ScheduleItemStatus}
*/
status: Terrasoft.ScheduleItemStatus.NEW,
/**
* Vertical position of the element
* @type {Number}
*/
top: 0,
/**
* Position of the element horizontally
* @type {Number}
*/
left: 0,
/**
* Item right indent
* @type {Number}
*/
rightSpace: 2,
/**
* Item width
* @type {Number}
*/
width: 100,
/**
* Time slot scale
* @type {Terrasoft.TimeScale}
*/
timeScale: null,
/**
* Item background
* @type {String}
*/
background: null,
/**
* Text color
* @type {String}
*/
fontColor: null,
/**
* Italic type font
* @type {Boolean}
*/
isItalic: false,
/**
* Bold font
* @type {Boolean}
*/
isBold: false,
/**
* Underline font
* @type {Boolean}
*/
isUnderline: false,
/**
* Indicates that the item is selected
* @type {Boolean}
*/
isSelected: false,
/**
* Short day names.
* @type {String[]}
*/
shortDayNames: Terrasoft.Resources.CultureSettings.shortDayNames,
/**
* Click event task item.
* @type {Object}
*/
itemTask: null,
/**
* Click event wait interval.
* @type {Number}
*/
clickHandlerTimeout: 300,
/**
* Common control template, contains the scrolling of elements and a method for rendering content
* @override
* @type {Array}
*/
// jscs:disable
/* jshint quotmark:false */
tpl: ['<div tabindex="0" id="{id}-scheduleritem" style="{schedulerItemStyle}" class="{scheduleItemClass}">', '<div id="{id}-scheduleritem-resize-top" class="{scheduleItemResizeTopClass}"></div>', '{%this.prepareSchedulerItem(out, values)%}', '<div id="{id}-scheduleritem-resize-bottom" class="{scheduleItemResizeBottomClass}"></div>', '</div>'],
/* jshint quotmark:true */
// jscs:enable
/**
* List of styles and classes for mapping a one-day task
* @private
* @type {Object}
*/
oneDayItemConfig: {
classes: {
scheduleItemClass: ["scheduleritem"],
scheduleItemResizeTopClass: ["scheduleritem-resize-top"],
scheduleItemResizeBottomClass: ["scheduleritem-resize-bottom"],
scheduleItemStatusClass: ["scheduleritem-selected", "scheduleritem-new", "scheduleritem-done", "scheduleritem-overdue"],
scheduleItemCaptionClass: ["scheduleritem-caption"],
scheduleItemTitleClass: ["scheduleritem-title"]
}
},
/**
* List of styles and classes for mapping a multi-day task
* @private
* @type {Object}
*/
multiDayItemConfig: {
classes: {
scheduleItemClass: ["multi-day-item"],
scheduleItemResizeTopClass: ["multi-day-item-resize-right"],
scheduleItemResizeBottomClass: ["multi-day-item-resize-left"],
scheduleItemCaptionClass: ["multi-day-item-caption"],
scheduleItemTitleClass: ["multi-day-item-title"],
scheduleItemStatusClass: ["scheduleritem-selected", "scheduleritem-new", "scheduleritem-done", "scheduleritem-overdue"],
scheduleItemLeftCaptionClass: ["multi-day-item-left-caption"]
}
},
/**
* The configuration of the binding of initial values by the method of binding. Defines at what method of data binding
* what property of the class will be assigned during the initialization of the binding. Used in
* Terrasoft.Bindable#setControlInitialValue.
* @private
* @type {Object}
*/
bindInitialValueConfig: {
onItemIdChange: "itemId",
onTitleChange: "title",
onStartDateChange: "startDate",
onDueDateChange: "dueDate",
onStatusChange: "status",
onBackgroundChange: "background",
onFontColorChange: "fontColor",
onIsBoldChange: "isBold",
onIsItalicChange: "isItalic",
onIsUnderlineChange: "isUnderline",
setMarkerValue: "markerValue"
},
/**
* Returns the date taking the time scale into account
* @private
* @param {Date} currentDate The current date
* @param {Date} newDate The new date
* @param {Terrasoft.TimeScale} timeScale Time scale
* @return {Date} The date taking the time scale into account
*/
getNewDateByScale: function (currentDate, newDate, timeScale) {
var newDateMinutes = currentDate.getMinutes();
if (newDateMinutes % timeScale === 0) {
return newDate;
} else {
var millisecondsInMinute = Terrasoft.DateRate.MILLISECONDS_IN_MINUTE;
newDate = newDate - currentDate;
newDate = newDate / millisecondsInMinute;
newDate = Math.floor(newDate / timeScale) + 1;
newDate = newDate * timeScale * millisecondsInMinute;
currentDate = currentDate - 0;
newDate = currentDate + newDate;
newDate = new Date(newDate);
return newDate;
}
},
/**
* Returns the parameters of the rectangle of the dom element
* @private
* @param {Object} The dom element
* @return {Object} The parameters of the rectangle of the dom element
*/
getElementBox: function (element) {
var elementEl = Ext.get(element);
return elementEl.getBox();
},
/**
* Returns the element header
* @private
* @return {String} The element header
*/
getItemCaption: function () {
var result = "";
var startDate = this.startDate;
var dueDate = this.dueDate;
if (this.isMultiDayItem()) {
var scheduleDueDate = Terrasoft.addDays(this.scheduler.getDueDate(), 1);
var isShowCaption = !Terrasoft.areDatesEqual(dueDate, scheduleDueDate) && scheduleDueDate < dueDate;
var showDueDate = new Date(dueDate - 1);
var day = showDueDate.getDate();
var dayOfWeek = showDueDate.getDay();
result = isShowCaption ? Ext.String.format("{0}, {1}", day, this.shortDayNames[dayOfWeek]) : "";
} else {
var startDateMinutes = startDate.getMinutes();
var dueDateMinutes = dueDate.getMinutes();
var timeScale = this.getTimeScale();
if (startDateMinutes % timeScale !== 0 || dueDateMinutes % timeScale !== 0) {
var displayStartDate = Ext.Date.format(startDate, Terrasoft.Resources.CultureSettings.timeFormat);
var displayDueDate = Ext.Date.format(dueDate, Terrasoft.Resources.CultureSettings.timeFormat);
result = Ext.String.format("{0}-{1}", displayStartDate, displayDueDate);
}
}
return result;
},
/**
* Returns the inscription on the left if the multi-day task does not fit into the scope
* @private
* @return {String} Inscription with date
*/
getLeftCaption: function () {
var result;
var startDate = this.getStartDate();
var scheduleStartDate = this.scheduler.getStartDate();
var isShowCaption = !Terrasoft.areDatesEqual(startDate, scheduleStartDate) && startDate < scheduleStartDate;
var day = startDate.getDate();
var dayOfWeek = startDate.getDay();
result = isShowCaption ? Ext.String.format("{0}, {1}", day, this.shortDayNames[dayOfWeek]) : "";
return result;
},
/**
* Checks the equality of days
* @private
* @return {Boolean} Returns the result of checking the equality of days
*/
getIsTheSameDay: function (dateA, dateB) {
return Terrasoft.areDatesEqual(dateA, dateB);
},
/**
* Generates the day column Id
* @private
* @param {Date} date Column date
* @return {String} The day column Id
*/
getDayColumnId: function (date) {
var day = String(date.getDate());
day = day.length === 1 ? Ext.String.format("0{0}", day) : day;
var month = String(date.getMonth() + 1);
month = month.length === 1 ? Ext.String.format("0{0}", month) : month;
var year = date.getFullYear();
return Ext.String.format("-day-{0}-{1}-{2}", day, month, year);
},
/**
* Returns the component to render the element
* @private
* @return {Object} The component to render the element
*/
getRenderTo: function () {
var startDate = this.startDate;
var dueDate = this.dueDate;
if (!startDate || !dueDate) {
return;
}
if (this.isMultiDayItem()) {
return this.scheduler.multiDayItemArea;
}
startDate = new Date(this.startDate);
var dateColumnName = this.getDayColumnId(startDate);
var columnId = Ext.String.format("[id*='{0}']", dateColumnName);
var dateColumn = Ext.select(columnId, false);
if (dateColumn) {
var dateColumnEl = dateColumn.elements;
if (dateColumnEl.length > 0) {
return Ext.get(dateColumnEl[0]);
}
}
},
/**
* Returns the scale of the calendar
* @private
* @return {Terrasoft.TimeScale} Day column Id
*/
getTimeScale: function () {
return this.scheduler.getTimeScale();
},
/**
* Gets an indication that the item is a multi-day
* @private
* @return {Boolean} An indication that the item is a multi-day
*/
isMultiDayItem: function () {
return !Terrasoft.areDatesEqual(this.startDate, this.dueDate);
},
/**
* Updates styles for selected item.
* @private
*/
updateItemSelectionStyle: function () {
var isSelected = this.isSelected;
var selectedCls = "scheduleritem-selected";
var className = "scheduleritem-";
switch (this.status) {
case 2:
className += "done";
break;
case 3:
className += "overdue";
break;
default:
className += "new";
break;
}
var wrapEl = this.getWrapEl();
if (wrapEl && wrapEl.dom) {
var itemBody = wrapEl.child("div");
var itemBodyEl = itemBody.next();
itemBodyEl.addCls(className);
if (isSelected) {
itemBodyEl.addCls(selectedCls);
} else {
itemBodyEl.removeCls(selectedCls);
}
itemBodyEl.setStyle({
"backgroundColor": isSelected ? "" : this.background,
"color": isSelected ? "" : this.fontColor
});
}
},
/**
* Schedule item double click event handler.
* @private
* @param {Object} event Click event.
* @param {Boolean} silent Event execution flag.
*/
onScheduleItemDoubleClick: function (event, silent) {
this.setSelected(event, silent);
this.scheduler.fireEvent("scheduleItemDoubleClick", this);
},
/**
* Schedule item click event handler.
* @private
* @param {Object} event Click event.
* @param {Boolean} silent Event execution flag.
*/
onScheduleItemClick: function (event, silent) {
this.setSelected(event, silent);
var target = this.getWrapEl();
if (target) {
this.scheduler.fireEvent("scheduleItemClick", { targetId: target.id });
}
},
/**
* Schedule item title mouse over event handler.
* @private
*/
onScheduleItemTitleMouseOver: function () {
var target = this.getWrapEl();
this.scheduler.fireEvent("scheduleItemTitleMouseOver", { targetId: target.id }, { recordId: this.itemId });
},
/**
* Schedule item title click event handler.
* @private
* @param {Object} event Click event.
* @param {Boolean} silent Event execution flag.
*/
onScheduleItemTitleClick: function (event, silent) {
this.setSelected(event, silent);
var target = this.getWrapEl();
this.scheduler.fireEvent("scheduleItemTitleClick", { targetId: target.id }, { recordId: this.itemId });
},
/**
* Schedule item title double click event handler.
* @param {Object} event Double click event.
*/
onScheduleItemTitleDoubleClick: function (event) {
event.stopEvent();
},
/**
* Subscribes title events.
* @private
*/
subscribeTitleEvents: function () {
var titleEl = this.getTitleEl();
titleEl.on("mouseover", this.onScheduleItemTitleMouseOver, this);
titleEl.on("click", Terrasoft.debounce(this.onScheduleItemTitleClick, this.clickHandlerTimeout, true), this);
titleEl.on("dblclick", this.onScheduleItemTitleDoubleClick, this);
},
/**
* Unsubscribes title events.
* @private
*/
unSubscribeTitleEvents: function () {
var titleEl = this.getTitleEl();
if (titleEl) {
titleEl.un("mouseover", this.onScheduleItemTitleMouseOver, this);
titleEl.un("click", this.onScheduleItemTitleClick, this);
titleEl.un("dblclick", this.onScheduleItemTitleDoubleClick, this);
}
},
/**
* Initialization of the calendar component
* @protected
* @override
*/
init: function () {
this.callParent(arguments);
this.selectors = {
wrapEl: ""
};
this.addEvents(
/**
* @event changeTitle
* This is triggerd when the header changes
*/
"changeTitle",
/**
* @event changeStartDate
* This is triggered when the start date changes
*/
"changeStartDate",
/**
* @event changeDueDate
* This is triggered when the end date changes
*/
"changeDueDate",
/**
* @event changeStatus
* This is triggered when the status changes
*/
"changeStatus");
},
/**
* Returns title element.
* @protected
* @return {Ext.dom.Element} Title element.
*/
getTitleEl: function () {
var titleEl = this.titleEl;
var multiDayItemTitleEl = this.multiDayItemTitleEl;
if (titleEl) {
return titleEl;
} else if (multiDayItemTitleEl) {
return multiDayItemTitleEl;
}
},
/**
* @inheritdoc Terrasoft.Component#initDomEvents
* @protected
* @override
*/
initDomEvents: function () {
this.callParent(arguments);
var wrapEl = this.getWrapEl();
wrapEl.on("click", Terrasoft.debounce(this.onScheduleItemClick, this.clickHandlerTimeout, true), this);
wrapEl.on("dblclick", this.onScheduleItemDoubleClick, this);
this.subscribeTitleEvents();
},
/**
* Destroys a calendar item
* @protected
* @override
*/
onDestroy: function () {
var wrapEl = this.getWrapEl();
if (wrapEl) {
wrapEl.un("click", this.onScheduleItemClick, this);
wrapEl.un("dblclick", this.onScheduleItemDoubleClick, this);
}
this.unSubscribeTitleEvents();
this.callParent(arguments);
},
/**
* Returns the configuration of the binding to the model. Implements the {@link Terrasoft.Bindable} mixin interface.
* @protected
* @override
*/
getBindConfig: function () {
var bindConfig = this.callParent(arguments);
var itemBindConfig = {
itemId: {
changeMethod: "onItemIdChange"
},
title: {
changeMethod: "onTitleChange",
changeEvent: "changeTitle"
},
startDate: {
changeMethod: "onStartDateChange",
changeEvent: "changeStartDate"
},
dueDate: {
changeMethod: "onDueDateChange",
changeEvent: "changeDueDate"
},
status: {
changeMethod: "onStatusChange",
changeEvent: "changeStatus"
},
background: {
changeMethod: "onBackgroundChange"
},
fontColor: {
changeMethod: "onFontColorChange"
},
isBold: {
changeMethod: "onIsBoldChange"
},
isItalic: {
changeMethod: "onIsItalicChange"
},
isUnderline: {
changeMethod: "onIsUnderlineChange"
}
};
Ext.apply(itemBindConfig, bindConfig);
return itemBindConfig;
},
/**
* @inheritdoc Terrasoft.Bindable#setControlInitialValue
* @override
*/
setControlInitialValue: function (binding, model) {
var propertyValue = this.getBindingValue(binding, model);
if (Ext.isDate(propertyValue)) {
propertyValue = new Date(propertyValue);
}
var changeMethodName = binding.config.changeMethod;
var bindInitialValueConfig = this.bindInitialValueConfig;
if (!bindInitialValueConfig.hasOwnProperty(changeMethodName)) {
return;
}
var bindPropertyName = bindInitialValueConfig[changeMethodName];
this[bindPropertyName] = propertyValue;
},
/**
* Handler of the "onItemIdChange" event
* @protected
* @param {Terrasoft.BaseViewModel} value
*/
onItemIdChange: function (value) {
this.itemId = value;
},
/**
* Handler of the "onTitleChange" event
* @protected
* @param {Terrasoft.BaseViewModel} value
*/
onTitleChange: function (value) {
this.title = value;
this.show();
},
/**
* Handler of the "onStartDateChange" event
* @protected
* @param {Terrasoft.BaseViewModel} value
*/
onStartDateChange: function (value) {
this.startDate = value;
this.show();
},
/**
* Handler of the "onDueDateChange" event
* @protected
* @param {Terrasoft.BaseViewModel} value
*/
onDueDateChange: function (value) {
this.dueDate = value;
this.show();
},
/**
* Handler of the "onStatusChange" event
* @protected
* @param {Terrasoft.BaseViewModel} value
*/
onStatusChange: function (value) {
this.setStatus(value);
this.show();
},
/**
* Handler of the "onBackgroundChange" event
* @protected
* @param {Terrasoft.BaseViewModel} value
*/
onBackgroundChange: function (value) {
this.background = value;
this.show();
},
/**
* Handler of the "onFontColorChange" event
* @protected
* @param {Terrasoft.BaseViewModel} value
*/
onFontColorChange: function (value) {
this.fontColor = value;
this.show();
},
/**
* Handler of the "onIsBoldChange" event
* @protected
* @param {Terrasoft.BaseViewModel} value
*/
onIsBoldChange: function (value) {
this.isBold = value;
this.show();
},
/**
* Handler of the "onIsItalicChange" event
* @protected
* @param {Terrasoft.BaseViewModel} value
*/
onIsItalicChange: function (value) {
this.isItalic = value;
this.show();
},
/**
* Handler of the "onIsUnderlineChange" event
* @protected
* @param {Terrasoft.BaseViewModel} value
*/
onIsUnderlineChange: function (value) {
this.isUnderline = value;
this.show();
},
/**
* Calculates data for template
* @protected
* @override
* throws {Terrasoft.ItemNotFoundException}
* If no suitable configuration is found among the configurations, then
* an error will be generated that will be processed in the XTemplate, so the only way to detect this
* error is to view the logs.
*/
getTplData: function () {
var tplData = this.callParent(arguments);
this.selectors.wrapEl = Ext.String.format("#{0}-scheduleritem", this.id);
var isMultiDayItem = this.isMultiDayItem();
var classes = isMultiDayItem ? this.multiDayItemConfig.classes : this.oneDayItemConfig.classes;
var styles = {};
var selectors = this.selectors;
selectors.titleEl = Ext.String.format("#{0}-scheduleritem .scheduleritem-title", this.id);
selectors.multiDayItemTitleEl = Ext.String.format("#{0}-scheduleritem .multi-day-item-title", this.id);
if (isMultiDayItem) {
selectors.resizeLeft = ".multi-day-item-resize-left";
selectors.resizeRight = ".multi-day-item-resize-right";
styles.top = Ext.String.format("{0}px", this.top);
styles.left = Ext.String.format("{0}px", this.left);
styles.width = Ext.String.format("{0}px", this.width - this.rightSpace);
} else {
selectors.resizeTop = selectors.wrapEl + "-resize-top";
selectors.resizeBottom = selectors.wrapEl + "-resize-bottom";
var startDate = new Date(this.startDate);
this.top = this.getTimePosition(startDate);
styles.top = Ext.String.format("{0}em", this.top);
if (Terrasoft.getIsRtlMode()) {
styles.right = Ext.String.format("{0}%", this.left);
} else {
styles.left = Ext.String.format("{0}%", this.left);
}
styles.width = Ext.String.format("{0}%", this.width - this.rightSpace);
styles.height = Ext.String.format("{0}em", this.getHeight());
}
tplData.scheduleItemClass = classes.scheduleItemClass;
tplData.scheduleItemResizeTopClass = classes.scheduleItemResizeTopClass;
tplData.scheduleItemResizeBottomClass = classes.scheduleItemResizeBottomClass;
tplData.scheduleItemStatusClass = classes.scheduleItemStatusClass;
tplData.scheduleItemCaptionClass = classes.scheduleItemCaptionClass;
tplData.scheduleItemLeftCaptionClass = classes.scheduleItemLeftCaptionClass;
tplData.scheduleItemTitleClass = classes.scheduleItemTitleClass;
tplData.schedulerItemStyle = styles;
tplData.prepareSchedulerItem = function (out, values) {
var encodeHtml = Terrasoft.encodeHtml;
var schedulerItem = values.self;
var status = schedulerItem.status;
var isSelected = schedulerItem.isSelected;
var schedulerItemStatusClasses = values.scheduleItemStatusClass;
var schedulerItemCaptionClass = values.scheduleItemCaptionClass;
var schedulerItemLeftCaptionClass = values.scheduleItemLeftCaptionClass;
var schedulerItemTitleClass = values.scheduleItemTitleClass;
var doShowCaption = schedulerItem.getHeight() > schedulerItem.timeItemHeight;
var caption = doShowCaption ? schedulerItem.getItemCaption() : "";
var title = encodeHtml(schedulerItem.title);
var markerValue = encodeHtml(schedulerItem.markerValue);
var itemStyle = "";
var background = schedulerItem.background;
var fontColor = schedulerItem.fontColor;
var isBold = schedulerItem.isBold;
var isItalic = schedulerItem.isItalic;
var isUnderline = schedulerItem.isUnderline;
itemStyle = fontColor && !isSelected ? itemStyle + "color: " + fontColor + "; " : itemStyle;
itemStyle = isBold ? itemStyle + "font-weight: bold; " : itemStyle;
itemStyle = isItalic ? itemStyle + "font-style: italic; " : itemStyle;
itemStyle = isUnderline ? itemStyle + "text-decoration: underline; " : itemStyle;
// jscs:disable
/*jshint quotmark: false */
if (background && isSelected) {
out.push('<div style="background: ' + background + ';" class="' + schedulerItemStatusClasses[status] + " " + schedulerItemStatusClasses[0] + '">');
} else if (background && !isSelected) {
out.push('<div style="background: ' + background + ';" class="' + schedulerItemStatusClasses[status] + '">');
} else if (!background && isSelected) {
out.push('<div class="' + schedulerItemStatusClasses[status] + " " + schedulerItemStatusClasses[0] + '">');
} else {
out.push('<div class="' + schedulerItemStatusClasses[status] + '">');
}
if (schedulerItem.isMultiDayItem()) {
out.push('<div class="' + schedulerItemLeftCaptionClass + '">' + schedulerItem.getLeftCaption() + '</div>');
}
out.push('<div class="' + schedulerItemCaptionClass + '">' + caption + "</div>");
itemStyle = itemStyle.length === 0 ? "" : Ext.String.format(' style="{0}" ', itemStyle);
markerValue = markerValue ? Ext.String.format(' data-item-marker="{0}"', markerValue) : "";
title = Ext.String.format('<div class="{0}"{1}{2}>{3}</div>', schedulerItemTitleClass, itemStyle, markerValue, title);
out.push(title);
/*jshint quotmark: true */
// jscs:enable
out.push("</div>");
};
return tplData;
},
/**
* Handler of the "afterrender" event
* @protected
* @override
*/
onAfterRender: function () {
this.callParent(arguments);
this.initDd();
var wrapEl = this.getWrapEl();
wrapEl.unselectable();
},
/**
* Handler of the "afterrerender" event
* @protected
* @override
*/
onAfterReRender: function () {
this.callParent(arguments);
this.initDd();
var wrapEl = this.getWrapEl();
wrapEl.unselectable();
},
/**
* Calendar item render
*/
show: function () {
var container = this.getRenderTo();
if (!container) {
this.setVisible(false);
} else {
this.visible = true;
if (!this.rendered) {
this.render(container);
} else {
this.reRender(null, container);
}
}
},
/**
* Returns the position of the specified date
* @param {Date} date The date
* @param {Boolean} isExact Parameter that determines the accuracy of the calculation
* false - the result will be a multiple of the time intervals
* true - the result will be accurate
* @return {Number} Returns the item's start date position
*/
getTimePosition: function (date, isExact) {
var timeItemHeight = this.timeItemHeight;
var minutes = Terrasoft.getMinutesFromMidnight(date);
return this.getTimeItemNumber(minutes, isExact) * timeItemHeight;
},
/**
* Calculates the number of time intervals relative to the time scale
* @param {Number} minuteCount Number of minutes
* @param {Boolean} isExact Parameter that determines the accuracy of the calculation
* false - the result will be a multiple of the time intervals
* true - the result will be accurate
* @return {Number} Returns the number of time intervals relative to the time scale
*/
getTimeItemNumber: function (minuteCount, isExact) {
var timeScale = this.getTimeScale();
var result = 0;
if (isExact) {
result = minuteCount / timeScale;
} else {
result = Math.floor(minuteCount / timeScale);
}
return result - this.scheduler.startHour * 60 / timeScale;
},
/**
* Calculates the height of the task depending on the scale
* @return {Number} The height of the task depending on the scale
*/
getHeight: function () {
var timeItemHeight = this.timeItemHeight;
return this.getTimeItemCount() * timeItemHeight;
},
/**
* Calculates the number of time units occupied by an element
* @return {Number} The number of time units occupied by an element
*/
getTimeItemCount: function () {
var millisecondsInMinute = Terrasoft.DateRate.MILLISECONDS_IN_MINUTE;
var timeScale = this.getTimeScale();
var epsilon = 1 / (timeScale * millisecondsInMinute);
var startDate = this.startDate.getTime();
var dueDate = this.dueDate.getTime();
var startRangeValue = startDate / (timeScale * millisecondsInMinute);
var dueRangeValue = dueDate / (timeScale * millisecondsInMinute);
startRangeValue = Math.abs(Math.round(startRangeValue) - startRangeValue) < epsilon ? Math.round(startRangeValue) : startRangeValue;
dueRangeValue = Math.abs(Math.round(dueRangeValue) - dueRangeValue) < epsilon ? Math.round(dueRangeValue) : dueRangeValue;
var timeItemCount = Math.ceil(dueRangeValue) - Math.floor(startRangeValue);
return timeItemCount > 0 ? timeItemCount : 1;
},
/**
* Gets the item width (%)
* @return {Number} Item width (%)
*/
getWidth: function () {
return this.width;
},
/**
* Returns the position of the element along the Y axis
* @return {Number} The position of the element along the Y axis
*/
getTop: function () {
return this.top;
},
/**
* Returns the View Model collection model Id
* @return {String} The View Model collection model Id
*/
getViewModelCollectionItemId: function () {
return this.viewModelCollectionItemId;
},
/**
* Gets the record Id
* @return {String} Record Id
*/
getItemId: function () {
return this.itemId;
},
/**
* Returns start date.
* @return {Date} Start date.
*/
getStartDate: function () {
return this.startDate;
},
/**
* Returns due date.
* @return {Date} Due date.
*/
getDueDate: function () {
return this.dueDate;
},
/**
* Gets the indication that the item is selected
* @return {Boolean} The indication that the item is selected
*/
getIsSelected: function () {
return this.isSelected;
},
/**
* Check element and fire click event.
* @param {Object} event Click event.
* @param {Boolean} silent Event execution flag.
*/
setSelected: function (event, silent) {
if (event) {
event.stopEvent(event);
}
var scheduler = this.scheduler;
scheduler.unSelectItems();
this.isSelected = true;
scheduler.getSelectedItems();
if (silent !== true) {
scheduler.fireEvent("changeSelectedItems");
}
this.updateItemSelectionStyle(true);
},
/**
* Clears the item selection.
* @param {Boolean} silent Indicates the need to run the event
* of updating the list of selected items.
*/
setNotSelected: function (silent) {
this.isSelected = false;
if (silent !== true) {
this.scheduler.fireEvent("changeSelectedItems");
}
this.updateItemSelectionStyle(false);
},
/**
* Sets the Id of the View Model collection
* @param {String} value The Id of the View Model collection
*/
setViewModelCollectionItemId: function (value) {
this.viewModelCollectionItemId = value;
this.tag = value;
},
/**
* Sets the item title
* @param {String} title The item title
*/
setTitle: function (title) {
if (this.title === title) {
return;
}
this.title = title;
this.fireEvent("changeTitle", this.title, this);
this.scheduler.fireEvent("change", this);
},
/**
* Sets the element status
* @param {Terrasoft.ScheduleItemStatus} status The element status
*/
setStatus: function (status) {
if (status !== Terrasoft.ScheduleItemStatus.NEW && status !== Terrasoft.ScheduleItemStatus.DONE && status !== Terrasoft.ScheduleItemStatus.OVERDUE) {
throw new Terrasoft.NotImplementedException({
message: Terrasoft.Resources.Controls.ScheduleEdit.SchedulerItemStatusIsNotValid
});
}
if (this.status === status) {
return;
}
this.status = status;
this.fireEvent("changeStatus", this.status, this);
this.scheduler.fireEvent("change", this);
},
/**
* Updates the element start date
* @param {Date} date The element start date
* @param {Boolean} pointInsideMultiDayItemArea Indicates that the task is in the multi-day task area
* @return {Boolean} Returns true if the update is successful
*/
updateDuration: function (date, pointInsideMultiDayItemArea) {
var dueDate,
changeDate = [];
var doMultiDayItemPositionProcess = true;
var isMultiDayItem = this.isMultiDayItem();
var scheduler = this.scheduler;
if (pointInsideMultiDayItemArea && !isMultiDayItem) {
dueDate = Terrasoft.addDays(date, 1);
changeDate.push(this.startDate);
} else if (!pointInsideMultiDayItemArea && isMultiDayItem) {
dueDate = Terrasoft.addMinutes(date, this.getTimeScale());
changeDate.push(date);
} else {
var timeScale = this.getTimeScale();
var startDate = new Date(this.startDate);
var minutesDiff;
date = this.getNewDateByScale(startDate, date, timeScale);
if (Ext.Date.isEqual(startDate, date)) {
if (isMultiDayItem) {
scheduler.multiDayItemPositionProcess();
}
this.show();
return true;
}
changeDate.push(date);
if (!Terrasoft.areDatesEqual(date, startDate)) {
changeDate.push(startDate);
}
dueDate = new Date(this.dueDate);
minutesDiff = (dueDate - startDate) / Terrasoft.DateRate.MILLISECONDS_IN_MINUTE;
dueDate = Terrasoft.addMinutes(date, minutesDiff);
doMultiDayItemPositionProcess = isMultiDayItem;
}
this.startDate = date;
this.dueDate = new Date(dueDate);
scheduler.itemPositionProcess(changeDate);
if (doMultiDayItemPositionProcess) {
scheduler.multiDayItemPositionProcess();
}
this.fireEvent("changeStartDate", this.startDate, this);
this.fireEvent("changeDueDate", this.dueDate, this);
scheduler.fireEvent("change", this);
return true;
},
/**
* Sets item's start date.
* @param {Date} date The date.
* @return {Boolean} True, if the new value has been set. False, if the two dates match.
*/
setStartDate: function (date) {
var startDate = this.startDate;
if (Ext.Date.isEqual(startDate, date)) {
return false;
}
var changeDate = [];
changeDate.push(date);
if (!Terrasoft.areDatesEqual(date, startDate)) {
changeDate.push(startDate);
}
var dueDate = this.dueDate;
var minutesDiff = dueDate - date;
if (minutesDiff < 0) {
throw new Terrasoft.NullOrEmptyException({
message: Terrasoft.Resources.Controls.ScheduleEdit.DaysCountShouldBeGreaterThenZero
});
}
this.startDate = date;
this.fireEvent("changeStartDate", this.startDate, this);
this.scheduler.fireEvent("change", this);
var scheduler = this.scheduler;
scheduler.multiDayItemPositionProcess();
scheduler.itemPositionProcess(changeDate);
return true;
},
/**
* Sets the item's end date.
* @param {Date} date The date.
* @return {Boolean} True, if the new value has been set. False, if date values match.
*/
setDueDate: function (date) {
var dueDate = this.dueDate;
if (Ext.Date.isEqual(dueDate, date)) {
return false;
}
var changeDate = [];
changeDate.push(date);
if (!Terrasoft.areDatesEqual(date, dueDate)) {
changeDate.push(dueDate);
}
var startDate = this.startDate;
var minutesDiff = date - startDate;
if (minutesDiff < 0) {
throw new Terrasoft.NullOrEmptyException({
message: Terrasoft.Resources.Controls.ScheduleEdit.DaysCountShouldBeGreaterThenZero
});
}
var isMultiDayItem = this.isMultiDayItem();
if (!isMultiDayItem && Math.abs(date.getDate() - dueDate.getDate()) === 1 && date.getHours() === 0 && date.getMinutes() === 0) {
date = new Date(date - 1);
} else if (isMultiDayItem) {
date = Terrasoft.addDays(date, 1);
}
this.dueDate = date;
this.fireEvent("changeDueDate", this.dueDate, this);
this.scheduler.fireEvent("change", this);
var scheduler = this.scheduler;
scheduler.multiDayItemPositionProcess();
scheduler.itemPositionProcess(changeDate);
return true;
},
/**
* Sets the X axis position of the element
* @param {Number} left X-axis position value of the element
*/
setLeft: function (left) {
if (this.left === left) {
return;
}
this.left = left;
},
/**
* Sets the width of an element
* @param {Number} width The element width
*/
setWidth: function (width) {
if (this.width === width) {
return;
}
this.width = width;
},
/**
* Sets element top position.
* @param {Number} Element top position.
*/
setTop: function (top) {
if (this.top === top) {
return;
}
this.top = top;
},
/**
* Initializing the allowable values for moving the D&D element.
* @protected
* @param {Object} dragEl Element of the D&D.
*/
initScheduleItemDDTicksOnMove: function (dragEl) {
var ddEl = Ext.get(dragEl.getEl());
var item = dragEl.config.item;
var scheduler = item.scheduler;
var schedulerId = scheduler.id;
var schedulerDayColumnArea = Ext.getElementById(schedulerId + "-scheduler-day-column-area");
var firstColumn = Terrasoft.getIsRtlMode() ? schedulerDayColumnArea.lastChild : schedulerDayColumnArea.firstChild;
var lastColumn = Terrasoft.getIsRtlMode() ? schedulerDayColumnArea.firstChild : schedulerDayColumnArea.lastChild;
var schedulerDayColumnAreaFirstChildElBox = item.getElementBox(firstColumn);
var schedulerDayColumnAreaLastChildElBox = item.getElementBox(lastColumn);
var xLeft = schedulerDayColumnAreaFirstChildElBox.left;
dragEl.minX = dragEl.initPageX = xLeft;
var scrollbarSize = Ext.getScrollbarSize();
var xRightNumber = schedulerDayColumnAreaLastChildElBox.right - ddEl.getWidth();
var xRight = !scrollbarSize.width ? xRightNumber : xRightNumber + scrollbarSize.width;
dragEl.maxX = xRight;
var tickX = schedulerDayColumnAreaFirstChildElBox.width;
dragEl.setXTicks(xLeft, tickX);
var schedulerDayRowArea = Ext.get(schedulerId + "-scheduler-day-row-area");
var schedulerDayRowAreaDom = schedulerDayRowArea.dom;
var schedulerDayRowAreaLastChildElBox = item.getElementBox(schedulerDayRowAreaDom.lastChild);
var schedulerDayRowAreaFirstChildElBox = item.getElementBox(schedulerDayRowAreaDom.firstChild);
var yTop = schedulerDayRowAreaFirstChildElBox.top;
var ddElHeight = Ext.isIE ? ddEl.getHeight() / 2 : ddEl.getHeight();
var yBottom = schedulerDayRowAreaLastChildElBox.bottom - ddElHeight;
dragEl.minY = dragEl.initPageY = yTop;
dragEl.maxY = yBottom;
var tickY = schedulerDayRowAreaLastChildElBox.height;
dragEl.setYTicks(yTop, tickY);
var viewArea = Ext.get(schedulerId + "-scroll-area");
var viewAreaBox = viewArea.getBox();
var yTicks = dragEl.yTicks;
var top = viewAreaBox.top;
var bottom = viewAreaBox.bottom;
yTicks = Ext.Array.filter(yTicks, function (item) {
if (item <= bottom && item >= top) {
return true;
}
});
var scheduleMultiDayItemAreaBox = scheduler.multiDayItemArea.getBox();
var multiDayItemAreaYTicks = this.getYTicksForMultiDayItemArea(scheduleMultiDayItemAreaBox);
dragEl.yTicks = Ext.Array.merge(multiDayItemAreaYTicks, yTicks);
},
/**
* Calculates an array of moving points of an element vertically
* @protected
* @param {Object} scheduleItemDayItemAreaBox object with the dimensions of the area of multi-day tasks
*/
getYTicksForMultiDayItemArea: function (scheduleItemDayItemAreaBox) {
var yTicks = [];
var multiDayItemHeight = this.multiDayItemHeight;
var MultiDayItemAreaLayoutSizes = Terrasoft.MultiDayItemAreaLayoutSizes;
var top = scheduleItemDayItemAreaBox.top + MultiDayItemAreaLayoutSizes.MULTI_DAY_ITEM_PADDING_TOP;
var bottom = scheduleItemDayItemAreaBox.bottom - MultiDayItemAreaLayoutSizes.MULTI_DAY_ITEM_PADDING_BOTTOM;
yTicks.push(top);
while (top < bottom) {
top = top + multiDayItemHeight + MultiDayItemAreaLayoutSizes.BORDER_HEIGHT;
yTicks.push(top);
}
return yTicks;
},
/**
* Initializes resize constraints of the D&D element.
* @protected
* @param {Object} dragEl D&D element.
* @param {Terrasoft.DDAction} resizeDirection Resize direction.
*/
initScheduleItemDDTicksOnHorizontalResize: function (dragEl, resizeDirection) {
var item = dragEl.config.item;
var scheduler = item.scheduler;
var schedulerId = scheduler.id;
var schedulerDayColumnArea = Ext.get(schedulerId + "-scheduler-day-column-area");
dragEl.setYConstraint(0, 0, 0);
var borderWidth = Terrasoft.MultiDayItemAreaLayoutSizes.BORDER_WIDTH;
var resizeParams = this._getConstraintResizeParams(item, schedulerDayColumnArea, borderWidth, resizeDirection);
dragEl.setXConstraint(resizeParams.xLeft, resizeParams.xRight, resizeParams.tickWidth);
},
/**
* Returns drag element resize constraints for resizing.
* @private
* @param {Object} item D&D element config item.
* @param {Object} schedulerDayColumnArea D&D scheduler day column area.
* @param {Number} borderWidth D&D element border width.
* @param {Terrasoft.DDAction} resizeDirection Resize direction.
* @return {Object} Resize constraints.
*/
_getConstraintResizeParams: function (item, schedulerDayColumnArea, borderWidth, resizeDirection) {
var itemWrapEl = item.getWrapEl();
var itemBox = itemWrapEl.getBox();
if (Terrasoft.getIsRtlMode()) {
if (resizeDirection === Terrasoft.DDAction.RESIZE_LEFT) {
return this._getConstraintResizeParamsLeft(itemBox, item.getElementBox(schedulerDayColumnArea.dom.lastChild), borderWidth);
} else {
return this._getConstraintResizeParamsRight(itemBox, item.getElementBox(schedulerDayColumnArea.dom.firstChild), borderWidth);
}
} else {
if (resizeDirection === Terrasoft.DDAction.RESIZE_LEFT) {
return this._getConstraintResizeParamsLeft(itemBox, item.getElementBox(schedulerDayColumnArea.dom.firstChild), borderWidth);
} else {
return this._getConstraintResizeParamsRight(itemBox, item.getElementBox(schedulerDayColumnArea.dom.lastChild), borderWidth);
}
}
},
/**
* Returns drag element resize constraints for the left side resizing.
* @private
* @param {Object} itemBox D&D element itemBox.
* @param {Object} dayColumnItemBox D&D column element itemBox.
* @param {Number} borderWidth D&D element border width.
* @return {Object} Resize constraints.
*/
_getConstraintResizeParamsLeft: function (itemBox, dayColumnItemBox, borderWidth) {
var xLeft;
var xRight;
var tickWidth = dayColumnItemBox.width;
xLeft = itemBox.left - dayColumnItemBox.left;
xLeft = xLeft + Math.ceil(xLeft / tickWidth) * borderWidth;
xRight = itemBox.width - tickWidth;
xRight = xRight + Math.ceil(xRight / tickWidth) * borderWidth;
return {
xLeft: xLeft,
xRight: xRight,
tickWidth: tickWidth
};
},
/**
* Returns drag element resize constraints for the right side resizing.
* @private
* @param {Object} itemBox D&D element itemBox.
* @param {Object} dayColumnItemBox D&D column element itemBox.
* @param {Number} borderWidth D&D element border width.
* @return {Object} Resize constraints.
*/
_getConstraintResizeParamsRight: function (itemBox, dayColumnItemBox, borderWidth) {
var xLeft;
var xRight;
var tickWidth = dayColumnItemBox.width;
xLeft = itemBox.width - tickWidth;
xLeft = xLeft + Math.ceil(xLeft / tickWidth) * borderWidth;
xRight = dayColumnItemBox.right - itemBox.right;
xRight = xRight + Math.ceil(xRight / tickWidth) * borderWidth;
return {
xLeft: xLeft,
xRight: xRight,
tickWidth: tickWidth
};
},
/**
* Initializing the allowable values for changing the size of the top of the Drag-and-Drop element
* @protected
* @param {Object} dragEl The Drag-and-Drop element
*/
initScheduleItemDDTicksOnResizeTop: function (dragEl) {
var item = dragEl.config.item;
var scheduler = item.scheduler;
var schedulerId = scheduler.id;
var schedulerDayRowArea = Ext.get(schedulerId + "-scheduler-day-row-area");
var schedulerDayRowAreaFirstChildElBox = item.getElementBox(schedulerDayRowArea.dom.firstChild);
dragEl.setXConstraint(0, 0, 0);
var yTop = schedulerDayRowAreaFirstChildElBox.top;
var tick = schedulerDayRowAreaFirstChildElBox.height;
var itemWrapEl = item.getWrapEl();
var itemWrapElBottom = itemWrapEl.getBottom();
// BrowserSupport: IE
// Adjustment of allowable values for Drag-and-Drop
var yBottom = Ext.isIE ? itemWrapElBottom : itemWrapElBottom - tick;
dragEl.minY = dragEl.initPageY = yTop;
dragEl.maxY = yBottom;
dragEl.setYTicks(yTop, tick);
},
/**
* Initializing the allowed values for resizing the bottom of the Drag-and-Drop element
* @protected
* @param {Object} dragEl Drag&drop element
*/
initScheduleItemDDTicksOnResizeBottom: function (dragEl) {
var item = dragEl.config.item;
var scheduler = item.scheduler;
var schedulerId = scheduler.id;
var schedulerDayRowArea = Ext.get(schedulerId + "-scheduler-day-row-area");
var schedulerDayRowAreaDom = schedulerDayRowArea.dom;
var schedulerDayRowAreaFirstChildElBox = item.getElementBox(schedulerDayRowAreaDom.firstChild);
var schedulerDayRowAreaLastChildElBox = item.getElementBox(schedulerDayRowAreaDom.lastChild);
var tick = schedulerDayRowAreaFirstChildElBox.height;
dragEl.setXConstraint(0, 0, 0);
var yTop = item.getWrapEl().getTop() + tick;
// BrowserSupport: IE
// Adjustment of allowable values for Drag-and-Drop
var fixIE = 5;
var yBottom = Ext.isIE ? schedulerDayRowAreaLastChildElBox.bottom + fixIE : schedulerDayRowAreaLastChildElBox.bottom;
dragEl.minY = dragEl.initPageY = yTop;
dragEl.maxY = yBottom;
dragEl.setYTicks(yTop, tick);
},
ddItemOverride: {
b4StartDrag: function () {
var item = this.config.item;
item.unSubscribeTitleEvents();
var scheduler = item.scheduler;
var el = this.el = Ext.get(this.id);
this.elStyle = {
width: el.getStyle("width"),
left: el.getStyle("left")
};
var styles = {
"z-index": "12"
};
if (!item.isMultiDayItem()) {
styles.width = "100%";
styles.left = "0";
}
el.setStyle(styles);
scheduler.itemDDEl = {
item: this,
action: Terrasoft.DDAction.MOVE
};
item.initScheduleItemDDTicksOnMove(this);
var itemWrapEl = item.getWrapEl();
item.setSelected();
var point = itemWrapEl.getXY();
var multiDayItemAreaBox = scheduler.multiDayItemArea.getBox();
this.isMultidayItem = this.pointInsideRegion(point, multiDayItemAreaBox);
},
onDrag: function (event) {
var isMultidayItem;
var item = this.config.item;
var scheduler = item.scheduler;
var multiDayItemAreaBox = scheduler.multiDayItemArea.getBox();
var oneDayArea = Ext.get(scheduler.id + "-scroll-area");
var oneDayAreaBox = oneDayArea.getBox();
var ddEl = Ext.get(this.getEl());
var x = event.getX();
var y = event.getY();
isMultidayItem = this.pointInsideRegion([x, y], multiDayItemAreaBox);
var isItemInsideOneDayItemArea = this.pointInsideRegion([x, y], oneDayAreaBox);
if (isMultidayItem !== this.isMultidayItem) {
this.isMultidayItem = isMultidayItem;
var xTickSize = this.xTickSize;
var yTickSize = this.yTickSize;
var isOneDayItemInsideMultiDayItemArea = isMultidayItem && !item.isMultiDayItem();
var isMultiDayItemInsideOneDayItemArea = isItemInsideOneDayItemArea && item.isMultiDayItem();
if (isOneDayItemInsideMultiDayItemArea) {
var deltaY = this.deltaY;
this.deltaY = deltaY - yTickSize * Math.floor(deltaY / yTickSize);
ddEl.setStyle("position", "fixed");
ddEl.setHeight(item.multiDayItemHeight);
ddEl.setWidth(xTickSize);
} else if (isMultiDayItemInsideOneDayItemArea) {
ddEl.setWidth(xTickSize);
var deltaX = this.deltaX;
this.deltaX = deltaX - xTickSize * Math.floor(deltaX / xTickSize);
item.initScheduleItemDDTicksOnMove(this);
}
}
x = this.x = this.getTick(x - this.deltaX, this.xTicks);
y = this.y = this.getTick(y - this.deltaY, this.yTicks);
ddEl.setXY([x, y]);
},
onInvalidDrop: function () {
this.el.setStyle({
"z-index": "10",
"width": this.elStyle.width,
"left": this.elStyle.left
});
this.x = null;
this.y = null;
this.invalidDrop = true;
},
endDrag: function () {
var item = this.config.item;
item.subscribeTitleEvents();
if (this.invalidDrop === true) {
item.reRender();
delete this.invalidDrop;
}
},
onDragDrop: function (event) {
var x = event.getX();
var y = event.getY();
if (!this.x || !this.y) {
this.y = this.getTick(y - this.deltaY, this.yTicks);
this.x = this.getTick(x - this.deltaX, this.xTicks);
}
if (Terrasoft.getIsRtlMode() && this.el.dom) {
var elWidth = this.el.getWidth();
var elementTick = this.getTick(x + elWidth - this.deltaX, this.xTicks);
this.x = x + elWidth - this.deltaX <= this.xTicks[this.xTicks.length - 1] ? elementTick - this.xTickSize : elementTick;
}
var item = this.config.item;
var scheduler = item.scheduler;
var multiDayItemAreaBox = scheduler.multiDayItemArea.getBox();
var point = [this.x + 5, this.y + this.yTickSize / 2];
var pointInsideFewDayItemArea = this.pointInsideFewDayItemArea = this.pointInsideRegion([x, y], multiDayItemAreaBox);
var ddm = this.DDMInstance;
var days = ddm.ids.day;
var times = ddm.ids.time;
var date = this.pointInsideDays(point, days);
var time = pointInsideFewDayItemArea ? { hour: 0, minute: 0 } : this.pointInsideTimes(point, times);
if (!date || !time) {
this.onInvalidDrop();
return;
}
var dateObject = new Date(date.year, date.month, date.day, time.hour, time.minute);
item.updateDuration(dateObject, pointInsideFewDayItemArea);
scheduler.itemDDEl = null;
},
pointInsideInterval: function (point, interval) {
var x = point[0];
return interval.left < x && x < interval.right;
},
pointInsideDays: function (point, days) {
for (var i in days) {
var day = days[i];
var dayEl = day.getEl();
var region = Ext.util.Region.getRegion(dayEl);
var isPointInsideRegion = this.pointInsideFewDayItemArea ? this.pointInsideInterval(point, region) : this.pointInsideRegion(point, region);
if (isPointInsideRegion) {
var date = this.dateRe.exec(dayEl.id);
var result = {
day: date[1],
month: date[2],
year: date[3]
};
result.month = result.month - 1;
if (result.month.length === 1) {
result.month += "0";
}
return result;
}
}
return false;
},
pointInsideTimes: function (point, times) {
var result;
for (var i in times) {
var time = times[i];
var timeEl = time.getEl();
var region = Ext.util.Region.getRegion(timeEl);
if (this.pointInsideRegion(point, region)) {
var timing = this.timeRe.exec(timeEl.id);
result = {
hour: timing[1],
minute: timing[2]
};
}
}
return result;
},
pointInsideRegion: function (point, region) {
var x = point[0];
var y = point[1];
return !(x < region.left || x > region.right || y < region.top || y > region.bottom);
},
dateRe: new RegExp("(\\d{2})-(\\d{2})-(\\d{4})$"),
timeRe: new RegExp("(\\d{1,2})-(\\d{1,2})$")
},
ddItemResizeTopOverride: {
b4StartDrag: function () {
var item = this.config.item;
var el = this.el = Ext.get(this.id);
var elParent = this.elParent = el.parent();
// BrowserSupport: IE8 CR-207952
if (Ext.isIE8) {
this.position = {
top: elParent.getTop(),
bottom: elParent.getBottom()
};
}
elParent.setStyle({
"z-index": "11",
"width": "100%",
"left": 0
});
var scheduler = item.scheduler;
scheduler.itemDDEl = {
item: this,
action: Terrasoft.DDAction.RESIZE_TOP
};
item.initScheduleItemDDTicksOnResizeTop(this);
item.setSelected();
},
onDrag: function (event) {
var parent = this.elParent;
var parentRegion = parent.getRegion();
// BrowserSupport: IE8 CR-207952: При изменении размера(тянуть активность вниз или вверх): размер активности
// во время растягивания отображается не корректно (увеличивается в противоположном направлении)
var position = this.position;
if (Ext.isIE8) {
parentRegion.top = position.top;
parentRegion.bottom = position.bottom;
parent.setRegion(parentRegion);
}
this.y = this.getTick(event.getY() - this.deltaY, this.yTicks);
parentRegion.top = this.y;
// BrowserSupport: IE8 CR-207952: При изменении размера(тянуть активность вниз или вверх): размер активности
// во время растягивания отображается не корректно(увеличивается в противоположном направлении)
if (Ext.isIE8) {
parentRegion.bottom = position.bottom;
}
parent.setRegion(parentRegion);
},
onDragDrop: function () {
var el = Ext.get(this.id);
var point = el.getXY();
if (!this.y) {
var y = el.getY();
this.y = this.getTick(y - this.deltaY, this.yTicks);
}
point[1] = this.y === this.minY ? this.y : this.y + this.yTickSize / 2;
var ddm = this.DDMInstance;
var times = ddm.ids.time;
var time = this.pointInsideTimes(point, times);
var item = this.config.item;
var itemStartDate = new Date(item.getStartDate());
itemStartDate = new Date(itemStartDate.getFullYear(), itemStartDate.getMonth(), itemStartDate.getDate(), time.hour, time.minute);
if (item.setStartDate(itemStartDate)) {
item.scheduler.itemDDEl = null;
}
},
pointInsideTimes: function (point, times) {
var result;
for (var i in times) {
var time = times[i];
var timeEl = time.getEl();
var region = Ext.util.Region.getRegion(timeEl);
if (this.pointInsideRegion(point, region)) {
var timing = this.timeRe.exec(timeEl.id);
result = {
hour: timing[1],
minute: timing[2]
};
}
}
return result;
},
pointInsideRegion: function (point, region) {
var x = point[0];
var y = point[1];
return !(x < region.left || x > region.right || y < region.top || y > region.bottom);
},
dateRe: new RegExp("(\\d{2})-(\\d{2})-(\\d{4})$"),
timeRe: new RegExp("(\\d{1,2})-(\\d{1,2})$")
},
ddItemResizeBottomOverride: {
b4StartDrag: function () {
var item = this.config.item;
var el = this.el = Ext.get(this.id);
var elParent = this.elParent = el.parent();
this.position = {
top: elParent.getTop(),
bottom: elParent.getBottom()
};
elParent.setStyle({
"z-index": "11",
"width": "100%",
"left": 0
});
item.scheduler.itemDDEl = {
item: this,
action: Terrasoft.DDAction.RESIZE_BOTTOM
};
item.initScheduleItemDDTicksOnResizeBottom(this);
item.setSelected();
},
onDrag: function (event) {
var parent = this.elParent;
var parentRegion = parent.getRegion();
// BrowserSupport: IE8 CR-207952
var position = this.position;
if (Ext.isIE8) {
parentRegion.top = position.top;
parentRegion.bottom = position.bottom;
parent.setRegion(parentRegion);
}
this.y = this.getTick(event.getY() - this.deltaY, this.yTicks);
parentRegion.bottom = this.y;
// BrowserSupport: IE8 CR-207952
if (Ext.isIE8) {
parentRegion.top = position.top;
}
parent.setRegion(parentRegion);
},
onDragDrop: function (event) {
if (!this.y) {
var y = event.getY();
this.y = this.getTick(y - this.deltaY, this.yTicks);
}
var point = event.getXY();
var pointMaxCorrection = this.y - this.yTickSize / 2;
var pointCorrection = this.y + this.yTickSize / 2;
if (this.y >= this.maxY) {
point[1] = pointMaxCorrection;
} else {
// BrowserSupport: IE Корректировка расчетов изменения размеров элемента при изменении размера
// элемента снизу: без этого устанавливается размер на ячейку меньше чем нужно
point[1] = Ext.isIE ? pointMaxCorrection + this.yTickSize : pointCorrection;
}
var ddm = this.DDMInstance;
var times = ddm.ids.time;
var time = this.pointInsideTimes(point, times);
var item = this.config.item;
var itemDueDate = new Date(item.getDueDate());
itemDueDate = new Date(itemDueDate.getFullYear(), itemDueDate.getMonth(), itemDueDate.getDate(), time.hour, time.minute);
var timeScale = item.getTimeScale();
if (this.maxY - this.yTickSize < this.y) {
itemDueDate = Terrasoft.addMinutes(itemDueDate, timeScale);
}
if (item.setDueDate(itemDueDate)) {
item = this.config.item;
item.scheduler.itemDDEl = null;
}
},
pointInsideTimes: function (point, times) {
var result;
for (var i in times) {
var time = times[i];
var timeEl = time.getEl();
var region = Ext.util.Region.getRegion(timeEl);
if (this.pointInsideRegion(point, region)) {
var timing = this.timeRe.exec(timeEl.id);
result = {
hour: timing[1],
minute: timing[2]
};
}
}
return result;
},
pointInsideRegion: function (point, region) {
var x = point[0];
var y = point[1];
return !(x < region.left || x > region.right || y < region.top || y > region.bottom);
},
dateRe: new RegExp("(\\d{2})-(\\d{2})-(\\d{4})$"),
timeRe: new RegExp("(\\d{1,2})-(\\d{1,2})$")
},
ddItemResizeLeftOverride: {
b4StartDrag: function () {
var item = this.config.item;
var el = this.el = Ext.get(this.id);
var elParent = this.elParent = el.parent();
// BrowserSupport: IE8 CR-207952
if (Ext.isIE8) {
this.position = {
top: elParent.getTop(),
bottom: elParent.getBottom(),
left: elParent.getLeft(),
right: elParent.getRight()
};
}
elParent.setStyle({
"z-index": "11"
});
var scheduler = item.scheduler;
scheduler.itemDDEl = {
item: this,
action: Terrasoft.DDAction.RESIZE_LEFT
};
item.initScheduleItemDDTicksOnHorizontalResize(this, Terrasoft.DDAction.RESIZE_LEFT);
item.setSelected();
},
onDrag: function (event) {
var parent = this.elParent;
var parentRegion = parent.getRegion();
// BrowserSupport: IE8 CR-207952: При изменении размера(тянуть активность вниз или вверх): размер активности
// во время растягивания отображается не корректно(увеличивается в противоположном направлении)
var position = this.position;
if (Ext.isIE8) {
parentRegion.left = position.left;
parentRegion.right = position.right;
parent.setRegion(parentRegion);
}
this.x = this.getTick(event.getX() - this.deltaX, this.xTicks);
parentRegion.left = this.x;
// BrowserSupport: IE8 CR-207952: При изменении размера(тянуть активность вниз или вверх): размер активности
// во время растягивания отображается не корректно(увеличивается в противоположном направлении)
if (Ext.isIE8) {
parentRegion.right = position.right;
}
parent.setRegion(parentRegion);
},
endDrag: function (event) {
var point = event.xy;
var item = this.config.item;
if (point[0] < this.minX && item.allowRerender()) {
this.config.item.reRender();
}
},
onDragDrop: function () {
var ddm = this.DDMInstance;
var days = ddm.ids.day;
var date = this.pointInsideDays(this.x + this.xTickSize / 2, days);
var item = this.config.item;
var dateObject = new Date(date.year, date.month, date.day, 0, 0);
var sateDateFn = Terrasoft.getIsRtlMode() ? item.setDueDate : item.setStartDate;
if (sateDateFn.call(item, dateObject)) {
item.scheduler.itemDDEl = null;
}
},
pointInsideDays: function (point, days) {
var result;
for (var i in days) {
var day = days[i];
var dayEl = day.getEl();
var region = Ext.util.Region.getRegion(dayEl);
if (this.pointInsideRegion(point, region)) {
var date = this.dateRe.exec(dayEl.id);
result = {
day: date[1],
month: date[2],
year: date[3]
};
result.month = result.month - 1;
if (result.month.length === 1) {
result.month += "0";
}
}
}
return result;
},
pointInsideRegion: function (xPoint, region) {
return region.left < xPoint && xPoint < region.right;
},
dateRe: new RegExp("(\\d{2})-(\\d{2})-(\\d{4})$"),
timeRe: new RegExp("(\\d{1,2})-(\\d{1,2})$")
},
ddItemResizeRightOverride: {
b4StartDrag: function () {
var item = this.config.item;
var el = this.el = Ext.get(this.id);
var elParent = this.elParent = el.parent();
// BrowserSupport: IE8 CR-207952
if (Ext.isIE8) {
this.position = {
top: elParent.getTop(),
bottom: elParent.getBottom(),
left: elParent.getLeft(),
right: elParent.getRight()
};
}
elParent.setStyle({
"z-index": "11"
});
item.scheduler.itemDDEl = {
item: this,
action: Terrasoft.DDAction.RESIZE_RIGHT
};
item.initScheduleItemDDTicksOnHorizontalResize(this, Terrasoft.DDAction.RESIZE_RIGHT);
item.setSelected();
},
onDrag: function (event) {
var parent = this.elParent;
var parentRegion = parent.getRegion();
this.x = this.getTick(event.getX(), this.xTicks);
parentRegion.right = this.x + this.deltaX;
parent.setRegion(parentRegion);
},
endDrag: function (event) {
var point = event.xy;
var item = this.config.item;
if (point[0] > this.maxX && item.allowRerender()) {
this.config.item.reRender();
}
},
onDragDrop: function () {
var ddm = this.DDMInstance;
var days = ddm.ids.day;
var date = this.pointInsideDays(this.x - this.xTickSize / 2, days);
var item = this.config.item;
var dateObject = new Date(date.year, date.month, date.day, 0, 0);
var sateDateFn = Terrasoft.getIsRtlMode() ? item.setStartDate : item.setDueDate;
if (sateDateFn.call(item, dateObject)) {
item.scheduler.itemDDEl = null;
}
},
pointInsideDays: function (point, days) {
var result;
for (var i in days) {
var day = days[i];
var dayEl = day.getEl();
var region = Ext.util.Region.getRegion(dayEl);
if (this.pointInsideRegion(point, region)) {
var date = this.dateRe.exec(dayEl.id);
result = {
day: date[1],
month: date[2],
year: date[3]
};
result.month = result.month - 1;
if (result.month.length === 1) {
result.month += "0";
}
}
}
return result;
},
pointInsideRegion: function (xPoint, region) {
return region.left < xPoint && xPoint < region.right;
},
dateRe: new RegExp("(\\d{2})-(\\d{2})-(\\d{4})$"),
timeRe: new RegExp("(\\d{1,2})-(\\d{1,2})$")
},
initDd: function () {
Ext.dd.DragDropManager.notifyOccluded = true;
var wrapEl = this.getWrapEl();
var ddItem = wrapEl.initDD("item", { isTarget: false, item: this }, this.ddItemOverride);
ddItem.addToGroup("multi-day-item");
ddItem.addToGroup("day-item");
ddItem.addToGroup("time-item");
if (this.isMultiDayItem()) {
var resizeLeft = this.resizeLeft;
var resizeRight = this.resizeRight;
var ddResizeLeft;
var ddResizeRight;
ddResizeLeft = Terrasoft.getIsRtlMode() ? resizeLeft.initDD("item-resize-left", { isTarget: false, item: this }, this.ddItemResizeRightOverride) : resizeLeft.initDD("item-resize-left", { isTarget: false, item: this }, this.ddItemResizeLeftOverride);
ddResizeRight = Terrasoft.getIsRtlMode() ? resizeRight.initDD("item-resize-right", { isTarget: false, item: this }, this.ddItemResizeLeftOverride) : resizeRight.initDD("item-resize-right", { isTarget: false, item: this }, this.ddItemResizeRightOverride);
ddResizeLeft.addToGroup("multi-day-item");
ddResizeRight.addToGroup("multi-day-item");
} else {
var ddResizeTop = this.resizeTop.initDD("item-resize-top", { isTarget: false, item: this }, this.ddItemResizeTopOverride);
ddResizeTop.addToGroup("day-item");
ddResizeTop.addToGroup("time-item");
var ddResizeBottom = this.resizeBottom.initDD("item-resize-bottom", { isTarget: false, item: this }, this.ddItemResizeBottomOverride);
ddResizeBottom.addToGroup("day-item");
ddResizeBottom.addToGroup("time-item");
}
},
/**
* Gets box of the element by element date.
* @param {Date} date Date of the element.
* @return {Object} Box of the element by element date.
*/
getElBoxByDate: function (date) {
var dayElement = Ext.select("div[id*='" + this.getDayColumnId(date) + "']");
var dayElementFirst = dayElement.first();
return dayElementFirst.getBox();
}
});