ASPxClientAppointmentStatusViewInfo = _aspxCreateClass(null, {
 constructor: function(statusBackDivId, statusForeDivId, statusStartOffset, statusEndOffset) { 
  this.backDivId = statusBackDivId;
  this.foreDivId = statusForeDivId;
  this.startOffset = statusStartOffset;
  this.endOffset = statusEndOffset;
 }
});
ASPxClientAppointmentViewInfo = _aspxCreateClass(null, {
 constructor: function(schedulerViewInfo, containerIndex, firstCellIndex, lastCellIndex, startTime, duration, startRelativeIndent, endRelativeIndent, divId, appointmentId, statusBackDivId, statusForeDivId, statusStartOffset, statusEndOffset) {
  this.schedulerViewInfo = schedulerViewInfo;
  this.containerIndex = containerIndex;
  this.firstCellIndex = firstCellIndex;
  this.lastCellIndex = lastCellIndex;
  this.startRelativeIndent = _aspxIsExists(startRelativeIndent) ? startRelativeIndent : 0;
  this.endRelativeIndent = _aspxIsExists(endRelativeIndent) ? endRelativeIndent : 0;
  this.initialStartRelativeIndent = this.startRelativeIndent;
  this.initialEndRelativeIndent = this.endRelativeIndent;  
  if(startTime != null && duration != null)
   this.appointmentInterval = new ASPxClientTimeInterval(startTime, duration);
  else
   this.appointmentInterval = null;
  this.initialAppointmentInterval = this.appointmentInterval != null ? this.appointmentInterval.Clone() : null;
  this.appointmentId = appointmentId;
  this.visibleStartTime = startTime;
  this.visibleDuration = duration;  
  this.visibleFirstCellIndex = firstCellIndex;
  this.visibleLastCellIndex = lastCellIndex;
  this.divId = divId;
  this.contentDiv = null;
  this.visibleFirstCell = null;
  this.visibleLastCell = null;
  this.mouseEvents = new ASPxSchedulerMouseEvents();
  this.mouseEvents.AddMouseOverHandler(this);
  this.mouseEvents.AddMouseOutHandler(this);
  this.statusViewInfo = new ASPxClientAppointmentStatusViewInfo(statusBackDivId, statusForeDivId, statusStartOffset, statusEndOffset);
 },
 getStartTime: function() {
  return this.appointmentInterval.GetStart();
 },
 getEndTime: function() {  
  return this.appointmentInterval.GetEnd();
 },
 getDuration: function() {  
  return this.appointmentInterval.GetDuration();
 },
 CanResizeAtLeft: function() {
  return false;
 },
 CanResizeAtRight: function() {
  return false;
 },
 CanResizeAtTop: function() {
  return false;
 },
 CanResizeAtBottom: function() {
  return false;
 },
 OnMouseOver: function(evt) {
  this.schedulerViewInfo.OnAppointmentMouseOver(this);
 },
 OnMouseOut: function(evt) {
  this.schedulerViewInfo.OnAppointmentMouseOut(this);
 },
 CanResize: function() {
  var appointment = this.schedulerViewInfo.scheduler.GetAppointment(this.appointmentId);  
  return appointment.flags.allowResize;
 },
 GetToolTip: function() {
  var toolTip = this.schedulerViewInfo.scheduler.GetToolTipControl(this.schedulerViewInfo.scheduler);
  if(!_aspxIsExists(toolTip))
   return null;
  var appointment = this.schedulerViewInfo.scheduler.GetAppointment(this.appointmentId);  
  toolTip.SetContent(appointment.GetToolTipContent(this.schedulerViewInfo.scheduler));
  return toolTip;
 },
 ResetRelativeIndentAndTime: function() {
  this.startRelativeIndent = this.initialStartRelativeIndent;
  this.endRelativeIndent = this.initialEndRelativeIndent;
  this.appointmentInterval = this.initialAppointmentInterval != null ? this.initialAppointmentInterval.Clone() : null;
 }
});
ASPxClientHorizontalAppointmentViewInfo = _aspxCreateClass(ASPxClientAppointmentViewInfo, {
 constructor: function(schedulerViewInfo, containerIndex, firstCellIndex, lastCellIndex, startTime, duration, startRelativeIndent, endRelativeIndent, divId, appointmentId, hasLeftBorder, hasRightBorder, statusBackDivId, statusForeDivId, statusStartOffset, statusEndOffset) {
  this.constructor.prototype.constructor.call(this, schedulerViewInfo, containerIndex, firstCellIndex, lastCellIndex, startTime, duration, startRelativeIndent, endRelativeIndent, divId, appointmentId, statusBackDivId, statusForeDivId, statusStartOffset, statusEndOffset);
  this.height = 0;
  this.relativePosition = 0;
  this.hasLeftBorder = hasLeftBorder;
  this.hasRightBorder = hasRightBorder;
 },
 clone: function() {
  return new ASPxClientHorizontalAppointmentViewInfo(this.schedulerViewInfo, this.containerIndex, this.firstCellIndex, this.lastCellIndex, this.getStartTime(), this.getDuration(),
   this.startRelativeIndent, this.endRelativeIndent, this.divId, this.appointmentId);
 },
 CanResizeAtLeft: function() {
  return this.CanResize() && this.hasLeftBorder;
 },
 CanResizeAtRight: function() {
  return this.CanResize() && this.hasRightBorder;
 },
 IsHorizontal: function() {
  return true;
 }
});
ASPxClientVerticalAppointmentViewInfo = _aspxCreateClass(ASPxClientAppointmentViewInfo, {
 constructor: function(schedulerViewInfo, containerIndex, firstCellIndex, lastCellIndex, startTime, duration, divId, startHorizontalIndex, endHorizontalIndex, maxIndexInGroup, startRelativeIndent, endRelativeIndent, appointmentId, hasTopBorder, hasBottomBorder, statusBackDivId, statusForeDivId, statusStartOffset, statusEndOffset) {  
  this.constructor.prototype.constructor.call(this, schedulerViewInfo, containerIndex, firstCellIndex, lastCellIndex, startTime, duration, startRelativeIndent, endRelativeIndent, divId, appointmentId, statusBackDivId, statusForeDivId, statusStartOffset, statusEndOffset);
  this.startHorizontalIndex = startHorizontalIndex;
  this.endHorizontalIndex = endHorizontalIndex;
  this.maxIndexInGroup = maxIndexInGroup;
  this.hasTopBorder = hasTopBorder;
  this.hasBottomBorder = hasBottomBorder;  
 },
 clone: function(a) {
  return new ASPxClientVerticalAppointmentViewInfo(this.schedulerViewInfo, this.containerIndex, this.firstCellIndex,
   this.lastCellIndex, this.getStartTime(), this.getDuration(), this.divId, this.startHorizontalIndex, this.endHorizontalIndex, this.maxIndexInGroup, this.startRelativeIndent, this.endRelativeIndent, this.appointmentId, this.hasTopBorder, this.hasBottomBorder, statusBackDivId, statusForeDivId, statusStartOffset, statusEndOffset);
 },
 CanResizeAtTop: function() {
  return this.CanResize() && this.hasTopBorder;
 },
 CanResizeAtBottom: function() {
  return this.CanResize() && this.hasBottomBorder;
 },
 IsHorizontal: function() {
  return false;
 }
});
ASPxAppointmentOperationPresenter = _aspxCreateClass(null, {
 constructor: function(scheduler, appointmentDiv) {
  this.scheduler = scheduler;
  this.calculator = this.CreateCalculator();
  this.appointmentDiv = appointmentDiv;
  this.parent = this.GetParent();
  this.parentElement = this.GetParentElement();
  this.schedulerViewInfo = this.GetViewInfo();
  this.isSourceAppointmentVisible = new Object();
  this.sourceViewInfos = new Object();
  this.templateViewInfos = new Object();
  this.viewInfos = new Object();
 },
 ShowAppointment: function(appointment, showSourceAppointment) {
  var aptId = appointment.appointmentId;
  if(!_aspxIsExists(this.sourceViewInfos[aptId]) && !_aspxIsExists(this.templateViewInfos[aptId])) {
   this.sourceViewInfos[aptId] = this.FindSourceViewInfos(aptId, this.schedulerViewInfo);
   this.templateViewInfos[aptId] = this.GetTemplateViewInfos(aptId);
  }
  var sourceViewInfos = this.sourceViewInfos[aptId];
  var templateViewInfos = this.templateViewInfos[aptId];
  this.ShowSourceAppointment(showSourceAppointment, aptId);
  this.HidePrevViewInfos(aptId);
  if(templateViewInfos.length == 0)
   return;
  if(!this.CanShowAppointment(appointment))
   return;
  var containers = this.GetCellContainers();
  var count = containers.length;
  var viewInfos = new Array();
  this.viewInfos[aptId] = viewInfos;
  var operationInterval = appointment.operationInterval;
  var operationIntervalStartTime = operationInterval.GetStart();
  var operationIntervalEndTime = operationInterval.GetEnd();
  for(var i = 0; i < count; i++) {
   var container = containers[i];
   var containerInterval = container.interval;
   var containerStartTime = containerInterval.GetStart();
   var containerEndTime = containerInterval.GetEnd();
   var isAppointmentOutsideCell = operationIntervalStartTime >= containerEndTime || operationIntervalEndTime < containerStartTime || ((operationIntervalEndTime - containerStartTime) == 0 && !operationInterval.IsZerroDurationInterval());
   if(isAppointmentOutsideCell || !this.ShowAppointmentForResource(appointment, container.resource))
    continue;
   var intervalStart = _aspxDateTimeMaxValue(containerStartTime, operationIntervalStartTime);
   var intervalEnd = _aspxDateTimeMinValue(containerEndTime, operationIntervalEndTime);
   this.AddViewInfo(viewInfos, container, intervalStart, intervalEnd);
  }
  count = viewInfos.length;
  for(var i = 0; i < count; i++) {
   var sourceDiv = this.appointmentDiv;
   var isPrimaryAppointment = this.appointmentDiv.appointmentViewInfo.appointmentId == appointment.appointmentId;
   if(count > 1 || !isPrimaryAppointment) {
    if(i == count - 1 && count > 1) {
     var index = templateViewInfos.length - 1;
     sourceDiv = templateViewInfos[index].contentDiv;
    }
    else
     if(i == 0 || !isPrimaryAppointment)
      sourceDiv = templateViewInfos[0].contentDiv;
   }
   var sourceViewInfo = sourceDiv.appointmentViewInfo;
   var newDiv = sourceDiv.cloneNode(true);
   viewInfos[i].maxIndexInGroup = _aspxIsExists(sourceViewInfo.maxIndexInGroup) ? sourceViewInfo.maxIndexInGroup : 1;
   viewInfos[i].startHorizontalIndex = _aspxIsExists(sourceViewInfo.startHorizontalIndex) ? sourceViewInfo.startHorizontalIndex : 0;
   viewInfos[i].endHorizontalIndex = _aspxIsExists(sourceViewInfo.endHorizontalIndex) ? sourceViewInfo.endHorizontalIndex : 1;   
   var sourceStatusInfo = sourceViewInfo.statusViewInfo;
   if (_aspxIsExists(sourceStatusInfo))
    viewInfos[i].statusViewInfo = new ASPxClientAppointmentStatusViewInfo(sourceStatusInfo.backDivId, sourceStatusInfo.foreDivId, 0, 0);
   newDiv.style.width = "";
   newDiv.style.height = "";
   viewInfos[i].contentDiv = newDiv;
   viewInfos[i].startIndex;
   newDiv.appointmentViewInfo = viewInfos[i];
   this.parentElement.appendChild(newDiv);
   this.CalculateAppointmentLayout(viewInfos[i]);
   this.CalculateFinalContentLayout(viewInfos[i]);
   this.scheduler.appointmentSelection.SelectAppointmentViewInfoCore(viewInfos[i]);
  }
 },
 ShowAppointmentForResource: function(appointment, containerResource) {
  var appointmentResources = appointment.operationResources;
  if(!_aspxIsExists(appointmentResources))
   appointmentResources = appointment.resources;
  if(!_aspxIsExists(appointmentResources))
   return false;
  if(ASPxSchedulerUtils.IsAppointmentResourcesEmpty(appointmentResources) ||_aspxArrayIndexOf(appointmentResources, containerResource) >= 0 || containerResource == "null")
   return true;
  return false;
 },
 GetTemplateViewInfos: function(appointmentId) {
  if(this.sourceViewInfos[appointmentId].length != 0)
   return this.sourceViewInfos[appointmentId];
  else {
   var horizontalAppointmentsViewInfos = this.FindSourceViewInfos(appointmentId, this.scheduler.horizontalViewInfo);
   var verticalAppointmentsViewInfos  = this.FindSourceViewInfos(appointmentId, this.scheduler.verticalViewInfo);   
   if(horizontalAppointmentsViewInfos.length > 0)
    return horizontalAppointmentsViewInfos;
   else
    return verticalAppointmentsViewInfos;
  }
 },
 ShowSourceAppointment: function(showSourceAppointment, aptId) {
  if(this.isSourceAppointmentVisible[aptId] != showSourceAppointment) {
   _aspxClearSelection();
   var sourceViewInfos = this.sourceViewInfos[aptId];
   var count = sourceViewInfos.length;
   for(var i = 0; i < count; i++) {
    viewInfo = sourceViewInfos[i];
    _aspxSetSchedulerDivDisplay(viewInfo.contentDiv, showSourceAppointment);
    if(_aspxIsExists(viewInfo.adornerDiv))     
     _aspxSetSchedulerDivDisplay(viewInfo.adornerDiv, showSourceAppointment);
   }
   this.isSourceAppointmentVisible[aptId] = showSourceAppointment;
  }
 },
 HideAppointment: function(aptId, showSourceAppointment) { 
  this.HidePrevViewInfos(aptId);
  if(!_aspxIsExists(this.sourceViewInfos[aptId]) || this.sourceViewInfos[aptId].length == 0)
   return;
  if(showSourceAppointment)
   this.ShowSourceAppointment(true, aptId);
 },
 FindSourceViewInfos: function(appointmentId, viewInfo) {
  var result = new Array();
  var viewInfos = viewInfo.appointmentViewInfos;
  var count = viewInfos.length;
  for(var i = 0; i < count; i++) {
   if(viewInfos[i].appointmentId == appointmentId)
    _aspxArrayPush(result, viewInfos[i]);    
  }  
  return result;
 },
 HidePrevViewInfos: function(aptId) {
  var viewInfos = this.viewInfos[aptId];
  if(!_aspxIsExists(viewInfos))
   return;
  var count = viewInfos.length;
  for(var i = 0; i < count; i++) {   
   this.scheduler.appointmentSelection.UnselectAppointmentViewInfoCore(viewInfos[i]);
   _aspxRecycleNode(viewInfos[i].contentDiv);
   viewInfos[i].contentDiv = null;
  }
  this.viewInfos[aptId] = null;
 },
 CalculateFinalContentLayout: function(viewInfo) {
  this.calculator.CalculateContentDivSize(viewInfo);
 } 
});
ASPxVerticalAppointmentOperationPresenter = _aspxCreateClass(ASPxAppointmentOperationPresenter, {
 constructor: function(scheduler, appointmentDiv) {
  this.constructor.prototype.constructor.call(this, scheduler, appointmentDiv);
  this.isHorizontal = true;
 },
 CreateCalculator: function() {
  return this.scheduler.CreateVerticalAppointmentsCalculator();
 },
 GetCellContainers: function() {
  return this.scheduler.verticalViewInfo.cellContainers;
 },
 GetParent: function() {
  return this.scheduler.verticalViewInfo.parent;
 },
 GetParentElement: function() {
  return this.scheduler.verticalViewInfo.parent.parentElement;
 },
 GetViewInfo: function() {
  return this.scheduler.verticalViewInfo;
 },
 CanShowAppointment: function(appointment) {
  if (this.scheduler.privateShowAllAppointmentsOnTimeCells)
   return true;
  else
   return appointment.operationInterval.IsSmallerThanDay();  
 },
 AddViewInfo: function(aptViewInfos, cellContainer, startTime, endTime) {
  var viewInfo = new ASPxClientVerticalAppointmentViewInfo(this.schedulerViewInfo, cellContainer.containerIndex,
   null, null, startTime, _aspxDateSubsWithTimezone(endTime, startTime), null, 0, 1, 1, 0, 0, null);
  viewInfo.containerIndex = cellContainer.containerIndex;
  var startCellIndex = this.scheduler.verticalViewInfo.FindStartCellIndexByTime(cellContainer, startTime);
  var endCellIndex = this.scheduler.verticalViewInfo.FindEndCellIndexByTime(cellContainer, endTime);
  if(endCellIndex < startCellIndex)
   endCellIndex = startCellIndex;
  viewInfo.visibleFirstCellIndex = startCellIndex;
  viewInfo.visibleLastCellIndex = endCellIndex;
  var startCell = this.scheduler.verticalViewInfo.GetCell(cellContainer.index, startCellIndex);
  var endCell = this.scheduler.verticalViewInfo.GetCell(cellContainer.index, endCellIndex);
  if(!_aspxIsExists(startCell) || !_aspxIsExists(endCell))
   return null;
  var relativeTop = 0;
  var relativeBottom = 0;
  if(!this.scheduler.verticalViewInfo.appointmentsSnapToCells && startCell != endCell) {
   var startCellStartTime = this.scheduler.GetCellStartTime(startCell);
   var endCellEndTime = this.scheduler.GetCellEndTime(endCell);
   var startCellDuration = this.scheduler.GetCellDuration(startCell);
   var endCellDuration = this.scheduler.GetCellDuration(endCell);
   relativeTop = _aspxDateSubsWithTimezone(startTime, startCellStartTime) * startCell.offsetHeight / startCellDuration;
    relativeBottom = _aspxDateSubsWithTimezone(endCellEndTime, endTime) * endCell.offsetHeight / endCellDuration;
  }
  viewInfo.startCell = startCell;
  viewInfo.endCell = endCell;
  viewInfo.startRelativeIndent = relativeTop;
  viewInfo.endRelativeIndent = relativeBottom;
  viewInfo.initialStartRelativeIndent = relativeTop;
  viewInfo.initialEndRelativeIndent = relativeBottom;
  _aspxArrayPush(aptViewInfos, viewInfo);
 },
 CalculateAppointmentLayout: function(viewInfo) {
  this.calculator.CalculateAppointmentLayout(viewInfo);
 }
});
ASPxHorizontalAppointmentOperationPresenter = _aspxCreateClass(ASPxAppointmentOperationPresenter, {
 constructor: function(scheduler, appointmentDiv) {
  this.constructor.prototype.constructor.call(this, scheduler, appointmentDiv);
  this.isHorizontal = false;
 },
 CreateCalculator: function() {
  return this.scheduler.CreateHorizontalAppointmentsCalculator();
 },
 GetCellContainers: function() {
  return this.scheduler.horizontalViewInfo.cellContainers;
 },
 GetParent: function() {
  return this.scheduler.horizontalViewInfo.parent;
 },
 GetParentElement: function() {
  return this.scheduler.horizontalViewInfo.parent.innerParentElement;
 },
 GetViewInfo: function() {
  return this.scheduler.horizontalViewInfo;
 },
 CanShowAppointment: function(appointment) {
  var isDayView = this.scheduler.privateActiveViewType == ASPxSchedulerViewType.Day || this.scheduler.privateActiveViewType == ASPxSchedulerViewType.WorkWeek;
  var isAptLongerThanDay = !appointment.operationInterval.IsSmallerThanDay();     
  var showAllAppointmentsOnTimeCells = this.scheduler.privateShowAllAppointmentsOnTimeCells;
  if (isDayView)    
   return (isAptLongerThanDay && !showAllAppointmentsOnTimeCells);
  else
   return true;     
 },
 AddViewInfo: function(aptViewInfos, cellContainer, startTime, endTime) {
  var startCellIndex = this.scheduler.verticalViewInfo.FindStartCellIndexByTime(cellContainer, startTime);
  var endCellIndex = this.scheduler.verticalViewInfo.FindEndCellIndexByTime(cellContainer, endTime);
  if(startCellIndex < 0 || endCellIndex < 0)
   return null;
  var lastCellTop = null;
  for(var i = startCellIndex; i <= endCellIndex; i++) {
   var cell = this.schedulerViewInfo.GetCell(cellContainer.containerIndex, i);
   var cellTop = this.parent.CalcRelativeElementTop(cell);
   if(cellTop != lastCellTop && lastCellTop != null) {
    var viewInfo = this.CreateSingleViewInfo(cellContainer.containerIndex, startCellIndex, i > startCellIndex ? i - 1 : startCellIndex);
    _aspxArrayPush(aptViewInfos, viewInfo);
    startCellIndex = i;
   }
   lastCellTop = cellTop;
  }
  if(endCellIndex < startCellIndex)
   endCellIndex = startCellIndex;
  var viewInfo = this.CreateSingleViewInfo(cellContainer.containerIndex, startCellIndex, endCellIndex);
  _aspxArrayPush(aptViewInfos, viewInfo);
 },
 CreateSingleViewInfo: function(containerIndex, startCellIndex, endCellIndex) {
  var viewInfo = new ASPxClientHorizontalAppointmentViewInfo(this.schedulerViewInfo, containerIndex, startCellIndex, endCellIndex, null, null, 0, 0, null, this.appointmentDiv.appointmentViewInfo.appointmentId);
  viewInfo.visibleFirstCellIndex = startCellIndex;
  viewInfo.visibleLastCellIndex = endCellIndex;
  viewInfo.containerIndex = containerIndex;
  return viewInfo;
 },
 CalculateAppointmentLayout: function(viewInfo) {
  _aspxSetSchedulerDivDisplay(viewInfo.contentDiv, true);
  this.calculator.CalculateAppointmentSize(viewInfo);
  this.calculator.CalculateAppointmentPosition(viewInfo, true);
 }
});
ASPxDragViewHelper = _aspxCreateClass(null, {
 constructor: function(scheduler, primaryAppointmentId, appointmentDiv) {
  this.scheduler = scheduler;
  this.primaryAppointmentId = primaryAppointmentId;
  this.horizontalDragPresenter = new ASPxHorizontalAppointmentOperationPresenter(scheduler, appointmentDiv);
  this.verticalDragPresenter = new ASPxVerticalAppointmentOperationPresenter(scheduler, appointmentDiv);
 },
 ShowDraggedAppointmentPosition: function(e, draggedAppointments, copy) {
  var count = draggedAppointments.length;
  if(count <= 0)
   return;
  for(var i = 0; i < count; i++) {
   var appointment = draggedAppointments[i];
   copy &= appointment.flags.allowCopy;
   this.horizontalDragPresenter.ShowAppointment(appointment, copy != 0);
   this.verticalDragPresenter.ShowAppointment(appointment, copy != 0);
   if(appointment.appointmentId == this.primaryAppointmentId) {
    var content = appointment.GetToolTipContent(this.scheduler) + "<br />" + this.scheduler.operationToolTipCaption;
    var toolTip = this.scheduler.GetToolTipControl();
    if(_aspxIsExists(toolTip)) {
     toolTip.SetContent(content);
     toolTip.ShowToolTip(_aspxGetEventX(e), _aspxGetEventY(e));
    }
   }
    }
 },
 HideDraggedAppointmentPosition: function(draggedAppointments, restoreAptPos) {
  var count = draggedAppointments.length;
  for(var i = 0; i < count; i++) {
   var appointmentId = draggedAppointments[i].appointmentId;
   this.horizontalDragPresenter.HideAppointment(appointmentId, restoreAptPos);
   this.verticalDragPresenter.HideAppointment(appointmentId, restoreAptPos);
  }
  var toolTip = this.scheduler.GetToolTipControl();
  if(_aspxIsExists(toolTip)) {
   toolTip.HideToolTip();
  }
 },
 HideToolTip: function() {
  var toolTip = this.scheduler.GetToolTipControl();
  if(_aspxIsExists(toolTip)) {  
   toolTip.HideToolTip();
  }
 }
});
ASPxClientAppointmentDragHelper = _aspxCreateClass(null, {
    constructor: function(scheduler, appointmentDiv, cell, e, onDoClickHandler, owner) {
  if(__aspxDragHelper != null)
     __aspxDragHelper.cancelDrag();
  scheduler.DisableReminderTimer();
  this.dragArea = 5;
  this.lastX = e.clientX;
  this.lastY = e.clientY;
     this.scheduler = scheduler;          
  this.canDrag = true;
     this.startCell = cell;
     this.lastCell = null;
  this.lastCtrlState = null;
  this.scheduler = scheduler;
  this.appointmentSelection = scheduler.appointmentSelection;
  this.appointmentDiv = appointmentDiv;
  this.onDoClickHandler = onDoClickHandler;
  this.onEndDrag = this.OnApplyDrag;
  this.dragViewHelper = new ASPxDragViewHelper(scheduler, appointmentDiv.appointmentViewInfo.appointmentId, appointmentDiv);
  this.owner = owner;    
  __aspxDragHelper = this;  
    },
 drag: function(e) {
  if(!this.canDrag) return;
  if(!this.isDragging()) {
   if(!this.isOutOfDragArea(e.clientX, e.clientY)) 
    return;
   this.startDragCore(e);
  }
  if(!_aspxGetIsLeftButtonPressed(e)) {
   this.cancelDrag(e);
   return;
  }
  if(this.isDragging())
   this.dragCore(e);
 },
 startDragCore: function(e) {
  if(__aspxIE) {
      this.scheduler.innerContentElement.setActive();
  }
  this.startCellTime = this.scheduler.GetCellStartTime(this.startCell);
  this.startCellResource = this.scheduler.GetCellResource(this.startCell);
  var selectedAppointmentIds = this.appointmentSelection.selectedAppointmentIds;
  this.selectedAppointments = new Array();
  var count = selectedAppointmentIds.length;
  for(var i = 0; i < count; i++) {
   var apt = this.scheduler.GetAppointment(selectedAppointmentIds[i]);
   if(apt.flags.allowDrag)
    _aspxArrayPush(this.selectedAppointments, apt);   
  }
  if(this.selectedAppointments.length == 0)
   return;
  var hitTestResult = this.scheduler.CalcHitTest(e);
  var cell = hitTestResult.cell;
  if(_aspxIsExists(cell)) {
   var cellTime = this.scheduler.GetCellStartTime(cell);   
   var activeViewType = this.scheduler.GetActiveViewType();
   if(activeViewType ==  ASPxSchedulerViewType.Day || activeViewType == ASPxSchedulerViewType.WorkWeek) {
    this.dragState = new ASPxDragDayViewAppointmentState (this.selectedAppointments, this.selectedAppointments[0], _aspxDateSubsWithTimezone(this.startCellTime, this.selectedAppointments[0].interval.GetStart()), this.scheduler.privateShowAllAppointmentsOnTimeCells);
   }
   else
    this.dragState = new ASPxDragAppointmentState(this.selectedAppointments, this.selectedAppointments[0], _aspxDateSubsWithTimezone(this.startCellTime, this.selectedAppointments[0].interval.GetStart()));      
  }
 },
 dragCore: function(e) {
  var hitTestResult = this.scheduler.CalcHitTest(e);
  var cell = hitTestResult.cell; 
  if(_aspxIsExists(cell) && (cell != this.lastCell || this.lastCtrlState != ctrlPressed)) {
   var cellTime = this.scheduler.GetCellInterval(cell);
   var cellResource = this.scheduler.GetCellResource(cell);
   if(_aspxIsExists(cellTime) && _aspxIsExists(cellResource)) {
    this.dragState.DragTo(e, cellTime, cellResource);
    var ctrlPressed = _aspxGetCtrlKey(e);
    this.dragViewHelper.ShowDraggedAppointmentPosition(e, this.selectedAppointments, ctrlPressed);
    this.lastCell = cell;   
    this.lastCtrlState = ctrlPressed;    
   }
  }
 },
 isDragging: function() {
  return _aspxIsExists(this.dragState);
 },
 OnCallback: function() {
  this.cancelDrag(false);
 },
 OnCallbackError: function() {
  this.cancelDrag(true);
 },
 onEscKeyDown: function() {
  this.cancelDrag(true, true);
 },
 cancelDrag: function(restoreAptPos, restoreTimer) {
  if(!_aspxIsExists(restoreAptPos))
   restoreAptPos = true;
  if(this.isDragging())
   this.dragViewHelper.HideDraggedAppointmentPosition(this.selectedAppointments, restoreAptPos);
  this.scheduler.onCallback = null;
  this.scheduler.onCallbackError = null;
  __aspxDragHelper = null;
  if (restoreTimer)
   this.scheduler.EnableReminderTimer();
 },
 endDrag: function(e) {
  var restoreAptPos = true;
  var wasCallback = false;
  if(!this.isDragging() && !this.isOutOfDragArea(e.clientX, e.clientY)) {
   if(_aspxIsExists(this.onDoClickHandler))
    this.onDoClickHandler.call(this.owner, e);     
  }
  else {
   var ctrlPressed = _aspxGetCtrlKey(e);
   wasCallback = this.onEndDrag(ctrlPressed);
  }
  if(!wasCallback)
   this.cancelDrag(true);
  else {
   this.dragViewHelper.HideToolTip();
   __aspxDragHelper = null;
   this.scheduler.onCallback = _aspxCreateDelegate(this.OnCallback, this);
   this.scheduler.onCallbackError = _aspxCreateDelegate(this.OnCallbackError, this);
  }
 },
 isOutOfDragArea: function(newX, newY) {
  return Math.max(Math.abs(newX - this.lastX), Math.abs(newY - this.lastY)) >= this.dragArea;
 },
 OnApplyDrag: function(copy) {
  var selectedAppointmentIds = this.appointmentSelection.selectedAppointmentIds;
  var count = selectedAppointmentIds.length;
  var params = "APTSCHANGE|";
  var wasChanges = false;
  for(var i = 0; i < count; i++) {
   var id = selectedAppointmentIds[i];
   var appointment = this.scheduler.GetAppointment(id);
   if(!_aspxIsExists(appointment) || !_aspxIsExists(appointment.operationInterval) || !_aspxIsExists(appointment.operationResources))
    continue;    
   var canCopy = copy & appointment.flags.allowCopy;
   var wasDragged = !appointment.operationInterval.Equals(appointment.interval) || !_aspxArrayEqual(appointment.resources, appointment.operationResources);
   if(!wasDragged && !canCopy)
    continue;
   if(wasChanges)
    params += "!";
   params += id + "?START="+  _aspxDateTimeToMilliseconds(appointment.operationInterval.GetStart());
   if(appointment.operationInterval.GetDuration() != appointment.interval.GetDuration())
    params += "?DURATION=" + appointment.operationInterval.GetDuration();    
   if(!_aspxArrayEqual(appointment.resources, appointment.operationResources))
    params += "?RESOURCES=" + this.ResourcesToString(appointment.operationResources);
   if(canCopy)
    params += "?COPY=true";
   wasChanges = true;
  }
  if(wasChanges) {
   var operation = new ASPxClientAppointmentOperation(this, params);
   var isHandled = this.scheduler.RaiseAppointmentDrop(operation);
   if (isHandled)
    return true;
   this.Apply(params);
   return true;
  }
  else
   return false;
 },
 Apply: function(params) {
  this.scheduler.RaiseCallback(params);
 },
 Cancel: function() {
  this.cancelDrag(true, true);
 },
 ResourcesToString: function(resources) {
  var result = "";
  var count = resources.length;
  for(var i = 0; i < count; i++) {  
   if(i > 0)
    result += ",";
   result += resources[i];  
  }       
  return result;    
 }
});
ASPxDragAppointmentState = _aspxCreateClass(null, {
 constructor: function(sourceAppointments, primaryAppointment, appointmentDragOffset) {
  this.appointmentDragOffset = appointmentDragOffset;
  this.primaryAppointment = primaryAppointment;
  this.lastHitResource = "null";
  this.sourceAppointments = sourceAppointments;
 },
 DragTo: function(evt, layoutInterval, layoutResource) {
  var appointmentsOffset = this.CalculateAppointmentsOffset(layoutInterval);
  this.lastHitResource = layoutResource;
  this.DragAppointments(evt, layoutInterval, layoutResource, appointmentsOffset);
 },
 DragAppointments: function(evt, layoutInterval, layoutResource, appointmentsOffset) { 
  this.DragAppointmentsCore(evt, layoutInterval, layoutResource, appointmentsOffset, this.DragAppointment);
 },
 CalculateAppointmentsOffset: function(layoutInterval) {
  var newPrimaryAppointmentStart = _aspxDateIncreaseWithUtcOffset(layoutInterval.GetStart(), -this.appointmentDragOffset);
  return _aspxDateSubsWithTimezone(newPrimaryAppointmentStart, this.primaryAppointment.interval.GetStart());
 },
 DragAppointmentsCore: function(evt, layoutInterval, layoutResource, appointmentsOffset, dragAppointmentHandler) {
   var sourceAppointments = this.sourceAppointments;
   var count = sourceAppointments.length;
   for(var i = 0; i < count; i++) {
    var sourceAppointment = sourceAppointments[i];
    if(sourceAppointment.flags.allowDrag) {
     this.ChangeResource(evt, sourceAppointment, layoutResource); 
     dragAppointmentHandler.call(this, sourceAppointment, layoutInterval, appointmentsOffset);
    }
   }   
  },
 DragAppointment: function(appointment, layoutInterval, appointmentsOffset) {
  var startTime = _aspxDateIncreaseWithUtcOffset(appointment.interval.GetStart(), appointmentsOffset);
  var endTime = _aspxDateIncreaseWithUtcOffset(appointment.interval.GetEnd(), appointmentsOffset);
  var duration = _aspxDateSubsWithTimezone(endTime, startTime);
  if(duration < 0)
   duration = 0;
  appointment.operationInterval = new ASPxClientTimeInterval(startTime, duration);
 },
 ChangeResource: function(evt, sourceAppointment, layoutResource) {
  if(this.ShouldChangeResource(sourceAppointment, layoutResource))
   sourceAppointment.operationResources = [layoutResource];
  else
   sourceAppointment.operationResources = sourceAppointment.resources;
 },
 ShouldChangeResource: function(sourceAppointment, layoutResource) {
  if(sourceAppointment.appointmentType != ASPxAppointmentType.Normal || !sourceAppointment.flags.allowDragBetweenResources)
   return false;
  if(layoutResource == "null" || ASPxSchedulerUtils.IsAppointmentResourcesEmpty(sourceAppointment.resources) || _aspxArrayContains(sourceAppointment.resources, layoutResource))
   return false;
  return true;
 }
});
ASPxDragDayViewAppointmentState = _aspxCreateClass(ASPxDragAppointmentState, {
 constructor: function(sourceAppointments, primaryAppointment, appointmentDragOffset, showAllAppointmentsOnTimeCells) {
  this.constructor.prototype.constructor.call(this, sourceAppointments, primaryAppointment, appointmentDragOffset);
  this.showAllAppointmentsOnTimeCells = showAllAppointmentsOnTimeCells;  
 },
 DragAppointments: function(evt, layoutInterval, layoutResource, appointmentsOffset) {
  if(layoutInterval.IsSmallerThanDay())
   this.DragAppointmentsCore(evt, layoutInterval, layoutResource, appointmentsOffset, this.DragToCell);
  else
   this.DragAppointmentsCore(evt, layoutInterval, layoutResource, appointmentsOffset, this.DragToAllDayArea);  
 },
 DragToAllDayArea: function(sourceAppointment, layoutInterval, appointmentsOffset) {
  if(sourceAppointment.interval.IsSmallerThanDay()) 
   this.DragShortAppointmentToAllDayArea(sourceAppointment, appointmentsOffset);
  else 
   this.DragLongAppointmentToAllDayArea(sourceAppointment, appointmentsOffset, layoutInterval);  
 },
 DragShortAppointmentToAllDayArea: function(sourceAppointment, appointmentsOffset) {
  var start;  
  start = _aspxDateIncreaseWithUtcOffset(ASPxSchedulerDateTimeHelper.TruncToDate(sourceAppointment.interval.GetStart()), appointmentsOffset);
  sourceAppointment.operationInterval = new ASPxClientTimeInterval(start, ASPxSchedulerDateTimeHelper.DaySpan);
 },
 DragLongAppointmentToAllDayArea: function(sourceAppointment, appointmentsOffset, layoutInterval) {  
  var start;    
  if(this.showAllAppointmentsOnTimeCells) {   
   var offset = this.CalculateLongAppointmentOffset(layoutInterval, appointmentsOffset);
   var duration = this.ExtendToDay(sourceAppointment);
   start =  _aspxDateIncreaseWithUtcOffset(ASPxSchedulerDateTimeHelper.TruncToDate(sourceAppointment.interval.GetStart()), offset);
   sourceAppointment.operationInterval = new ASPxClientTimeInterval(start, duration);  
  }
  else {
   start =  _aspxDateIncreaseWithUtcOffset(sourceAppointment.interval.GetStart(), appointmentsOffset);
   sourceAppointment.operationInterval = new ASPxClientTimeInterval(start, sourceAppointment.interval.GetDuration());
  }
 },
 CalculateLongAppointmentOffset: function(layoutInterval, appointmentsOffset) {
  var dragStart = _aspxDateIncreaseWithUtcOffset(layoutInterval.GetStart(),-appointmentsOffset);
  var daysDifference = this.CalculateDaysDifference(dragStart, layoutInterval.GetStart()); 
  return ASPxSchedulerDateTimeHelper.DaySpan*daysDifference;
 },
 CalculateDaysDifference: function(date1, date2) {
  snappedDate1 = ASPxSchedulerDateTimeHelper.TruncToDate(date1);
  snappedDate2 = ASPxSchedulerDateTimeHelper.TruncToDate(date2);  
  return _aspxDateSubsWithTimezone(snappedDate2, snappedDate1) / ASPxSchedulerDateTimeHelper.DaySpan;   
 },
 ExtendToDay: function(sourceAppointment) {
  var duration = sourceAppointment.interval.GetDuration();;
  var remainder = duration % ASPxSchedulerDateTimeHelper.DaySpan;
  if(remainder != 0)
   return (duration - remainder + ASPxSchedulerDateTimeHelper.DaySpan);
  else
   return duration;
 },
 DragToCell: function(sourceAppointment, layoutInterval, appointmentsOffset) {
  if(sourceAppointment.interval.IsSmallerThanDay())
   this.DragShortAppointmentToCell(sourceAppointment, layoutInterval, appointmentsOffset);  
  else
   this.DragLongAppointmentToCell(sourceAppointment, layoutInterval, appointmentsOffset);  
 },
 DragLongAppointmentToCell: function(sourceAppointment, layoutInterval, appointmentsOffset) {  
  if (this.showAllAppointmentsOnTimeCells) {
   var start = _aspxDateIncreaseWithUtcOffset(sourceAppointment.interval.GetStart(), appointmentsOffset);
   sourceAppointment.operationInterval = new ASPxClientTimeInterval(start, sourceAppointment.interval.GetDuration());
  }
  else
   sourceAppointment.operationInterval = new ASPxClientTimeInterval(layoutInterval.GetStart(), layoutInterval.GetDuration());
 },
 DragShortAppointmentToCell: function(sourceAppointment, layoutInterval, appointmentsOffset) {
  var start = _aspxDateIncreaseWithUtcOffset(sourceAppointment.interval.GetStart(), appointmentsOffset);
  sourceAppointment.operationInterval = new ASPxClientTimeInterval(start, sourceAppointment.interval.GetDuration());
 },
 CalculateAppointmentsOffset: function(layoutInterval) {
  if(this.ShouldTruncToDate(layoutInterval))
   return _aspxDateSubsWithTimezone(layoutInterval.GetStart(), ASPxSchedulerDateTimeHelper.TruncToDate(this.primaryAppointment.interval.GetStart()));
  else
   return this.constructor.prototype.CalculateAppointmentsOffset.call(this,layoutInterval);
 },
 ShouldTruncToDate: function(layoutInterval) {
  var dragToAllDayArea = !layoutInterval.IsSmallerThanDay();
  var isShortAppointment = this.primaryAppointment.interval.IsSmallerThanDay();
  return dragToAllDayArea && isShortAppointment;
 }
});
ASPxClientAppointmentFlags = _aspxCreateClass(null, {
 constructor: function(){
  this.constructor.prototype.constructor.call(this);
  this.allowDelete = true;
  this.allowEdit = true;
  this.allowResize = true;
  this.allowCopy = true;
  this.allowDrag = true;
  this.allowDragBetweenResources = true;
  this.allowInplaceEditor = true;
  this.allowConflicts = true;
 }
});
ASPxClientAppointment = _aspxCreateClass(null, {
 constructor: function(interval, resources, flags, appointmentId, appointmentType, statusIndex, labelIndex){
  this.interval = interval;
  this.resources = resources;
  this.flags = flags;
  this.appointmentId = appointmentId;
  this.appointmentType = ( appointmentType ) ? appointmentType : ASPxAppointmentType.Normal;
  this.statusIndex = statusIndex;
  this.labelIndex = labelIndex;
 },
 __toJsonExceptKeys: ["flags"],
 GetToolTipContent: function(scheduler) { 
  var formatter = new ASPxDateFormatter();
  var interval = _aspxIsExists(this.operationInterval) ? this.operationInterval : this.interval;
  var startTimeFormat = this.SelectStartTimeFormat(scheduler, interval);
  var endTimeFormat = this.SelectEndTimeFormat(scheduler, interval);
  formatter.SetFormatString(startTimeFormat);
  var result = formatter.Format(interval.GetStart());
  if(_aspxIsExists(endTimeFormat)) {
   formatter.SetFormatString(endTimeFormat);
   result += " - " + formatter.Format(interval.GetEnd());
  }
  return result;  
 },
 SelectStartTimeFormat: function(scheduler, interval) {
  var intervalStart = interval.GetStart();
  var intervalEnd = interval.GetEnd();
  var startDate = intervalStart.getDate();
  var startYear = intervalStart.getYear();
  var startMonth = intervalStart.getMonth();
  var endDate = intervalEnd.getDate();
  var endYear = intervalEnd.getYear();
  var endMonth = intervalEnd.getMonth();
  var truncStartDate = new Date(startYear, startMonth, startDate);
  var truncEndDate = new Date(endYear, endMonth, endDate);
  var datesEquals = startDate == endDate && startMonth == endMonth && startYear == endYear;
  if(datesEquals) {
   if(interval.IsSmallerThanDay())
    return scheduler.formatsTimeWithMonthDay[0];
   else
    return scheduler.formatsWithoutYearAndWeekDay[0];
  }
  else {
   if(truncStartDate - interval.GetStart() == 0&& truncEndDate - interval.GetEnd() == 0) {   
    if(startYear == endYear || interval.IsDurationEqualToDay())
     return scheduler.formatsWithoutYearAndWeekDay[0];    
    else
     return scheduler.formatsDateWithYear[0];    
   }
   else {
    if(startYear == endYear)
     return scheduler.formatsTimeWithMonthDay[0];    
    else
     return scheduler.formatsDateTimeWithYear[0];    
   }
    }
 },
 SelectEndTimeFormat: function(scheduler, interval) {
  var intervalStart = interval.GetStart();
  var intervalEnd = interval.GetEnd();
  var startDate = intervalStart.getDate();
  var startYear = intervalStart.getYear();
  var startMonth = intervalStart.getMonth();
  var endDate = intervalEnd.getDate();
  var endYear = intervalEnd.getYear();
  var endMonth = intervalEnd.getMonth();
  var truncStartDate = new Date(startYear, startMonth, startDate);
  var truncEndDate = new Date(endYear, endMonth, endDate);
  var datesEquals = startDate == endDate && startMonth == endMonth && startYear == endYear;
  if(datesEquals) {
   if(interval.IsSmallerThanDay())
    return scheduler.formatsTimeOnly[0];
   else
    return null;
  }
  else {
   if(truncStartDate - interval.GetStart() == 0&& truncEndDate - interval.GetEnd() == 0) {   
    if(startYear == endYear || interval.IsDurationEqualToDay())
     return (interval.IsDurationEqualToDay()) ? null : scheduler.formatsWithoutYearAndWeekDay[0];    
    else
     return scheduler.formatsDateWithYear[0];    
   }
   else {
    if(startYear == endYear)
     return scheduler.formatsTimeWithMonthDay[0];    
    else
     return scheduler.formatsDateTimeWithYear[0];    
   }
    }
 },
 AddResource: function(resourceId) {
  if (!this.resources)
   this.resources = new Array();
  _aspxArrayPush(this.resources, resourceId);
 },
 GetResource: function(index) {
  if (!this.resources)
   this.resources = new Array();
  if (index >= 0 && index < this.resources.length)
   return this.resources[index];
  return null;
 },
 CreateDefaultTimeInterval: function() {
  return new ASPxClientTimeInterval(new Date(), 30 * 60 * 1000);
 },
 SetStart: function(start) {
  if (!this.interval) 
   this.interval = this.CreateDefaultTimeInterval();
  this.interval.SetStart(start);
 },
 GetStart: function() {
  if (!this.interval) 
   this.interval = this.CreateDefaultTimeInterval();
  return this.interval.GetStart();
 },
 SetEnd: function(end) {
  if (!this.interval) 
   this.interval = this.CreateDefaultTimeInterval();
  this.interval.SetEnd(end);
 },
 GetEnd: function() {
  if (!this.interval) 
   this.interval = this.CreateDefaultTimeInterval();
  return this.interval.GetEnd();
 },
 SetDuration: function(duration) {
  if (!this.interval)
   this.interval = this.CreateDefaultInterval();
  this.interval.SetDuration(duration);
 },
 GetDuration: function() {
  if (!this.interval)
   this.interval = this.CreateDefaultInterval();
  return this.interval.GetDuration();
 },
 SetId: function(id) {
  this.appointmentId = id;
 },
 GetId: function() {
  return this.appointmentId;
 },
 SetAppointmentType: function(type) {
  this.appointmentType = type;
 },
 GetAppointmentType: function() {
  return this.appointmentType;
 },
 SetStatusId: function(statusId) {
  this.statusIndex = statusId;
 },
 GetStatusId: function() {
  return this.statusIndex;
 },
 SetLabelId: function(labelId) {
  this.labelIndex = labelId;
 },
 GetLabelId: function() {
  return this.labelIndex;
 },
 SetSubject: function(subject) {
  this.subject = subject;
 },
 GetSubject: function() {
  if (!this.subject)
   return "";
  return this.subject;
 },
 SetDescription: function(description) {
  this.description = description;
 },
 GetDescription: function() {
  if (!this.description)
   return "";
  return this.description;
 },
 SetLocation: function(location) {
  this.location = location;
 },
 GetLocation: function() {
  if (!this.location)
   return "";
  return this.location;
 },
 SetAllDay: function(allDay) {
  this.allDay = allDay;
 },
 GetAllDay: function() {
  if (!this.allDay)
   return false;
  return this.allDay;
 },
 SetRecurrencePattern: function(recurrencePattern) {
  this.recurrencePattern = recurrencePattern;
 },
 GetRecurrencePattern: function() {
  return this.recurrencePattern;
 }, 
 SetRecurrenceInfo: function(recurrenceInfo) {
  this.recurrenceInfo = recurrenceInfo;
 },
 GetRecurrenceInfo: function() {
  return this.recurrenceInfo;
 }
});
ASPxClientAppointmentBounds = _aspxCreateClass(null, {
   constructor: function(x, y, width, height) { 
    this.x = x;
    this.y = y;
    this.width = width;
    this.height = height;
   },
   GetLeftBound: function() {
  return this.x;
   },
   GetRightBound: function() {
  return this.x + this.width;
   },
   GetTopBound: function() {
  return this.y;
   },
   GetBottomBound: function() {
  return this.y + this.height;
   },
   GetWidth: function() {
  return this.width;
   },   
   GetHeight: function() {
  return this.height;
   }
});
ASPxClientAppointmentLayoutCalculator = _aspxCreateClass(null, {
 constructor: function(schedulerViewInfo, parent) {
  this.schedulerViewInfo = schedulerViewInfo;
  this.minAppointmentWidth = 7;
  this.minAppointmentHeight = 7;
 },
 AfterCalculateAppointments: function(appointmentViewInfos) {
  var count = appointmentViewInfos.length;
  for(var i = 0; i < count; i++)
   this.AfterCalculateAppointment(appointmentViewInfos[i]);
 },
 AfterCalculateAppointment: function(appointmentViewInfo) {
  var appointmentDiv = appointmentViewInfo.contentDiv;
  if(!_aspxIsExists(appointmentDiv))
   return;
    _aspxSubscribeSchedulerMouseEvents(appointmentDiv, appointmentViewInfo);
    _aspxAddSmartTag(appointmentViewInfo, this.schedulerViewInfo.scheduler.appointmentSmartTagDiv);
    this.CalculateFinalContentLayout(appointmentViewInfo);
 },
 CalculateFinalContentLayout: function(appointmentViewInfo) {
  this.CalculateContentDivSize(appointmentViewInfo);
  this.LayoutAppointmentStatus(appointmentViewInfo);  
 }, 
 LayoutAppointmentStatus : function(appointmentViewInfo) {    
  var statusBackDivId = appointmentViewInfo.statusViewInfo.backDivId;
  var statusForeDivId = appointmentViewInfo.statusViewInfo.foreDivId;
  if (_aspxIsExists(statusBackDivId) && _aspxIsExists(statusForeDivId)) {
   var statusBackDiv = this.schedulerViewInfo.scheduler.GetAppointmentBlockElementById(statusBackDivId);
   var statusForeDiv = this.schedulerViewInfo.scheduler.GetAppointmentBlockElementById(statusForeDivId);
   if (_aspxIsExists(statusBackDiv) && _aspxIsExists(statusForeDiv)) {    
    var innerContentDiv = this.FindInnerContentDiv(appointmentViewInfo);
    if (!_aspxIsExists(innerContentDiv))
     innerContentDiv = appointmentViewInfo.contentDiv;     
    statusBackDiv.appointmentDiv = innerContentDiv;
    statusForeDiv.appointmentDiv = innerContentDiv;    
    this.LayoutAppointmentStatusCore(statusForeDiv, statusBackDiv, appointmentViewInfo);    
   }
  }
 },
 CalculateContentDivSize : function(appointmentViewInfo) {
  var innerContentDiv = this.FindInnerContentDiv(appointmentViewInfo);
  if(_aspxIsExists(innerContentDiv))
   this.SetInnerContentDivSize(innerContentDiv, appointmentViewInfo);  
 },
 ResetContentDivSize : function(appointmentViewInfo) {
  var innerContentDiv = this.FindInnerContentDiv(appointmentViewInfo);
  if(_aspxIsExists(innerContentDiv))
   innerContentDiv.style.height = "";  
 },
 FindInnerContentDiv : function(appointmentViewInfo) {
  var appointmentDiv = appointmentViewInfo.contentDiv; 
  if(!_aspxIsExists(appointmentDiv))
   return null;
  var children = appointmentDiv.childNodes;
  var count = children.length;
  for(var i = 0; i < count; i++) {
   var child = children[i];
   if(this.IsInnerContentDiv(child))    
    return child;   
  }
  return null;
 },
 IsInnerContentDiv : function(child) {  
  if (!_aspxIsExists(child.tagName))
   return false;
  else {
   var tagName = child.tagName.toUpperCase();
   return ((tagName == "TABLE") || (tagName == "DIV"));
  }
 },
 SetInnerContentDivSize : function(contentDiv, aptViewInfo) {
  if(__aspxIE && __aspxBrowserMajorVersion >=7) { 
   if (contentDiv.clientHeight <= 0)
    contentDiv.style.height = "0";
   if (contentDiv.clientWidth <= 0)
    contentDiv.style.width = "0";
  }
  var bordersHeight = contentDiv.offsetHeight - contentDiv.clientHeight;   
  var bordersWidth = contentDiv.offsetWidth - contentDiv.clientWidth;   
  contentDiv.style.height = "";
  contentDiv.style.height = Math.max(aptViewInfo.contentDiv.offsetHeight - bordersHeight, this.minAppointmentHeight) + "px";
  contentDiv.style.width = Math.max(0, aptViewInfo.contentDiv.offsetWidth - bordersWidth) + "px";
 },
 RecalcAppointmentIntervalAndOffset: function(viewInfo, aptBounds, firstCell, lastCell) {
  var firstCellInterval = this.schedulerViewInfo.scheduler.GetCellInterval(firstCell);
  var lastCellInterval = this.schedulerViewInfo.scheduler.GetCellInterval(lastCell);
  viewInfo.startRelativeIndent = this.RecalcStartOffset(aptBounds, firstCell);
  viewInfo.endRelativeIndent = this.RecalcEndOffset(aptBounds, lastCell);  
  var start = this.CalculateStartTimeByOffset(firstCellInterval, viewInfo.startRelativeIndent);
  var end = this.CalculateEndTimeByOffset(lastCellInterval, viewInfo.endRelativeIndent);    
  viewInfo.appointmentInterval.SetStart(start);
  viewInfo.appointmentInterval.SetDuration(end - start);  
 },
 CalculateStartTimeByOffset: function(baseInterval, startOffset) {
  var offset =  baseInterval.GetDuration() * startOffset / 100;
  return _aspxDateIncrease(baseInterval.GetStart(), offset);
 },
 CalculateEndTimeByOffset: function(baseInterval, endOffset) {
  var offset =  - baseInterval.GetDuration() * endOffset / 100;
  return _aspxDateIncrease(baseInterval.GetEnd(), offset);  
 },
 RecalcStartOffset: function(aptBounds, firstCell) {
 },
 RecalcEndOffset: function(aptBounds, lastCell) {
 } 
});
ASPxClientVerticalAppointmentLayoutCalculator = _aspxCreateClass(ASPxClientAppointmentLayoutCalculator, {
 constructor: function(schedulerViewInfo, parent) {
  this.constructor.prototype.constructor.call(this, schedulerViewInfo);
  this.gapBetweenAppointment = 4;
  this.leftAppointmentIndent = 2;
  this.rightAppointmentIndent = 2;  
  this.parent = parent;
 },
 CalculateLayout: function(appointmentViewInfos) {
  if(!_aspxIsExists(appointmentViewInfos) || !_aspxIsExists(appointmentViewInfos.length)) 
   return;
  var count = appointmentViewInfos.length;
  if(count <= 0)
   return;
  var count = appointmentViewInfos.length;
  for(var i = 0; i < count; i ++)
   this.CalculateAppointmentLayout(appointmentViewInfos[i]);
  this.AfterCalculateAppointments(appointmentViewInfos); 
   },
   CalculateAppointmentLayout: function(viewInfo){
  viewInfo.ResetRelativeIndentAndTime();
  this.ResetContentDivSize(viewInfo);
  var schedulerViewInfo = this.schedulerViewInfo;
  var div = viewInfo.contentDiv;
  if(_aspxIsExists(div)){
   var startCell = _aspxIsExists(viewInfo.startCell) ? viewInfo.startCell : schedulerViewInfo.GetCell(viewInfo.containerIndex, viewInfo.firstCellIndex) ;
   var endCell = _aspxIsExists(viewInfo.endCell) ? viewInfo.endCell : schedulerViewInfo.GetCell(viewInfo.containerIndex, viewInfo.lastCellIndex);
   if(_aspxIsExists(startCell) && _aspxIsExists(endCell)){    
    _aspxSetSchedulerDivDisplay(div, true);
    viewInfo.startCell = startCell;
    viewInfo.endCell = endCell;
    var paddingBeforeAppointment = this.GetPaddingBeforeAppointment(viewInfo);
    var paddingAfterAppointment = this.GetPaddingAfterAppointment(viewInfo);
    var factor = startCell.offsetWidth / viewInfo.maxIndexInGroup;
    var topIndent = this.GetIndent(startCell, viewInfo.startRelativeIndent);
    var bottomIndent = this.GetIndent(endCell, viewInfo.endRelativeIndent);
    var aptLeft = Math.floor(schedulerViewInfo.parent.CalcRelativeElementLeft(startCell) + viewInfo.startHorizontalIndex * factor  + paddingBeforeAppointment);      
    var aptWidth = Math.floor((viewInfo.endHorizontalIndex - viewInfo.startHorizontalIndex) * factor - (paddingAfterAppointment + paddingBeforeAppointment));
    var aptTop = schedulerViewInfo.parent.CalcRelativeElementTop(startCell) + topIndent;
    var aptBottom = schedulerViewInfo.parent.CalcRelativeElementBottom(endCell) - bottomIndent;
    if (__aspxFirefox)
     aptTop = aptTop - 1;
    var aptHeight = aptBottom - aptTop ;      
    var aptBounds = new ASPxClientAppointmentBounds(aptLeft, aptTop, aptWidth, aptHeight);
    if(aptHeight < this.minAppointmentHeight) {
     this.ExtendAppointmentBounds(aptBounds, startCell, endCell);
     this.RecalcAppointmentIntervalAndOffset(viewInfo, aptBounds, startCell, endCell);
    }
    div.style.left = aptLeft + "px";
    div.style.width = Math.max(aptWidth, 0)  + "px";
    div.style.top = aptBounds.GetTopBound() + "px";
    div.style.height = aptBounds.GetHeight() + "px";
   }
  }
 },
 ExtendAppointmentBounds: function(aptBounds, firstCell, lastCell) {
  var firstCellTopBound = this.schedulerViewInfo.parent.CalcRelativeElementTop(firstCell);
  var lastCellBottomBound = this.schedulerViewInfo.parent.CalcRelativeElementBottom(lastCell);  
  aptBounds.height = Math.min(this.minAppointmentHeight, lastCellBottomBound - aptBounds.GetTopBound());       
  if (aptBounds.height < this.minAppointmentHeight)    
   aptBounds.y = Math.max(firstCellTopBound, aptBounds.GetBottomBound() - this.minAppointmentHeight);  
 },
 RecalcStartOffset: function(aptBounds, firstCell) {
   var cellTopBound = this.schedulerViewInfo.parent.CalcRelativeElementTop(firstCell);
  var cellHeight = this.schedulerViewInfo.parent.CalcRelativeElementBottom(firstCell) - cellTopBound;
  return Math.floor((aptBounds.GetTopBound() - cellTopBound) / cellHeight * 100);
 },
 RecalcEndOffset: function(aptBounds, lastCell) {
   var cellBottomBound = this.schedulerViewInfo.parent.CalcRelativeElementBottom(lastCell);
  var cellHeight = cellBottomBound - this.schedulerViewInfo.parent.CalcRelativeElementTop(lastCell);
  return Math.floor((cellBottomBound - aptBounds.GetBottomBound()) / cellHeight * 100);  
 },
 GetPaddingBeforeAppointment: function(viewInfo) {
  if (this.IsFirstAppointment(viewInfo))
   return this.leftAppointmentIndent;
  else
   return this.gapBetweenAppointment / 2;
 },
 GetPaddingAfterAppointment: function(viewInfo) {
  if (this.IsLastAppointment(viewInfo))
   return this.rightAppointmentIndent;
  else
   return this.gapBetweenAppointment / 2;
 },
 IsLastAppointment: function(viewInfo) {
  return viewInfo.endHorizontalIndex == viewInfo.maxIndexInGroup;
 },
 IsFirstAppointment: function(viewInfo) {
  return viewInfo.startHorizontalIndex == 0;
 },
 GetIndent: function(cell, relativeIndent) {
  if(!_aspxIsExists(relativeIndent))
   return 0;
  else
   return relativeIndent * cell.offsetHeight / 100;
 },  
 LayoutAppointmentStatusCore : function(statusForeDiv, statusBackDiv, appointmentViewInfo) {   
  var statusViewInfo = appointmentViewInfo.statusViewInfo;
  var aptDiv = statusBackDiv.appointmentDiv;  
  var height = aptDiv.clientHeight;    
  var topBorderHeight = this.CalculateTopBorderHeight(appointmentViewInfo, aptDiv);
  statusBackDiv.style.height = height + "px";  
  statusBackDiv.style.top =  topBorderHeight  +  "px";  
  var topIndent = Math.floor(statusViewInfo.startOffset * height / 100);
  var bottomIndent = Math.floor(statusViewInfo.endOffset * height / 100);
  statusForeDiv.style.top =  topIndent  + topBorderHeight + "px";   
  statusForeDiv.style.height =  height - topIndent - bottomIndent + "px";
 },
 CalculateTopBorderHeight: function(aptViewInfo, aptDiv) {
  var aptBordersHeight = aptDiv.offsetHeight - aptDiv.clientHeight;
  if (!aptViewInfo.hasTopBorder)
   return 0;
  if (aptViewInfo.hasBottomBorder)
   return Math.ceil(aptBordersHeight / 2);
  else
   return aptBordersHeight;
 }
});
ASPxClientBusyInterval = _aspxCreateClass(null, {
 constructor: function(start, end) {
  this.start = start;
  this.end = end;
 },
 ContainsExcludeEndBound: function(value) {
  return this.start <= value && this.end > value;
 }
});
ASPxClientHorizontalAppointmentLayoutCalculator = _aspxCreateClass(ASPxClientAppointmentLayoutCalculator, {
 constructor: function(schedulerViewInfo) {
  this.constructor.prototype.constructor.call(this, schedulerViewInfo);
  this.gapBetweenAppointments = 3;
  this.leftAppointmentIndent = 2;
  this.rightAppointmentIndent = 2;
  this.topAppointmentIndent = 2;
  this.schedulerViewInfo = schedulerViewInfo;
  this.maxCellsInWeek = 7;
  this.appointmentNotFitted = 0;
  this.appointmentPartialFitted = 1;
  this.appointmentFitted = 2;  
 },
 CalculateLayout: function(appointmentViewInfos) {
  if(!_aspxIsExists(appointmentViewInfos) || !_aspxIsExists(appointmentViewInfos.length)) 
   return;
  var count = appointmentViewInfos.length;
  if(count <= 0)
   return;
  this.PrepareViewInfos(appointmentViewInfos);
  var containerCount = this.schedulerViewInfo.cellContainers.length;
  for(var i = 0; i < containerCount; i++) {
   var containerViewInfos = this.SelectViewInfosForContainer(appointmentViewInfos, this.schedulerViewInfo.cellContainers[i].containerIndex);
   if(containerViewInfos.length > 0)
    this.CalculateLayoutCore(containerViewInfos);
  }
  this.AfterCalculateAppointments(appointmentViewInfos);
 },
 SelectViewInfosForContainer: function(viewInfos, containerIndex) {
  var count = viewInfos.length;
  var result = new Array();
  for(var i = 0; i < count; i++) {
   if(viewInfos[i].containerIndex == containerIndex)
    _aspxArrayPush(result, viewInfos[i]);
  }
  return result;
 },
 CalculateLayoutCore: function(viewInfos) {
  var count = viewInfos.length;
  var relativePositionCalculator = this.CreateRelativePositionCalculator();      
  var index = 0;
  do {  
   relativePositionCalculator.CalculateAppointmentRelativePositions(viewInfos, index);
   index = this.CalculateAppointmentsPosition(viewInfos, index);
  } while(index < count);
 },
 CreateRelativePositionCalculator: function() {
  return new ASPxClientHorizontalAppointmentRelativePositionCalculator(this.gapBetweenAppointments);
 },
 PrepareViewInfos: function(viewInfos) {
  for(var i = 0; i < viewInfos.length; i++) {
   this.PrepareViewInfo(viewInfos[i]);
  }
 },
 PrepareViewInfo: function(viewInfo){
  viewInfo.ResetRelativeIndentAndTime();
  this.ResetContentDivSize(viewInfo);
  var div = viewInfo.contentDiv;
  viewInfo.visibleFirstCellIndex = viewInfo.firstCellIndex;
  viewInfo.visibleLastCellIndex = viewInfo.lastCellIndex;  
  if(_aspxIsExists(div)) {
   _aspxSetSchedulerDivDisplay(div, true);
   this.CalculateAppointmentSize(viewInfo);
  }  
 },
 CalculateAppointmentSize: function(viewInfo) {
  var containerIndex = viewInfo.containerIndex;
  var firstCell = this.schedulerViewInfo.GetCell(containerIndex, viewInfo.visibleFirstCellIndex);
  var lastCell = this.schedulerViewInfo.GetCell(containerIndex, viewInfo.visibleLastCellIndex);
  if(_aspxIsExists(firstCell) && _aspxIsExists(lastCell)){
   this.CalculateAppointmentHeight(viewInfo);
   this.CalculateAppointmentWidthAndPosition(viewInfo, firstCell, lastCell);
   viewInfo.height = viewInfo.contentDiv.offsetHeight;
   viewInfo.visibleFirstCell = firstCell;
   viewInfo.visibleLastCell = lastCell;
  }
 },
 CalculateAppointmentHeight: function(viewInfo) { 
  var div = viewInfo.contentDiv;
  this.ResetInnerContentDivHeight(viewInfo);
  var aptHeight = this.schedulerViewInfo.scheduler.privateAppointmentHeight;
  if(aptHeight != 0)
   div.style.height = aptHeight + "px";
  else
   div.style.height = "";
 },
 CalculateAppointmentWidthAndPosition: function(viewInfo, firstCell, lastCell) {
  var div = viewInfo.contentDiv;
  div.style.width = "";
  var borderWidth = div.offsetWidth - div.clientWidth;
  var leftIndent = this.GetIndent(firstCell, viewInfo.startRelativeIndent) + this.leftAppointmentIndent;
  var rightIndent =  this.GetIndent(lastCell, viewInfo.endRelativeIndent) + this.rightAppointmentIndent;
  var left = this.schedulerViewInfo.parent.CalcRelativeElementLeft(firstCell) + leftIndent; 
  var width = this.schedulerViewInfo.parent.CalcRelativeElementRight(lastCell) - left - rightIndent;
  var aptBounds = new ASPxClientAppointmentBounds(left, 0, width, div.offsetHeight);
  if(width < this.minAppointmentWidth) {
   this.ExtendAppointmentBounds(aptBounds, firstCell, lastCell);
   this.RecalcAppointmentIntervalAndOffset(viewInfo, aptBounds, firstCell, lastCell);
  }
  div.style.left = aptBounds.GetLeftBound() + "px";
  div.style.width = Math.max(aptBounds.GetWidth() - borderWidth, 0) + "px";
 },
 ResetInnerContentDivHeight: function(aptViewInfo) {
  var innerDiv = this.FindInnerContentDiv(aptViewInfo);
  if(_aspxIsExists(innerDiv)) {
   innerDiv.style.height = "";
   innerDiv.style.width = "";
  }
 }, 
 ExtendAppointmentBounds: function(aptBounds, firstCell, lastCell) {
  var firstCellLeftBound = this.schedulerViewInfo.parent.CalcRelativeElementLeft(firstCell);
  var lastCellRightBound = this.schedulerViewInfo.parent.CalcRelativeElementRight(lastCell);
  aptBounds.width = Math.min(this.minAppointmentWidth, lastCellRightBound - aptBounds.GetLeftBound());
  if (aptBounds.width < this.minAppointmentWidth)
   aptBounds.x = Math.max(firstCellLeftBound, aptBounds.GetRightBound() - this.minAppointmentWidth);
 },
 RecalcStartOffset: function(aptBounds, firstCell) {
   var cellLeftBound = this.schedulerViewInfo.parent.CalcRelativeElementLeft(firstCell);
  var cellWidth = this.schedulerViewInfo.parent.CalcRelativeElementRight(firstCell) - cellLeftBound;
  return Math.floor((aptBounds.GetLeftBound() - cellLeftBound) / cellWidth * 100);
 },
 RecalcEndOffset: function(aptBounds, lastCell) {
   var cellRightBound = this.schedulerViewInfo.parent.CalcRelativeElementRight(lastCell);
  var cellWidth = cellRightBound - this.schedulerViewInfo.parent.CalcRelativeElementLeft(lastCell);
  return Math.floor((cellRightBound - aptBounds.GetRightBound()) / cellWidth * 100);
 },
 CalculateAppointmentsPosition: function(viewInfos, startIndex) {
  var count = viewInfos.length;
  for(var i = startIndex; i < count; i++) {
   var viewInfo = viewInfos[i];
   var result = this.CalculateAppointmentPosition(viewInfo, false);
   if(result == this.appointmentPartialFitted) {
    this.CalculateAppointmentSize(viewInfo);
    return i;
   }
  }
  return count;
 },
 CalculateAppointmentPosition: function(viewInfo, dragMode) {
  var firstCell = viewInfo.visibleFirstCell;
  var dxtop = this.schedulerViewInfo.parent.CalcRelativeElementTop(firstCell) + viewInfo.relativePosition + this.topAppointmentIndent;
  var bottom = dxtop + viewInfo.contentDiv.offsetHeight;
  var fitCount = 0;
  var weekId = viewInfo.containerIndex;
  for(var i = viewInfo.visibleFirstCellIndex; i <= viewInfo.visibleLastCellIndex; i++) {
   var isFitted = this.CalculateIsFitted(viewInfo.containerIndex, i, bottom);
   if(!isFitted && !dragMode) {
    var cell = this.schedulerViewInfo.GetCell(viewInfo.containerIndex, i);
       this.schedulerViewInfo.ShowMoreButton(cell, viewInfo);
    if(i > viewInfo.visibleFirstCellIndex && i < viewInfo.visibleLastCellIndex && fitCount > 0) {
     throw new Error("internal scheduler error");
    }
    var prevCellsFitted = fitCount > 0;
    if(viewInfo.visibleFirstCellIndex < viewInfo.visibleLastCellIndex && i == viewInfo.visibleLastCellIndex && prevCellsFitted) {
     viewInfo.visibleLastCellIndex--;     
     return this.appointmentPartialFitted;
    }
   }
   else {
    fitCount++;    
   }
  }
  if(fitCount == 0) {
     _aspxSetSchedulerDivDisplay(viewInfo.contentDiv, false);
   return this.appointmentNotFitted;
  }
  else {
   viewInfo.contentDiv.style.top = dxtop + "px";
   return this.appointmentFitted;
  }
 },
 GetIndent: function(cell, relativeIndent) {  
  if(!_aspxIsExists(relativeIndent))
   return 0;
  else
   return relativeIndent * cell.offsetWidth / 100;
 },
 CalculateIsFitted: function(containerIndex, cellIndex, bottom) {
  var cell = this.schedulerViewInfo.GetCell(containerIndex, cellIndex);
  var cellBottom = this.schedulerViewInfo.parent.CalcRelativeElementBottom(cell);
  return bottom + this.schedulerViewInfo.GetMoreButtonSize() < cellBottom;
 },
 LayoutAppointmentStatusCore : function(statusForeDiv, statusBackDiv, appointmentViewInfo) {  
  var statusViewInfo = appointmentViewInfo.statusViewInfo;
  statusBackDiv.style.width = statusBackDiv.appointmentDiv.clientWidth + "px";
  var leftIndent = Math.ceil(statusViewInfo.startOffset * statusBackDiv.offsetWidth / 100);
  var rightIndent = Math.ceil(statusViewInfo.endOffset * statusBackDiv.offsetWidth / 100);  
  statusForeDiv.style.top = "1px";
  statusForeDiv.style.left = leftIndent + 1 + "px";  
  statusForeDiv.style.width = Math.max(statusBackDiv.offsetWidth - leftIndent - rightIndent, 1) + "px";
 }
});
ASPxClientHorizontalAppointmentLayoutCalculatorInfinityHeight = _aspxCreateClass(ASPxClientHorizontalAppointmentLayoutCalculator, {
 constructor: function(schedulerViewInfo) {
  this.constructor.prototype.constructor.call(this, schedulerViewInfo);
  this.maxBottom = 0;
 },
 CalculateIsFitted: function(containerIndex, cellIndex, bottom) {
  this.maxBottom = Math.max(bottom, this.maxBottom);
  return true;
 }
});
ASPxClientAppointmentCellIndexes = _aspxCreateClass(null, {
 constructor: function(firstCellIndex, lastCellIndex) {
  this.firstCellIndex = firstCellIndex;
  this.lastCellIndex = lastCellIndex;
 }
 });
