Skip to content

Instantly share code, notes, and snippets.

@tilomitra
Created March 1, 2013 21:11
Show Gist options
  • Save tilomitra/5067803 to your computer and use it in GitHub Desktop.
Save tilomitra/5067803 to your computer and use it in GitHub Desktop.
A custom calendar that lets you select multiple calendar without clicking on any keyboard keys
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body class="yui3-skin-sam">
<div id="myCal"></div>
<script src="http://yui.yahooapis.com/3.8.1/build/yui/yui-debug.js"></script>
<script>
YUI({
filter: 'raw'
}).use('calendar', 'widget', function (Y) {
var getCN = Y.ClassNameManager.getClassName,
CALENDAR = 'calendar',
KEY_DOWN = 40,
KEY_UP = 38,
KEY_LEFT = 37,
KEY_RIGHT = 39,
KEY_ENTER = 13,
KEY_SPACE = 32,
CAL_DAY_SELECTED = getCN(CALENDAR, 'day-selected'),
CAL_DAY_HILITED = getCN(CALENDAR, 'day-highlighted'),
CAL_DAY = getCN(CALENDAR, 'day'),
CAL_PREVMONTH_DAY = getCN(CALENDAR, 'prevmonth-day'),
CAL_NEXTMONTH_DAY = getCN(CALENDAR, 'nextmonth-day'),
CAL_GRID = getCN(CALENDAR, 'grid'),
ydate = Y.DataType.Date,
CAL_PANE = getCN(CALENDAR, 'pane'),
os = Y.UA.os;
function CustomCalendar() {
CustomCalendar.CSS_PREFIX = 'yui3';
CustomCalendar.superclass.constructor.apply ( this, arguments );
}
Y.CustomCalendar = Y.extend(CustomCalendar, Y.Calendar, {
_clickCalendar : function (ev) {
var clickedCell = ev.currentTarget,
clickedCellIsDay = clickedCell.hasClass(CAL_DAY) &&
!clickedCell.hasClass(CAL_PREVMONTH_DAY) &&
!clickedCell.hasClass(CAL_NEXTMONTH_DAY),
clickedCellIsSelected = clickedCell.hasClass(CAL_DAY_SELECTED),
selectedDate,
initialSelectedDate = false;
switch (this.get("selectionMode")) {
case("single"):
if (clickedCellIsDay) {
if (!clickedCellIsSelected) {
this._clearSelection(true);
this._addDateToSelection(this._nodeToDate(clickedCell));
}
}
break;
case("multiple-sticky"):
if (clickedCellIsDay) {
if (clickedCellIsSelected) {
this._removeDateFromSelection(this._nodeToDate(clickedCell));
} else {
this._addDateToSelection(this._nodeToDate(clickedCell));
}
}
break;
case("multiple"):
if (clickedCellIsDay) {
if (!ev.metaKey && !ev.ctrlKey && !ev.shiftKey) {
if (this._lastSelectedDate && !clickedCellIsSelected) {
//a previous date has been selected
selectedDate = this._nodeToDate(clickedCell);
this._addDateRangeToSelection(selectedDate, this._lastSelectedDate);
this._lastSelectedDate = selectedDate;
}
else if (clickedCellIsSelected) {
this._clearSelection(true);
this._lastSelectedDate = null;
}
else {
this._clearSelection(true);
this._lastSelectedDate = this._nodeToDate(clickedCell);
this._addDateToSelection(this._lastSelectedDate);
initialSelectedDate = this._lastSelectedDate;
}
} else if (((os === 'macintosh' && ev.metaKey) || (os !== 'macintosh' && ev.ctrlKey)) && !ev.shiftKey) {
if (clickedCellIsSelected) {
this._removeDateFromSelection(this._nodeToDate(clickedCell));
this._lastSelectedDate = null;
} else {
this._lastSelectedDate = this._nodeToDate(clickedCell);
this._addDateToSelection(this._lastSelectedDate);
}
} else if (((os === 'macintosh' && ev.metaKey) || (os !== 'macintosh' && ev.ctrlKey)) && ev.shiftKey) {
if (this._lastSelectedDate) {
selectedDate = this._nodeToDate(clickedCell);
this._addDateRangeToSelection(selectedDate, this._lastSelectedDate);
this._lastSelectedDate = selectedDate;
} else {
this._lastSelectedDate = this._nodeToDate(clickedCell);
this._addDateToSelection(this._lastSelectedDate);
}
} else if (!ev.shiftKey && this._lastSelectedDate) {
if (this._lastSelectedDate) {
selectedDate = this._nodeToDate(clickedCell);
this._clearSelection(true);
this._addDateRangeToSelection(selectedDate, this._lastSelectedDate);
this._lastSelectedDate = selectedDate;
} else {
this._clearSelection(true);
this._lastSelectedDate = this._nodeToDate(clickedCell);
this._addDateToSelection(this._lastSelectedDate);
}
}
}
break;
}
if (clickedCellIsDay) {
/**
* Fired when a specific date cell in the calendar is clicked. The event carries a
* payload which includes a `cell` property corresponding to the node of the actual
* date cell, and a `date` property, with the `Date` that was clicked.
*
* @event dateClick
*/
this.fire("dateClick", {cell: clickedCell, date: this._nodeToDate(clickedCell)});
} else if (clickedCell.hasClass(CAL_PREVMONTH_DAY)) {
/**
* Fired when any of the previous month's days displayed before the calendar grid
* are clicked.
*
* @event prevMonthClick
*/
this.fire("prevMonthClick");
} else if (clickedCell.hasClass(CAL_NEXTMONTH_DAY)) {
/**
* Fired when any of the next month's days displayed after the calendar grid
* are clicked.
*
* @event nextMonthClick
*/
this.fire("nextMonthClick");
}
}
});
var calendar = new Y.CustomCalendar({
contentBox: "#myCal",
width: "700px",
showPrevMonth: true,
showNextMonth: true,
selectionMode: 'multiple'
}).render();
});
</script>
</body>
</html>
@tilomitra
Copy link
Author

A simple Y.extend() does the trick. Minor modifications to Y.Calendar's _clickCalendar method.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment