var _aspxSchedulerMoreButtonId = "moreButton";
ASPxClientCellDurationIterator = _aspxCreateClass(null, {
 constructor: function(durations) {
  this.durations = durations;
  this.start();
 },
 start: function() {
  this.currentDurationIndex = -1;
  this.restDurationCount = 0;
 },
 getNextDuration: function() {
  if(this.restDurationCount == 0) {
   this.currentDurationIndex++;
   this.restDurationCount = this.durations[2 * this.currentDurationIndex];
   this.currentDuration = this.durations[2 * this.currentDurationIndex + 1];
  }
  this.restDurationCount--;
  return this.currentDuration;
 }
});
ASPxSchedulerContainer = _aspxCreateClass(null, {
 constructor: function(containerIndex, index, startTime, cellCount, cellDurationInfos, resource, isVertical, cellsLocation) {
  this.index = index;
  this.cellCount = cellCount;
  this.cellDurationInfos = cellDurationInfos;
  this.containerIndex = containerIndex;
  this.resource = resource;
  this.interval = new ASPxClientTimeInterval(startTime, this.GetTotalContainerDuration(cellDurationInfos));
  this.isVertical = isVertical;
  this.privateCellsLocation = cellsLocation;
  this.cellsLocation = this.ExpandCellsLocation(cellsLocation);
  this.initializedCells = new Array();  
 },  
 GetTotalContainerDuration: function(cellDurationInfos) {
  this.cellTimes = new Array();
  var count = cellDurationInfos.length;
  var totalDuration = 0;
  for(var i = 0; i < count; i += 2) {
   _aspxArrayPush(this.cellTimes, totalDuration);
   totalDuration += cellDurationInfos[i] * cellDurationInfos[i + 1];
  }
  _aspxArrayPush(this.cellTimes, totalDuration);
  return totalDuration;
 },
 ExpandCellsLocation: function(cellsLocation) {
  var result = new Array();
  var count = cellsLocation.length;
  for(var i = 0; i < count; i++) {
   this.ExpandCellsLocationCore(cellsLocation[i], result);
  }
  return result;
 },
 ExpandCellsLocationCore: function(cellsLocation, result) {
  var count = cellsLocation[0];
  var row = cellsLocation[1];
  var column = cellsLocation[2];
  for(var i = 0; i < count; i++) {
   var position = new Object();
   if(this.isVertical) {
    position.row = row + i;
    position.column = column;
   }
   else {
    position.row = row;
    position.column = column + i;
   }
   _aspxArrayPush(result, position);
  }
 }, 
 GetCellLocation: function(cellIndex) {
  return this.cellsLocation[cellIndex];
 },
 InitializeCell: function(cell, cellIndex) {
  var cellDurations = this.cellDurationInfos;
  var time = this.interval.GetStart();
  var durationIndex = 0;
  var duration;
  while(cellIndex >= cellDurations[durationIndex]) {
   var cellCount = cellDurations[durationIndex];
   if(cellCount > 0) {
    cellIndex -= cellCount;      
    duration = cellDurations[durationIndex] * cellDurations[durationIndex + 1];
   }
   else
    duration = -cellDurations[durationIndex + 1];
   time = _aspxDateIncreaseWithUtcOffset(time, duration);
   durationIndex += 2;
  }
  duration = cellDurations[durationIndex + 1];
  var cellStart = _aspxDateIncreaseWithUtcOffset(time, cellIndex * duration);
  var cellEnd = _aspxDateIncreaseWithUtcOffset(cellStart, duration);
  cell.interval = new ASPxClientTimeInterval(cellStart, duration);
  cell.resource = this.resource;
  cell.container = this;
  _aspxArrayPush(this.initializedCells, cell);
 },
 ClearInitializedCells: function() {
  var count = this.initializedCells.length;
  for(var i = 0; i < count; i++) {
   var cell = this.initializedCells[i];
   cell.interval = null;
   cell.resource = null;
   cell.container = null;
  }
 }
});
ASPxSchedulerViewInfo = _aspxCreateClass(null, {
 constructor: function(scheduler, prevViewInfo, usePrevCache) {
  this.scheduler = scheduler;
  this.appointmentViewInfos = new Array();
  this.cellContainers = new Array();
  this.isVertical = null;
  if(_aspxIsExists(prevViewInfo) && usePrevCache) {
   this.ClearPrevContainers(prevViewInfo.cellContainers);
   this.cachedCells = prevViewInfo.cachedCells;
  }     
  else {
   this.cachedCells = null;
  }
 },
 ClearPrevContainers: function(containers) {
  var count = containers.length;
  for(var i = 0; i < count; i++) {
   containers[i].ClearInitializedCells();
  }  
 },
 Initialize: function(table) {
  this.table = table;
  if(!this.cachedCells)
   this.cachedCells = new Object();
 },
 Dispose: function() {
  var count = this.appointmentViewInfos.length;
  for(var i = 0; i < count; i++)
   this.DisposeAppointmentViewInfo(this.appointmentViewInfos[i]);
 },
 DisposeAppointmentViewInfo: function(appointmentViewInfo) {
  var appointmentDiv = appointmentViewInfo.contentDiv;
  if(!_aspxIsExists(appointmentDiv))
   return;
    _aspxUnsubscribeSchedulerMouseEvents(appointmentDiv, appointmentViewInfo);
 },
 Prepare: function(parent) {
  this.parent = parent;
  var count = this.appointmentViewInfos.length;
  for(var i = 0; i < count; i++) {
   var viewInfo = this.appointmentViewInfos[i];
   var div = this.scheduler.GetAppointmentDivById(viewInfo.divId);
   if(!_aspxIsExists(div))
    continue;
   viewInfo.contentDiv = div;
   viewInfo.contentDiv.appointmentId = viewInfo.appointmentId;
   div.appointmentViewInfo = viewInfo;
   if(div.parentNode != parent.appointmentLayer)
    parent.AppendChildToAppointmentLayer(div);
  }
  this.selectionViewInfo = this.CreateSelectionViewInfoCore();
 },
 HideAppointments: function() {
  var count = this.appointmentViewInfos.length;
  for(var i = 0; i < count; i++) {
   _aspxSetSchedulerDivDisplay(this.appointmentViewInfos[i].contentDiv, false);
  }   
 }, 
 ShowCellSelection: function(interval, resource, highlightPartiallySelectedCell, selectionVisible) {
  if(_aspxIsExists(interval) && _aspxIsExists(resource))
   this.selectionViewInfo.HighlightCells(interval, resource, this.scheduler.smartTagDiv, highlightPartiallySelectedCell, selectionVisible);
 },
 AddCellContainer: function(containerIndex, cellCount, containerStartTime, cellDurationInfos, resource, cellsLocations) { 
  var container = new ASPxSchedulerContainer(containerIndex, this.cellContainers.length, containerStartTime, cellCount, cellDurationInfos, resource, this.isVertical, cellsLocations);
  _aspxArrayPush(this.cellContainers, container);
 },
 InitializeCell: function(cell, containerIndex, cellIndex) {
  this.cellContainers[containerIndex].InitializeCell(cell, cellIndex);
 }, 
 GetCellById: function(id) {
  return this.cachedCells[id];
 },
 GetCell: function(containerIndex, index) { 
  var hashCode = (containerIndex << 16) + index;
  var result = this.cachedCells[hashCode];
  if(!_aspxIsExists(result)) {
   var container = this.cellContainers[containerIndex];
   if(!_aspxIsExists(container))
    return null;
   var loc = container.GetCellLocation(index);
   if(_aspxIsExists(loc)) {
    result = this.table.rows[loc.row].cells[loc.column];    
    this.cachedCells[hashCode] = result;
   }
  }
  return result;
 },
 FindCellContainerByTimeInterval: function(start, end) {
  var interval = new ASPxClientTimeInterval(start, _aspxDateSubsWithTimezone(end, start));
  var index = _aspxArrayBinarySearch(this.cellContainers, interval, this.ContainerWithIntervalComparer);
  if(index < 0)
   return null;
  else
   return this.cellContainers[index];
 },
 FindStartCellIndexByTime: function(cellContainer, time) {
  var start = cellContainer.interval.GetStart();
  var durations = cellContainer.cellDurationInfos;
  var count = durations.length;
  var cellCount = 0;
  var i = 0;
  for(; i < count - 2; i += 2) {
   var duration = durations[i] * durations[i+1];
   if(duration > 0) {
    if((start - time) + duration > 0) {
     break;
    }
    cellCount += durations[i];
   }
   else {
    duration = -durations[i+1];
    if(start - time + duration > 0)
     return cellCount;
   }
   start = _aspxDateIncrease(start, duration);
  }
  var dif =_aspxDateSubsWithTimezone(time, start);
  var rem = dif % durations[i + 1];
  return (dif - rem) / durations[i + 1] + cellCount;  
 },
 FindStartCellByTime: function(cellContainer, time) {
  return this.GetCell(cellContainer.index, this.FindStartCellIndexByTime(cellContainer, time));
 },
 FindEndCellIndexByTime: function(cellContainer, time) {
  var start = cellContainer.interval.GetStart();
  var durations = cellContainer.cellDurationInfos;
  var count = durations.length;
  var cellCount = 0;
  var i = 0;
  for(; i < count - 2; i += 2) {
   var duration = durations[i] * durations[i+1];
   if(duration > 0) {
    if((start - time) + duration > 0) {
     break;
    }
    cellCount += durations[i];
   }
   else {
    duration = -durations[i+1];
    if(start - time + duration > 0)
     return cellCount - 1;
   }
   start = _aspxDateIncrease(start, duration);
  }
  var dif = _aspxDateSubsWithTimezone(time, start);
  var rem = dif % durations[i + 1];
  var cellIndex = (dif - rem) / durations[i + 1] + cellCount;
  if(rem == 0 && cellIndex > 0)
   cellIndex --;
  return Math.min(cellIndex, cellContainer.cellCount - 1);
 },
 FindEndCellByTime: function(cellContainer, time) {
  return this.GetCell(cellContainer.index, this.FindEndCellIndexByTime(cellContainer, time));
 },
 ContainerWithIntervalComparer: function(container, interval) {
  var conteinerInterval = container.interval;    
  if(conteinerInterval.GetStart() > interval.GetEnd())
   return 1;
  if(conteinerInterval.GetEnd() < interval.GetStart())
   return -1;
  return 0;
   }, 
 AddViewInfo: function(viewInfo) {
  _aspxArrayPush(this.appointmentViewInfos, viewInfo);
 },
 RemoveViewInfo: function(viewInfo) {
  _aspxArrayRemove(this.appointmentViewInfos, viewInfo);
 },
 FindCellByPosition: function(containerIndex, firstCellIndex, lastCellIndex, x, y) {
  if(_aspxIsExists(containerIndex))
   return this.FindCellByPositionCore(containerIndex, firstCellIndex, lastCellIndex, x, y);
  var count = this.cellContainers.length;
  for(var i = 0; i < count; i++) {
   var container = this.cellContainers[i];
   var lastCellIndex = container.cellCount - 1;
   if(!this.IsPointInsideContainer(i, 0, lastCellIndex, x, y))
    continue;
   var result = this.FindCellByPositionCore(i, 0, lastCellIndex, x, y);
   if(_aspxIsExists(result))
    return result;
  }  
  return null;
 },
 IsPointInsideContainer: function(containerIndex, firstCellIndex, lastCellIndex, x, y) {
  var firstCell = this.GetCell(containerIndex, firstCellIndex);
  var lastCell = this.GetCell(containerIndex, lastCellIndex);
  if(!_aspxIsExists(firstCell) || !_aspxIsExists(lastCell))
   return false;
  var dxtop = this.parent.CalcRelativeElementTop(firstCell);
  if(y < dxtop)
   return false;
  var bottom = this.parent.CalcRelativeElementBottom(lastCell);
  if(y > bottom)  
   return false;
  var left = this.parent.CalcRelativeElementLeft(firstCell);
  if(x < left)
   return false;
  var right = this.parent.CalcRelativeElementRight(lastCell);
  if(x > right)
   return false;
  return true;  
 },
 FindCellByPositionCore: function(containerIndex, firstCellIndex, lastCellIndex, x, y) {
  var firstCell = this.GetCell(containerIndex, firstCellIndex);
  var lastCell = this.GetCell(containerIndex, lastCellIndex);
  if(!_aspxIsExists(firstCell) || !_aspxIsExists(lastCell))
   return null;
  if(this.CompareCellAndPosition(x, y, firstCell) < 0) 
   return null;
  if(this.CompareCellAndPosition(x, y, lastCell) > 0) 
   return null;
  while(firstCellIndex <= lastCellIndex) {
   var cellIndex = (firstCellIndex + lastCellIndex) >> 1;
   var cell = this.GetCell(containerIndex, cellIndex);
   var result = this.CompareCellAndPosition(x, y, cell);
   if(result == 0) 
    return cell;
   if(result < 0)
    lastCellIndex = cellIndex - 1;
   else
    firstCellIndex = cellIndex + 1;
  }
  return null;
 },
 FindViewInfosByAppointmentId: function(appointmentId) {
  var result = new Array();
  var count = this.appointmentViewInfos.length;
  for(var i = 0; i < count; i++) {
   var viewInfo = this.appointmentViewInfos[i];
   if(viewInfo.appointmentId == appointmentId)
    _aspxArrayPush(result, viewInfo);
  }
  return result;
 },
 RemoveViewInfosByAppointmentId: function(appointmentId) {
  var viewInfos = this.FindViewInfosByAppointmentId(appointmentId);
  var count = viewInfos.length;
  for (var i = 0; i < count; i++) {
   var viewInfo = viewInfos[i];
   this.RemoveViewInfo(viewInfo);
   _aspxRecycleNode(viewInfo.contentDiv);
   viewInfo.contentDiv = null;
  }
 },
 OnAppointmentMouseOver: function(appointmentViewInfo) {
  var div = appointmentViewInfo.contentDiv;
  var resizeDivs = new Array();
  if(appointmentViewInfo.CanResizeAtTop()) 
   _aspxArrayPush(resizeDivs, this.ShowResizeDiv(appointmentViewInfo, this.scheduler.topResizeDiv, 0, 0, div.clientWidth, null));
  if(appointmentViewInfo.CanResizeAtLeft())
   _aspxArrayPush(resizeDivs, this.ShowResizeDiv(appointmentViewInfo, this.scheduler.leftResizeDiv, 0, 0, null, div.clientHeight));
  if(appointmentViewInfo.CanResizeAtBottom())
   _aspxArrayPush(resizeDivs, this.ShowResizeDiv(appointmentViewInfo, this.scheduler.bottomResizeDiv, 0, null, div.clientWidth, null));
  if(appointmentViewInfo.CanResizeAtRight()) 
   _aspxArrayPush(resizeDivs, this.ShowResizeDiv(appointmentViewInfo, this.scheduler.rightResizeDiv, null, 0, null, div.clientHeight));
  if(resizeDivs.length > 0)
   appointmentViewInfo.contentDiv.resizeDivs = resizeDivs;
 },
 OnAppointmentMouseOut: function(appointmentViewInfo) {
  this.HideResizeDivs(appointmentViewInfo);
 },  
 ShowResizeDiv: function(viewInfo, resizeDiv, left, dxtop, width, height) {
  var appointmentDiv = viewInfo.contentDiv;
  var offsetX = 0;
  var offsetY = 0;
  var targetDiv = appointmentDiv;
  var clone = resizeDiv.cloneNode(true);
  _aspxSetElementDisplay(clone, true);
  targetDiv.appendChild(clone);
  if(!_aspxIsExists(width))
   width = clone.offsetWidth;
  if(!_aspxIsExists(height))
   height = clone.offsetHeight;
  if(!_aspxIsExists(left))
   left = appointmentDiv.clientWidth - width;
  if(!_aspxIsExists(dxtop))
   dxtop = appointmentDiv.clientHeight - height;
  clone.style.left = left + offsetX + "px";
  clone.style.top = dxtop + offsetY + "px";
  clone.style.width = width + "px";
  clone.style.height = height + "px";  
  return clone;
 },
 HideResizeDivs: function(viewInfo) {
  var appointmentDiv = viewInfo.contentDiv;
  var targetDiv =  appointmentDiv;  
  if(!_aspxIsExists(targetDiv.resizeDivs))
   return;
  var count = appointmentDiv.resizeDivs.length;
  for(var i = 0; i < count; i++) {
   var resizeDiv = appointmentDiv.resizeDivs[i];
   if(_aspxIsExists(resizeDiv) && resizeDiv.parentNode == targetDiv) {
    _aspxRemoveChildFromParent(targetDiv, resizeDiv);
   }
  }
  appointmentDiv.resizeDivs = null;
 }
});
function _aspxCreateDelegate(method, object, args) {
 function handler(e) {
  if(_aspxIsExists(object))
   method.apply(object, [e, args]);
  else
   method(e, args);
 }
 return handler;
}
ASPxMoreButtonHelper = _aspxCreateClass(null, {
 constructor: function(schedulerViewInfo) {
  this.schedulerViewInfo = schedulerViewInfo;  
  this.scheduler = schedulerViewInfo.scheduler;
  this.moreButtonParent = this.scheduler.containerCell;
  this.scrollContainer = this.schedulerViewInfo.parent.parentElement.parentNode;
  this.moreButtonContainers = this.CreateMoreButtonContainers(this.scrollContainer.scrollHeight);
  this.horizontalOffset = 2;
  this.verticalOffset = 2;
  this.subscribedElements = new Array();
 },
 Dispose: function() {
  var count = this.subscribedElements.length;
  for(var i = 0; i < count; i++) {
   var elem = this.subscribedElements[i];
   _aspxDetachEventFromElement(elem[0], elem[1], elem[2]);
  }
  this.subscribedElements = new Array();
 },
 CalculateMoreButtons: function() {
  var visibleTop = this.scrollContainer.scrollTop;  
  var visibleBottom = visibleTop + this.scrollContainer.offsetHeight;
  var appointmentViewInfos = this.schedulerViewInfo.appointmentViewInfos;
  var count = appointmentViewInfos.length;
  this.ResetMoreButtonContainers();
  for(var i = 0; i < count; i++) {
   var viewInfo = appointmentViewInfos[i];
   var div = viewInfo.contentDiv;
   var dxtop = div.offsetTop;
   var bottom = dxtop + div.offsetHeight;
   var moreButtonContainerObject = this.GetMoreButtonContainer(viewInfo);
   if(bottom <= visibleTop) {
    if(dxtop >= moreButtonContainerObject.nearestTopAppointmentPosition) {
     moreButtonContainerObject.nearestTopAppointmentPosition = dxtop;
     moreButtonContainerObject.nearestTopAppointmentViewInfo = viewInfo;
    }
    continue;
   }
   if(dxtop >= visibleBottom) {
    if(bottom <= moreButtonContainerObject.nearestBottomAppointmentPosition) {
     moreButtonContainerObject.nearestBottomAppointmentPosition = bottom;
     moreButtonContainerObject.nearestBottomAppointmentViewInfo = viewInfo;
    }
    continue;
   }
  }
  this.DisplayMoreButtons();  
 },
 DisplayMoreButtons: function() {
  var count = this.moreButtonContainers.length;
  for(var i = 0; i < count; i++) {
   this.DisplayMoreButtonsCore(this.moreButtonContainers[i]);
  }  
 },
 ResetMoreButtonContainers: function() {
  var count = this.moreButtonContainers.length;
  for(var i = 0; i < count; i++)
   this.moreButtonContainers[i].Reset(this.scrollContainer.scrollHeight);     
 },
 DisplayMoreButtonsCore: function(moreButtonContainer) {
  var scrollContainer = this.scrollContainer;
  var moreButtonParent = this.moreButtonParent;    
  if(_aspxIsExists(moreButtonContainer.nearestTopAppointmentViewInfo)) {
   var div = this.GetDivForContainer(moreButtonContainer, 0);
   if(!_aspxIsExists(div))
    return;
   div.targetAppointmentViewInfo = moreButtonContainer.nearestTopAppointmentViewInfo;
   var appointment = this.scheduler.GetAppointment(div.targetAppointmentViewInfo.appointmentId);
   div.targetDateTime = appointment.interval.GetStart();
   var top = _aspxGetAbsoluteY(scrollContainer) - _aspxGetAbsoluteY(moreButtonParent);
   div.style.top = top + this.verticalOffset + "px";
  }
  else
   this.HideDivForContainer(moreButtonContainer, 0);
  if(_aspxIsExists(moreButtonContainer.nearestBottomAppointmentViewInfo)) {
   var div = this.GetDivForContainer(moreButtonContainer, 1);
   if(!_aspxIsExists(div))
    return;
   div.targetAppointmentViewInfo = moreButtonContainer.nearestBottomAppointmentViewInfo;   
   var appointment = this.scheduler.GetAppointment(div.targetAppointmentViewInfo.appointmentId);
   div.targetDateTime = appointment.interval.GetEnd();
   var top = _aspxGetAbsoluteY(scrollContainer) - _aspxGetAbsoluteY(moreButtonParent);
   var bottom = top + scrollContainer.clientHeight;
   div.style.top = bottom - this.verticalOffset - div.offsetHeight + "px";
  }
  else
   this.HideDivForContainer(moreButtonContainer, 1);
 },
 GetDivForContainer: function(moreButtonContainer, buttonIndex) {
  var div = moreButtonContainer.moreButtons[buttonIndex];
  if(!_aspxIsExists(div)) {
   var isTop = buttonIndex == 0;
   div = this.scheduler.GetContainerElementById("MoreButtons_" + (isTop ? "Top_" : "Bottom_") + moreButtonContainer.index);
   if(!_aspxIsExists(div))
    return null;
   moreButtonContainer.moreButtons[buttonIndex] = div;
   var clickDelegate = _aspxCreateDelegate(this.schedulerViewInfo.OnMoreButtonClick, this.schedulerViewInfo, [div, isTop]);
   _aspxAttachEventToElement(div, "click", clickDelegate);
   _aspxArrayPush(this.subscribedElements, [div, "click", clickDelegate]);
  }  
  _aspxSetElementDisplay(div, true);
  div.style.left = this.GetDivLeftPosition(moreButtonContainer, div) + "px";
  return div;
 },
 HideMoreButtons: function() {
  var count = this.moreButtonContainers.length;
  for(var i = 0; i < count; i++) {
   var container = this.moreButtonContainers[i];
   this.HideDivForContainer(container, 0);
   this.HideDivForContainer(container, 1);
  }
 },
 HideDivForContainer: function(moreButtonContainer, buttonIndex) {
  var div = moreButtonContainer.moreButtons[buttonIndex];
  if(_aspxIsExists(div))
   _aspxSetElementDisplay(div, false);
 } 
});
ASPxMoreButtonContainer = _aspxCreateClass(null, {
 constructor: function(scrollHeight, index) {
  this.Reset(scrollHeight);
  this.moreButtons = [null, null];
  this.index = index;
 },
 Reset: function(scrollHeight) {
  this.nearestTopAppointmentViewInfo = null;
  this.nearestBottomAppointmentViewInfo = null;
  this.nearestTopAppointmentPosition = -1;
  this.nearestBottomAppointmentPosition = scrollHeight + 1;
 } 
});
ASPxSingleMoreButtonHelper = _aspxCreateClass(ASPxMoreButtonHelper, {
 constructor: function(schedulerViewInfo) {
  this.constructor.prototype.constructor.call(this, schedulerViewInfo);
 },
 CreateMoreButtonContainers: function(scrollHeight) {
  return [new ASPxMoreButtonContainer(scrollHeight, 0)];
 },
 GetMoreButtonContainer: function(viewInfo) {
  return this.moreButtonContainers[0];
 },
 GetDivLeftPosition: function(moreButtonContainer, div) {
  return this.schedulerViewInfo.parent.CalcRelativeElementLeft(this.schedulerViewInfo.GetCell(0, 0)) - div.offsetWidth - this.horizontalOffset;
 }
});
ASPxMoreButtonInEachColumnHelper = _aspxCreateClass(ASPxMoreButtonHelper, {
 constructor: function(schedulerViewInfo) {
  this.constructor.prototype.constructor.call(this, schedulerViewInfo);
 },
 CreateMoreButtonContainers: function(scrollHeight) {
  var count = this.schedulerViewInfo.cellContainers.length;
  var result = new Array();
  for(var i = 0; i < count; i++) {
   var moreButtonContainer = new ASPxMoreButtonContainer(scrollHeight, i);
   _aspxArrayPush(result, moreButtonContainer);
  }
  return result;
 },
 GetMoreButtonContainer: function(viewInfo) {
  return this.moreButtonContainers[viewInfo.containerIndex];
 },
 GetDivLeftPosition: function(moreButtonContainer) {
  return this.schedulerViewInfo.parent.CalcRelativeElementLeft(this.schedulerViewInfo.GetCell(moreButtonContainer.index, 0)) + this.horizontalOffset;
 }
});
ASPxClientVerticalSchedulerViewInfo = _aspxCreateClass(ASPxSchedulerViewInfo, {
 constructor: function(scheduler, prevViewInfo, usePrevCache, appointmentsSnapToCells) {
  this.constructor.prototype.constructor.call(this, scheduler, prevViewInfo, usePrevCache);
  this.appointmentsSnapToCells = appointmentsSnapToCells;
  this.isVertical = true;
  if(_aspxIsExists(prevViewInfo) && _aspxIsExists(prevViewInfo.moreButtonHelper)) {
   prevViewInfo.moreButtonHelper.HideMoreButtons();
  }
 },
 _constCellPrefix: function() { return "DXCntv"; },
 CreateSelectionViewInfoCore: function() {
  return new ASPxVerticalCellHighlightViewInfo(this.scheduler, this, this.scheduler.selectionDiv, this.parent.selectionLayer);
 },
 CompareCellAndPosition: function(x, y, cell) {
  var dxtop = this.parent.CalcRelativeElementTop(cell);
  if(y < dxtop)
   return -1;
  var bottom = this.parent.CalcRelativeElementBottom(cell);
  if(y > bottom)
   return 1;
  return 0;
 },
 Dispose: function() {
  this.constructor.prototype.Dispose.call(this);
  if(this.containerScrollDelegate && this.scrollContainer) {
   _aspxDetachEventFromElement(this.scrollContainer, "scroll", this.containerScrollDelegate);
   this.containerScrollDelegate = null;
  }
  this.moreButtonHelper.Dispose();
 },
 Prepare: function(parent) {
  this.constructor.prototype.Prepare.call(this, parent);
  if(_aspxIsExists(this.scheduler.privateShowMoreButtonsOnEachColumn) && this.scheduler.privateShowMoreButtonsOnEachColumn)
   this.moreButtonHelper = new ASPxMoreButtonInEachColumnHelper(this);
  else
   this.moreButtonHelper = new ASPxSingleMoreButtonHelper(this);
 },
 ShowMoreButton: function() {
  var scrollContainer = this.parent.parentElement.parentNode;
  if(scrollContainer.scrollHeight == scrollContainer.offsetHeight)
   return;
  this.ShowMoreButtonCore();
  this.containerScrollDelegate = _aspxCreateDelegate(this.OnContainerScroll, this);
  this.scrollContainer = scrollContainer;
  _aspxAttachEventToElement(scrollContainer, "scroll", this.containerScrollDelegate);
 },
 OnContainerScroll: function() {
  _aspxSetTimeout(_aspxCreateDelegate(this.ShowMoreButtonCore, this), 0);
 },
 ShowMoreButtonCore: function() {
  this.moreButtonHelper.CalculateMoreButtons();
 },
 OnMoreButtonClick: function(e, arguments) {  
  var moreButtonDiv = arguments[0];  
  var targetDateTime = moreButtonDiv.targetDateTime;
  var args = new MoreButtonClickedEventArgs(targetDateTime, moreButtonDiv.interval, moreButtonDiv.resource );
  this.scheduler.RaiseMoreButtonClickedEvent(args);
  if (args.handled)
   return;
  if (args.processOnServer) {
   if (_aspxIsExists(moreButtonDiv.interval))
    var intervalArgs = _aspxDateTimeToMilliseconds(moreButtonDiv.interval.GetStart()) + "," + moreButtonDiv.interval.GetDuration();
   else
    var intervalArgs = "0, 0";
   var targetDateTimeArg = _aspxDateTimeToMilliseconds(targetDateTime);
   this.scheduler.RaiseCallback("RAISEMOREBTN|" + targetDateTimeArg + "," + intervalArgs + "," + moreButtonDiv.resource );
   return;
  }
  var toTop = arguments[1];
  var appointmentDiv = moreButtonDiv.targetAppointmentViewInfo.contentDiv;
  var scrollContainer = this.parent.parentElement.parentNode;
  if(toTop)
   scrollContainer.scrollTop = appointmentDiv.offsetTop;
  else {
   if(scrollContainer.clientHeight > appointmentDiv.offsetHeight)
    scrollContainer.scrollTop = appointmentDiv.offsetTop - scrollContainer.clientHeight + appointmentDiv.offsetHeight;
   else
    scrollContainer.scrollTop = appointmentDiv.offsetTop;
  }
 }
});
ASPxClientHorizontalSchedulerViewInfo = _aspxCreateClass(ASPxSchedulerViewInfo, {  
 constructor: function(scheduler, prevViewInfo, usePrevCache) { 
  this.constructor.prototype.constructor.call(this, scheduler, prevViewInfo, usePrevCache);
  this.moreButtonDiv = this.GetMoreButtonDiv();  
  this.isVertical = false;
  this.moreButtonLeftMargin = 3;
  this.moreButtonRightMargin = 3;
  this.moreButtonBottomMargin = 3;
 }, 
 _constCellPrefix: function() { return "DXCnth"; },
 GetMoreButtonDiv: function() {   
  return this.scheduler.GetContainerElementById(_aspxSchedulerMoreButtonId);
 },
 GetMoreButtonSize: function() {
  if(!_aspxIsExists(this.moreButtonSize) || this.moreButtonSize <= 0)
   this.moreButtonSize = this.CalculateMoreButtonSize();
  return this.moreButtonSize;
 },
 CalculateMoreButtonSize: function() {     
  var result;
  if (_aspxIsExists(this.moreButtonDiv)) {
   this.moreButtonDiv.style.display = "block";
   result = this.moreButtonDiv.offsetHeight;
   this.moreButtonDiv.style.display = "none";   
  }
  else
   result = 0;
  return result;
 },
 CreateSelectionViewInfoCore: function() {
  return new ASPxHorizontalCellHighlightViewInfo(this.scheduler, this, this.scheduler.selectionDiv, this.parent.selectionLayer);
 },
 ShowMoreButton: function(cell, viewInfo) {
  if(_aspxIsExists(this.moreButtonDiv) &&(!_aspxIsExists(cell.hasMoreButton) || !cell.hasMoreButton)) {
   var newDiv = this.moreButtonDiv.cloneNode(true);
   newDiv.id = cell.id + "_moreButton";
   newDiv.style.display = "block";
   newDiv.schedulerControl = this.scheduler;   
   newDiv.interval = this.scheduler.GetCellInterval(cell);
   newDiv.targetDateTime = this.CalculateMoreButtonTargetDateTime(cell, viewInfo);
   newDiv.resource = this.scheduler.GetCellResource(cell);
   newDiv.isMoreButton = true;
   this.parent.AppendChildToMoreButtonLayer(newDiv);
   cell.hasMoreButton = true;
   _aspxSetElementDisplay(newDiv, true);
   _aspxAttachEventToElement(newDiv, "click", aspxMoreButtonClickEvent);
   var newDivWidth = newDiv.scrollWidth;
   var cellLeft = this.parent.CalcRelativeElementLeft(cell) + this.moreButtonLeftMargin;
   var cellRight = this.parent.CalcRelativeElementRight(cell) - this.moreButtonRightMargin;
   newDiv.style.left = Math.max(cellLeft, cellRight - newDivWidth) + "px";
   newDiv.style.width = Math.max(0,Math.min(newDivWidth, cellRight - cellLeft)) + "px";
   newDiv.style.top = this.parent.CalcRelativeElementBottom(cell) - newDiv.offsetHeight - this.moreButtonBottomMargin + "px";
  }   
 },
 CalculateMoreButtonTargetDateTime: function(cell, aptViewInfo) {  
  var appointment = this.scheduler.GetAppointment(aptViewInfo.appointmentId);
  var cellInterval = this.scheduler.GetCellInterval(cell);
  var cellStart = cellInterval.GetStart();
  var aptStart = appointment.interval.GetStart();  
  var cellStartMSec = parseInt(_aspxDateTimeToMilliseconds(cellStart));
  var aptStartMSec = parseInt(_aspxDateTimeToMilliseconds(aptStart));
  if (cellStartMSec > aptStartMSec)
   return cellStart;
  else
   return aptStart;
 },
 CompareCellAndPosition: function(x, y, cell) {
  var left = this.parent.CalcRelativeElementLeft(cell);
  if(x < left)
   return -1;
  var right = this.parent.CalcRelativeElementRight(cell);
  if(x > right)
   return 1;
  var dxtop = this.parent.CalcRelativeElementTop(cell);
  if(y < dxtop)
   return -1;
  var bottom = this.parent.CalcRelativeElementBottom(cell);
  if(y > bottom)
   return 1;
  return 0;
 }
});
ASPxClientTimelineHeaderLevelViewInfo = _aspxCreateClass(null, {
 constructor: function() {
  this.timelineHeaders = new Array();
 },
 Add: function(cellLocation, offset, baseCellLocation) {
  var header = new ASPxClientTimelineHeaderCellViewInfo(cellLocation, offset, baseCellLocation);
  this.timelineHeaders.push(header);
 }
});   
ASPxClientTimelineHeaderCellViewInfo = _aspxCreateClass(null, {
 constructor: function(cellLocation, offset, baseCellLocation) {
  this.cellLocation = cellLocation;
  this.offset = offset;
  this.baseCellLocation = baseCellLocation;
 }
});   
ASPxClientTimelineHeaderLayoutCalculator = _aspxCreateClass(null, {
 constructor: function(schedulerControl) {
  this.schedulerControl = schedulerControl;
  this.headerCellFinder = new ASPxTimelineHeaderCellFinder(this.schedulerControl.horzTable);
  this.coordinatesCalculator = schedulerControl.horizontalViewInfo.parent;
 },
 CalculateLayout: function(headerLevels) {
  var levelCount = headerLevels.length;
  for(levelIndex = 0; levelIndex < levelCount; levelIndex++) {
   if (headerLevels[levelIndex] != null) {
    var headerLevel = headerLevels[levelIndex];
    this.CalculateLevelLayout(headerLevel.timelineHeaders);
   }
  }
 },
 CalculateLevelLayout: function(headers) {
  var count = headers.length;
  var header = headers[0];
  var start = this.GetStartPosition(header);
  var end = 0;
  for (var headerIndex = 1; headerIndex < count - 1; headerIndex++) {
   var nextHeader = headers[headerIndex];
   end = this.GetStartPosition(nextHeader);
   this.SetHeaderPosition(header, start, end);
   header = nextHeader;
   start = end;
  }
  this.SetLastHeaderPosition(headers[count-2], end);
 },
 GetStartPosition: function(header) {
  var cell = this.headerCellFinder.GetCellByPathLocation(header.baseCellLocation);
  return this.coordinatesCalculator.CalcRelativeElementLeft(cell) + header.offset * cell.offsetWidth / 100;
 },
 SetHeaderPosition: function(header, start, end) {
  var headerCell = this.headerCellFinder.GetCellByPathLocation(header.cellLocation);
  var totalBorderWidth = headerCell.offsetWidth - headerCell.clientWidth;
  var totalHorizontalPadding = 0;
  headerCell.style.left = start + "px";
  var expectedOffsetWidth = end - start;
  if (expectedOffsetWidth > 0)
   _aspxSetTableCellOffsetWidth(headerCell, expectedOffsetWidth - totalBorderWidth);
 },
 SetLastHeaderPosition: function(header, start) {
  var headerCell = this.headerCellFinder.GetCellByPathLocation(header.cellLocation);
  headerCell.style.width = "100%";
  headerCell.style.left = start + "px";
 }
}); 
ASPxTimelineHeaderCellFinder = _aspxCreateClass(null, {
 constructor: function(parentTable) {
  this.parentTable = parentTable;
 },
 GetCellByPathLocation: function(path) {
  var count = path.length;
  var table = this.parentTable;
  var result = null;
  for (var i = 0; i < count; i++) {
   var location = path[i];
   var rowIndex = location[0];
   var cellIndex = location[1];
   result = table.rows[rowIndex].cells[cellIndex];
   table = this.GetNextTable(table.rows[rowIndex].cells[cellIndex]);
  }
  return result;
 },
 GetNextTable: function(cell) {
  var children = cell.childNodes;
  var count = children.length;
  for(var i = 0; i < count; i++) {
   var child = children[i];
   if(_aspxIsExists(child.tagName) && child.tagName.toUpperCase() == "TABLE") 
    return child;
  }  
  return null;
 }
}); 
ASPxNavigationButton = _aspxCreateClass(null, {
 constructor: function(divId, resourceId, anchorType) {
  this.divId = divId;
  this.anchorType = anchorType;
  this.resourceId = resourceId;
 }
});