ASPxClientHorizontalAppointmentRelativePositionCalculator = _aspxCreateClass(null, {
 constructor: function(gapBetweenAppointments) {
  this.gapBetweenAppointments = gapBetweenAppointments;
 },
 CreateAppointmentCellIndexesCollection : function(viewInfos) {
  var result = new Array();
  var count = viewInfos.length;
  for (var i = 0; i < count; i++) {
   var viewInfo = viewInfos[i];
   var cellIndexes = new ASPxClientAppointmentCellIndexes(viewInfo.visibleFirstCellIndex, viewInfo.visibleLastCellIndex);
   _aspxArrayPush(result, cellIndexes);
  }
  return result;
 },
 RestoreCellIndexes : function(viewInfos, appointmentsCellIndexes) {
  var count = viewInfos.length;
  if (count == appointmentsCellIndexes.length) 
   for (var i = 0; i < count; i++) {
    var indexes = appointmentsCellIndexes[i];
    var viewInfo = viewInfos[i];
    viewInfo.visibleFirstCellIndex = indexes.firstCellIndex;
    viewInfo.visibleLastCellIndex = indexes.lastCellIndex;
   }
 },
 CalculateAppointmentRelativePositions: function(viewInfos, startIndex) {     
  var previousCellIndexes = this.CreateAppointmentCellIndexesCollection(viewInfos);  
  this.AdjustAppointmentCellIndexes(viewInfos);
  this.CalculateAppointmentRelativePositionsCore(viewInfos, startIndex);
  this.RestoreCellIndexes(viewInfos, previousCellIndexes);
 }, 
 AdjustAppointmentCellIndexes : function(viewInfos) {
  var dateTimes = this.CreateViewInfosDateTimeCollection(viewInfos);
  this.CalculateAdjustedCellIndexes(viewInfos, dateTimes);
 },
 CalculateAdjustedCellIndexes : function (viewInfos, dateTimes) {
  var count = viewInfos.length;
  for (var i = 0; i < count; i++)
   this.CalculateAdjustedCellIndexesCore(viewInfos[i], dateTimes);   
 },
 CalculateAdjustedCellIndexesCore : function (viewInfo, dateTimes) {    
   var firstCellIndex = _aspxArrayBinarySearch(dateTimes, viewInfo.getStartTime(), aspxSchedulerDateTimeComparer);
   var lastCellIndex = _aspxArrayBinarySearch(dateTimes, viewInfo.getEndTime(), aspxSchedulerDateTimeComparer) - 1;
   viewInfo.visibleFirstCellIndex = firstCellIndex;
   viewInfo.visibleLastCellIndex = lastCellIndex;  
 },  
 CreateViewInfosDateTimeCollection : function(viewInfos) {
  var count = viewInfos.length;
  var dateTimeCollection = new Array();
  for (var i = 0; i < count; i++) {
   var viewInfo = viewInfos[i];
   this.AddDateTime(dateTimeCollection, viewInfo.getStartTime());   
   this.AddDateTime(dateTimeCollection, viewInfo.getEndTime());     
  }
  dateTimeCollection.sort(aspxSchedulerDateTimeComparer);
  return dateTimeCollection;
 }, 
 AddDateTime : function(dateTimeCollection, dateTime) {
  if (!this.IsAlreadyAdded(dateTimeCollection, dateTime))
   _aspxArrayPush(dateTimeCollection, dateTime);
 }, 
 IsAlreadyAdded : function(dateTimeCollection, dateTime) {
    var count = dateTimeCollection.length;
    for (var i = 0; i < count; i++) 
    if (dateTimeCollection[i].valueOf() == dateTime.valueOf())
     return true;
    return false;
 }, 
 CalculateAppointmentRelativePositionsCore: function(viewInfos, startIndex) {   
  var count = viewInfos.length;
  var busyIntervals = this.CreateBusyIntervals(2*count);  
  var i = 0;
  while (i < startIndex) {
   this.MakeIntervalBusy(viewInfos[i], busyIntervals);
   i++;
  }
  while (i < count) {
   var viewInfo = viewInfos[i];
   var relativePosition = this.FindAvailableRelativePosition(viewInfo, busyIntervals);
   viewInfo.relativePosition = relativePosition;
   this.MakeIntervalBusy(viewInfo, busyIntervals);
   i++;
  }
 },
 CreateBusyIntervals: function(cellsCount) { 
  var result = new Array(cellsCount);
  for (var i = 0; i < cellsCount; i++)
   result[i] = new Array();
  return result;
 },
 FindAvailableRelativePosition: function(viewInfo, cellsBusyIntervals){
  viewInfo.relativePosition = 0;
  var relativePosition = 0;  
  var from = viewInfo.visibleFirstCellIndex;
  var to = viewInfo.visibleLastCellIndex;
  var i = from;
  while (i <= to) {
   var busyIntervals = cellsBusyIntervals[i];
   var interval = this.FindPossibleIntersectionInterval(busyIntervals, relativePosition);
   if ((interval == null) || (interval.start >= relativePosition + viewInfo.height))
    i++;
   else {
    relativePosition = interval.end;
    i = from;
   }
  }
  return relativePosition;
 },
 FindPossibleIntersectionInterval: function(busyIntervals, value) {
  for (var i = 0; i < busyIntervals.length; i++) {
   var interval = busyIntervals[i];
   if ((interval.ContainsExcludeEndBound(value)) || (interval.start > value))
    return new ASPxClientBusyInterval(interval.start, interval.end);
  }
  return null;
 },
 MakeIntervalBusy: function(info, busyIntervals) {
  for (var i = info.visibleFirstCellIndex; i <= info.visibleLastCellIndex; i++)
   this.AddBusyInterval(busyIntervals[i], new ASPxClientBusyInterval(info.relativePosition, info.relativePosition + info.height + this.gapBetweenAppointments));
 },
 AddBusyInterval: function(busyIntervals, busyInterval) {
  var count = busyIntervals.length;
  var i = 0;
  while (i < count) {
   if (busyIntervals[i].start > busyInterval.start)
    break;
   i++;
  }
  _aspxArrayInsert(busyIntervals, busyInterval, i);
 } 
});
ASPxClientTimelineAppointmentLayoutCalculator = _aspxCreateClass(ASPxClientHorizontalAppointmentLayoutCalculator, {
 constructor: function(schedulerViewInfo) {
  this.constructor.prototype.constructor.call(this, schedulerViewInfo);
  this.leftAppointmentIndent = 0;
  this.rightAppointmentIndent = 0;
 }
});
ASPxClientRecurrenceInfo = _aspxCreateClass(null, {
 constructor: function(){
  this.interval = new ASPxClientTimeInterval(new Date(), 0);
  this.type = ASPxClientRecurrenceInfo.DefaultRecurrenceType;
  this.range = ASPxClientRecurrenceInfo.DefaultRecurrenceRange;
  this.weekDays = ASPxClientRecurrenceInfo.DefaultWeekDays;
  this.occurrenceCount = 1;
  this.periodicity = ASPxClientRecurrenceInfo.DefaultPeriodicity;
  this.dayNumber = 1; 
  this.weekOfMonth = ASPxClientRecurrenceInfo.DefaultWeekOfMonth;
  this.month = 1; 
 },
 CreateDefaultInterval: function() {
  return new ASPxClientTimeInterval(new Date(), 0);
 },
 SetStart: function(start) {
  if (!this.interval)
   this.interval = this.CreateDefaultInterval();
  this.interval.SetStart(start);
 },
 GetStart: function() {
  if (!this.interval)
   this.interval = this.CreateDefaultInterval();
  return this.interval.GetStart();
 },
 SetEnd: function(end) {
  if (!this.interval)
   this.interval = this.CreateDefaultInterval();
  this.interval.SetEnd(end);
 },
 GetEnd: function() {
  if (!this.interval)
   this.interval = this.CreateDefaultInterval();
  return this.interval.GetEnd();
 },
 SetDuration: function(duration) {
  if (!this.interval)
   this.interval = this.CreateDefaultInterval();
  this.interval.SetDuration(duration);
 },
 GetDuration: function() {
  if (!this.interval)
   this.interval = this.CreateDefaultInterval();
  return this.interval.GetDuration();
 },
 SetRecurrenceType: function(type) {
  this.type = type;
 },
 GetRecurrenceType: function() {
  if (!this.type)
   this.type = ASPxClientRecurrenceInfo.DefaultRecurrenceType;
  return this.type;
 },
 SetWeekDays: function(weekDays) {
  this.weekDays = weekDays;
 },
 GetWeekDays: function() {
  if (!this.weekDays)
   this.weekDays = ASPxClientRecurrenceInfo.DefaultWeekDays;
  return this.weekDays;
 },
 SetOccurrenceCount: function(occurrenceCount) {
  this.occurrenceCount = occurrenceCount;
 },
 GetOccurrenceCount: function() {
  if (!this.occurrenceCount)
   this.occurrenceCount = 1;
  return this.occurrenceCount = 1;
 },
 SetPeriodicity: function(periodicity) {
  this.periodicity = periodicity;
 },
 GetPeriodicity: function() {
  if (!this.periodicity)
   this.periodicity = ASPxClientRecurrenceInfo.DefaultPeriodicity;
  return this.periodicity;
 },
 SetDayNumber: function(dayNumber) {
  this.dayNumber = dayNumber;
 },
 GetDayNumber: function() {
  if (!this.dayNumber)
   this.dayNumber = 1;
  return this.dayNumber;
 },
 SetWeekOfMonth: function(weekOfMonth ) {
  this.weekOfMonth = weekOfMonth;
 },
 GetWeekOfMonth: function() {
  if(!this.weekOfMonth)
   this.weekOfMonth = ASPxClientRecurrenceInfo.DefaultWeekOfMonth;
  return this.weekOfMonth;
 },
 SetMonth: function(month) {
  this.month = month;
 },
 GetMonth: function() {
  if (!this.month)
   this.month = 1;
  return this.month;
 },
 GetRange: function() {
  return this.range;
 },
 SetRange: function(range) {
  this.range = range;
 }
});
ASPxClientRecurrenceInfo.DefaultPeriodicity = 1;
ASPxClientRecurrenceInfo.DefaultRecurrenceRange = ASPxClientRecurrenceRange.NoEndDate;
ASPxClientRecurrenceInfo.DefaultRecurrenceType = ASPxClientRecurrenceType.Daily;   
ASPxClientRecurrenceInfo.DefaultWeekDays = 127;
ASPxClientRecurrenceInfo.DefaultWeekOfMonth = ASPxClientWeekOfMonth.First;

