You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
540 lines
18 KiB
540 lines
18 KiB
/* Copyright (c) Business Objects 2006. All rights reserved. */
|
|
|
|
if (typeof bobj == 'undefined') {
|
|
bobj = {};
|
|
}
|
|
if (typeof bobj.crv == 'undefined') {
|
|
bobj.crv = {};
|
|
}
|
|
if (typeof bobj.crv.Calendar == 'undefined') {
|
|
bobj.crv.Calendar = {};
|
|
}
|
|
|
|
/*
|
|
================================================================================
|
|
Calendar Widget
|
|
================================================================================
|
|
*/
|
|
|
|
/**
|
|
* Get a shared calendar instance
|
|
*/
|
|
bobj.crv.Calendar.getInstance = function() {
|
|
if (!bobj.crv.Calendar.__instance) {
|
|
bobj.crv.Calendar.__instance = bobj.crv.newCalendar();
|
|
}
|
|
return bobj.crv.Calendar.__instance;
|
|
};
|
|
|
|
bobj.crv.Calendar.Signals = {
|
|
OK_CLICK: 'okClick',
|
|
CANCEL_CLICK: 'cancelClick',
|
|
ON_HIDE: 'onHide'
|
|
};
|
|
|
|
bobj.crv.newCalendar = function(kwArgs) {
|
|
var UPDATE = MochiKit.Base.update;
|
|
kwArgs = UPDATE({
|
|
id: bobj.uniqueId() + "_calendar",
|
|
showTime: false,
|
|
date: new Date(),
|
|
// List of formats to match in order of preference. Once a format is
|
|
// matched, the time field will be displayed in that format.
|
|
timeFormats: ["HH:mm:ss", "H:mm:ss", "H:m:s", "HH:mm", "H:mm", "H:m",
|
|
"h:mm:ss a", "h:m:s a", "h:mm:ssa", "h:m:sa", "h:mm a", "h:m a",
|
|
"h:mma", "h:ma"]
|
|
}, kwArgs);
|
|
|
|
var o = newMenuWidget( );
|
|
|
|
o.widgetType = 'Calendar';
|
|
|
|
// Update instance with constructor arguments
|
|
bobj.fillIn(o, kwArgs);
|
|
|
|
// Update instance with member functions
|
|
o._menuJustInTimeInit = o.justInTimeInit;
|
|
UPDATE(o, bobj.crv.Calendar);
|
|
|
|
o._curTimeFormat = o.timeFormats[0];
|
|
o._cells = [];
|
|
o._firstDay = 0;
|
|
o._numDays = 0;
|
|
|
|
return o;
|
|
};
|
|
|
|
bobj.crv.Calendar._createHeaderButtons = function() {
|
|
var w = 8;
|
|
var h = 4;
|
|
var dx = 46;
|
|
var dyUp = 0;
|
|
var dyDown = 12;
|
|
|
|
var bind = MochiKit.Base.bind;
|
|
|
|
this._prevMonthBtn = newIconWidget(this.id+"_pm",_skin+'../lov.gif',bind(this._onPrevMonthClick, this),"",_calendarPrevMonthLab,w,h,dx,dyDown);
|
|
this._prevYearBtn = newIconWidget(this.id+"_py",_skin+'../lov.gif',bind(this._onPrevYearClick, this),"",_calendarPrevYearLab,w,h,dx,dyDown);
|
|
this._nextMonthBtn = newIconWidget(this.id+"_nm",_skin+'../lov.gif',bind(this._onNextMonthClick, this),"",_calendarNextMonthLab,w,h,dx,dyUp);
|
|
this._nextYearBtn = newIconWidget(this.id+"_ny",_skin+'../lov.gif',bind(this._onNextYearClick, this),"",_calendarNextYearLab,w,h,dx,dyUp);
|
|
};
|
|
|
|
bobj.crv.Calendar._createTimeTextField = function() {
|
|
var bind = MochiKit.Base.bind;
|
|
|
|
this._timeField = newTextFieldWidget(
|
|
this.id + '_time',
|
|
bind(this._onTimeChange, this), //changeCB
|
|
null, //maxChar
|
|
null, //keyUpCB
|
|
null, //enterCB
|
|
true, //noMargin
|
|
null, //tooltip
|
|
null, //width
|
|
null, //focusCB
|
|
null); //blurCB
|
|
};
|
|
|
|
bobj.crv.Calendar._createOKCancelButtons = function() {
|
|
var bind = MochiKit.Base.bind;
|
|
this._okBtn = newButtonWidget(this.id + "_ok", L_bobj_crv_OK, bind(this._onOKClick, this));
|
|
this._cancelBtn = newButtonWidget(this.id + "_cancel", L_bobj_crv_Cancel, bind(this._onCancelClick, this));
|
|
};
|
|
|
|
/**
|
|
* Widget will auto-initialize the first time its show method is called.
|
|
* Client code shoud not call this method.
|
|
*/
|
|
bobj.crv.Calendar.justInTimeInit = function() {
|
|
this._menuJustInTimeInit();
|
|
|
|
this._prevMonthBtn.init();
|
|
this._prevYearBtn.init();
|
|
this._nextMonthBtn.init();
|
|
this._nextYearBtn.init();
|
|
|
|
this._okBtn.init();
|
|
this._cancelBtn.init();
|
|
|
|
this._timeField.init();
|
|
this._timeField.layer.style.width = '100%';
|
|
this._timeField.setValue(bobj.external.date.formatDate(this.date, this._curTimeFormat));
|
|
|
|
this._timeRow = getLayer(this.id + '_timeRow');
|
|
this._timeSep = getLayer(this.id + '_timeSep');
|
|
|
|
this._month = getLayer(this.id + "_month");
|
|
this._year = getLayer(this.id + "_year");
|
|
|
|
var numCells = 6 * 7; // six rows in the calendar with 7 days each
|
|
for (var i = 0; i < numCells; i++) {
|
|
this._cells[i] = getLayer(this.id + '_c' + i);
|
|
}
|
|
|
|
this._update();
|
|
};
|
|
|
|
/**
|
|
* Widget will be written into the document the first time its show method is called.
|
|
* Client code shoud not call this method.
|
|
*/
|
|
bobj.crv.Calendar.getHTML = function() {
|
|
var h = bobj.html;
|
|
var TABLE = h.TABLE;
|
|
var TBODY = h.TBODY;
|
|
var TR = h.TR;
|
|
var TD = h.TD;
|
|
var DIV = h.DIV;
|
|
var SPAN = h.SPAN;
|
|
var A = h.A;
|
|
|
|
this._createHeaderButtons();
|
|
this._createTimeTextField();
|
|
this._createOKCancelButtons();
|
|
|
|
var onkeydown = "MenuWidget_keyDown('" + this.id + "', event); return true";
|
|
var onmousedown = "eventCancelBubble(event)";
|
|
var onmouseup = "eventCancelBubble(event)";
|
|
var onkeypress = "eventCancelBubble(event)";
|
|
|
|
var dayHeaderAtt = {'class':"calendarTextPart"};
|
|
|
|
var html = TABLE({dir: 'ltr', id: this.id, border:"0", cellpadding:"0", cellspacing:"0",
|
|
onkeydown: onkeydown, onmousedown: onmousedown, onmouseup: onmouseup, onkeypress: onkeypress,
|
|
'class':"menuFrame", style:{cursor:"default", visibility:"hidden",'z-index': 10000}},
|
|
TBODY(null,
|
|
TR(null, TD(null, this._getMonthYearHTML())),
|
|
TR(null, TD({align:"center"},
|
|
TABLE({border:"0", cellspacing:"0", cellpadding:"0", style:{margin:"2px", 'margin-top': "6px"}},
|
|
TR({align:"center"},
|
|
TD(dayHeaderAtt, L_bobj_crv_SundayShort),
|
|
TD(dayHeaderAtt, L_bobj_crv_MondayShort),
|
|
TD(dayHeaderAtt, L_bobj_crv_TuesdayShort),
|
|
TD(dayHeaderAtt, L_bobj_crv_WednesdayShort),
|
|
TD(dayHeaderAtt, L_bobj_crv_ThursdayShort),
|
|
TD(dayHeaderAtt, L_bobj_crv_FridayShort),
|
|
TD(dayHeaderAtt, L_bobj_crv_SaturdayShort)),
|
|
TR(null, TD({colspan:"7", style:{padding:"2px"}}, this._getSeparatorHTML())),
|
|
this._getDaysHTML(),
|
|
TR(null, TD({colspan:"7", style:{padding:"2px"}}, this._getSeparatorHTML())),
|
|
TR({id:this.id + '_timeRow', style:{display:this.showTime ? '' : 'none'}},
|
|
TD({colspan:"7", style:{'padding-top':"3px", 'padding-bottom':"3px", 'padding-right':"10px", 'padding-left':"10px"}},
|
|
this._timeField.getHTML())),
|
|
TR({id:this.id + '_timeSep',style:{display:this.showTime ? '' : 'none'}},
|
|
TD({colspan:"7", style:{padding:"2px"}}, this._getSeparatorHTML())),
|
|
TR(null, TD({colspan:"7", align:"right", style:{'padding-bottom':"3px", 'padding-top':"3px"}},
|
|
TABLE(null, TBODY(null, TR(null,
|
|
TD(null, this._okBtn.getHTML()),
|
|
TD(null, this._cancelBtn.getHTML())))))))))));
|
|
|
|
return this._getLinkHTML('startLink_' + this.id) + html + this._getLinkHTML('endLink_' + this.id);
|
|
};
|
|
|
|
bobj.crv.Calendar._getMonthYearHTML = function() {
|
|
var h = bobj.html;
|
|
var TABLE = h.TABLE;
|
|
var TBODY = h.TBODY;
|
|
var TR = h.TR;
|
|
var TD = h.TD;
|
|
var DIV = h.DIV;
|
|
var SPAN = h.SPAN;
|
|
|
|
return TABLE({'class':"dialogzone", width:"100%", cellpadding:"0", cellspacing:"0"},
|
|
TBODY(null,
|
|
TR(null,
|
|
TD({style:{'padding-top':"1px"}}, this._nextMonthBtn.getHTML()),
|
|
TD({rowspan:"2", width:"100%", align:"center", 'class':"dialogzone"},
|
|
SPAN({id:this.id + "_month", tabIndex:"0"}, _month[this.date.getMonth()]),
|
|
" ",
|
|
SPAN({id:this.id + "_year", tabIndex:"0"}, this.date.getFullYear())),
|
|
TD({style:{'pading-top':"1px"}}, this._nextYearBtn.getHTML())),
|
|
TR({valign:"top"},
|
|
TD({style:{'padding-bottom':"1px"}}, this._prevMonthBtn.getHTML()),
|
|
TD({style:{'padding-bottom':"1px"}}, this._prevYearBtn.getHTML()))));
|
|
};
|
|
|
|
bobj.crv.Calendar._getSeparatorHTML = function() {
|
|
var h = bobj.html;
|
|
var TABLE = h.TABLE;
|
|
var TBODY = h.TBODY;
|
|
var TR = h.TR;
|
|
var TD = h.TD;
|
|
|
|
return TABLE({width:"100%",
|
|
height:"3",
|
|
cellpadding:"0",
|
|
cellspacing:"0",
|
|
border:"0",
|
|
style:backImgOffset(_skin+"menus.gif",0,80)},
|
|
TBODY(null, TR(null, TD())));
|
|
};
|
|
|
|
bobj.crv.Calendar._getLinkHTML = function(id) {
|
|
return bobj.html.A({
|
|
id: id,
|
|
href: "javascript:void(0)",
|
|
onfocus: "MenuWidget_keepFocus('"+this.id+"')",
|
|
style:{
|
|
visibility:"hidden",
|
|
position:"absolute"
|
|
}});
|
|
};
|
|
|
|
bobj.crv.Calendar._getDaysHTML = function() {
|
|
var TD = bobj.html.TD;
|
|
var DIV = bobj.html.DIV;
|
|
var html = '';
|
|
|
|
for (i = 0; i < 6; ++i) {
|
|
html += '<tr align="right">';
|
|
|
|
for (j = 0; j < 7; ++j) {
|
|
var cellNum = j + (i * 7);
|
|
var eventArgs = "(this," + cellNum + "," + "event);";
|
|
|
|
html += TD({id: this.id + '_c' + (i * 7 + j),
|
|
'class':"calendarTextPart",
|
|
onmousedown: "bobj.crv.Calendar._onDayMouseDown" + eventArgs,
|
|
onmouseover: "bobj.crv.Calendar._onDayMouseOver" + eventArgs,
|
|
onmouseout: "bobj.crv.Calendar._onDayMouseOut" + eventArgs,
|
|
ondblclick: "bobj.crv.Calendar._onDayDoubleClick" + eventArgs,
|
|
onkeydown: "bobj.crv.Calendar._onDayKeyDown" + eventArgs},
|
|
DIV({'class':"menuCalendar"}));
|
|
}
|
|
|
|
html += '</tr>';
|
|
}
|
|
|
|
return html;
|
|
};
|
|
|
|
/**
|
|
* Update the calendar's display using the current date value
|
|
*/
|
|
bobj.crv.Calendar._update = function() {
|
|
var numCells = 6 * 7; // six rows in the calendar with 7 days each
|
|
var curDate = this.date.getDate();
|
|
|
|
var info = this._getMonthInfo(this.date.getMonth(), this.date.getFullYear());
|
|
|
|
var firstCellInMonth = info.firstDay;
|
|
this._firstDay = info.firstDay;
|
|
this._numDays = info.numDays;
|
|
|
|
var year = "" + this.date.getFullYear();
|
|
while (year.length < 4) {
|
|
year = "0" + year;
|
|
}
|
|
this._year.innerHTML = year;
|
|
this._month.innerHTML = _month[this.date.getMonth()];
|
|
|
|
this._selectedDate = null;
|
|
|
|
for (var cellNum = 0; cellNum < numCells; cellNum++) {
|
|
var cell = this._cells[cellNum].firstChild;
|
|
var cssClass = "menuCalendar";
|
|
var cellDate = this._getDateFromCellNum(cellNum);
|
|
|
|
if (cellDate < 1 || cellDate > info.numDays) {
|
|
cell.innerHTML = "";
|
|
cell.tabIndex = "-1";
|
|
}
|
|
else {
|
|
cell.innerHTML = "" + cellDate;
|
|
cell.tabIndex = "0";
|
|
if (cellDate == curDate) {
|
|
cssClass = "menuCalendarSel";
|
|
this._selectedDay = cell;
|
|
}
|
|
}
|
|
|
|
cell.className = cssClass;
|
|
}
|
|
};
|
|
|
|
bobj.crv.Calendar._getMonthInfo = function(month, year) {
|
|
var date = new Date();
|
|
date.setDate(1);
|
|
date.setFullYear(year);
|
|
date.setMonth(month);
|
|
|
|
var firstDay = date.getDay(); // First day of the week in this month
|
|
|
|
date.setDate(28);
|
|
var lastDate = 28; // Last date in this month
|
|
|
|
for (var i = 29; i < 32; i++) {
|
|
date.setDate(i);
|
|
if (date.getMonth() != month) {
|
|
break;
|
|
}
|
|
lastDate = i;
|
|
}
|
|
|
|
return {firstDay: firstDay, numDays: lastDate};
|
|
};
|
|
|
|
bobj.crv.Calendar._setDayOfMonth = function(date) {
|
|
if (date > 0 && date <= this._numDays) {
|
|
var prevDate = this.date.getDate();
|
|
|
|
if (date != prevDate) {
|
|
var prevCell = this._getCellFromDate(prevDate);
|
|
|
|
if (prevCell) {
|
|
prevCell.firstChild.className = "menuCalendar";
|
|
}
|
|
|
|
this._getCellFromDate(date).firstChild.className = "menuCalendarSel";
|
|
this.date.setDate(date);
|
|
}
|
|
}
|
|
};
|
|
|
|
bobj.crv.Calendar._getCellFromDate = function(date) {
|
|
var cellNum = date + this._firstDay - 1;
|
|
return this._cells[cellNum];
|
|
};
|
|
|
|
bobj.crv.Calendar._getDateFromCellNum = function(cellNum) {
|
|
return cellNum - this._firstDay + 1;
|
|
};
|
|
|
|
bobj.crv.Calendar._onDayMouseOver = function(node, cellNum, event) {
|
|
var o = getWidget(node);
|
|
var div = node.firstChild;
|
|
|
|
var date = cellNum - o._firstDay + 1;
|
|
if (date < 1 || date > o._numDays) {
|
|
div.className = "menuCalendar";
|
|
}
|
|
else {
|
|
div.className = "menuCalendarSel";
|
|
}
|
|
};
|
|
|
|
bobj.crv.Calendar._onDayMouseOut = function(node, cellNum, event) {
|
|
var o = getWidget(node);
|
|
var div = node.firstChild;
|
|
|
|
var date = cellNum - o._firstDay + 1;
|
|
|
|
if (date != o.date.getDate()) {
|
|
div.className = "menuCalendar";
|
|
}
|
|
};
|
|
|
|
bobj.crv.Calendar._onDayMouseDown = function(node, cellNum, event) {
|
|
var o = getWidget(node);
|
|
var date = cellNum - o._firstDay + 1;
|
|
o._setDayOfMonth(date);
|
|
};
|
|
|
|
bobj.crv.Calendar._onDayDoubleClick = function(node, cellNum, event) {
|
|
var o = getWidget(node);
|
|
o._onOKClick();
|
|
};
|
|
|
|
bobj.crv.Calendar._onDayKeyDown = function(node, cellNum, event) {
|
|
event = new MochiKit.Signal.Event(node, event);
|
|
var key = event.key().string;
|
|
if (key === "KEY_ENTER") {
|
|
var o = getWidget(node);
|
|
var date = cellNum - o._firstDay + 1;
|
|
o._setDayOfMonth(date);
|
|
}
|
|
};
|
|
|
|
bobj.crv.Calendar._onPrevMonthClick = function() {
|
|
var d = this.date;
|
|
var oldMonth = d.getMonth();
|
|
if(d.getMonth() === 0) {
|
|
d.setYear(d.getFullYear() -1);
|
|
d.setMonth(11);
|
|
}
|
|
else {
|
|
d.setMonth(d.getMonth() - 1);
|
|
if (oldMonth === d.getMonth()) {
|
|
// that means we have decremented 0 month instead of 1. This happens if the current date is Oct 31, for eg. Since there's no Sept 31, it jumps to October 1.
|
|
d.setMonth(oldMonth-1);
|
|
}
|
|
}
|
|
this._update();
|
|
};
|
|
|
|
bobj.crv.Calendar._onPrevYearClick = function() {
|
|
this.date.setFullYear(this.date.getFullYear() - 1);
|
|
this._update();
|
|
};
|
|
|
|
bobj.crv.Calendar._onNextMonthClick = function() {
|
|
var d = this.date;
|
|
var oldMonth = d.getMonth();
|
|
d.setMonth(d.getMonth() + 1);
|
|
if ((oldMonth+1) < d.getMonth()) {
|
|
// that means we have incremented 2 months instead of 1. This happens if the current date is Oct 31, for eg. Since there's no Nov 31, it jumps to Dec 1.
|
|
// For Dec 31, we don't need to worry because there's Jan 31.
|
|
d.setMonth(oldMonth+1);
|
|
}
|
|
this._update();
|
|
};
|
|
|
|
bobj.crv.Calendar._onNextYearClick = function() {
|
|
this.date.setFullYear(this.date.getFullYear() + 1);
|
|
this._update();
|
|
};
|
|
|
|
bobj.crv.Calendar._onOKClick = function() {
|
|
this.restoreFocus();
|
|
MochiKit.Signal.signal(this, this.Signals.OK_CLICK, this._copyDate(this.date));
|
|
this.show(false);
|
|
};
|
|
|
|
bobj.crv.Calendar._copyDate = function(date) {
|
|
if (date) {
|
|
return new Date(date.getFullYear(),
|
|
date.getMonth(),
|
|
date.getDate(),
|
|
date.getHours(),
|
|
date.getMinutes(),
|
|
date.getSeconds(),
|
|
date.getMilliseconds());
|
|
}
|
|
return new Date();
|
|
};
|
|
|
|
bobj.crv.Calendar._onCancelClick = function() {
|
|
this.restoreFocus();
|
|
this.show(false);
|
|
MochiKit.Signal.signal(this, this.Signals.CANCEL_CLICK);
|
|
};
|
|
|
|
bobj.crv.Calendar._onTimeChange = function() {
|
|
var text = this._timeField.getValue();
|
|
var date = null;
|
|
var format = null;
|
|
|
|
for (var i = 0; i < this.timeFormats.length && date === null; ++i) {
|
|
format = this.timeFormats[i];
|
|
date = bobj.external.date.getDateFromFormat(text, format);
|
|
}
|
|
|
|
if (date) {
|
|
this._curTimeFormat = format;
|
|
this.date.setHours(date.getHours());
|
|
this.date.setMinutes(date.getMinutes());
|
|
this.date.setSeconds(date.getSeconds());
|
|
this.date.setMilliseconds(date.getMilliseconds());
|
|
}
|
|
else {
|
|
this._timeField.setValue(bobj.external.date.formatDate(this.date, this._curTimeFormat));
|
|
}
|
|
};
|
|
|
|
bobj.crv.Calendar.setShowTime = function(isShow) {
|
|
var disp = isShow ? '' : 'none';
|
|
this.showTime = isShow;
|
|
if (this.layer) {
|
|
this._timeRow.style.display = disp;
|
|
this._timeSep.style.display = disp;
|
|
}
|
|
};
|
|
|
|
bobj.crv.Calendar.setDate = function(date) {
|
|
this.date = date;
|
|
if (this.layer) {
|
|
this._timeField.setValue(bobj.external.date.formatDate(this.date, this._curTimeFormat));
|
|
this._update();
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Show the calendar. Will write out the HTML and init the widget also.
|
|
*
|
|
* @param isShow [bool] Show calendar if true. Hide it if false.
|
|
* @param x [int] x coordinate for left of calendar
|
|
* @param y [int] y coordinate for top of calendar
|
|
* @param isAlignRight [bool, optional] When true, the x coordinate applies to
|
|
* the right edge of the calendar
|
|
* @param isAlignBottom [bool, optional] When true, the y coordinate applies to
|
|
* the bottom edge of the calendar
|
|
*/
|
|
bobj.crv.Calendar.show = function(isShow, x, y, isAlignRight, isAlignBottom) {
|
|
ScrollMenuWidget_show.call(this, isShow, x, y);
|
|
if(isShow) {
|
|
this.focus();
|
|
}
|
|
else {
|
|
MochiKit.Signal.signal(this, this.Signals.ON_HIDE);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Set focus on the Calendar. The currently selected day will receive focus.
|
|
*/
|
|
bobj.crv.Calendar.focus = function() {
|
|
if (this._selectedDay) {
|
|
this._selectedDay.focus();
|
|
}
|
|
};
|