getting ready for next version
|
@ -1,184 +0,0 @@
|
||||||
|
|
||||||
/* top area w/ month title and buttons */
|
|
||||||
|
|
||||||
.full-calendar-title {
|
|
||||||
text-align: left;
|
|
||||||
}
|
|
||||||
|
|
||||||
.full-calendar-buttons {
|
|
||||||
float: right;
|
|
||||||
margin: 0 0 1em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.full-calendar-buttons button {
|
|
||||||
vertical-align: middle;
|
|
||||||
margin: 0 0 0 5px;
|
|
||||||
font-size: 1em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.full-calendar-buttons button span {
|
|
||||||
padding: 0 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* To always display the "today" button:
|
|
||||||
*
|
|
||||||
* .full-calendar-buttons button.today {
|
|
||||||
* visibility: visible !important;
|
|
||||||
* }
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* table layout & outer border */
|
|
||||||
|
|
||||||
.full-calendar-month-wrap {
|
|
||||||
clear: both;
|
|
||||||
border: 1px solid #ccc; /* outer border color & style */
|
|
||||||
}
|
|
||||||
|
|
||||||
.full-calendar-month {
|
|
||||||
width: 100%;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.full-calendar-month table {
|
|
||||||
border-collapse: collapse;
|
|
||||||
border-spacing: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* cell styling */
|
|
||||||
|
|
||||||
.full-calendar-month th,
|
|
||||||
.full-calendar-month td.day {
|
|
||||||
padding: 0;
|
|
||||||
vertical-align: top;
|
|
||||||
border-style: solid; /* inner border style */
|
|
||||||
border-color: #ccc; /* inner border color */
|
|
||||||
border-width: 1px 0 0 1px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.full-calendar-month th {
|
|
||||||
border-top: 0;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.full-calendar-month th.first,
|
|
||||||
.full-calendar-month td.first {
|
|
||||||
border-left: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.full-calendar-month td.today {
|
|
||||||
background: #FFFFCC;
|
|
||||||
}
|
|
||||||
|
|
||||||
.full-calendar-month .day-number {
|
|
||||||
text-align: right;
|
|
||||||
padding: 0 2px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.full-calendar-month .other-month .day-number {
|
|
||||||
color: #bbb;
|
|
||||||
}
|
|
||||||
|
|
||||||
.full-calendar-month .day-content {
|
|
||||||
padding: 2px 2px 0; /* distance between events and day edges */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* FullCalendar automatically chooses a cell's height,
|
|
||||||
* but this can be overridden:
|
|
||||||
*
|
|
||||||
* .full-calendar-month td.day {
|
|
||||||
* height: 100px !important;
|
|
||||||
* }
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* event styling */
|
|
||||||
|
|
||||||
.full-calendar-month .event {
|
|
||||||
margin-bottom: 2px;
|
|
||||||
font-size: .85em;
|
|
||||||
cursor: pointer;
|
|
||||||
text-align: left;
|
|
||||||
}
|
|
||||||
|
|
||||||
.full-calendar-month .ui-draggable-dragging td {
|
|
||||||
cursor: move;
|
|
||||||
}
|
|
||||||
|
|
||||||
.full-calendar-month .event td {
|
|
||||||
background: #C1D9EC;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.full-calendar-month .event td.ne,
|
|
||||||
.full-calendar-month .event td.nw,
|
|
||||||
.full-calendar-month .event td.se,
|
|
||||||
.full-calendar-month .event td.sw {
|
|
||||||
background: none;
|
|
||||||
width: 1px; /* <-- remove if you dont want "rounded" corners */
|
|
||||||
height: 1px; /* <-- */
|
|
||||||
}
|
|
||||||
|
|
||||||
.full-calendar-month .nobg td {
|
|
||||||
background: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.full-calendar-month .event td.c {
|
|
||||||
padding: 0 2px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.full-calendar-month .event-time {
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* To change the color of events on a per-class basis (such as with the
|
|
||||||
* "className" attribute of a CalEvent), do something like this:
|
|
||||||
*
|
|
||||||
* .full-calendar-month .myclass td {
|
|
||||||
* background: green;
|
|
||||||
* }
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* the rectangle that covers a day when dragging an event */
|
|
||||||
|
|
||||||
.full-calendar-month .over-day {
|
|
||||||
background: #ADDBFF;
|
|
||||||
opacity: .2;
|
|
||||||
filter: alpha(opacity=20); /* for IE */
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* right-to-left support */
|
|
||||||
|
|
||||||
.r2l .full-calendar-title {
|
|
||||||
text-align: right;
|
|
||||||
}
|
|
||||||
|
|
||||||
.r2l .full-calendar-buttons {
|
|
||||||
float: left;
|
|
||||||
}
|
|
||||||
|
|
||||||
.r2l .full-calendar-buttons button {
|
|
||||||
margin: 0 5px 0 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.r2l .full-calendar-month .day-number {
|
|
||||||
text-align: left;
|
|
||||||
}
|
|
||||||
|
|
||||||
.r2l .full-calendar-month .event {
|
|
||||||
text-align: right;
|
|
||||||
}
|
|
||||||
|
|
876
src/agenda.js
Executable file
|
@ -0,0 +1,876 @@
|
||||||
|
|
||||||
|
/********************************* week view ***********************************/
|
||||||
|
|
||||||
|
$.fullCalendar.views.week = function(element, options) {
|
||||||
|
|
||||||
|
var agenda = new Agenda(element, options);
|
||||||
|
|
||||||
|
safeExtend(options, {
|
||||||
|
weekTitleFormat: 'M j Y{ - M j Y}' // TODO: shift around
|
||||||
|
});
|
||||||
|
|
||||||
|
agenda.render = function(date, delta, fetchEvents) {
|
||||||
|
|
||||||
|
if (delta) {
|
||||||
|
addDays(date, delta * 7);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.start = addDays(cloneDate(date), -date.getDay());
|
||||||
|
this.end = addDays(cloneDate(this.start), 7);
|
||||||
|
this.title = formatDates(this.start, this.end, options.weekTitleFormat);
|
||||||
|
|
||||||
|
this.renderAgenda(fetchEvents);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
return agenda;
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************* day view *************************************/
|
||||||
|
|
||||||
|
$.fullCalendar.views.day = function(element, options) {
|
||||||
|
|
||||||
|
var agenda = new Agenda(element, options);
|
||||||
|
|
||||||
|
safeExtend(options, {
|
||||||
|
dayTitleFormat: 'l F j Y' // TODO: shift around
|
||||||
|
});
|
||||||
|
|
||||||
|
agenda.render = function(date, delta, fetchEvents) {
|
||||||
|
|
||||||
|
if (delta) {
|
||||||
|
addDays(date, delta);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.start = cloneDate(date, true);
|
||||||
|
this.end = addDays(cloneDate(date), 1);
|
||||||
|
this.title = formatDate(date, options.dayTitleFormat);
|
||||||
|
|
||||||
|
this.renderAgenda(fetchEvents);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
return agenda;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*********************** shared by month and day views *************************/
|
||||||
|
|
||||||
|
function Agenda(element, options) {
|
||||||
|
|
||||||
|
safeExtend(options, {
|
||||||
|
slotMinutes: 30,
|
||||||
|
defaultEventMinutes: 120,
|
||||||
|
agendaEventTimeFormat: 'g:i{ - g:i}',
|
||||||
|
agendaSideTimeFormat: 'ga',
|
||||||
|
agendaEventDragOpacity: .5
|
||||||
|
});
|
||||||
|
|
||||||
|
var view = this,
|
||||||
|
head, body, panel, bg,
|
||||||
|
dayCnt,
|
||||||
|
dayWidth, slotHeight,
|
||||||
|
timeWidth,
|
||||||
|
cachedEvents,
|
||||||
|
cachedSlotSegs, cachedDaySegs,
|
||||||
|
eventElements = [],
|
||||||
|
eventElementsByID = {},
|
||||||
|
eventsByID = {};
|
||||||
|
|
||||||
|
element.addClass('fc-agenda').css('position', 'relative');
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/******************************** cell rendering ********************************/
|
||||||
|
|
||||||
|
|
||||||
|
this.renderAgenda = function(fetchEvents) { // TODO: get z-indexes sorted out
|
||||||
|
|
||||||
|
var start = view.start,
|
||||||
|
end = view.end,
|
||||||
|
today = getToday(),
|
||||||
|
todayI = -1,
|
||||||
|
tm = options.theme ? 'ui' : 'fc',
|
||||||
|
slotNormal = options.slotMinutes % 15 == 0,
|
||||||
|
dayAbbrevs = $.fullCalendar.dayAbbrevs;
|
||||||
|
|
||||||
|
if (!head) { // first time rendering, build from scratch TODO: need all the nbsp's?
|
||||||
|
|
||||||
|
// head
|
||||||
|
var i, d, dDay, dMinutes,
|
||||||
|
s = "<div class='fc-agenda-head' style='position:relative;z-index:3'>" +
|
||||||
|
"<table style='width:100%' cellpadding='0' cellspacing='0'>" +
|
||||||
|
"<tr class='fc-first'>" +
|
||||||
|
"<th class='fc-first " + tm + "-state-default'> </th>";
|
||||||
|
dayCnt = 0;
|
||||||
|
for (d=cloneDate(start); d<end; addDays(d, 1)) {
|
||||||
|
s += "<th class='fc-" +
|
||||||
|
dayIDs[d.getDay()] + ' ' + // needs to be first
|
||||||
|
tm + '-state-default' +
|
||||||
|
"'>" + dayAbbrevs[d.getDay()] + "</th>";
|
||||||
|
if (+d == +today) {
|
||||||
|
todayI = dayCnt;
|
||||||
|
}
|
||||||
|
dayCnt++;
|
||||||
|
}
|
||||||
|
s += "<th class='fc-last " + tm + "-state-default'> </th></tr>" +
|
||||||
|
"<tr class='fc-last'>" +
|
||||||
|
"<th class='fc-first " + tm + "-state-default' style='font-weight:normal;text-align:right;padding:4px 2px'>all day</th>" +
|
||||||
|
"<td colspan='" + dayCnt + "' class='" + tm + "-state-default'>" +
|
||||||
|
"<div class='fc-day-content'><div/></div></td>" +
|
||||||
|
"<th class='fc-last " + tm + "-state-default'> </th>" +
|
||||||
|
"</tr></table></div>";
|
||||||
|
head = $(s).appendTo(element);
|
||||||
|
|
||||||
|
// body & event panel
|
||||||
|
s = "<div style='position:relative;overflow:hidden'>" +
|
||||||
|
"<table cellpadding='0' cellspacing='0'>";
|
||||||
|
d = getToday();
|
||||||
|
dDay = d.getDay();
|
||||||
|
for (i=0; d.getDay()==dDay; i++, addMinutes(d, options.slotMinutes)) {
|
||||||
|
dMinutes = d.getMinutes();
|
||||||
|
s += "<tr class='" +
|
||||||
|
(i==0 ? 'fc-first' : (dMinutes==0 ? '' : 'fc-minor')) +
|
||||||
|
"'><th class='" + tm + "-state-default'>" +
|
||||||
|
(!slotNormal || dMinutes==0 ? formatDate(d, options.agendaSideTimeFormat) : ' ') +
|
||||||
|
"</th><td class='fc-slot " + tm + "-state-default'> </td></tr>";
|
||||||
|
}
|
||||||
|
s += "</table></div>";
|
||||||
|
body = $("<div class='fc-agenda-body' style='position:relative;z-index:2'/>")
|
||||||
|
.append(panel = $(s))
|
||||||
|
.appendTo(element);
|
||||||
|
|
||||||
|
// background stripes
|
||||||
|
s = "<div class='fc-agenda-bg' style='position:absolute;top:0;z-index:1'>" +
|
||||||
|
"<table style='width:100%;height:100%' cellpadding='0' cellspacing='0'><tr>";
|
||||||
|
for (i=0; i<dayCnt; i++) {
|
||||||
|
s += "<td class='fc-" +
|
||||||
|
dayIDs[i] + ' ' + // needs to be first
|
||||||
|
tm + '-state-default ' +
|
||||||
|
(i==todayI ? tm + '-state-highlight fc-today' : 'fc-not-today') +
|
||||||
|
"'><div class='fc-day-content'><div> </div></div></td>";
|
||||||
|
}
|
||||||
|
s += "</tr></table></div>";
|
||||||
|
bg = $(s).appendTo(element);
|
||||||
|
|
||||||
|
}else{ // skeleton already built, just modify it
|
||||||
|
|
||||||
|
clearEvents();
|
||||||
|
|
||||||
|
// change classes of background stripes
|
||||||
|
todayI = Math.round((today - start) / msInDay);
|
||||||
|
bg.find('td').each(function(i) {
|
||||||
|
if (i == todayI) {
|
||||||
|
$(this).removeClass('fc-not-today')
|
||||||
|
.addClass('fc-today')
|
||||||
|
.addClass(tm + '-state-highlight');
|
||||||
|
}else{
|
||||||
|
$(this).addClass('fc-not-today')
|
||||||
|
.removeClass('fc-today')
|
||||||
|
.removeClass(tm + '-state-highlight');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// if 1-day view, change day-of-week class and header text
|
||||||
|
if (dayCnt == 1) {
|
||||||
|
var th = head.find('th:eq(1)').html(dayAbbrevs[start.getDay()])[0],
|
||||||
|
td = bg.find('td')[0];
|
||||||
|
th.className = th.className.replace(/^fc-\w+(?= )/, 'fc-' + dayIDs[start.getDay()]);
|
||||||
|
td.className = td.className.replace(/^fc-\w+(?= )/, 'fc-' + dayIDs[start.getDay()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
updateSize();
|
||||||
|
fetchEvents(renderEvents);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
function updateSize() {
|
||||||
|
|
||||||
|
// align first 'time' column
|
||||||
|
timeWidth = body.find('th:first').outerWidth();
|
||||||
|
head.find('th:first').width(timeWidth);
|
||||||
|
|
||||||
|
// set table width (100% in css wasn't working in IE)
|
||||||
|
var panelWidth = body[0].clientWidth || body.width(); // first time, there are no scrollbars!? for IE6?
|
||||||
|
body.find('table').width(panelWidth);
|
||||||
|
|
||||||
|
// align spacer column to scrollbar width
|
||||||
|
setOuterWidth(head.find('th:last'), body.width() - panelWidth);
|
||||||
|
|
||||||
|
// position background stripe container
|
||||||
|
bg.css({
|
||||||
|
left: timeWidth,
|
||||||
|
width: panelWidth - timeWidth,
|
||||||
|
height: element.height()
|
||||||
|
});
|
||||||
|
|
||||||
|
// align other columns
|
||||||
|
dayWidth = Math.floor((panelWidth - timeWidth) / dayCnt);
|
||||||
|
var topCells = head.find('tr:first th:gt(0)'),
|
||||||
|
bgCells = bg.find('td');
|
||||||
|
for (var i=0, len=bgCells.length-1; i<len; i++) { // TODO: use slice
|
||||||
|
setOuterWidth(topCells.eq(i), dayWidth);
|
||||||
|
setOuterWidth(bgCells.eq(i), dayWidth);
|
||||||
|
}
|
||||||
|
|
||||||
|
slotHeight = body.find('tr:eq(1)').height(); // use second, first prob doesn't have a border
|
||||||
|
|
||||||
|
// body height
|
||||||
|
body.height(Math.round(body.width() / contentAspectRatio) - head.height());
|
||||||
|
// but this will add scrollbars...
|
||||||
|
// TODO: bug, iE6 view heights dont match up
|
||||||
|
// also, no scrollbars
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/********************************** event rendering *********************************/
|
||||||
|
|
||||||
|
|
||||||
|
function renderEvents(events) {
|
||||||
|
|
||||||
|
var i, len=events.length, event,
|
||||||
|
fakeID=0, nextDay,
|
||||||
|
slotEvents=[], dayEvents=[];
|
||||||
|
|
||||||
|
for (i=0; i<len; i++) {
|
||||||
|
event = events[i];
|
||||||
|
event._id = typeof event.id == 'undefined' ? '_fc' + fakeID++ : event.id + '';
|
||||||
|
if (eventsByID[event._id]) {
|
||||||
|
eventsByID[event._id].push(event);
|
||||||
|
}else{
|
||||||
|
eventsByID[event._id] = [event];
|
||||||
|
}
|
||||||
|
if (event.hasTime) {
|
||||||
|
event._end = event.end || addMinutes(cloneDate(event.start), options.defaultEventMinutes);
|
||||||
|
}else{
|
||||||
|
event._end = addDays(cloneDate(event.end || event.start), 1);
|
||||||
|
}
|
||||||
|
if (event.start < view.end && event._end > view.start) {
|
||||||
|
if (event.hasTime) {
|
||||||
|
event._end = event.end || addMinutes(cloneDate(event.start), options.defaultEventMinutes);
|
||||||
|
slotEvents.push(event);
|
||||||
|
}else{
|
||||||
|
event._end = addDays(cloneDate(event.end || event.start), 1);
|
||||||
|
dayEvents.push(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cachedEvents = events;
|
||||||
|
cachedSlotSegs = compileSlotSegs(slotEvents, view.start, view.end);
|
||||||
|
cachedDaySegs = levelizeSegs(sliceSegs(dayEvents, view.start, view.end));
|
||||||
|
|
||||||
|
renderSlotSegs(cachedSlotSegs);
|
||||||
|
renderDaySegs(cachedDaySegs);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function rerenderEvents(skipCompile) {
|
||||||
|
clearEvents();
|
||||||
|
if (skipCompile) {
|
||||||
|
renderSlotSegs(cachedSlotSegs);
|
||||||
|
renderDaySegs(cachedDaySegs);
|
||||||
|
}else{
|
||||||
|
renderEvents(cachedEvents);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function clearEvents() {
|
||||||
|
for (var i=0; i<eventElements.length; i++) {
|
||||||
|
eventElements[i].remove();
|
||||||
|
}
|
||||||
|
eventElements = [];
|
||||||
|
eventElementsByID = {};
|
||||||
|
eventsByID = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// renders events in the 'time slots' at the bottom
|
||||||
|
|
||||||
|
function renderSlotSegs(segCols) {
|
||||||
|
var colI, colLen=segCols.length, col,
|
||||||
|
levelI, level,
|
||||||
|
segI, seg,
|
||||||
|
event, start, end,
|
||||||
|
top, bottom,
|
||||||
|
tdInner, left, width,
|
||||||
|
eventElement, anchorElement, timeElement, titleElement;
|
||||||
|
for (colI=0; colI<colLen; colI++) {
|
||||||
|
col = segCols[colI];
|
||||||
|
for (levelI=0; levelI<col.length; levelI++) {
|
||||||
|
level = col[levelI];
|
||||||
|
for (segI=0; segI<level.length; segI++) {
|
||||||
|
seg = level[segI];
|
||||||
|
event = seg.event;
|
||||||
|
top = timeCoord(seg.start, seg.start);
|
||||||
|
bottom = timeCoord(seg.start, seg.end);
|
||||||
|
tdInner = bg.find('td:eq('+colI+') div div');
|
||||||
|
availWidth = tdInner.width();
|
||||||
|
left = timeWidth + tdInner.position().left + // leftmost possible
|
||||||
|
(availWidth / (levelI + seg.right + 1) * levelI); // indentation
|
||||||
|
if (levelI == 0) {
|
||||||
|
if (seg.right == 0) {
|
||||||
|
// can be entire width, aligned left
|
||||||
|
width = availWidth * .96;
|
||||||
|
}else{
|
||||||
|
// moderately wide, aligned left still
|
||||||
|
width = ((availWidth / (seg.right + 1)) - (12/2)) * 2; // 12 is the predicted width of resizer =
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
// indented and thinner
|
||||||
|
width = availWidth / (levelI + seg.right + 1);
|
||||||
|
}
|
||||||
|
eventElement = $("<div class='fc-event fc-event-vert' />")
|
||||||
|
.append(anchorElement = $("<a><span class='fc-event-bg'/></a>")
|
||||||
|
.append(titleElement = $("<span class='fc-event-title'/>")
|
||||||
|
.text(event.title)))
|
||||||
|
.css({
|
||||||
|
position: 'absolute',
|
||||||
|
zIndex: 1000,
|
||||||
|
top: top,
|
||||||
|
left: left
|
||||||
|
});
|
||||||
|
if (event.url) {
|
||||||
|
anchorElement.attr('href', event.url);
|
||||||
|
}
|
||||||
|
if (seg.isStart) {
|
||||||
|
eventElement.addClass('fc-corner-top');
|
||||||
|
// add the time header
|
||||||
|
anchorElement
|
||||||
|
.prepend(timeElement = $("<span class='fc-event-time'/>")
|
||||||
|
.text(formatDates(event.start, event.end, options.agendaEventTimeFormat)))
|
||||||
|
}else{
|
||||||
|
timeElement = null;
|
||||||
|
}
|
||||||
|
if (seg.isEnd) {
|
||||||
|
eventElement.addClass('fc-corner-bottom');
|
||||||
|
resizableSlotEvent(event, eventElement, timeElement);
|
||||||
|
}
|
||||||
|
eventElement.appendTo(panel);
|
||||||
|
setOuterWidth(eventElement, width, true);
|
||||||
|
setOuterHeight(eventElement, bottom-top, true);
|
||||||
|
if (timeElement && eventElement.height() - titleElement.position().top < 10) {
|
||||||
|
// event title doesn't have enough room, but next to the time
|
||||||
|
timeElement.text(formatDate(event.start, options.agendaEventTimeFormat) + ' - ' + event.title);
|
||||||
|
titleElement.remove();
|
||||||
|
}
|
||||||
|
draggableSlotEvent(event, eventElement, timeElement);
|
||||||
|
reportEventElement(event, eventElement);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// renders 'all-day' events at the top
|
||||||
|
|
||||||
|
function renderDaySegs(segRow) {
|
||||||
|
var td = head.find('td');
|
||||||
|
var tdInner = td.find('div div');
|
||||||
|
var top = tdInner.position().top,
|
||||||
|
rowHeight = 0,
|
||||||
|
i, len=segRow.length, level,
|
||||||
|
levelHeight,
|
||||||
|
j, seg,
|
||||||
|
event, left, right,
|
||||||
|
eventElement, anchorElement;
|
||||||
|
for (i=0; i<len; i++) {
|
||||||
|
level = segRow[i];
|
||||||
|
levelHeight = 0;
|
||||||
|
for (j=0; j<level.length; j++) {
|
||||||
|
seg = level[j];
|
||||||
|
event = seg.event;
|
||||||
|
left = seg.isStart ?
|
||||||
|
bg.find('td:eq('+((seg.start.getDay()+dayCnt)%dayCnt)+') div div') :
|
||||||
|
bg.find('td:eq('+((seg.start.getDay()+dayCnt)%dayCnt)+')');
|
||||||
|
left = left.position().left;
|
||||||
|
right = seg.isEnd ?
|
||||||
|
bg.find('td:eq('+((seg.end.getDay()-1+dayCnt)%dayCnt)+') div div') :
|
||||||
|
bg.find('td:eq('+((seg.end.getDay()-1+dayCnt)%dayCnt)+')');
|
||||||
|
right = right.position().left + right.outerWidth();
|
||||||
|
eventElement = $("<div class='fc-event fc-event-hori' />")
|
||||||
|
.append(anchorElement = $("<a/>")
|
||||||
|
.append($("<span class='fc-event-title' />")
|
||||||
|
.text(event.title)))
|
||||||
|
.css({
|
||||||
|
position: 'absolute',
|
||||||
|
top: top,
|
||||||
|
left: timeWidth + left
|
||||||
|
});
|
||||||
|
if (seg.isStart) {
|
||||||
|
eventElement.addClass('fc-corner-left');
|
||||||
|
}
|
||||||
|
if (seg.isEnd) {
|
||||||
|
eventElement.addClass('fc-corner-right');
|
||||||
|
}
|
||||||
|
if (event.url) {
|
||||||
|
anchorElement.attr('href', event.url);
|
||||||
|
}
|
||||||
|
eventElement.appendTo(head);
|
||||||
|
setOuterWidth(eventElement, right-left, true);
|
||||||
|
draggableDayEvent(event, eventElement);
|
||||||
|
//resizableDayEvent(event, eventElement);
|
||||||
|
reportEventElement(event, eventElement);
|
||||||
|
levelHeight = Math.max(levelHeight, eventElement.outerHeight(true));
|
||||||
|
}
|
||||||
|
top += levelHeight;
|
||||||
|
rowHeight += levelHeight;
|
||||||
|
}
|
||||||
|
tdInner.height(rowHeight);
|
||||||
|
//bg.height(element.height()); // tdInner might have pushed the body down, so resize
|
||||||
|
//updateSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/******************************************* draggable *****************************************/
|
||||||
|
|
||||||
|
|
||||||
|
// when event starts out IN TIMESLOTS
|
||||||
|
|
||||||
|
function draggableSlotEvent(event, eventElement, timeElement) {
|
||||||
|
var origPosition, origMarginTop,
|
||||||
|
prevSlotDelta, slotDelta,
|
||||||
|
matrix;
|
||||||
|
eventElement.draggable({
|
||||||
|
zIndex: 1001,
|
||||||
|
scroll: false,
|
||||||
|
grid: [dayWidth, slotHeight],
|
||||||
|
axis: dayCnt==1 ? 'y' : false,
|
||||||
|
cancel: '.ui-resizable-handle',
|
||||||
|
opacity: .5,
|
||||||
|
start: function(ev, ui) {
|
||||||
|
if ($.browser.msie) {
|
||||||
|
eventElement.find('span.fc-event-bg').hide();
|
||||||
|
}
|
||||||
|
origPosition = eventElement.position();
|
||||||
|
origMarginTop = parseInt(eventElement.css('margin-top')) || 0;
|
||||||
|
prevSlotDelta = 0;
|
||||||
|
matrix = new HoverMatrix(function(cell) {
|
||||||
|
if (event.hasTime) {
|
||||||
|
// event is an original slot-event
|
||||||
|
if (cell && cell.row == 0) {
|
||||||
|
// but needs to convert to temporary full-day-event
|
||||||
|
var topDiff = panel.offset().top - head.offset().top;
|
||||||
|
eventElement.css('margin-top', origMarginTop + topDiff)
|
||||||
|
.appendTo(head);
|
||||||
|
// TODO: bug in IE8 w/ above technique, draggable ends immediately
|
||||||
|
event.hasTime = false;
|
||||||
|
if (timeElement) {
|
||||||
|
timeElement.hide();
|
||||||
|
}
|
||||||
|
eventElement.draggable('option', 'grid', null);
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
// event is a temporary full-day-event
|
||||||
|
if (cell && cell.row == 1) {
|
||||||
|
// but needs to convert to original slot-event
|
||||||
|
eventElement.css('margin-top', origMarginTop)
|
||||||
|
.appendTo(panel);
|
||||||
|
event.hasTime = true;
|
||||||
|
if (timeElement) {
|
||||||
|
timeElement.css('display', ''); // show() was causing display=inline
|
||||||
|
}
|
||||||
|
eventElement.draggable('option', 'grid', [dayWidth, slotHeight]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (cell && cell.row == 0) {
|
||||||
|
showDayOverlay(cell);
|
||||||
|
}else{
|
||||||
|
hideDayOverlay();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
matrix.row(head.find('td'));
|
||||||
|
bg.find('td').each(function() {
|
||||||
|
matrix.col(this);
|
||||||
|
});
|
||||||
|
matrix.row(body);
|
||||||
|
matrix.start();
|
||||||
|
hideSimilarEvents(event, eventElement);
|
||||||
|
},
|
||||||
|
drag: function(ev, ui) {
|
||||||
|
slotDelta = Math.round((ui.position.top - origPosition.top) / slotHeight);
|
||||||
|
if (slotDelta != prevSlotDelta) {
|
||||||
|
if (timeElement && event.hasTime) {
|
||||||
|
// update time header
|
||||||
|
var newStart = addMinutes(cloneDate(event.start), slotDelta * options.slotMinutes),
|
||||||
|
newEnd;
|
||||||
|
if (event.end) {
|
||||||
|
newEnd = addMinutes(cloneDate(event.end), slotDelta * options.slotMinutes);
|
||||||
|
}
|
||||||
|
timeElement.text(formatDates(newStart, newEnd, options.agendaEventTimeFormat));
|
||||||
|
}
|
||||||
|
prevSlotDelta = slotDelta;
|
||||||
|
}
|
||||||
|
matrix.mouse(ev.pageX, ev.pageY);
|
||||||
|
},
|
||||||
|
stop: function(ev, ui) {
|
||||||
|
if (event.hasTime) {
|
||||||
|
if (matrix.cell) {
|
||||||
|
// over slots
|
||||||
|
var dayDelta = Math.round((ui.position.left - origPosition.left) / dayWidth);
|
||||||
|
reportEventMove(event, dayDelta, true, slotDelta * options.slotMinutes);
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
// over full-days
|
||||||
|
if (!matrix.cell) {
|
||||||
|
// was being dragged over full-days, but finished over nothing, reset
|
||||||
|
event.hasTime = true;
|
||||||
|
}else{
|
||||||
|
event.end = null;
|
||||||
|
reportEventMove(event, matrix.cell.colDelta);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
hideDayOverlay();
|
||||||
|
rerenderEvents();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// when event starts out FULL-DAY
|
||||||
|
|
||||||
|
function draggableDayEvent(event, eventElement) {
|
||||||
|
var origWidth, matrix;
|
||||||
|
eventElement.draggable({
|
||||||
|
zIndex: 1001,
|
||||||
|
start: function() {
|
||||||
|
origWidth = eventElement.width();
|
||||||
|
matrix = new HoverMatrix(function(cell) {
|
||||||
|
if (!cell) {
|
||||||
|
// mouse is outside of everything
|
||||||
|
hideDayOverlay();
|
||||||
|
}else{
|
||||||
|
if (cell.row == 0) {
|
||||||
|
// on full-days
|
||||||
|
if (event.hasTime) {
|
||||||
|
// and needs to be original full-day event
|
||||||
|
eventElement
|
||||||
|
.width(origWidth)
|
||||||
|
.height('')
|
||||||
|
.draggable('option', 'grid', null);
|
||||||
|
event.hasTime = false;
|
||||||
|
}
|
||||||
|
showDayOverlay(cell);
|
||||||
|
}else{
|
||||||
|
// mouse is over bottom slots
|
||||||
|
if (!event.hasTime) {
|
||||||
|
// convert event to temporary slot-event
|
||||||
|
//if (+cloneDate(event.start, true) == +cloneDate(event._end, true)) {
|
||||||
|
// only change styles if a 1-day event
|
||||||
|
eventElement
|
||||||
|
.width(dayWidth - 10) // don't use entire width
|
||||||
|
.height(slotHeight * Math.round(options.defaultEventMinutes/options.slotMinutes) - 2);
|
||||||
|
//}
|
||||||
|
eventElement.draggable('option', 'grid', [dayWidth, 1]);
|
||||||
|
event.hasTime = true;
|
||||||
|
}
|
||||||
|
hideDayOverlay();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
matrix.row(head.find('td'));
|
||||||
|
bg.find('td').each(function() {
|
||||||
|
matrix.col(this);
|
||||||
|
});
|
||||||
|
matrix.row(body);
|
||||||
|
matrix.start();
|
||||||
|
hideSimilarEvents(event, eventElement);
|
||||||
|
},
|
||||||
|
drag: function(ev, ui) {
|
||||||
|
matrix.mouse(ev.pageX, ev.pageY);
|
||||||
|
},
|
||||||
|
stop: function() {
|
||||||
|
var cell = matrix.cell;
|
||||||
|
if (!cell) {
|
||||||
|
// over nothing
|
||||||
|
if (event.hasTime) {
|
||||||
|
// event was on the slots before going out, convert back
|
||||||
|
event.hasTime = false;
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
if (!event.hasTime) {
|
||||||
|
// event has been dropped on a full-day
|
||||||
|
reportEventMove(event, cell.colDelta);
|
||||||
|
}else{
|
||||||
|
// event has been dropped on the slots
|
||||||
|
var slots = Math.floor((eventElement.offset().top - panel.offset().top) / slotHeight);
|
||||||
|
event.end = null;
|
||||||
|
reportEventMove(event, cell.colDelta, false, slots * options.slotMinutes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
hideDayOverlay();
|
||||||
|
rerenderEvents();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// hover effect when dragging events over top days
|
||||||
|
|
||||||
|
var dayOverlay;
|
||||||
|
|
||||||
|
function showDayOverlay(props) {
|
||||||
|
if (!dayOverlay) {
|
||||||
|
dayOverlay = $("<div class='fc-day-overlay' style='position:absolute;display:none'/>")
|
||||||
|
.appendTo(element);
|
||||||
|
}
|
||||||
|
var o = element.offset();
|
||||||
|
dayOverlay
|
||||||
|
.css({
|
||||||
|
top: props.top - o.top,
|
||||||
|
left: props.left - o.left,
|
||||||
|
width: props.width,
|
||||||
|
height: props.height
|
||||||
|
})
|
||||||
|
.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
function hideDayOverlay() {
|
||||||
|
if (dayOverlay) {
|
||||||
|
dayOverlay.hide();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/************************************* resizable **************************************/
|
||||||
|
|
||||||
|
|
||||||
|
function resizableSlotEvent(event, eventElement, timeElement) {
|
||||||
|
var prevSlotDelta, slotDelta, newEnd;
|
||||||
|
eventElement
|
||||||
|
.resizable({
|
||||||
|
handles: 's',
|
||||||
|
grid: [0, slotHeight],
|
||||||
|
start: function() {
|
||||||
|
prevSlotDelta = 0;
|
||||||
|
hideSimilarEvents(event, eventElement);
|
||||||
|
if ($.browser.msie && $.browser.version == '6.0') {
|
||||||
|
eventElement.css('overflow', 'hidden');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
resize: function(ev, ui) {
|
||||||
|
slotDelta = Math.round((Math.max(slotHeight, ui.size.height) - ui.originalSize.height) / slotHeight);
|
||||||
|
if (slotDelta != prevSlotDelta) {
|
||||||
|
newEnd = addMinutes(cloneDate(event._end), options.slotMinutes * slotDelta);
|
||||||
|
if (timeElement) {
|
||||||
|
timeElement.text(formatDates(event.start, newEnd, options.agendaEventTimeFormat));
|
||||||
|
}
|
||||||
|
prevSlotDelta = slotDelta;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
stop: function(ev, ui) {
|
||||||
|
reportEventResize(event, 0, true, options.slotMinutes * slotDelta);
|
||||||
|
rerenderEvents();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.find('div.ui-resizable-s').text('=');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function resizableDayEvent(event, eventElement) {
|
||||||
|
eventElement.resizable({
|
||||||
|
handles: 'e',
|
||||||
|
grid: [dayWidth, 0],
|
||||||
|
start: function() {
|
||||||
|
hideSimilarEvents(event, eventElement);
|
||||||
|
},
|
||||||
|
stop: function(ev, ui) {
|
||||||
|
var dayDelta = Math.round((Math.max(dayWidth, ui.size.width) - ui.originalSize.width) / dayWidth);
|
||||||
|
reportEventResize(event, dayDelta);
|
||||||
|
rerenderEvents();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************** misc **************************************/
|
||||||
|
|
||||||
|
|
||||||
|
function reportEventElement(event, eventElement) {
|
||||||
|
eventElements.push(eventElement);
|
||||||
|
if (eventElementsByID[event._id]) {
|
||||||
|
eventElementsByID[event._id].push(eventElement);
|
||||||
|
}else{
|
||||||
|
eventElementsByID[event._id] = [eventElement];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function hideSimilarEvents(event, eventElement) {
|
||||||
|
var elements = eventElementsByID[event._id];
|
||||||
|
for (var i=0; i<elements.length; i++) {
|
||||||
|
if (elements[i] != eventElement) {
|
||||||
|
elements[i].hide();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function reportEventMove(event, days, keepTime, minutes) {
|
||||||
|
minutes = minutes || 0;
|
||||||
|
var events = eventsByID[event._id];
|
||||||
|
for (var i=0, event2; i<events.length; i++) {
|
||||||
|
event2 = events[i];
|
||||||
|
event2.hasTime = event.hasTime;
|
||||||
|
addMinutes(addDays(event2.start, days, keepTime), minutes);
|
||||||
|
if (event.end) {
|
||||||
|
event2.end = addMinutes(addDays(event2.end || event2._end, days, keepTime), minutes);
|
||||||
|
}else{
|
||||||
|
event2.end = event2._end = null;
|
||||||
|
// hopefully renderEvents() will always be called after this
|
||||||
|
// to reset _end.... TODO?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function reportEventResize(event, days, keepTime, minutes) {
|
||||||
|
minutes = minutes || 0;
|
||||||
|
var events = eventsByID[event._id];
|
||||||
|
for (var i=0, event2; i<events.length; i++) {
|
||||||
|
event2 = events[i];
|
||||||
|
event2.end = addMinutes(addDays(event2.end || event2._end, days, keepTime), minutes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// get the Y coordinate of the given time on the given day
|
||||||
|
|
||||||
|
function timeCoord(day, time) {
|
||||||
|
var nextDay = addDays(cloneDate(day), 1);
|
||||||
|
if (time < nextDay) {
|
||||||
|
var slotMinutes = options.slotMinutes;
|
||||||
|
var minutes = time.getHours()*60 + time.getMinutes();
|
||||||
|
var slotI = Math.floor(minutes / slotMinutes);
|
||||||
|
var td = body.find('tr:eq(' + slotI + ') td');
|
||||||
|
return Math.round(td.position().top + slotHeight * ((minutes % slotMinutes) / slotMinutes));
|
||||||
|
}else{
|
||||||
|
return panel.height();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function compileSlotSegs(events, start, end) {
|
||||||
|
|
||||||
|
// slice by day
|
||||||
|
var segCols = [],
|
||||||
|
d1 = cloneDate(start),
|
||||||
|
d2 = addDays(cloneDate(start), 1);
|
||||||
|
for (; d1<end; addDays(d1, 1), addDays(d2, 1)) {
|
||||||
|
segCols.push(sliceSegs(events, d1, d2));
|
||||||
|
}
|
||||||
|
|
||||||
|
var segLevelCols = [],
|
||||||
|
segLevels,
|
||||||
|
segs,
|
||||||
|
segI, seg,
|
||||||
|
levelI, level,
|
||||||
|
collide,
|
||||||
|
segI2, seg2;
|
||||||
|
|
||||||
|
for (var i=0; i<segCols.length; i++) {
|
||||||
|
|
||||||
|
// divide segments into levels
|
||||||
|
segLevels = segLevelCols[i] = [];
|
||||||
|
segs = segCols[i];
|
||||||
|
for (segI=0; segI<segs.length; segI++) {
|
||||||
|
seg = segs[segI];
|
||||||
|
for (levelI=0; true; levelI++) {
|
||||||
|
level = segLevels[levelI];
|
||||||
|
if (!level) {
|
||||||
|
segLevels[levelI] = [seg];
|
||||||
|
break;
|
||||||
|
}else{
|
||||||
|
collide = false;
|
||||||
|
for (segI2=0; segI2<level.length; segI2++) {
|
||||||
|
if (segsCollide(level[segI2], seg)) {
|
||||||
|
collide = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!collide) {
|
||||||
|
level.push(seg);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
seg.right = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// determine # of segments to the 'right' of each segment
|
||||||
|
for (levelI=segLevels.length-1; levelI>0; levelI--) {
|
||||||
|
level = segLevels[levelI];
|
||||||
|
for (segI=0; segI<level.length; segI++) {
|
||||||
|
seg = level[segI];
|
||||||
|
for (segI2=0; segI2<segLevels[levelI-1].length; segI2++) {
|
||||||
|
seg2 = segLevels[levelI-1][segI2];
|
||||||
|
if (segsCollide(seg, seg2)) {
|
||||||
|
seg2.right = Math.max(seg2.right, seg.right+1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return segLevelCols;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: move to month.js
|
||||||
|
|
||||||
|
function sliceSegs(events, start, end) {
|
||||||
|
var segs = [],
|
||||||
|
i, len=events.length, event,
|
||||||
|
eventStart, eventEnd,
|
||||||
|
segStart, segEnd,
|
||||||
|
isStart, isEnd;
|
||||||
|
for (i=0; i<len; i++) {
|
||||||
|
event = events[i];
|
||||||
|
eventStart = event.start;
|
||||||
|
eventEnd = event._end;
|
||||||
|
if (eventEnd > start && eventStart < end) {
|
||||||
|
if (eventStart < start) {
|
||||||
|
segStart = cloneDate(start);
|
||||||
|
isStart = false;
|
||||||
|
}else{
|
||||||
|
segStart = eventStart;
|
||||||
|
isStart = true;
|
||||||
|
}
|
||||||
|
if (eventEnd > end) {
|
||||||
|
segEnd = cloneDate(end);
|
||||||
|
isEnd = false;
|
||||||
|
}else{
|
||||||
|
segEnd = eventEnd;
|
||||||
|
isEnd = true;
|
||||||
|
}
|
||||||
|
segs.push({
|
||||||
|
event: event,
|
||||||
|
start: segStart,
|
||||||
|
end: segEnd,
|
||||||
|
isStart: isStart,
|
||||||
|
isEnd: isEnd,
|
||||||
|
msLength: segEnd - segStart
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return segs.sort(segCmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function segCmp(a, b) {
|
||||||
|
return (b.msLength - a.msLength) * 100 + (a.event.start - b.event.start);
|
||||||
|
}
|
166
src/css/agenda.css
Executable file
|
@ -0,0 +1,166 @@
|
||||||
|
|
||||||
|
|
||||||
|
/* header styles */
|
||||||
|
|
||||||
|
.fc .fc-agenda-head th.fc-first {
|
||||||
|
border-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fc .fc-agenda-head th,
|
||||||
|
.fc .fc-agenda-head td {
|
||||||
|
border-width: 1px 0 0 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fc-agenda-head tr.fc-first th {
|
||||||
|
border-width: 0 0 0 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fc-agenda-head tr.fc-last th,
|
||||||
|
.fc-agenda-head tr.fc-last td {
|
||||||
|
border-bottom-width: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.fc-agenda-head tr.fc-last th {
|
||||||
|
/*border-width: 1px 0 1px 1px;*/
|
||||||
|
background-image: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fc-agenda-head tr.fc-last th.fc-first {
|
||||||
|
/*border-width: 0 2px 1px 0;*/
|
||||||
|
}
|
||||||
|
|
||||||
|
.fc-agenda-head tr.fc-last th.fc-last {
|
||||||
|
/*border-width: 0 0 0 3px;*/
|
||||||
|
}
|
||||||
|
|
||||||
|
.fc .fc-agenda-head td {
|
||||||
|
/*border-width: 3px 0 3px 1px;*/
|
||||||
|
background: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.fc-agenda-body {
|
||||||
|
/*width: 100%;*/
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.fc .fc-agenda-body th {
|
||||||
|
border-width: 1px 0 0 0;
|
||||||
|
background-image: none;
|
||||||
|
text-align: right;
|
||||||
|
font-weight: normal;
|
||||||
|
vertical-align: middle;
|
||||||
|
width: 48px;
|
||||||
|
height: 22px;
|
||||||
|
padding-right: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fc .fc-agenda-body td {
|
||||||
|
border-width: 1px 0 0 1px;
|
||||||
|
background: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fc .fc-agenda-body tr.fc-minor th,
|
||||||
|
.fc .fc-agenda-body tr.fc-minor td {
|
||||||
|
border-top-style: dotted;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fc .fc-agenda-body tr.fc-first th,
|
||||||
|
.fc .fc-agenda-body tr.fc-first td {
|
||||||
|
border-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.fc .fc-agenda-bg td {
|
||||||
|
border-style: double;
|
||||||
|
border-width: 0 0 0 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fc .fc-agenda-bg td.fc-not-today {
|
||||||
|
background: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.fc-agenda .fc-day-content {
|
||||||
|
padding: 2px 1px 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* vertical events */
|
||||||
|
|
||||||
|
.fc-event-vert {
|
||||||
|
border-width: 0 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fc-event-vert a {
|
||||||
|
border-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fc-content .fc-corner-top {
|
||||||
|
margin-top: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fc-content .fc-corner-top a {
|
||||||
|
margin-top: -1px;
|
||||||
|
border-top-width: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fc-content .fc-corner-bottom {
|
||||||
|
margin-bottom: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fc-content .fc-corner-bottom a {
|
||||||
|
margin-bottom: -1px;
|
||||||
|
border-bottom-width: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fc-event-vert span {
|
||||||
|
display: block;
|
||||||
|
position: relative;
|
||||||
|
z-index: 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fc-event-vert span.fc-event-time {
|
||||||
|
white-space: nowrap;
|
||||||
|
_white-space: normal;
|
||||||
|
overflow: hidden;
|
||||||
|
font-size: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fc-event-vert span.fc-event-title {
|
||||||
|
line-height: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fc-event-vert span.fc-event-bg {
|
||||||
|
position: absolute;
|
||||||
|
z-index: 1;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background: #fff;
|
||||||
|
opacity: .3;
|
||||||
|
filter: alpha(opacity=30);
|
||||||
|
}
|
||||||
|
|
||||||
|
.fc-event-vert .ui-resizable-s {
|
||||||
|
font-family: monospace;
|
||||||
|
height: 8px;
|
||||||
|
font-size: 11px;
|
||||||
|
line-height: 8px;
|
||||||
|
bottom: 0;
|
||||||
|
text-align: center;
|
||||||
|
}
|
56
src/css/grid.css
Executable file
|
@ -0,0 +1,56 @@
|
||||||
|
|
||||||
|
/* Month View, Basic Week View, Basic Day View
|
||||||
|
------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
.fc-grid table {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fc-grid th {
|
||||||
|
border-width: 0 0 0 1px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fc-grid td {
|
||||||
|
border-width: 1px 0 0 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fc-grid th.fc-left,
|
||||||
|
.fc-grid td.fc-left {
|
||||||
|
border-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fc-grid .fc-day-number {
|
||||||
|
float: right;
|
||||||
|
padding: 0 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fc-grid .fc-other-month .fc-day-number {
|
||||||
|
opacity: 0.3;
|
||||||
|
filter: alpha(opacity=30);
|
||||||
|
}
|
||||||
|
|
||||||
|
.fc-grid .fc-day-content {
|
||||||
|
clear: both;
|
||||||
|
padding: 2px 2px 0; /* distance between events and day edges */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* event styles */
|
||||||
|
|
||||||
|
.fc-grid .fc-event-time {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* right-to-left */
|
||||||
|
|
||||||
|
.fc-rtl .fc-grid {
|
||||||
|
direction: rtl;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fc-rtl .fc-grid .fc-day-number {
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fc-rtl .fc-grid .fc-event-time {
|
||||||
|
float: right;
|
||||||
|
}
|
279
src/css/main.css
Executable file
|
@ -0,0 +1,279 @@
|
||||||
|
|
||||||
|
.fc,
|
||||||
|
.fc .fc-header,
|
||||||
|
.fc .fc-content {
|
||||||
|
font-size: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fc table {
|
||||||
|
border-collapse: collapse;
|
||||||
|
border-spacing: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fc td, .fc th {
|
||||||
|
padding: 0;
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Header
|
||||||
|
------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
table.fc-header {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fc-header-left {
|
||||||
|
width: 25%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fc-header-left table {
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fc-header-center {
|
||||||
|
width: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fc-header-center table {
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fc-header-right {
|
||||||
|
width: 25%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fc-header-right table {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fc-header-title {
|
||||||
|
margin-top: 0;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fc-header-space {
|
||||||
|
padding-left: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* right-to-left */
|
||||||
|
|
||||||
|
.fc-rtl .fc-header-title {
|
||||||
|
direction: rtl;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* button rounded corners */
|
||||||
|
|
||||||
|
.fc-header .fc-state-default {
|
||||||
|
border-width: 1px 0;
|
||||||
|
padding: 0 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fc-header .fc-state-default a {
|
||||||
|
display: block;
|
||||||
|
position: relative;
|
||||||
|
margin: 0 -1px;
|
||||||
|
border-width: 0 1px;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fc-header .fc-state-default span {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fc-header .fc-corner-left {
|
||||||
|
margin-left: 1px;
|
||||||
|
padding-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fc-header .fc-corner-right {
|
||||||
|
margin-right: 1px;
|
||||||
|
padding-right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fc-header .fc-no-left {
|
||||||
|
padding-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fc-header .ui-no-left {
|
||||||
|
border-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* default button state */
|
||||||
|
|
||||||
|
.fc-header .fc-state-default,
|
||||||
|
.fc-header .ui-state-default {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fc-header .fc-state-default,
|
||||||
|
.fc-header .fc-state-default a {
|
||||||
|
border-style: solid;
|
||||||
|
border-color: #6E6E6E;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fc-header .fc-state-default span {
|
||||||
|
border-width: 1px 0 0 1px;
|
||||||
|
border-style: solid;
|
||||||
|
border-color: #fff;
|
||||||
|
background: #F0F0F0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fc-header .fc-state-default span,
|
||||||
|
.fc-header .ui-state-default {
|
||||||
|
padding: 4px 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* active button state */
|
||||||
|
|
||||||
|
.fc-header .fc-state-active a {
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fc-header .fc-state-active span {
|
||||||
|
background: #787878;
|
||||||
|
border-color: #777;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* down button state */
|
||||||
|
|
||||||
|
.fc-header .fc-state-down span {
|
||||||
|
background: #787878;
|
||||||
|
border-color: #777;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* disabled button state */
|
||||||
|
|
||||||
|
.fc-header .fc-state-disabled,
|
||||||
|
.fc-header .fc-state-disabled a {
|
||||||
|
border-color: #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fc-header .fc-state-disabled a {
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fc-header .fc-state-disabled span {
|
||||||
|
border-color: #fff;
|
||||||
|
background: #F0F0F0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Content Area & Global Cell Styles
|
||||||
|
------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
.fc-widget-content {
|
||||||
|
border: 1px solid #ccc; /* outer border color */
|
||||||
|
}
|
||||||
|
|
||||||
|
.fc-content {
|
||||||
|
clear: both;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fc-content .fc-state-default {
|
||||||
|
border-style: solid;
|
||||||
|
border-color: #ccc; /* inner border color */
|
||||||
|
}
|
||||||
|
|
||||||
|
.fc-content .fc-state-highlight { /* today */
|
||||||
|
background: #FFFFCC;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fc-content td.fc-not-today {
|
||||||
|
background: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fc-cell-overlay { /* semi-transparent rectangle while dragging */
|
||||||
|
background: #ADDBFF;
|
||||||
|
opacity: .2;
|
||||||
|
filter: alpha(opacity=20); /* for IE */
|
||||||
|
}
|
||||||
|
|
||||||
|
.fc-view { /* prevents dragging outside of widget */
|
||||||
|
width: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Global Event Styles
|
||||||
|
------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
.fc-event,
|
||||||
|
.fc-event a,
|
||||||
|
.fc-agenda .fc-event-time {
|
||||||
|
color: #fff;
|
||||||
|
border-style: solid;
|
||||||
|
border-color: blue;
|
||||||
|
background-color: blue;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fc-event-nobg,
|
||||||
|
.fc-event-nobg a,
|
||||||
|
.fc-agenda .fc-event-nobg .fc-event-time {
|
||||||
|
border-style: none;
|
||||||
|
background: none;
|
||||||
|
color: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fc-event a {
|
||||||
|
overflow: hidden;
|
||||||
|
font-size: 11px;
|
||||||
|
text-decoration: none;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fc-event-time,
|
||||||
|
.fc-event-title {
|
||||||
|
padding: 0 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fc-event a { /* prep for rounded corners */
|
||||||
|
display: block;
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Horizontal Events
|
||||||
|
------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
.fc-event-hori {
|
||||||
|
border-width: 1px 0;
|
||||||
|
margin-bottom: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fc-event-hori a {
|
||||||
|
border-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fc-content .fc-corner-left {
|
||||||
|
margin-left: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fc-content .fc-corner-left a {
|
||||||
|
margin-left: -1px;
|
||||||
|
border-left-width: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fc-content .fc-corner-right {
|
||||||
|
margin-right: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fc-content .fc-corner-right a {
|
||||||
|
margin-right: -1px;
|
||||||
|
border-right-width: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fc-event-hori .ui-resizable-handle {
|
||||||
|
_height: 10px; /* IE6 had 0 height */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
44
fullcalendar/gcal.js → src/gcal.js
Normal file → Executable file
|
@ -1,32 +1,17 @@
|
||||||
/*!
|
|
||||||
* FullCalendar Google Calendar Extension
|
|
||||||
*
|
|
||||||
* Visit http://arshaw.com/fullcalendar/docs/#google-calendar
|
|
||||||
* for docs and examples.
|
|
||||||
*
|
|
||||||
* Copyright (c) 2009 Adam Shaw
|
|
||||||
* Dual licensed under the MIT and GPL licenses:
|
|
||||||
* http://www.opensource.org/licenses/mit-license.php
|
|
||||||
* http://www.gnu.org/licenses/gpl.html
|
|
||||||
*
|
|
||||||
* Date:
|
|
||||||
* Revision:
|
|
||||||
*/
|
|
||||||
|
|
||||||
(function($) {
|
(function($) {
|
||||||
|
|
||||||
$.fullCalendar.gcalFeed = function(feedUrl, options) {
|
$.fullCalendar.gcalFeed = function(feedUrl, options) {
|
||||||
|
|
||||||
feedUrl = feedUrl.replace(/\/basic$/, '/full');
|
feedUrl = feedUrl.replace(/\/basic$/, '/full');
|
||||||
options = options || {};
|
options = options || {};
|
||||||
var draggable = options.draggable || false;
|
|
||||||
|
|
||||||
return function(start, end, callback) {
|
return function(start, end, callback) {
|
||||||
$.getJSON(feedUrl + "?alt=json-in-script&callback=?",
|
$.getJSON(feedUrl + "?alt=json-in-script&callback=?",
|
||||||
{
|
{
|
||||||
'start-min': $.fullCalendar.formatDate(start, 'c'),
|
'start-min': $.fullCalendar.formatDate(start, 'u'),
|
||||||
'start-max': $.fullCalendar.formatDate(end, 'c'),
|
'start-max': $.fullCalendar.formatDate(end, 'u'),
|
||||||
'singleevents': true
|
'singleevents': true,
|
||||||
|
'max-results': 1000
|
||||||
},
|
},
|
||||||
function(data) {
|
function(data) {
|
||||||
var events = [];
|
var events = [];
|
||||||
|
@ -34,12 +19,19 @@
|
||||||
$.each(data.feed.entry, function(i, entry) {
|
$.each(data.feed.entry, function(i, entry) {
|
||||||
var url;
|
var url;
|
||||||
$.each(entry['link'], function(j, link) {
|
$.each(entry['link'], function(j, link) {
|
||||||
if (link.type == 'text/html') url = link.href;
|
if (link.type == 'text/html') {
|
||||||
|
url = link.href;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
var showTime = entry['gd$when'][0]['startTime'].indexOf('T') != -1;
|
var startStr = entry['gd$when'][0]['startTime'];
|
||||||
|
var start = $.fullCalendar.parseDate(startStr);
|
||||||
|
var end = $.fullCalendar.parseDate(entry['gd$when'][0]['endTime']);
|
||||||
|
var hasTime = startStr.indexOf('T') != -1;
|
||||||
var classNames = [];
|
var classNames = [];
|
||||||
if (showTime) {
|
if (hasTime) {
|
||||||
classNames.push('nobg');
|
classNames.push('fc-event-nobg');
|
||||||
|
}else{
|
||||||
|
end = new Date(end - 1);
|
||||||
}
|
}
|
||||||
if (options.className) {
|
if (options.className) {
|
||||||
if (typeof options.className == 'string') {
|
if (typeof options.className == 'string') {
|
||||||
|
@ -53,12 +45,12 @@
|
||||||
url: url,
|
url: url,
|
||||||
title: entry['title']['$t'],
|
title: entry['title']['$t'],
|
||||||
start: $.fullCalendar.parseDate(entry['gd$when'][0]['startTime']),
|
start: $.fullCalendar.parseDate(entry['gd$when'][0]['startTime']),
|
||||||
end: $.fullCalendar.parseDate(entry['gd$when'][0]['endTime']),
|
end: end,
|
||||||
location: entry['gd$where'][0]['valueString'],
|
location: entry['gd$where'][0]['valueString'],
|
||||||
description: entry['content']['$t'],
|
description: entry['content']['$t'],
|
||||||
showTime: showTime,
|
hasTime: hasTime,
|
||||||
className: classNames,
|
className: classNames,
|
||||||
draggable: draggable
|
editable: options.editable || false
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
callback(events);
|
callback(events);
|
556
src/grid.js
Executable file
|
@ -0,0 +1,556 @@
|
||||||
|
|
||||||
|
setDefaults({
|
||||||
|
weekMode: 'fixed'
|
||||||
|
});
|
||||||
|
|
||||||
|
views.month = function(element, options) {
|
||||||
|
return new Grid(element, options, {
|
||||||
|
render: function(date, delta, fetchEvents) {
|
||||||
|
if (delta) {
|
||||||
|
addMonths(date, delta);
|
||||||
|
}
|
||||||
|
var start = this.start = cloneDate(date, true);
|
||||||
|
start.setDate(1);
|
||||||
|
this.title = formatDates(
|
||||||
|
start,
|
||||||
|
addDays(cloneDate(this.end = addMonths(cloneDate(start), 1)), -1),
|
||||||
|
strProp(options.titleFormat, 'month'),
|
||||||
|
options
|
||||||
|
);
|
||||||
|
addDays(this.visStart = cloneDate(start), -((start.getDay() - options.weekStart + 7) % 7));
|
||||||
|
addDays(this.visEnd = cloneDate(this.end), (7 - this.visEnd.getDay() + options.weekStart) % 7);
|
||||||
|
var rowCnt = Math.round((this.visEnd - this.visStart) / (DAY_MS * 7));
|
||||||
|
if (options.weekMode == 'fixed') {
|
||||||
|
addDays(this.visEnd, (6 - rowCnt) * 7);
|
||||||
|
rowCnt = 6;
|
||||||
|
}
|
||||||
|
this.renderGrid(rowCnt, 7, strProp(options.columnFormat, 'month'), true, fetchEvents);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
views.basicWeek = function(element, options) {
|
||||||
|
return new Grid(element, options, {
|
||||||
|
render: function(date, delta, fetchEvents) {
|
||||||
|
if (delta) {
|
||||||
|
addDays(date, delta * 7);
|
||||||
|
}
|
||||||
|
this.title = formatDates(
|
||||||
|
this.start = this.visStart = addDays(cloneDate(date), -((date.getDay() - options.weekStart + 7) % 7)),
|
||||||
|
addDays(cloneDate(this.end = this.visEnd = addDays(cloneDate(this.start), 7)), -1),
|
||||||
|
strProp(options.titleFormat, 'week'),
|
||||||
|
options
|
||||||
|
);
|
||||||
|
this.renderGrid(1, 7, strProp(options.columnFormat, 'week'), false, fetchEvents);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
views.basicDay = function(element, options) {
|
||||||
|
return new Grid(element, options, {
|
||||||
|
render: function(date, delta, fetchEvents) {
|
||||||
|
if (delta) {
|
||||||
|
addDays(date, delta);
|
||||||
|
}
|
||||||
|
this.title = formatDate(date, strProp(options.titleFormat, 'day'), options);
|
||||||
|
this.start = this.visStart = cloneDate(date, true);
|
||||||
|
this.end = this.visEnd = addDays(cloneDate(this.start), 1);
|
||||||
|
this.renderGrid(1, 1, strProp(options.columnFormat, 'day'), false, fetchEvents);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// flags for [Opera] rendering bugs
|
||||||
|
var tdTopBug, trTopBug, tbodyTopBug, sniffBugs = true;
|
||||||
|
|
||||||
|
var tdHeightBug;
|
||||||
|
|
||||||
|
var sniffedEventLeftBug, eventLeftDiff=0;
|
||||||
|
|
||||||
|
|
||||||
|
function Grid(element, options, methods) {
|
||||||
|
|
||||||
|
var tm, weekStart,
|
||||||
|
rtl, dis, dit, // day index sign / translate
|
||||||
|
rowCnt, colCnt,
|
||||||
|
colWidth,
|
||||||
|
thead, tbody,
|
||||||
|
cachedSegs, //...
|
||||||
|
|
||||||
|
// initialize superclass
|
||||||
|
view = $.extend(this, viewMethods, methods, {
|
||||||
|
renderGrid: renderGrid,
|
||||||
|
rerenderEvents: rerenderEvents,
|
||||||
|
updateSize: updateSize,
|
||||||
|
eventEnd: function(event) {
|
||||||
|
return event.end || cloneDate(event.start);
|
||||||
|
},
|
||||||
|
visEventEnd: function(event) {
|
||||||
|
if (event.end) {
|
||||||
|
var end = cloneDate(event.end);
|
||||||
|
return (!event.hasTime || end.getHours() || end.getMinutes()) ? addDays(end, 1) : end;
|
||||||
|
}else{
|
||||||
|
return addDays(cloneDate(event.start), 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
view.init(element, options);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/********************************* grid rendering *************************************/
|
||||||
|
|
||||||
|
|
||||||
|
element.addClass('fc-grid').css('position', 'relative');
|
||||||
|
if (element.disableSelection) {
|
||||||
|
element.disableSelection();
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderGrid(r, c, colFormat, showNumbers, fetchEvents) {
|
||||||
|
//console.log('renderGrid!');
|
||||||
|
rowCnt = r;
|
||||||
|
colCnt = c;
|
||||||
|
|
||||||
|
var month = view.start.getMonth(),
|
||||||
|
today = clearTime(new Date()),
|
||||||
|
s, s2, s3, i, j, d = cloneDate(view.visStart);
|
||||||
|
|
||||||
|
// update option-derived variables
|
||||||
|
tm = options.theme ? 'ui' : 'fc';
|
||||||
|
weekStart = options.weekStart;
|
||||||
|
if (rtl = options.isRTL) {
|
||||||
|
dis = -1;
|
||||||
|
dit = colCnt - 1;
|
||||||
|
}else{
|
||||||
|
dis = 1;
|
||||||
|
dit = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!tbody) { // first time, build all cells from scratch
|
||||||
|
|
||||||
|
var table = $("<table/>").appendTo(element);
|
||||||
|
|
||||||
|
s = '';
|
||||||
|
for (i=0; i<colCnt; i++) {
|
||||||
|
s2 = "<th class='fc-" +
|
||||||
|
dayIDs[d.getDay()] + ' ' + // needs to be first
|
||||||
|
tm + '-state-default ' +
|
||||||
|
(i==dit ? ' fc-left' : '') +
|
||||||
|
"'>" + formatDate(d, colFormat, options) + "</th>"; // TODO: optionize
|
||||||
|
//if (rtl) {
|
||||||
|
// s = s2 + s;
|
||||||
|
//}else{
|
||||||
|
s += s2;
|
||||||
|
//}
|
||||||
|
addDays(d, 1);
|
||||||
|
}
|
||||||
|
thead = $("<thead><tr>" + s + "</tr></thead>").appendTo(table);
|
||||||
|
|
||||||
|
s = "<tbody>";
|
||||||
|
d = cloneDate(view.visStart);
|
||||||
|
for (i=0; i<rowCnt; i++) {
|
||||||
|
s2 = '';
|
||||||
|
for (j=0; j<colCnt; j++) {
|
||||||
|
s3 = "<td class='fc-" +
|
||||||
|
dayIDs[d.getDay()] + ' ' + // needs to be first
|
||||||
|
tm + '-state-default fc-day' + (i*colCnt+j) +
|
||||||
|
(j==dit ? ' fc-left' : '') +
|
||||||
|
(rowCnt>1 && d.getMonth() != month ? ' fc-other-month' : '') +
|
||||||
|
(+d == +today ?
|
||||||
|
' fc-today '+tm+'-state-highlight' :
|
||||||
|
' fc-not-today') + "'>" +
|
||||||
|
(showNumbers ? "<div class='fc-day-number'>" + d.getDate() + "</div>" : '') +
|
||||||
|
"<div class='fc-day-content'><div> </div></div></td>";
|
||||||
|
//if (rtl) {
|
||||||
|
// s2 = s3 + s2;
|
||||||
|
//}else{
|
||||||
|
s2 += s3;
|
||||||
|
//}
|
||||||
|
addDays(d, 1);
|
||||||
|
}
|
||||||
|
s += "<tr class='fc-week" + i + "'>" + s2 + "</tr>";
|
||||||
|
}
|
||||||
|
tbody = $(s + "</tbody>").appendTo(table);
|
||||||
|
tbody.find('td').click(dayClick);
|
||||||
|
|
||||||
|
}else{ // NOT first time, reuse as many cells as possible
|
||||||
|
|
||||||
|
view.clearEvents();
|
||||||
|
|
||||||
|
var prevRowCnt = tbody.find('tr').length;
|
||||||
|
if (rowCnt < prevRowCnt) {
|
||||||
|
tbody.find('tr:gt(' + (rowCnt-1) + ')').remove(); // remove extra rows
|
||||||
|
}
|
||||||
|
else if (rowCnt > prevRowCnt) {
|
||||||
|
s = '';
|
||||||
|
for (i=prevRowCnt; i<rowCnt; i++) {
|
||||||
|
s2 = '';
|
||||||
|
for (j=0; j<colCnt; j++) {
|
||||||
|
s3 = "<td class='fc-" +
|
||||||
|
dayIDs[(j * dis + dit + weekStart) % 7] + ' ' + // needs to be first
|
||||||
|
tm + '-state-default fc-new fc-day' + (i*colCnt + j) +
|
||||||
|
(j==dit ? ' fc-left' : '') + "'>" +
|
||||||
|
(showNumbers ? "<div class='fc-day-number'></div>" : '') +
|
||||||
|
"<div class='fc-day-content'><div> </div></div>" +
|
||||||
|
"</td>";
|
||||||
|
//if (rtl) {
|
||||||
|
// s2 = s3 + s2;
|
||||||
|
//}else{
|
||||||
|
s2 += s3;
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
s += "<tr class='fc-week" + i + "'>" + s2 + "</tr>";
|
||||||
|
}
|
||||||
|
tbody.append(s);
|
||||||
|
}
|
||||||
|
tbody.find('td.fc-new').removeClass('fc-new').click(dayClick);
|
||||||
|
|
||||||
|
// re-label and re-class existing cells
|
||||||
|
tbody.find('tr').each(function() {
|
||||||
|
for (i=0; i<colCnt; i++) {
|
||||||
|
var td = $(this.childNodes[i]); // * dis + dit TODO: clean
|
||||||
|
if (rowCnt > 1) {
|
||||||
|
if (d.getMonth() == month) {
|
||||||
|
td.removeClass('fc-other-month');
|
||||||
|
}else{
|
||||||
|
td.addClass('fc-other-month');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (+d == +today) {
|
||||||
|
td.removeClass('fc-not-today')
|
||||||
|
.addClass('fc-today')
|
||||||
|
.addClass(tm + '-state-highlight');
|
||||||
|
}else{
|
||||||
|
td.addClass('fc-not-today')
|
||||||
|
.removeClass('fc-today')
|
||||||
|
.removeClass(tm + '-state-highlight');
|
||||||
|
}
|
||||||
|
td.find('div.fc-day-number').text(d.getDate());
|
||||||
|
addDays(d, 1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (colCnt == 1) {
|
||||||
|
var startDay = this.visStart.getDay();
|
||||||
|
var td = tbody.find('td')[0];
|
||||||
|
td.className = td.className.replace(/^fc-\w+(?= )/, 'fc-' + dayIDs[startDay]);
|
||||||
|
thead.find('th').text(formatDate(this.start, colFormat, options));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
updateSize();
|
||||||
|
fetchEvents(renderEvents);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
function updateSize() {
|
||||||
|
var width = element.width();
|
||||||
|
var height = Math.round(width / options.aspectRatio);
|
||||||
|
setOuterWidth(
|
||||||
|
thead.find('th').slice(0, -1),
|
||||||
|
colWidth = Math.floor(width / colCnt)
|
||||||
|
);
|
||||||
|
var leftTDs = tbody.find('tr td:first-child');
|
||||||
|
var tbodyHeight = height - thead.height();
|
||||||
|
var rowHeight1, rowHeight2;
|
||||||
|
if (options.weekMode == 'variable') {
|
||||||
|
rowHeight1 = rowHeight2 = Math.floor(tbodyHeight / (rowCnt==1 ? 2 : 6));
|
||||||
|
}else{
|
||||||
|
rowHeight1 = Math.floor(tbodyHeight / rowCnt);
|
||||||
|
rowHeight2 = tbodyHeight - rowHeight1*(rowCnt-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sniffBugs) {
|
||||||
|
// nasty bugs in opera 9.25
|
||||||
|
// position() returning relative to direct parent
|
||||||
|
var tr = tbody.find('tr:first');
|
||||||
|
var td = tr.find('td:first');
|
||||||
|
var trTop = tr.position().top;
|
||||||
|
var tdTop = td.position().top;
|
||||||
|
tdTopBug = tdTop < 0;
|
||||||
|
trTopBug = trTop != tdTop;
|
||||||
|
tbodyTopBug = tbody.position().top != trTop;
|
||||||
|
sniffBugs = false;
|
||||||
|
//
|
||||||
|
td.height(rowHeight1);
|
||||||
|
tdHeightBug = rowHeight1 != td.height();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tdHeightBug) {
|
||||||
|
leftTDs.slice(0, -1).height(rowHeight1);
|
||||||
|
leftTDs.slice(-1).height(rowHeight2);
|
||||||
|
}else{
|
||||||
|
setOuterHeight(leftTDs.slice(0, -1), rowHeight1);
|
||||||
|
setOuterHeight(leftTDs.slice(-1), rowHeight2);
|
||||||
|
}
|
||||||
|
|
||||||
|
//alert(tbodyHeight + ' === ' + tbody.height());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/******************************** event rendering *****************************/
|
||||||
|
|
||||||
|
|
||||||
|
function renderEvents(events) {
|
||||||
|
view.reportEvents(events);
|
||||||
|
renderSegs(cachedSegs = compileSegs(events)); // view.visibleEvents(
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function rerenderEvents(skipCompile) {
|
||||||
|
//console.log('rerender events');
|
||||||
|
view.clearEvents();
|
||||||
|
if (skipCompile) {
|
||||||
|
renderSegs(cachedSegs);
|
||||||
|
}else{
|
||||||
|
renderEvents(view.cachedEvents);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function compileSegs(events) {
|
||||||
|
var d1 = cloneDate(view.visStart);
|
||||||
|
var d2 = addDays(cloneDate(d1), colCnt);
|
||||||
|
var rows = [];
|
||||||
|
for (var i=0; i<rowCnt; i++) {
|
||||||
|
rows.push(stackSegs(view.sliceSegs(events, d1, d2)));
|
||||||
|
addDays(d1, 7);
|
||||||
|
addDays(d2, 7);
|
||||||
|
}
|
||||||
|
return rows;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function renderSegs(segRows) {
|
||||||
|
var i, len = segRows.length, levels,
|
||||||
|
tr, td,
|
||||||
|
innerDiv,
|
||||||
|
top,
|
||||||
|
weekHeight,
|
||||||
|
j, segs,
|
||||||
|
levelHeight,
|
||||||
|
k, seg,
|
||||||
|
event,
|
||||||
|
eventClasses,
|
||||||
|
startE, endE,
|
||||||
|
left1, left2,
|
||||||
|
eventElement, eventAnchor,
|
||||||
|
triggerRes;
|
||||||
|
for (i=0; i<len; i++) {
|
||||||
|
levels = segRows[i];
|
||||||
|
tr = tbody.find('tr:eq('+i+')');
|
||||||
|
td = tr.find('td:first');
|
||||||
|
innerDiv = td.find('div.fc-day-content div').css('position', 'relative');
|
||||||
|
top = innerDiv.position().top;
|
||||||
|
if (tdTopBug) top -= td.position().top;
|
||||||
|
if (trTopBug) top += tr.position().top;
|
||||||
|
if (tbodyTopBug) top += tbody.position().top;
|
||||||
|
weekHeight = 0;
|
||||||
|
for (j=0; j<levels.length; j++) {
|
||||||
|
segs = levels[j];
|
||||||
|
levelHeight = 0;
|
||||||
|
for (k=0; k<segs.length; k++) {
|
||||||
|
seg = segs[k];
|
||||||
|
event = seg.event;
|
||||||
|
eventClasses = event.className || [];
|
||||||
|
if (typeof eventClasses == 'string') {
|
||||||
|
eventClasses = eventClasses.split(' ');
|
||||||
|
}
|
||||||
|
eventClasses.push('fc-event', 'fc-event-hori');
|
||||||
|
startE = seg.isStart ?
|
||||||
|
tr.find('td:eq('+((seg.start.getDay()-weekStart+colCnt)%colCnt)+') div.fc-day-content div') :
|
||||||
|
tbody;
|
||||||
|
endE = seg.isEnd ?
|
||||||
|
tr.find('td:eq('+((seg.end.getDay()-weekStart+colCnt-1)%colCnt)+') div.fc-day-content div') :
|
||||||
|
tbody;
|
||||||
|
if (rtl) {
|
||||||
|
left1 = endE.position().left;
|
||||||
|
left2 = startE.position().left + startE.width();
|
||||||
|
if (seg.isStart) {
|
||||||
|
eventClasses.push('fc-corner-right');
|
||||||
|
}
|
||||||
|
if (seg.isEnd) {
|
||||||
|
eventClasses.push('fc-corner-left');
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
left1 = startE.position().left;
|
||||||
|
left2 = endE.position().left + endE.width();
|
||||||
|
if (seg.isStart) {
|
||||||
|
eventClasses.push('fc-corner-left');
|
||||||
|
}
|
||||||
|
if (seg.isEnd) {
|
||||||
|
eventClasses.push('fc-corner-right');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
eventElement = $("<div class='" + eventClasses.join(' ') + "'/>")
|
||||||
|
.append(eventAnchor = $("<a/>")
|
||||||
|
.append(event.hasTime ?
|
||||||
|
$("<span class='fc-event-time'/>")
|
||||||
|
.html(formatDate(event.start, options.eventTimeFormat, options)) :
|
||||||
|
null)
|
||||||
|
.append($("<span class='fc-event-title'/>")
|
||||||
|
.text(event.title)));
|
||||||
|
if (event.url) {
|
||||||
|
eventAnchor.attr('href', event.url);
|
||||||
|
}
|
||||||
|
triggerRes = view.trigger('eventRender', event, event, eventElement);
|
||||||
|
if (triggerRes !== false) {
|
||||||
|
if (triggerRes && typeof triggerRes != 'boolean') {
|
||||||
|
eventElement = $(triggerRes);
|
||||||
|
}
|
||||||
|
eventElement
|
||||||
|
.css({
|
||||||
|
position: 'absolute',
|
||||||
|
top: top,
|
||||||
|
left: left1 + eventLeftDiff,
|
||||||
|
zIndex: 3
|
||||||
|
})
|
||||||
|
.appendTo(element);
|
||||||
|
setOuterWidth(eventElement, left2-left1, true);
|
||||||
|
if (!sniffedEventLeftBug) {
|
||||||
|
if (rtl) {
|
||||||
|
eventLeftDiff = left1 - eventElement.position().left;
|
||||||
|
if (eventLeftDiff) {
|
||||||
|
eventElement.css('left', left1 + eventLeftDiff);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sniffedEventLeftBug = true;
|
||||||
|
}
|
||||||
|
eventElementHandlers(event, eventElement);
|
||||||
|
if (event.editable || typeof event.editable == 'undefined' && options.editable) {
|
||||||
|
draggableEvent(event, eventElement);
|
||||||
|
resizableEvent(event, eventElement);
|
||||||
|
}
|
||||||
|
view.reportEventElement(event, eventElement);
|
||||||
|
levelHeight = Math.max(levelHeight, eventElement.outerHeight(true));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
weekHeight += levelHeight;
|
||||||
|
top += levelHeight;
|
||||||
|
}
|
||||||
|
innerDiv.height(weekHeight);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function eventElementHandlers(event, eventElement) {
|
||||||
|
eventElement
|
||||||
|
.click(function(ev) {
|
||||||
|
if (!eventElement.hasClass('ui-draggable-dragging')) {
|
||||||
|
return view.trigger('eventClick', this, event, ev);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.hover(
|
||||||
|
function(ev) {
|
||||||
|
view.trigger('eventMouseover', this, event, ev);
|
||||||
|
},
|
||||||
|
function(ev) {
|
||||||
|
view.trigger('eventMouseover', this, event, ev);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/***************************** draggable *********************************/
|
||||||
|
|
||||||
|
|
||||||
|
function draggableEvent(event, eventElement) {
|
||||||
|
if (!options.disableDragging && eventElement.draggable) {
|
||||||
|
var matrix;
|
||||||
|
eventElement.draggable({
|
||||||
|
zIndex: 4,
|
||||||
|
delay: 50,
|
||||||
|
opacity: options.dragOpacity,
|
||||||
|
revertDuration: options.dragRevertDuration,
|
||||||
|
start: function(ev, ui) {
|
||||||
|
matrix = new HoverMatrix(function(cell) {
|
||||||
|
eventElement.draggable('option', 'revert', !cell || !cell.rowDelta && !cell.colDelta);
|
||||||
|
if (cell) {
|
||||||
|
view.showOverlay(cell);
|
||||||
|
}else{
|
||||||
|
view.hideOverlay();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
tbody.find('tr').each(function() {
|
||||||
|
matrix.row(this);
|
||||||
|
});
|
||||||
|
var tds = tbody.find('tr:first td');
|
||||||
|
if (rtl) {
|
||||||
|
tds = $(tds.get().reverse());
|
||||||
|
}
|
||||||
|
tds.each(function() {
|
||||||
|
matrix.col(this);
|
||||||
|
});
|
||||||
|
matrix.start();
|
||||||
|
view.hideEvents(event, eventElement);
|
||||||
|
view.trigger('eventDragStart', eventElement, event, ev, ui);
|
||||||
|
},
|
||||||
|
drag: function(ev) {
|
||||||
|
matrix.mouse(ev.pageX, ev.pageY);
|
||||||
|
},
|
||||||
|
stop: function(ev, ui) {
|
||||||
|
view.hideOverlay();
|
||||||
|
view.trigger('eventDragStop', eventElement, event, ev, ui);
|
||||||
|
var cell = matrix.cell;
|
||||||
|
if (!cell || !cell.rowDelta && !cell.colDelta) {
|
||||||
|
view.showEvents(event, eventElement);
|
||||||
|
}else{
|
||||||
|
var dayDelta = cell.rowDelta*7 + cell.colDelta*dis;
|
||||||
|
view.moveEvent(event, dayDelta);
|
||||||
|
view.trigger('eventDrop', this, event, dayDelta, 0, ev, ui);
|
||||||
|
rerenderEvents();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/******************************* resizable *****************************/
|
||||||
|
|
||||||
|
|
||||||
|
function resizableEvent(event, eventElement) {
|
||||||
|
if (!options.disableResizing && eventElement.resizable) {
|
||||||
|
eventElement.resizable({
|
||||||
|
handles: rtl ? 'w' : 'e',
|
||||||
|
grid: [colWidth, 0],
|
||||||
|
containment: element,
|
||||||
|
start: function(ev, ui) {
|
||||||
|
eventElement.css('z-index', 4);
|
||||||
|
view.hideEvents(event, eventElement);
|
||||||
|
view.trigger('eventResizeStart', this, event, ev, ui);
|
||||||
|
},
|
||||||
|
stop: function(ev, ui) {
|
||||||
|
view.trigger('eventResizeStop', this, event, ev, ui);
|
||||||
|
var dayDelta = Math.round((Math.max(colWidth, ui.size.width) - ui.originalSize.width) / colWidth);
|
||||||
|
if (dayDelta) {
|
||||||
|
view.resizeEvent(event, dayDelta);
|
||||||
|
view.trigger('eventResize', this, event, dayDelta, 0, ev, ui);
|
||||||
|
rerenderEvents();
|
||||||
|
}else{
|
||||||
|
view.showEvents(event, eventElement);
|
||||||
|
}
|
||||||
|
eventElement.css('z-index', 3);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
function dayClick() {
|
||||||
|
var dayIndex = parseInt(this.className.match(/fc\-day(\d+)/)[1]);
|
||||||
|
var date = addDays(cloneDate(view.visStart), dayIndex);
|
||||||
|
view.trigger('dayClick', this, date);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
};
|
0
jquery/jquery.js → src/jquery/jquery.js
vendored
Normal file → Executable file
4
jquery/ui.core.js → src/jquery/ui.core.js
Normal file → Executable file
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* jQuery UI 1.7
|
* jQuery UI 1.7.2
|
||||||
*
|
*
|
||||||
* Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
|
* Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
|
||||||
* Dual licensed under the MIT (MIT-LICENSE.txt)
|
* Dual licensed under the MIT (MIT-LICENSE.txt)
|
||||||
|
@ -14,7 +14,7 @@ var _remove = $.fn.remove,
|
||||||
|
|
||||||
//Helper functions and ui object
|
//Helper functions and ui object
|
||||||
$.ui = {
|
$.ui = {
|
||||||
version: "1.7",
|
version: "1.7.2",
|
||||||
|
|
||||||
// $.ui.plugin is deprecated. Use the proxy pattern instead.
|
// $.ui.plugin is deprecated. Use the proxy pattern instead.
|
||||||
plugin: {
|
plugin: {
|
4
jquery/ui.draggable.js → src/jquery/ui.draggable.js
Normal file → Executable file
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* jQuery UI Draggable 1.7
|
* jQuery UI Draggable 1.7.2
|
||||||
*
|
*
|
||||||
* Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
|
* Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
|
||||||
* Dual licensed under the MIT (MIT-LICENSE.txt)
|
* Dual licensed under the MIT (MIT-LICENSE.txt)
|
||||||
|
@ -400,7 +400,7 @@ $.widget("ui.draggable", $.extend({}, $.ui.mouse, {
|
||||||
}));
|
}));
|
||||||
|
|
||||||
$.extend($.ui.draggable, {
|
$.extend($.ui.draggable, {
|
||||||
version: "1.7",
|
version: "1.7.2",
|
||||||
eventPrefix: "drag",
|
eventPrefix: "drag",
|
||||||
defaults: {
|
defaults: {
|
||||||
addClasses: true,
|
addClasses: true,
|
800
src/jquery/ui.resizable.js
Executable file
|
@ -0,0 +1,800 @@
|
||||||
|
/*
|
||||||
|
* jQuery UI Resizable 1.7.2
|
||||||
|
*
|
||||||
|
* Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
|
||||||
|
* Dual licensed under the MIT (MIT-LICENSE.txt)
|
||||||
|
* and GPL (GPL-LICENSE.txt) licenses.
|
||||||
|
*
|
||||||
|
* http://docs.jquery.com/UI/Resizables
|
||||||
|
*
|
||||||
|
* Depends:
|
||||||
|
* ui.core.js
|
||||||
|
*/
|
||||||
|
(function($) {
|
||||||
|
|
||||||
|
$.widget("ui.resizable", $.extend({}, $.ui.mouse, {
|
||||||
|
|
||||||
|
_init: function() {
|
||||||
|
|
||||||
|
var self = this, o = this.options;
|
||||||
|
this.element.addClass("ui-resizable");
|
||||||
|
|
||||||
|
$.extend(this, {
|
||||||
|
_aspectRatio: !!(o.aspectRatio),
|
||||||
|
aspectRatio: o.aspectRatio,
|
||||||
|
originalElement: this.element,
|
||||||
|
_proportionallyResizeElements: [],
|
||||||
|
_helper: o.helper || o.ghost || o.animate ? o.helper || 'ui-resizable-helper' : null
|
||||||
|
});
|
||||||
|
|
||||||
|
//Wrap the element if it cannot hold child nodes
|
||||||
|
if(this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)) {
|
||||||
|
|
||||||
|
//Opera fix for relative positioning
|
||||||
|
if (/relative/.test(this.element.css('position')) && $.browser.opera)
|
||||||
|
this.element.css({ position: 'relative', top: 'auto', left: 'auto' });
|
||||||
|
|
||||||
|
//Create a wrapper element and set the wrapper to the new current internal element
|
||||||
|
this.element.wrap(
|
||||||
|
$('<div class="ui-wrapper" style="overflow: hidden;"></div>').css({
|
||||||
|
position: this.element.css('position'),
|
||||||
|
width: this.element.outerWidth(),
|
||||||
|
height: this.element.outerHeight(),
|
||||||
|
top: this.element.css('top'),
|
||||||
|
left: this.element.css('left')
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
//Overwrite the original this.element
|
||||||
|
this.element = this.element.parent().data(
|
||||||
|
"resizable", this.element.data('resizable')
|
||||||
|
);
|
||||||
|
|
||||||
|
this.elementIsWrapper = true;
|
||||||
|
|
||||||
|
//Move margins to the wrapper
|
||||||
|
this.element.css({ marginLeft: this.originalElement.css("marginLeft"), marginTop: this.originalElement.css("marginTop"), marginRight: this.originalElement.css("marginRight"), marginBottom: this.originalElement.css("marginBottom") });
|
||||||
|
this.originalElement.css({ marginLeft: 0, marginTop: 0, marginRight: 0, marginBottom: 0});
|
||||||
|
|
||||||
|
//Prevent Safari textarea resize
|
||||||
|
this.originalResizeStyle = this.originalElement.css('resize');
|
||||||
|
this.originalElement.css('resize', 'none');
|
||||||
|
|
||||||
|
//Push the actual element to our proportionallyResize internal array
|
||||||
|
this._proportionallyResizeElements.push(this.originalElement.css({ position: 'static', zoom: 1, display: 'block' }));
|
||||||
|
|
||||||
|
// avoid IE jump (hard set the margin)
|
||||||
|
this.originalElement.css({ margin: this.originalElement.css('margin') });
|
||||||
|
|
||||||
|
// fix handlers offset
|
||||||
|
this._proportionallyResize();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
this.handles = o.handles || (!$('.ui-resizable-handle', this.element).length ? "e,s,se" : { n: '.ui-resizable-n', e: '.ui-resizable-e', s: '.ui-resizable-s', w: '.ui-resizable-w', se: '.ui-resizable-se', sw: '.ui-resizable-sw', ne: '.ui-resizable-ne', nw: '.ui-resizable-nw' });
|
||||||
|
if(this.handles.constructor == String) {
|
||||||
|
|
||||||
|
if(this.handles == 'all') this.handles = 'n,e,s,w,se,sw,ne,nw';
|
||||||
|
var n = this.handles.split(","); this.handles = {};
|
||||||
|
|
||||||
|
for(var i = 0; i < n.length; i++) {
|
||||||
|
|
||||||
|
var handle = $.trim(n[i]), hname = 'ui-resizable-'+handle;
|
||||||
|
var axis = $('<div class="ui-resizable-handle ' + hname + '"></div>');
|
||||||
|
|
||||||
|
// increase zIndex of sw, se, ne, nw axis
|
||||||
|
//TODO : this modifies original option
|
||||||
|
if(/sw|se|ne|nw/.test(handle)) axis.css({ zIndex: ++o.zIndex });
|
||||||
|
|
||||||
|
//TODO : What's going on here?
|
||||||
|
if ('se' == handle) {
|
||||||
|
axis.addClass('ui-icon ui-icon-gripsmall-diagonal-se');
|
||||||
|
};
|
||||||
|
|
||||||
|
//Insert into internal handles object and append to element
|
||||||
|
this.handles[handle] = '.ui-resizable-'+handle;
|
||||||
|
this.element.append(axis);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
this._renderAxis = function(target) {
|
||||||
|
|
||||||
|
target = target || this.element;
|
||||||
|
|
||||||
|
for(var i in this.handles) {
|
||||||
|
|
||||||
|
if(this.handles[i].constructor == String)
|
||||||
|
this.handles[i] = $(this.handles[i], this.element).show();
|
||||||
|
|
||||||
|
//Apply pad to wrapper element, needed to fix axis position (textarea, inputs, scrolls)
|
||||||
|
if (this.elementIsWrapper && this.originalElement[0].nodeName.match(/textarea|input|select|button/i)) {
|
||||||
|
|
||||||
|
var axis = $(this.handles[i], this.element), padWrapper = 0;
|
||||||
|
|
||||||
|
//Checking the correct pad and border
|
||||||
|
padWrapper = /sw|ne|nw|se|n|s/.test(i) ? axis.outerHeight() : axis.outerWidth();
|
||||||
|
|
||||||
|
//The padding type i have to apply...
|
||||||
|
var padPos = [ 'padding',
|
||||||
|
/ne|nw|n/.test(i) ? 'Top' :
|
||||||
|
/se|sw|s/.test(i) ? 'Bottom' :
|
||||||
|
/^e$/.test(i) ? 'Right' : 'Left' ].join("");
|
||||||
|
|
||||||
|
target.css(padPos, padWrapper);
|
||||||
|
|
||||||
|
this._proportionallyResize();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO: What's that good for? There's not anything to be executed left
|
||||||
|
if(!$(this.handles[i]).length)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//TODO: make renderAxis a prototype function
|
||||||
|
this._renderAxis(this.element);
|
||||||
|
|
||||||
|
this._handles = $('.ui-resizable-handle', this.element)
|
||||||
|
.disableSelection();
|
||||||
|
|
||||||
|
//Matching axis name
|
||||||
|
this._handles.mouseover(function() {
|
||||||
|
if (!self.resizing) {
|
||||||
|
if (this.className)
|
||||||
|
var axis = this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);
|
||||||
|
//Axis, default = se
|
||||||
|
self.axis = axis && axis[1] ? axis[1] : 'se';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
//If we want to auto hide the elements
|
||||||
|
if (o.autoHide) {
|
||||||
|
this._handles.hide();
|
||||||
|
$(this.element)
|
||||||
|
.addClass("ui-resizable-autohide")
|
||||||
|
.hover(function() {
|
||||||
|
$(this).removeClass("ui-resizable-autohide");
|
||||||
|
self._handles.show();
|
||||||
|
},
|
||||||
|
function(){
|
||||||
|
if (!self.resizing) {
|
||||||
|
$(this).addClass("ui-resizable-autohide");
|
||||||
|
self._handles.hide();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
//Initialize the mouse interaction
|
||||||
|
this._mouseInit();
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
destroy: function() {
|
||||||
|
|
||||||
|
this._mouseDestroy();
|
||||||
|
|
||||||
|
var _destroy = function(exp) {
|
||||||
|
$(exp).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing")
|
||||||
|
.removeData("resizable").unbind(".resizable").find('.ui-resizable-handle').remove();
|
||||||
|
};
|
||||||
|
|
||||||
|
//TODO: Unwrap at same DOM position
|
||||||
|
if (this.elementIsWrapper) {
|
||||||
|
_destroy(this.element);
|
||||||
|
var wrapper = this.element;
|
||||||
|
wrapper.parent().append(
|
||||||
|
this.originalElement.css({
|
||||||
|
position: wrapper.css('position'),
|
||||||
|
width: wrapper.outerWidth(),
|
||||||
|
height: wrapper.outerHeight(),
|
||||||
|
top: wrapper.css('top'),
|
||||||
|
left: wrapper.css('left')
|
||||||
|
})
|
||||||
|
).end().remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.originalElement.css('resize', this.originalResizeStyle);
|
||||||
|
_destroy(this.originalElement);
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
_mouseCapture: function(event) {
|
||||||
|
|
||||||
|
var handle = false;
|
||||||
|
for(var i in this.handles) {
|
||||||
|
if($(this.handles[i])[0] == event.target) handle = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.options.disabled || !!handle;
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
_mouseStart: function(event) {
|
||||||
|
|
||||||
|
var o = this.options, iniPos = this.element.position(), el = this.element;
|
||||||
|
|
||||||
|
this.resizing = true;
|
||||||
|
this.documentScroll = { top: $(document).scrollTop(), left: $(document).scrollLeft() };
|
||||||
|
|
||||||
|
// bugfix for http://dev.jquery.com/ticket/1749
|
||||||
|
if (el.is('.ui-draggable') || (/absolute/).test(el.css('position'))) {
|
||||||
|
el.css({ position: 'absolute', top: iniPos.top, left: iniPos.left });
|
||||||
|
}
|
||||||
|
|
||||||
|
//Opera fixing relative position
|
||||||
|
if ($.browser.opera && (/relative/).test(el.css('position')))
|
||||||
|
el.css({ position: 'relative', top: 'auto', left: 'auto' });
|
||||||
|
|
||||||
|
this._renderProxy();
|
||||||
|
|
||||||
|
var curleft = num(this.helper.css('left')), curtop = num(this.helper.css('top'));
|
||||||
|
|
||||||
|
if (o.containment) {
|
||||||
|
curleft += $(o.containment).scrollLeft() || 0;
|
||||||
|
curtop += $(o.containment).scrollTop() || 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Store needed variables
|
||||||
|
this.offset = this.helper.offset();
|
||||||
|
this.position = { left: curleft, top: curtop };
|
||||||
|
this.size = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
|
||||||
|
this.originalSize = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
|
||||||
|
this.originalPosition = { left: curleft, top: curtop };
|
||||||
|
this.sizeDiff = { width: el.outerWidth() - el.width(), height: el.outerHeight() - el.height() };
|
||||||
|
this.originalMousePosition = { left: event.pageX, top: event.pageY };
|
||||||
|
|
||||||
|
//Aspect Ratio
|
||||||
|
this.aspectRatio = (typeof o.aspectRatio == 'number') ? o.aspectRatio : ((this.originalSize.width / this.originalSize.height) || 1);
|
||||||
|
|
||||||
|
var cursor = $('.ui-resizable-' + this.axis).css('cursor');
|
||||||
|
$('body').css('cursor', cursor == 'auto' ? this.axis + '-resize' : cursor);
|
||||||
|
|
||||||
|
el.addClass("ui-resizable-resizing");
|
||||||
|
this._propagate("start", event);
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
|
||||||
|
_mouseDrag: function(event) {
|
||||||
|
|
||||||
|
//Increase performance, avoid regex
|
||||||
|
var el = this.helper, o = this.options, props = {},
|
||||||
|
self = this, smp = this.originalMousePosition, a = this.axis;
|
||||||
|
|
||||||
|
var dx = (event.pageX-smp.left)||0, dy = (event.pageY-smp.top)||0;
|
||||||
|
var trigger = this._change[a];
|
||||||
|
if (!trigger) return false;
|
||||||
|
|
||||||
|
// Calculate the attrs that will be change
|
||||||
|
var data = trigger.apply(this, [event, dx, dy]), ie6 = $.browser.msie && $.browser.version < 7, csdif = this.sizeDiff;
|
||||||
|
|
||||||
|
if (this._aspectRatio || event.shiftKey)
|
||||||
|
data = this._updateRatio(data, event);
|
||||||
|
|
||||||
|
data = this._respectSize(data, event);
|
||||||
|
|
||||||
|
// plugins callbacks need to be called first
|
||||||
|
this._propagate("resize", event);
|
||||||
|
|
||||||
|
el.css({
|
||||||
|
top: this.position.top + "px", left: this.position.left + "px",
|
||||||
|
width: this.size.width + "px", height: this.size.height + "px"
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!this._helper && this._proportionallyResizeElements.length)
|
||||||
|
this._proportionallyResize();
|
||||||
|
|
||||||
|
this._updateCache(data);
|
||||||
|
|
||||||
|
// calling the user callback at the end
|
||||||
|
this._trigger('resize', event, this.ui());
|
||||||
|
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
|
||||||
|
_mouseStop: function(event) {
|
||||||
|
|
||||||
|
this.resizing = false;
|
||||||
|
var o = this.options, self = this;
|
||||||
|
|
||||||
|
if(this._helper) {
|
||||||
|
var pr = this._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName),
|
||||||
|
soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height,
|
||||||
|
soffsetw = ista ? 0 : self.sizeDiff.width;
|
||||||
|
|
||||||
|
var s = { width: (self.size.width - soffsetw), height: (self.size.height - soffseth) },
|
||||||
|
left = (parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left)) || null,
|
||||||
|
top = (parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top)) || null;
|
||||||
|
|
||||||
|
if (!o.animate)
|
||||||
|
this.element.css($.extend(s, { top: top, left: left }));
|
||||||
|
|
||||||
|
self.helper.height(self.size.height);
|
||||||
|
self.helper.width(self.size.width);
|
||||||
|
|
||||||
|
if (this._helper && !o.animate) this._proportionallyResize();
|
||||||
|
}
|
||||||
|
|
||||||
|
$('body').css('cursor', 'auto');
|
||||||
|
|
||||||
|
this.element.removeClass("ui-resizable-resizing");
|
||||||
|
|
||||||
|
this._propagate("stop", event);
|
||||||
|
|
||||||
|
if (this._helper) this.helper.remove();
|
||||||
|
return false;
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
_updateCache: function(data) {
|
||||||
|
var o = this.options;
|
||||||
|
this.offset = this.helper.offset();
|
||||||
|
if (isNumber(data.left)) this.position.left = data.left;
|
||||||
|
if (isNumber(data.top)) this.position.top = data.top;
|
||||||
|
if (isNumber(data.height)) this.size.height = data.height;
|
||||||
|
if (isNumber(data.width)) this.size.width = data.width;
|
||||||
|
},
|
||||||
|
|
||||||
|
_updateRatio: function(data, event) {
|
||||||
|
|
||||||
|
var o = this.options, cpos = this.position, csize = this.size, a = this.axis;
|
||||||
|
|
||||||
|
if (data.height) data.width = (csize.height * this.aspectRatio);
|
||||||
|
else if (data.width) data.height = (csize.width / this.aspectRatio);
|
||||||
|
|
||||||
|
if (a == 'sw') {
|
||||||
|
data.left = cpos.left + (csize.width - data.width);
|
||||||
|
data.top = null;
|
||||||
|
}
|
||||||
|
if (a == 'nw') {
|
||||||
|
data.top = cpos.top + (csize.height - data.height);
|
||||||
|
data.left = cpos.left + (csize.width - data.width);
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
},
|
||||||
|
|
||||||
|
_respectSize: function(data, event) {
|
||||||
|
|
||||||
|
var el = this.helper, o = this.options, pRatio = this._aspectRatio || event.shiftKey, a = this.axis,
|
||||||
|
ismaxw = isNumber(data.width) && o.maxWidth && (o.maxWidth < data.width), ismaxh = isNumber(data.height) && o.maxHeight && (o.maxHeight < data.height),
|
||||||
|
isminw = isNumber(data.width) && o.minWidth && (o.minWidth > data.width), isminh = isNumber(data.height) && o.minHeight && (o.minHeight > data.height);
|
||||||
|
|
||||||
|
if (isminw) data.width = o.minWidth;
|
||||||
|
if (isminh) data.height = o.minHeight;
|
||||||
|
if (ismaxw) data.width = o.maxWidth;
|
||||||
|
if (ismaxh) data.height = o.maxHeight;
|
||||||
|
|
||||||
|
var dw = this.originalPosition.left + this.originalSize.width, dh = this.position.top + this.size.height;
|
||||||
|
var cw = /sw|nw|w/.test(a), ch = /nw|ne|n/.test(a);
|
||||||
|
|
||||||
|
if (isminw && cw) data.left = dw - o.minWidth;
|
||||||
|
if (ismaxw && cw) data.left = dw - o.maxWidth;
|
||||||
|
if (isminh && ch) data.top = dh - o.minHeight;
|
||||||
|
if (ismaxh && ch) data.top = dh - o.maxHeight;
|
||||||
|
|
||||||
|
// fixing jump error on top/left - bug #2330
|
||||||
|
var isNotwh = !data.width && !data.height;
|
||||||
|
if (isNotwh && !data.left && data.top) data.top = null;
|
||||||
|
else if (isNotwh && !data.top && data.left) data.left = null;
|
||||||
|
|
||||||
|
return data;
|
||||||
|
},
|
||||||
|
|
||||||
|
_proportionallyResize: function() {
|
||||||
|
|
||||||
|
var o = this.options;
|
||||||
|
if (!this._proportionallyResizeElements.length) return;
|
||||||
|
var element = this.helper || this.element;
|
||||||
|
|
||||||
|
for (var i=0; i < this._proportionallyResizeElements.length; i++) {
|
||||||
|
|
||||||
|
var prel = this._proportionallyResizeElements[i];
|
||||||
|
|
||||||
|
if (!this.borderDif) {
|
||||||
|
var b = [prel.css('borderTopWidth'), prel.css('borderRightWidth'), prel.css('borderBottomWidth'), prel.css('borderLeftWidth')],
|
||||||
|
p = [prel.css('paddingTop'), prel.css('paddingRight'), prel.css('paddingBottom'), prel.css('paddingLeft')];
|
||||||
|
|
||||||
|
this.borderDif = $.map(b, function(v, i) {
|
||||||
|
var border = parseInt(v,10)||0, padding = parseInt(p[i],10)||0;
|
||||||
|
return border + padding;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($.browser.msie && !(!($(element).is(':hidden') || $(element).parents(':hidden').length)))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
prel.css({
|
||||||
|
height: (element.height() - this.borderDif[0] - this.borderDif[2]) || 0,
|
||||||
|
width: (element.width() - this.borderDif[1] - this.borderDif[3]) || 0
|
||||||
|
});
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
_renderProxy: function() {
|
||||||
|
|
||||||
|
var el = this.element, o = this.options;
|
||||||
|
this.elementOffset = el.offset();
|
||||||
|
|
||||||
|
if(this._helper) {
|
||||||
|
|
||||||
|
this.helper = this.helper || $('<div style="overflow:hidden;"></div>');
|
||||||
|
|
||||||
|
// fix ie6 offset TODO: This seems broken
|
||||||
|
var ie6 = $.browser.msie && $.browser.version < 7, ie6offset = (ie6 ? 1 : 0),
|
||||||
|
pxyoffset = ( ie6 ? 2 : -1 );
|
||||||
|
|
||||||
|
this.helper.addClass(this._helper).css({
|
||||||
|
width: this.element.outerWidth() + pxyoffset,
|
||||||
|
height: this.element.outerHeight() + pxyoffset,
|
||||||
|
position: 'absolute',
|
||||||
|
left: this.elementOffset.left - ie6offset +'px',
|
||||||
|
top: this.elementOffset.top - ie6offset +'px',
|
||||||
|
zIndex: ++o.zIndex //TODO: Don't modify option
|
||||||
|
});
|
||||||
|
|
||||||
|
this.helper
|
||||||
|
.appendTo("body")
|
||||||
|
.disableSelection();
|
||||||
|
|
||||||
|
} else {
|
||||||
|
this.helper = this.element;
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
_change: {
|
||||||
|
e: function(event, dx, dy) {
|
||||||
|
return { width: this.originalSize.width + dx };
|
||||||
|
},
|
||||||
|
w: function(event, dx, dy) {
|
||||||
|
var o = this.options, cs = this.originalSize, sp = this.originalPosition;
|
||||||
|
return { left: sp.left + dx, width: cs.width - dx };
|
||||||
|
},
|
||||||
|
n: function(event, dx, dy) {
|
||||||
|
var o = this.options, cs = this.originalSize, sp = this.originalPosition;
|
||||||
|
return { top: sp.top + dy, height: cs.height - dy };
|
||||||
|
},
|
||||||
|
s: function(event, dx, dy) {
|
||||||
|
return { height: this.originalSize.height + dy };
|
||||||
|
},
|
||||||
|
se: function(event, dx, dy) {
|
||||||
|
return $.extend(this._change.s.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
|
||||||
|
},
|
||||||
|
sw: function(event, dx, dy) {
|
||||||
|
return $.extend(this._change.s.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
|
||||||
|
},
|
||||||
|
ne: function(event, dx, dy) {
|
||||||
|
return $.extend(this._change.n.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
|
||||||
|
},
|
||||||
|
nw: function(event, dx, dy) {
|
||||||
|
return $.extend(this._change.n.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_propagate: function(n, event) {
|
||||||
|
$.ui.plugin.call(this, n, [event, this.ui()]);
|
||||||
|
(n != "resize" && this._trigger(n, event, this.ui()));
|
||||||
|
},
|
||||||
|
|
||||||
|
plugins: {},
|
||||||
|
|
||||||
|
ui: function() {
|
||||||
|
return {
|
||||||
|
originalElement: this.originalElement,
|
||||||
|
element: this.element,
|
||||||
|
helper: this.helper,
|
||||||
|
position: this.position,
|
||||||
|
size: this.size,
|
||||||
|
originalSize: this.originalSize,
|
||||||
|
originalPosition: this.originalPosition
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
}));
|
||||||
|
|
||||||
|
$.extend($.ui.resizable, {
|
||||||
|
version: "1.7.2",
|
||||||
|
eventPrefix: "resize",
|
||||||
|
defaults: {
|
||||||
|
alsoResize: false,
|
||||||
|
animate: false,
|
||||||
|
animateDuration: "slow",
|
||||||
|
animateEasing: "swing",
|
||||||
|
aspectRatio: false,
|
||||||
|
autoHide: false,
|
||||||
|
cancel: ":input,option",
|
||||||
|
containment: false,
|
||||||
|
delay: 0,
|
||||||
|
distance: 1,
|
||||||
|
ghost: false,
|
||||||
|
grid: false,
|
||||||
|
handles: "e,s,se",
|
||||||
|
helper: false,
|
||||||
|
maxHeight: null,
|
||||||
|
maxWidth: null,
|
||||||
|
minHeight: 10,
|
||||||
|
minWidth: 10,
|
||||||
|
zIndex: 1000
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Resizable Extensions
|
||||||
|
*/
|
||||||
|
|
||||||
|
$.ui.plugin.add("resizable", "alsoResize", {
|
||||||
|
|
||||||
|
start: function(event, ui) {
|
||||||
|
|
||||||
|
var self = $(this).data("resizable"), o = self.options;
|
||||||
|
|
||||||
|
_store = function(exp) {
|
||||||
|
$(exp).each(function() {
|
||||||
|
$(this).data("resizable-alsoresize", {
|
||||||
|
width: parseInt($(this).width(), 10), height: parseInt($(this).height(), 10),
|
||||||
|
left: parseInt($(this).css('left'), 10), top: parseInt($(this).css('top'), 10)
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
if (typeof(o.alsoResize) == 'object' && !o.alsoResize.parentNode) {
|
||||||
|
if (o.alsoResize.length) { o.alsoResize = o.alsoResize[0]; _store(o.alsoResize); }
|
||||||
|
else { $.each(o.alsoResize, function(exp, c) { _store(exp); }); }
|
||||||
|
}else{
|
||||||
|
_store(o.alsoResize);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
resize: function(event, ui){
|
||||||
|
var self = $(this).data("resizable"), o = self.options, os = self.originalSize, op = self.originalPosition;
|
||||||
|
|
||||||
|
var delta = {
|
||||||
|
height: (self.size.height - os.height) || 0, width: (self.size.width - os.width) || 0,
|
||||||
|
top: (self.position.top - op.top) || 0, left: (self.position.left - op.left) || 0
|
||||||
|
},
|
||||||
|
|
||||||
|
_alsoResize = function(exp, c) {
|
||||||
|
$(exp).each(function() {
|
||||||
|
var el = $(this), start = $(this).data("resizable-alsoresize"), style = {}, css = c && c.length ? c : ['width', 'height', 'top', 'left'];
|
||||||
|
|
||||||
|
$.each(css || ['width', 'height', 'top', 'left'], function(i, prop) {
|
||||||
|
var sum = (start[prop]||0) + (delta[prop]||0);
|
||||||
|
if (sum && sum >= 0)
|
||||||
|
style[prop] = sum || null;
|
||||||
|
});
|
||||||
|
|
||||||
|
//Opera fixing relative position
|
||||||
|
if (/relative/.test(el.css('position')) && $.browser.opera) {
|
||||||
|
self._revertToRelativePosition = true;
|
||||||
|
el.css({ position: 'absolute', top: 'auto', left: 'auto' });
|
||||||
|
}
|
||||||
|
|
||||||
|
el.css(style);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
if (typeof(o.alsoResize) == 'object' && !o.alsoResize.nodeType) {
|
||||||
|
$.each(o.alsoResize, function(exp, c) { _alsoResize(exp, c); });
|
||||||
|
}else{
|
||||||
|
_alsoResize(o.alsoResize);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
stop: function(event, ui){
|
||||||
|
var self = $(this).data("resizable");
|
||||||
|
|
||||||
|
//Opera fixing relative position
|
||||||
|
if (self._revertToRelativePosition && $.browser.opera) {
|
||||||
|
self._revertToRelativePosition = false;
|
||||||
|
el.css({ position: 'relative' });
|
||||||
|
}
|
||||||
|
|
||||||
|
$(this).removeData("resizable-alsoresize-start");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$.ui.plugin.add("resizable", "animate", {
|
||||||
|
|
||||||
|
stop: function(event, ui) {
|
||||||
|
var self = $(this).data("resizable"), o = self.options;
|
||||||
|
|
||||||
|
var pr = self._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName),
|
||||||
|
soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height,
|
||||||
|
soffsetw = ista ? 0 : self.sizeDiff.width;
|
||||||
|
|
||||||
|
var style = { width: (self.size.width - soffsetw), height: (self.size.height - soffseth) },
|
||||||
|
left = (parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left)) || null,
|
||||||
|
top = (parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top)) || null;
|
||||||
|
|
||||||
|
self.element.animate(
|
||||||
|
$.extend(style, top && left ? { top: top, left: left } : {}), {
|
||||||
|
duration: o.animateDuration,
|
||||||
|
easing: o.animateEasing,
|
||||||
|
step: function() {
|
||||||
|
|
||||||
|
var data = {
|
||||||
|
width: parseInt(self.element.css('width'), 10),
|
||||||
|
height: parseInt(self.element.css('height'), 10),
|
||||||
|
top: parseInt(self.element.css('top'), 10),
|
||||||
|
left: parseInt(self.element.css('left'), 10)
|
||||||
|
};
|
||||||
|
|
||||||
|
if (pr && pr.length) $(pr[0]).css({ width: data.width, height: data.height });
|
||||||
|
|
||||||
|
// propagating resize, and updating values for each animation step
|
||||||
|
self._updateCache(data);
|
||||||
|
self._propagate("resize", event);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
$.ui.plugin.add("resizable", "containment", {
|
||||||
|
|
||||||
|
start: function(event, ui) {
|
||||||
|
var self = $(this).data("resizable"), o = self.options, el = self.element;
|
||||||
|
var oc = o.containment, ce = (oc instanceof $) ? oc.get(0) : (/parent/.test(oc)) ? el.parent().get(0) : oc;
|
||||||
|
if (!ce) return;
|
||||||
|
|
||||||
|
self.containerElement = $(ce);
|
||||||
|
|
||||||
|
if (/document/.test(oc) || oc == document) {
|
||||||
|
self.containerOffset = { left: 0, top: 0 };
|
||||||
|
self.containerPosition = { left: 0, top: 0 };
|
||||||
|
|
||||||
|
self.parentData = {
|
||||||
|
element: $(document), left: 0, top: 0,
|
||||||
|
width: $(document).width(), height: $(document).height() || document.body.parentNode.scrollHeight
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// i'm a node, so compute top, left, right, bottom
|
||||||
|
else {
|
||||||
|
var element = $(ce), p = [];
|
||||||
|
$([ "Top", "Right", "Left", "Bottom" ]).each(function(i, name) { p[i] = num(element.css("padding" + name)); });
|
||||||
|
|
||||||
|
self.containerOffset = element.offset();
|
||||||
|
self.containerPosition = element.position();
|
||||||
|
self.containerSize = { height: (element.innerHeight() - p[3]), width: (element.innerWidth() - p[1]) };
|
||||||
|
|
||||||
|
var co = self.containerOffset, ch = self.containerSize.height, cw = self.containerSize.width,
|
||||||
|
width = ($.ui.hasScroll(ce, "left") ? ce.scrollWidth : cw ), height = ($.ui.hasScroll(ce) ? ce.scrollHeight : ch);
|
||||||
|
|
||||||
|
self.parentData = {
|
||||||
|
element: ce, left: co.left, top: co.top, width: width, height: height
|
||||||
|
};
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
resize: function(event, ui) {
|
||||||
|
var self = $(this).data("resizable"), o = self.options,
|
||||||
|
ps = self.containerSize, co = self.containerOffset, cs = self.size, cp = self.position,
|
||||||
|
pRatio = self._aspectRatio || event.shiftKey, cop = { top:0, left:0 }, ce = self.containerElement;
|
||||||
|
|
||||||
|
if (ce[0] != document && (/static/).test(ce.css('position'))) cop = co;
|
||||||
|
|
||||||
|
if (cp.left < (self._helper ? co.left : 0)) {
|
||||||
|
self.size.width = self.size.width + (self._helper ? (self.position.left - co.left) : (self.position.left - cop.left));
|
||||||
|
if (pRatio) self.size.height = self.size.width / o.aspectRatio;
|
||||||
|
self.position.left = o.helper ? co.left : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cp.top < (self._helper ? co.top : 0)) {
|
||||||
|
self.size.height = self.size.height + (self._helper ? (self.position.top - co.top) : self.position.top);
|
||||||
|
if (pRatio) self.size.width = self.size.height * o.aspectRatio;
|
||||||
|
self.position.top = self._helper ? co.top : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.offset.left = self.parentData.left+self.position.left;
|
||||||
|
self.offset.top = self.parentData.top+self.position.top;
|
||||||
|
|
||||||
|
var woset = Math.abs( (self._helper ? self.offset.left - cop.left : (self.offset.left - cop.left)) + self.sizeDiff.width ),
|
||||||
|
hoset = Math.abs( (self._helper ? self.offset.top - cop.top : (self.offset.top - co.top)) + self.sizeDiff.height );
|
||||||
|
|
||||||
|
var isParent = self.containerElement.get(0) == self.element.parent().get(0),
|
||||||
|
isOffsetRelative = /relative|absolute/.test(self.containerElement.css('position'));
|
||||||
|
|
||||||
|
if(isParent && isOffsetRelative) woset -= self.parentData.left;
|
||||||
|
|
||||||
|
if (woset + self.size.width >= self.parentData.width) {
|
||||||
|
self.size.width = self.parentData.width - woset;
|
||||||
|
if (pRatio) self.size.height = self.size.width / self.aspectRatio;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hoset + self.size.height >= self.parentData.height) {
|
||||||
|
self.size.height = self.parentData.height - hoset;
|
||||||
|
if (pRatio) self.size.width = self.size.height * self.aspectRatio;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
stop: function(event, ui){
|
||||||
|
var self = $(this).data("resizable"), o = self.options, cp = self.position,
|
||||||
|
co = self.containerOffset, cop = self.containerPosition, ce = self.containerElement;
|
||||||
|
|
||||||
|
var helper = $(self.helper), ho = helper.offset(), w = helper.outerWidth() - self.sizeDiff.width, h = helper.outerHeight() - self.sizeDiff.height;
|
||||||
|
|
||||||
|
if (self._helper && !o.animate && (/relative/).test(ce.css('position')))
|
||||||
|
$(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });
|
||||||
|
|
||||||
|
if (self._helper && !o.animate && (/static/).test(ce.css('position')))
|
||||||
|
$(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$.ui.plugin.add("resizable", "ghost", {
|
||||||
|
|
||||||
|
start: function(event, ui) {
|
||||||
|
|
||||||
|
var self = $(this).data("resizable"), o = self.options, cs = self.size;
|
||||||
|
|
||||||
|
self.ghost = self.originalElement.clone();
|
||||||
|
self.ghost
|
||||||
|
.css({ opacity: .25, display: 'block', position: 'relative', height: cs.height, width: cs.width, margin: 0, left: 0, top: 0 })
|
||||||
|
.addClass('ui-resizable-ghost')
|
||||||
|
.addClass(typeof o.ghost == 'string' ? o.ghost : '');
|
||||||
|
|
||||||
|
self.ghost.appendTo(self.helper);
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
resize: function(event, ui){
|
||||||
|
var self = $(this).data("resizable"), o = self.options;
|
||||||
|
if (self.ghost) self.ghost.css({ position: 'relative', height: self.size.height, width: self.size.width });
|
||||||
|
},
|
||||||
|
|
||||||
|
stop: function(event, ui){
|
||||||
|
var self = $(this).data("resizable"), o = self.options;
|
||||||
|
if (self.ghost && self.helper) self.helper.get(0).removeChild(self.ghost.get(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
$.ui.plugin.add("resizable", "grid", {
|
||||||
|
|
||||||
|
resize: function(event, ui) {
|
||||||
|
var self = $(this).data("resizable"), o = self.options, cs = self.size, os = self.originalSize, op = self.originalPosition, a = self.axis, ratio = o._aspectRatio || event.shiftKey;
|
||||||
|
o.grid = typeof o.grid == "number" ? [o.grid, o.grid] : o.grid;
|
||||||
|
var ox = Math.round((cs.width - os.width) / (o.grid[0]||1)) * (o.grid[0]||1), oy = Math.round((cs.height - os.height) / (o.grid[1]||1)) * (o.grid[1]||1);
|
||||||
|
|
||||||
|
if (/^(se|s|e)$/.test(a)) {
|
||||||
|
self.size.width = os.width + ox;
|
||||||
|
self.size.height = os.height + oy;
|
||||||
|
}
|
||||||
|
else if (/^(ne)$/.test(a)) {
|
||||||
|
self.size.width = os.width + ox;
|
||||||
|
self.size.height = os.height + oy;
|
||||||
|
self.position.top = op.top - oy;
|
||||||
|
}
|
||||||
|
else if (/^(sw)$/.test(a)) {
|
||||||
|
self.size.width = os.width + ox;
|
||||||
|
self.size.height = os.height + oy;
|
||||||
|
self.position.left = op.left - ox;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
self.size.width = os.width + ox;
|
||||||
|
self.size.height = os.height + oy;
|
||||||
|
self.position.top = op.top - oy;
|
||||||
|
self.position.left = op.left - ox;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
var num = function(v) {
|
||||||
|
return parseInt(v, 10) || 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
var isNumber = function(value) {
|
||||||
|
return !isNaN(parseInt(value, 10));
|
||||||
|
};
|
||||||
|
|
||||||
|
})(jQuery);
|
577
src/main.js
Executable file
|
@ -0,0 +1,577 @@
|
||||||
|
|
||||||
|
var fc = $.fullCalendar = {};
|
||||||
|
var views = fc.views = {};
|
||||||
|
|
||||||
|
|
||||||
|
/* Defaults
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
var defaults = {
|
||||||
|
|
||||||
|
// display
|
||||||
|
defaultView: 'month',
|
||||||
|
aspectRatio: 1.35,
|
||||||
|
header: {
|
||||||
|
left: 'prev,next today',
|
||||||
|
center: 'title',
|
||||||
|
right: 'month,basicWeek,basicDay'
|
||||||
|
},
|
||||||
|
|
||||||
|
// event ajax
|
||||||
|
startParam: 'start',
|
||||||
|
endParam: 'end',
|
||||||
|
cacheParam: '_',
|
||||||
|
|
||||||
|
// time formats
|
||||||
|
eventTimeFormat: 'h(:mm)t',
|
||||||
|
titleFormat: {
|
||||||
|
month: 'MMMM yyyy',
|
||||||
|
week: "MMM d[ yyyy]{ '—' [MMM ]d yyyy}",
|
||||||
|
day: 'dddd, MMM d, yyyy'
|
||||||
|
},
|
||||||
|
columnFormat: {
|
||||||
|
month: 'ddd',
|
||||||
|
week: 'ddd M/d',
|
||||||
|
day: 'dddd M/d'
|
||||||
|
},
|
||||||
|
|
||||||
|
// regional
|
||||||
|
isRTL: false,
|
||||||
|
weekStart: 0,
|
||||||
|
monthNames: ['January','February','March','April','May','June','July','August','September','October','November','December'],
|
||||||
|
monthNamesShort: ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'],
|
||||||
|
dayNames: ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'],
|
||||||
|
dayNamesShort: ['Sun','Mon','Tue','Wed','Thu','Fri','Sat'],
|
||||||
|
buttonText: {
|
||||||
|
prev: '◄',
|
||||||
|
next: '►',
|
||||||
|
today: 'today',
|
||||||
|
month: 'month',
|
||||||
|
week: 'week',
|
||||||
|
day: 'day'
|
||||||
|
},
|
||||||
|
|
||||||
|
// jquery-ui theming
|
||||||
|
theme: false,
|
||||||
|
buttonIcons: {
|
||||||
|
prev: 'circle-triangle-w',
|
||||||
|
next: 'circle-triangle-e'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// right-to-left defaults
|
||||||
|
var rtlDefaults = {
|
||||||
|
header: {
|
||||||
|
left: 'basicDay,basicWeek,month',
|
||||||
|
center: 'title',
|
||||||
|
right: 'today next,prev'
|
||||||
|
},
|
||||||
|
buttonText: {
|
||||||
|
prev: '►',
|
||||||
|
next: '◄'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// function for adding/overriding defaults
|
||||||
|
var setDefaults = fc.setDefaults = function(d) {
|
||||||
|
$.extend(true, defaults, d);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* .fullCalendar jQuery function
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
$.fn.fullCalendar = function(options) {
|
||||||
|
|
||||||
|
// method calling
|
||||||
|
if (typeof options == 'string') {
|
||||||
|
var args = Array.prototype.slice.call(arguments, 1), res;
|
||||||
|
this.each(function() {
|
||||||
|
var r = $.data(this, 'fullCalendar')[options].apply(this, args);
|
||||||
|
if (typeof res == 'undefined') res = r;
|
||||||
|
});
|
||||||
|
if (typeof res != 'undefined') {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// pluck the 'events' and 'eventSources' options
|
||||||
|
var eventSources = options.eventSources || [];
|
||||||
|
delete options.eventSources;
|
||||||
|
if (options.events) {
|
||||||
|
eventSources.push(options.events);
|
||||||
|
delete options.event;
|
||||||
|
}
|
||||||
|
|
||||||
|
// first event source reserved for 'sticky' events
|
||||||
|
eventSources.unshift([]);
|
||||||
|
|
||||||
|
// initialize options
|
||||||
|
options = $.extend(true, {},
|
||||||
|
defaults,
|
||||||
|
(options.isRTL || typeof options.isRTL == 'undefined' && defaults.isRTL) ? rtlDefaults : {},
|
||||||
|
options
|
||||||
|
);
|
||||||
|
var tm = options.theme ? 'ui' : 'fc';
|
||||||
|
|
||||||
|
|
||||||
|
this.each(function() {
|
||||||
|
|
||||||
|
|
||||||
|
/* Instance Initialization
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
// element
|
||||||
|
var _element = this,
|
||||||
|
element = $(this).addClass('fc'),
|
||||||
|
content = $("<div class='fc-content " + tm + "-widget-content'/>").appendTo(this);
|
||||||
|
if (options.isRTL) {
|
||||||
|
element.addClass('fc-rtl');
|
||||||
|
}
|
||||||
|
if (options.theme) {
|
||||||
|
element.addClass('ui-widget');
|
||||||
|
}
|
||||||
|
|
||||||
|
// view managing
|
||||||
|
var date = new Date(),
|
||||||
|
viewName, view, // the current view
|
||||||
|
prevView,
|
||||||
|
viewInstances = {};
|
||||||
|
if (options.year) {
|
||||||
|
date.setYear(options.year);
|
||||||
|
}
|
||||||
|
if (options.month) {
|
||||||
|
date.setMonth(options.month);
|
||||||
|
}
|
||||||
|
if (options.date) {
|
||||||
|
date.setDate(options.date);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* View Rendering
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
function switchView(v) {
|
||||||
|
if (v != viewName) {
|
||||||
|
prevView = view;
|
||||||
|
if (viewInstances[v]) {
|
||||||
|
(view = viewInstances[v]).element.show();
|
||||||
|
}else{
|
||||||
|
view = viewInstances[v] = $.fullCalendar.views[v](
|
||||||
|
$("<div class='fc-view fc-view-" + v + "'/>").appendTo(content),
|
||||||
|
options);
|
||||||
|
}
|
||||||
|
if (prevView) {
|
||||||
|
prevView.element.hide();
|
||||||
|
if (prevView.eventsChanged) {
|
||||||
|
eventsDirtyExcept(prevView);
|
||||||
|
prevView.eventsChanged = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (header) {
|
||||||
|
header.find('div.fc-button-' + viewName).removeClass(tm + '-state-active');
|
||||||
|
header.find('div.fc-button-' + v).addClass(tm + '-state-active');
|
||||||
|
}
|
||||||
|
view.name = viewName = v;
|
||||||
|
render();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function render(inc) {
|
||||||
|
if (inc || !view.date || +view.date != +date) {
|
||||||
|
ignoreResizes = true;
|
||||||
|
view.render(date, inc || 0, function(callback) {
|
||||||
|
if (!eventStart || view.visStart < eventStart || view.visEnd > eventEnd) {
|
||||||
|
fetchEvents(callback);
|
||||||
|
}else{
|
||||||
|
callback(events);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
ignoreResizes = false;
|
||||||
|
view.date = cloneDate(date);
|
||||||
|
if (header) {
|
||||||
|
var today = new Date();
|
||||||
|
if (today >= view.start && today < view.end) {
|
||||||
|
header.find('div.fc-button-today').addClass(tm + '-state-disabled');
|
||||||
|
}else{
|
||||||
|
header.find('div.fc-button-today').removeClass(tm + '-state-disabled');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (view.eventsDirty) {
|
||||||
|
view.rerenderEvents();
|
||||||
|
}
|
||||||
|
if (header) {
|
||||||
|
header.find('h2.fc-header-title').html(view.title);
|
||||||
|
}
|
||||||
|
view.eventsDirty = false;
|
||||||
|
view.trigger('viewDisplay', _element, date);
|
||||||
|
}
|
||||||
|
|
||||||
|
function eventsDirtyExcept(exceptView) {
|
||||||
|
$.each(viewInstances, function() {
|
||||||
|
if (this != exceptView) {
|
||||||
|
this.eventsDirty = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function eventsChanged() {
|
||||||
|
view.clearEvents();
|
||||||
|
view.renderEvents(events);
|
||||||
|
eventsDirtyExcept(view);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Event Sources and Fetching
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
var events = [],
|
||||||
|
eventStart, eventEnd;
|
||||||
|
|
||||||
|
// Fetch from ALL sources. Clear 'events' array and populate
|
||||||
|
function fetchEvents(callback) {
|
||||||
|
events = [];
|
||||||
|
eventStart = cloneDate(view.visStart);
|
||||||
|
eventEnd = cloneDate(view.visEnd);
|
||||||
|
var queued = eventSources.length,
|
||||||
|
sourceDone = function() {
|
||||||
|
if (--queued == 0) {
|
||||||
|
if (callback) {
|
||||||
|
callback(events);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, i=0;
|
||||||
|
for (; i<eventSources.length; i++) {
|
||||||
|
fetchEventSource(eventSources[i], sourceDone);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetch from a particular source. Append to the 'events' array
|
||||||
|
function fetchEventSource(src, callback) {
|
||||||
|
var prevDate = cloneDate(date),
|
||||||
|
reportEvents = function(a, dontPopLoading) {
|
||||||
|
if (+date == +prevDate) {
|
||||||
|
for (var i=0; i<a.length; i++) {
|
||||||
|
normalizeEvent(a[i]);
|
||||||
|
a[i].source = src;
|
||||||
|
}
|
||||||
|
events = events.concat(a);
|
||||||
|
}
|
||||||
|
if (!dontPopLoading) {
|
||||||
|
popLoading();
|
||||||
|
}
|
||||||
|
if (callback) {
|
||||||
|
callback(a);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if (typeof src == 'string') {
|
||||||
|
var params = {};
|
||||||
|
params[options.startParam] = Math.round(eventStart.getTime() / 1000);
|
||||||
|
params[options.endParam] = Math.round(eventEnd.getTime() / 1000);
|
||||||
|
params[options.cacheParam] = (new Date()).getTime();
|
||||||
|
pushLoading();
|
||||||
|
$.getJSON(src, params, reportEvents);
|
||||||
|
}
|
||||||
|
else if ($.isFunction(src)) {
|
||||||
|
pushLoading();
|
||||||
|
src(cloneDate(eventStart), cloneDate(eventEnd), reportEvents);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
reportEvents(src, true); // src is an array
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Loading State
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
var loadingLevel = 0;
|
||||||
|
|
||||||
|
function pushLoading() {
|
||||||
|
if (!loadingLevel++ && options.loading) {
|
||||||
|
options.loading(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function popLoading() {
|
||||||
|
if (!--loadingLevel && options.loading) {
|
||||||
|
options.loading(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Public Methods
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
var publicMethods = {
|
||||||
|
|
||||||
|
//
|
||||||
|
// Navigation
|
||||||
|
//
|
||||||
|
|
||||||
|
prev: function() {
|
||||||
|
render(-1);
|
||||||
|
},
|
||||||
|
|
||||||
|
next: function() {
|
||||||
|
render(1);
|
||||||
|
},
|
||||||
|
|
||||||
|
today: function() {
|
||||||
|
date = new Date();
|
||||||
|
render();
|
||||||
|
},
|
||||||
|
|
||||||
|
//
|
||||||
|
// Event Rendering
|
||||||
|
//
|
||||||
|
|
||||||
|
renderEvent: function(event, stick) {
|
||||||
|
if (typeof event != 'object') {
|
||||||
|
event = eventsByID(event)[0]; // assumed to be ID
|
||||||
|
if (!event) return;
|
||||||
|
}else{
|
||||||
|
normalizeEvent(event);
|
||||||
|
}
|
||||||
|
var startDelta = event.start - event._start,
|
||||||
|
msDuration = event.end - event.start,
|
||||||
|
i, len = events.length, e,
|
||||||
|
found = false;
|
||||||
|
for (i=0; i<len; i++) {
|
||||||
|
e = events[i];
|
||||||
|
if (e._id == event._id) {
|
||||||
|
if (e != event) {
|
||||||
|
e._start = cloneDate(e.start = new Date(+e.start + startDelta));
|
||||||
|
e.end = new Date(+e.start + msDuration);
|
||||||
|
e.title = event.title;
|
||||||
|
e.hasTime = event.hasTime;
|
||||||
|
if (stick && !event.source) {
|
||||||
|
(event.source = eventSources[0]).push(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!found) {
|
||||||
|
events.push(event);
|
||||||
|
}
|
||||||
|
eventsChanged();
|
||||||
|
},
|
||||||
|
|
||||||
|
removeEvent: function(id) {
|
||||||
|
if (typeof id == 'object') {
|
||||||
|
id = id._id;
|
||||||
|
}else{
|
||||||
|
id += '';
|
||||||
|
}
|
||||||
|
removeEvents(function(e) {
|
||||||
|
return e._id != id;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
clientEvents: function(filter) {
|
||||||
|
if (filter) {
|
||||||
|
return filterArray(events, filter);
|
||||||
|
}else{
|
||||||
|
return events;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
clientEventsByID: eventsByID,
|
||||||
|
removeEvents: removeEvents,
|
||||||
|
|
||||||
|
//
|
||||||
|
// Event Source
|
||||||
|
//
|
||||||
|
|
||||||
|
addEventSource: function(src) {
|
||||||
|
eventSources.push(src);
|
||||||
|
fetchEventSource(src, function() {
|
||||||
|
eventsChanged();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
removeEventSource: function(source) {
|
||||||
|
eventSources = filterArray(eventSources, function(src) {
|
||||||
|
return src != source;
|
||||||
|
});
|
||||||
|
// remove all client events from that source
|
||||||
|
events = filterArray(events, function(e) {
|
||||||
|
return e.source != source;
|
||||||
|
});
|
||||||
|
eventsChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
$.data(this, 'fullCalendar', publicMethods);
|
||||||
|
|
||||||
|
function eventsByID(id) {
|
||||||
|
id += '';
|
||||||
|
return filterArray(events, function(e) {
|
||||||
|
e._id == id;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function removeEvents(filter) {
|
||||||
|
var i, len = eventSources.length;
|
||||||
|
if (filter) {
|
||||||
|
events = filterArray(events, function(e) {
|
||||||
|
return !filter(e);
|
||||||
|
});
|
||||||
|
// remove events from array sources
|
||||||
|
for (i=0; i<len; i++) {
|
||||||
|
if (typeof eventSources[i] == 'object') {
|
||||||
|
eventSources[i] = filterArray(eventSources[i], function(e) {
|
||||||
|
return !filter(e);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
events = [];
|
||||||
|
// clear all array sources
|
||||||
|
for (i=0; i<len; i++) {
|
||||||
|
if (typeof eventSources[i] == 'object') {
|
||||||
|
eventSources[i] = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
eventsChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Header
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
var header,
|
||||||
|
sections = options.header;
|
||||||
|
if (sections) {
|
||||||
|
header = $("<table class='fc-header'/>")
|
||||||
|
.append($("<tr/>")
|
||||||
|
.append($("<td class='fc-header-left'/>").append(buildSection(sections.left)))
|
||||||
|
.append($("<td class='fc-header-center'/>").append(buildSection(sections.center)))
|
||||||
|
.append($("<td class='fc-header-right'/>").append(buildSection(sections.right))))
|
||||||
|
.prependTo(element);
|
||||||
|
}
|
||||||
|
function buildSection(buttonStr) {
|
||||||
|
if (buttonStr) {
|
||||||
|
var tr = $("<tr/>"),
|
||||||
|
prevTitle = false;
|
||||||
|
$.each(buttonStr.split(' '), function(i) {
|
||||||
|
if (i > 0) {
|
||||||
|
tr.append("<td><span class='fc-header-space'/></td>");
|
||||||
|
}
|
||||||
|
$.each(this.split(','), function(j) {
|
||||||
|
var buttonName = this,
|
||||||
|
buttonNameShort = this.replace(/^(basic|agenda)/, '').toLowerCase();
|
||||||
|
if (buttonName == 'title') {
|
||||||
|
tr.find('> :last div').addClass(tm + '-corner-right');
|
||||||
|
tr.append("<td><h2 class='fc-header-title'/></td>");
|
||||||
|
prevTitle = true;
|
||||||
|
}else{
|
||||||
|
var button,
|
||||||
|
icon = options.theme ? options.buttonIcons[buttonNameShort] : null,
|
||||||
|
text = options.buttonText[buttonNameShort];
|
||||||
|
if (icon) {
|
||||||
|
button = $("<div class='fc-button-" + buttonName + " ui-state-default'>" +
|
||||||
|
"<a><span class='ui-icon ui-icon-" + icon + "'/></a></div>");
|
||||||
|
}
|
||||||
|
else if (text) {
|
||||||
|
button = $("<div class='fc-button-" + buttonName + " " + tm + "-state-default'>" +
|
||||||
|
"<a><span>" + text + "</span></a></div>");
|
||||||
|
}
|
||||||
|
if (button) {
|
||||||
|
button
|
||||||
|
.mousedown(function() {
|
||||||
|
button.addClass(tm + '-state-down');
|
||||||
|
})
|
||||||
|
.mouseup(function() {
|
||||||
|
button.removeClass(tm + '-state-down');
|
||||||
|
})
|
||||||
|
.hover(function() {
|
||||||
|
button.addClass(tm + '-state-hover');
|
||||||
|
},
|
||||||
|
function() {
|
||||||
|
button.removeClass(tm + '-state-hover')
|
||||||
|
.removeClass(tm + '-state-down');
|
||||||
|
})
|
||||||
|
.appendTo($("<td/>").appendTo(tr));
|
||||||
|
if (publicMethods[buttonNameShort]) {
|
||||||
|
button.click(publicMethods[buttonNameShort]);
|
||||||
|
}
|
||||||
|
else if (views[buttonName]) {
|
||||||
|
button.click(function() {
|
||||||
|
switchView(buttonName);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (j == 0 || prevTitle) {
|
||||||
|
button.addClass(tm + '-corner-left');
|
||||||
|
}else{
|
||||||
|
button.addClass(tm + '-no-left');
|
||||||
|
}
|
||||||
|
prevTitle = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
tr.find('> :last div').addClass(tm + '-corner-right');
|
||||||
|
});
|
||||||
|
return $("<table/>").append(tr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Resizing
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
var elementWidth,
|
||||||
|
ignoreResizes = false,
|
||||||
|
resizeCnt = 0;
|
||||||
|
|
||||||
|
$(window).resize(function() {
|
||||||
|
if (!ignoreResizes) {
|
||||||
|
var rcnt = ++resizeCnt; // add a delay
|
||||||
|
setTimeout(function() {
|
||||||
|
if (rcnt == resizeCnt) {
|
||||||
|
var newWidth = element.width();
|
||||||
|
if (newWidth != elementWidth) {
|
||||||
|
elementWidth = newWidth;
|
||||||
|
view.updateSize();
|
||||||
|
view.rerenderEvents(true);
|
||||||
|
view.trigger('windowResize', _element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, 200);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// let's begin...
|
||||||
|
switchView(options.defaultView);
|
||||||
|
elementWidth = element.width();
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Important Event Utilities
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
var fakeID = 0;
|
||||||
|
|
||||||
|
function normalizeEvent(event) {
|
||||||
|
event._id = event._id || (typeof event.id == 'undefined' ? '_fc' + fakeID++ : event.id + '');
|
||||||
|
event._start = cloneDate(event.start = parseDate(event.start));
|
||||||
|
event.end = parseDate(event.end);
|
||||||
|
}
|
||||||
|
|
1
src/misc/foot.txt
Executable file
|
@ -0,0 +1 @@
|
||||||
|
})(jQuery);
|
17
src/misc/head.txt
Executable file
|
@ -0,0 +1,17 @@
|
||||||
|
/*!
|
||||||
|
* FullCalendar
|
||||||
|
* http://arshaw.com/fullcalendar/
|
||||||
|
*
|
||||||
|
* use fullcalendar.css for basic styling
|
||||||
|
* requires jQuery UI core and draggables ONLY if you plan to do drag & drop
|
||||||
|
*
|
||||||
|
* Copyright (c) 2009 Adam Shaw
|
||||||
|
* Dual licensed under the MIT and GPL licenses:
|
||||||
|
* http://www.opensource.org/licenses/mit-license.php
|
||||||
|
* http://www.gnu.org/licenses/gpl.html
|
||||||
|
*
|
||||||
|
* Date:
|
||||||
|
* Revision:
|
||||||
|
*/
|
||||||
|
|
||||||
|
(function($) {
|
332
src/util.js
Executable file
|
@ -0,0 +1,332 @@
|
||||||
|
|
||||||
|
/* Date Math
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
var DAY_MS = 86400000;
|
||||||
|
|
||||||
|
function addMonths(d, n, keepTime) {
|
||||||
|
d.setMonth(d.getMonth() + n);
|
||||||
|
if (keepTime) return d;
|
||||||
|
return clearTime(d);
|
||||||
|
}
|
||||||
|
|
||||||
|
function addYears(d, n, keepTime) {
|
||||||
|
d.setFullYear(d.getFullYear() + n);
|
||||||
|
if (keepTime) return d;
|
||||||
|
return clearTime(d);
|
||||||
|
}
|
||||||
|
|
||||||
|
function addDays(d, n, keepTime) {
|
||||||
|
d.setDate(d.getDate() + n);
|
||||||
|
if (keepTime) return d;
|
||||||
|
return clearTime(d);
|
||||||
|
}
|
||||||
|
|
||||||
|
function addMinutes(d, n) {
|
||||||
|
d.setMinutes(d.getMinutes() + n);
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
|
function clearTime(d) {
|
||||||
|
d.setHours(0);
|
||||||
|
d.setMinutes(0);
|
||||||
|
d.setSeconds(0);
|
||||||
|
d.setMilliseconds(0);
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
|
function cloneDate(d, dontKeepTime) {
|
||||||
|
if (dontKeepTime) {
|
||||||
|
return clearTime(new Date(+d));
|
||||||
|
}else{
|
||||||
|
return new Date(+d);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Date Parsing
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
var parseDate = fc.parseDate = function(s) {
|
||||||
|
if (typeof s == 'object')
|
||||||
|
return s; // already a Date object
|
||||||
|
if (typeof s == 'undefined')
|
||||||
|
return null;
|
||||||
|
if (typeof s == 'number')
|
||||||
|
return new Date(s * 1000);
|
||||||
|
return parseISO8601(s, true) ||
|
||||||
|
Date.parse(s) ||
|
||||||
|
new Date(parseInt(s) * 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
var parseISO8601 = fc.parseISO8601 = function(s, ignoreTimezone) {
|
||||||
|
// derived from http://delete.me.uk/2005/03/iso8601.html
|
||||||
|
var regexp = "([0-9]{4})(-([0-9]{2})(-([0-9]{2})" +
|
||||||
|
"(T([0-9]{2}):([0-9]{2})(:([0-9]{2})(\.([0-9]+))?)?" +
|
||||||
|
"(Z|(([-+])([0-9]{2}):([0-9]{2})))?)?)?)?";
|
||||||
|
var d = s.match(new RegExp(regexp));
|
||||||
|
if (!d) return null;
|
||||||
|
var offset = 0;
|
||||||
|
var date = new Date(d[1], 0, 1);
|
||||||
|
if (d[3]) { date.setMonth(d[3] - 1); }
|
||||||
|
if (d[5]) { date.setDate(d[5]); }
|
||||||
|
if (d[7]) { date.setHours(d[7]); }
|
||||||
|
if (d[8]) { date.setMinutes(d[8]); }
|
||||||
|
if (d[10]) { date.setSeconds(d[10]); }
|
||||||
|
if (d[12]) { date.setMilliseconds(Number("0." + d[12]) * 1000); }
|
||||||
|
if (!ignoreTimezone) {
|
||||||
|
if (d[14]) {
|
||||||
|
offset = (Number(d[16]) * 60) + Number(d[17]);
|
||||||
|
offset *= ((d[15] == '-') ? 1 : -1);
|
||||||
|
}
|
||||||
|
offset -= date.getTimezoneOffset();
|
||||||
|
}
|
||||||
|
return new Date(Number(date) + (offset * 60 * 1000));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Date Formatting
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
var formatDate = fc.formatDate = function(date, format, options) {
|
||||||
|
return formatDates(date, null, format, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
var formatDates = fc.formatDates = function(date1, date2, format, options) {
|
||||||
|
options = options || defaults;
|
||||||
|
var date = date1,
|
||||||
|
otherDate = date2,
|
||||||
|
i, len = format.length, c,
|
||||||
|
i2, formatter,
|
||||||
|
res = '';
|
||||||
|
for (i=0; i<len; i++) {
|
||||||
|
c = format.charAt(i);
|
||||||
|
if (c == "'") {
|
||||||
|
for (i2=i+1; i2<len; i2++) {
|
||||||
|
if (format.charAt(i2) == "'") {
|
||||||
|
if (date) {
|
||||||
|
if (i2 == i+1) {
|
||||||
|
res += "'";
|
||||||
|
}else{
|
||||||
|
res += format.substring(i+1, i2);
|
||||||
|
}
|
||||||
|
i = i2;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (c == '(') {
|
||||||
|
for (i2=i+1; i2<len; i2++) {
|
||||||
|
if (format.charAt(i2) == ')') {
|
||||||
|
var subres = formatDate(date, format.substring(i+1, i2), options);
|
||||||
|
if (parseInt(subres.replace(/\D/, ''))) {
|
||||||
|
res += subres;
|
||||||
|
}
|
||||||
|
i = i2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (c == '[') {
|
||||||
|
for (i2=i+1; i2<len; i2++) {
|
||||||
|
if (format.charAt(i2) == ']') {
|
||||||
|
var subformat = format.substring(i+1, i2);
|
||||||
|
var subres = formatDate(date, subformat, options);
|
||||||
|
if (subres != formatDate(otherDate, subformat, options)) {
|
||||||
|
res += subres;
|
||||||
|
}
|
||||||
|
i = i2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (c == '{') {
|
||||||
|
date = date2;
|
||||||
|
otherDate = date1;
|
||||||
|
}
|
||||||
|
else if (c == '}') {
|
||||||
|
date = date1;
|
||||||
|
otherDate = date2;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
for (i2=len; i2>i; i2--) {
|
||||||
|
if (formatter = dateFormatters[format.substring(i, i2)]) {
|
||||||
|
if (date) {
|
||||||
|
res += formatter(date, options);
|
||||||
|
}
|
||||||
|
i = i2 - 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (i2 == i) {
|
||||||
|
if (date) {
|
||||||
|
res += c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
var dateFormatters = {
|
||||||
|
s : function(d) { return d.getSeconds() },
|
||||||
|
ss : function(d) { return zeroPad(d.getSeconds()) },
|
||||||
|
m : function(d) { return d.getMinutes() },
|
||||||
|
mm : function(d) { return zeroPad(d.getMinutes()) },
|
||||||
|
h : function(d) { return d.getHours() % 12 || 12 },
|
||||||
|
hh : function(d) { return zeroPad(d.getHours() % 12 || 12) },
|
||||||
|
H : function(d) { return d.getHours() },
|
||||||
|
HH : function(d) { return zeroPad(d.getHours()) },
|
||||||
|
d : function(d) { return d.getDate() },
|
||||||
|
dd : function(d) { return zeroPad(d.getDate()) },
|
||||||
|
ddd : function(d,o) { return o.dayNamesShort[d.getDay()] },
|
||||||
|
dddd: function(d,o) { return o.dayNames[d.getDay()] },
|
||||||
|
M : function(d) { return d.getMonth() + 1 },
|
||||||
|
MM : function(d) { return zeroPad(d.getMonth() + 1) },
|
||||||
|
MMM : function(d,o) { return o.monthNamesShort[d.getMonth()] },
|
||||||
|
MMMM: function(d,o) { return o.monthNames[d.getMonth()] },
|
||||||
|
yy : function(d) { return (d.getFullYear()+'').substring(2) },
|
||||||
|
yyyy: function(d) { return d.getFullYear() },
|
||||||
|
t : function(d) { return d.getHours() < 12 ? 'a' : 'p' },
|
||||||
|
tt : function(d) { return d.getHours() < 12 ? 'am' : 'pm' },
|
||||||
|
T : function(d) { return d.getHours() < 12 ? 'A' : 'P' },
|
||||||
|
TT : function(d) { return d.getHours() < 12 ? 'AM' : 'PM' },
|
||||||
|
u : function(d) { return formatDate(d, "yyyy-MM-dd'T'HH:mm:ss'Z'") },
|
||||||
|
S : function(d) {
|
||||||
|
var date = d.getDate();
|
||||||
|
if (date > 10 && date < 20) return 'th';
|
||||||
|
return ['st', 'nd', 'rd'][date%10-1] || 'th';
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Element Dimensions
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
function setOuterWidth(element, width, includeMargins) {
|
||||||
|
element.each(function() {
|
||||||
|
var e = $(this);
|
||||||
|
var w = width - (
|
||||||
|
(parseInt(e.css('border-left-width')) || 0) +
|
||||||
|
(parseInt(e.css('padding-left')) || 0) +
|
||||||
|
(parseInt(e.css('padding-right')) || 0) +
|
||||||
|
(parseInt(e.css('border-right-width')) || 0));
|
||||||
|
if (includeMargins) {
|
||||||
|
w -=
|
||||||
|
(parseInt(e.css('margin-left')) || 0) +
|
||||||
|
(parseInt(e.css('margin-right')) || 0);
|
||||||
|
}
|
||||||
|
e.width(w);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function setOuterHeight(element, height, includeMargins) {
|
||||||
|
element.each(function() {
|
||||||
|
var e = $(this);
|
||||||
|
var h = height - (
|
||||||
|
(parseInt(e.css('border-top-width')) || 0) +
|
||||||
|
(parseInt(e.css('padding-top')) || 0) +
|
||||||
|
(parseInt(e.css('padding-bottom')) || 0) +
|
||||||
|
(parseInt(e.css('border-bottom-width')) || 0));
|
||||||
|
if (includeMargins) {
|
||||||
|
h -=
|
||||||
|
(parseInt(e.css('margin-top')) || 0) +
|
||||||
|
(parseInt(e.css('margin-bottom')) || 0);
|
||||||
|
}
|
||||||
|
e.height(h);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Hover Matrix
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
function HoverMatrix(changeCallback) {
|
||||||
|
|
||||||
|
var tops=[], lefts=[],
|
||||||
|
prevRowE, prevColE,
|
||||||
|
origRow, origCol,
|
||||||
|
currRow, currCol;
|
||||||
|
|
||||||
|
// this.cell = null;
|
||||||
|
|
||||||
|
this.row = function(e) {
|
||||||
|
prevRowE = $(e);
|
||||||
|
tops.push(prevRowE.offset().top);
|
||||||
|
};
|
||||||
|
|
||||||
|
this.col = function(e) {
|
||||||
|
prevColE = $(e);
|
||||||
|
lefts.push(prevColE.offset().left);
|
||||||
|
};
|
||||||
|
|
||||||
|
this.start = function() {
|
||||||
|
tops.push(tops[tops.length-1] + prevRowE.outerHeight());
|
||||||
|
lefts.push(lefts[lefts.length-1] + prevColE.outerWidth());
|
||||||
|
origRow = currRow = currCol = -1;
|
||||||
|
};
|
||||||
|
|
||||||
|
this.mouse = function(x, y) {
|
||||||
|
var r, c;
|
||||||
|
for (r=0; r<tops.length && y>=tops[r]; r++) ;
|
||||||
|
for (c=0; c<lefts.length && x>=lefts[c]; c++) ;
|
||||||
|
r = r >= tops.length ? -1 : r - 1;
|
||||||
|
c = c >= lefts.length ? -1 : c - 1;
|
||||||
|
if (r != currRow || c != currCol) {
|
||||||
|
currRow = r;
|
||||||
|
currCol = c;
|
||||||
|
if (r == -1 || c == -1) {
|
||||||
|
this.cell = null;
|
||||||
|
}else{
|
||||||
|
if (origRow == -1) {
|
||||||
|
origRow = r;
|
||||||
|
origCol = c;
|
||||||
|
}
|
||||||
|
this.cell = {
|
||||||
|
row: r,
|
||||||
|
col: c,
|
||||||
|
top: tops[r],
|
||||||
|
left: lefts[c],
|
||||||
|
width: lefts[c+1] - lefts[c],
|
||||||
|
height: tops[r+1] - tops[r],
|
||||||
|
isOrig: r==origRow && c==origCol,
|
||||||
|
rowDelta: r-origRow,
|
||||||
|
colDelta: c-origCol
|
||||||
|
};
|
||||||
|
}
|
||||||
|
changeCallback(this.cell);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Misc Utils
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
var dayIDs = ['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat'];
|
||||||
|
|
||||||
|
function zeroPad(n) {
|
||||||
|
return (n < 10 ? '0' : '') + n;
|
||||||
|
}
|
||||||
|
|
||||||
|
function strProp(s, prop) {
|
||||||
|
return typeof s == 'string' ? s : s[prop];
|
||||||
|
}
|
||||||
|
|
||||||
|
function filterArray(a, test) {
|
||||||
|
var res = [],
|
||||||
|
i, len = a.length;
|
||||||
|
for (i=0; i<len; i++) {
|
||||||
|
if (test(a[i])) {
|
||||||
|
res.push(a[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
269
src/view.js
Executable file
|
@ -0,0 +1,269 @@
|
||||||
|
|
||||||
|
var viewMethods = {
|
||||||
|
|
||||||
|
//
|
||||||
|
// Objects inheriting these methods must implement the following properties/methods:
|
||||||
|
// - title
|
||||||
|
// - start
|
||||||
|
// - end
|
||||||
|
// - visStart
|
||||||
|
// - visEnd
|
||||||
|
// - eventEnd(event)
|
||||||
|
// - visEventEnd(event)
|
||||||
|
//
|
||||||
|
// - render
|
||||||
|
// - rerenderEvents
|
||||||
|
//
|
||||||
|
|
||||||
|
init: function(element, options) {
|
||||||
|
this.element = element;
|
||||||
|
this.options = options;
|
||||||
|
this.cachedEvents = [];
|
||||||
|
this.eventsByID = {};
|
||||||
|
this.eventElements = [];
|
||||||
|
this.eventElementsByID = {};
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
trigger: function(name, thisObj) {
|
||||||
|
if (this.options[name]) {
|
||||||
|
return this.options[name].apply(thisObj, Array.prototype.slice.call(arguments, 2).concat([this]));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// event/element creation reporting
|
||||||
|
|
||||||
|
reportEvents: function(events) {
|
||||||
|
var i, len=events.length, event,
|
||||||
|
fakeID = 0,
|
||||||
|
eventsByID = this.eventsByID = {},
|
||||||
|
cachedEvents = this.cachedEvents = [];
|
||||||
|
for (i=0; i<len; i++) { // TODO: move _id creation to more global 'cleanEvents'
|
||||||
|
event = events[i];
|
||||||
|
if (eventsByID[event._id]) {
|
||||||
|
eventsByID[event._id].push(event);
|
||||||
|
}else{
|
||||||
|
eventsByID[event._id] = [event];
|
||||||
|
}
|
||||||
|
cachedEvents.push(event);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
reportEventElement: function(event, element) {
|
||||||
|
this.eventElements.push(element);
|
||||||
|
var eventElementsByID = this.eventElementsByID;
|
||||||
|
if (eventElementsByID[event._id]) {
|
||||||
|
eventElementsByID[event._id].push(element);
|
||||||
|
}else{
|
||||||
|
eventElementsByID[event._id] = [element];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// get events within visStart and visEnd TODO: need this? move it somewhere else?
|
||||||
|
|
||||||
|
visibleEvents: function(events) {
|
||||||
|
var res=[], i, len=events.length, event;
|
||||||
|
for (i=0; i<len; i++) {
|
||||||
|
event = events[i];
|
||||||
|
if (this.visEventEnd(event) > this.visStart && event.start < this.visEnd) {
|
||||||
|
res.push(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// event element manipulation
|
||||||
|
|
||||||
|
clearEvents: function() { // just remove ELEMENTS
|
||||||
|
$.each(this.eventElements, function() {
|
||||||
|
this.remove();
|
||||||
|
});
|
||||||
|
this.eventElements = [];
|
||||||
|
this.eventElementsByID = {};
|
||||||
|
},
|
||||||
|
|
||||||
|
showEvents: function(event, exceptElement) {
|
||||||
|
this._eee(event, exceptElement, 'show');
|
||||||
|
},
|
||||||
|
|
||||||
|
hideEvents: function(event, exceptElement) {
|
||||||
|
this._eee(event, exceptElement, 'hide'); // fadeOut
|
||||||
|
},
|
||||||
|
|
||||||
|
_eee: function(event, exceptElement, funcName) { // event-element-each
|
||||||
|
var elements = this.eventElementsByID[event._id];
|
||||||
|
for (var i=0; i<elements.length; i++) {
|
||||||
|
if (elements[i] != exceptElement) {
|
||||||
|
elements[i][funcName]();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// event modification reporting
|
||||||
|
|
||||||
|
moveEvent: function(event, days, minutes) { // and actually DO the date change too
|
||||||
|
minutes = minutes || 0;
|
||||||
|
var i, event2, events = this.eventsByID[event._id];
|
||||||
|
for (i=0; i<events.length; i++) {
|
||||||
|
event2 = events[i];
|
||||||
|
event2.hasTime = event.hasTime;
|
||||||
|
addMinutes(addDays(event2.start, days, true), minutes);
|
||||||
|
if (event.end) {
|
||||||
|
event2.end = addMinutes(addDays(this.eventEnd(event2), days, true), minutes);
|
||||||
|
}else{
|
||||||
|
event2.end = null;
|
||||||
|
}
|
||||||
|
normalizeEvent(event2);
|
||||||
|
}
|
||||||
|
this.eventsChanged = true;
|
||||||
|
},
|
||||||
|
|
||||||
|
resizeEvent: function(event, days, minutes) { // and actually DO the date change too
|
||||||
|
minutes = minutes || 0;
|
||||||
|
var i, event2, events = this.eventsByID[event._id];
|
||||||
|
for (i=0; i<events.length; i++) {
|
||||||
|
event2 = events[i];
|
||||||
|
event2.end = addMinutes(addDays(this.eventEnd(event2), days, true), minutes);
|
||||||
|
normalizeEvent(event2);
|
||||||
|
}
|
||||||
|
this.eventsChanged = true;
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// semi-transparent overlay (for days while dragging)
|
||||||
|
|
||||||
|
showOverlay: function(props) {
|
||||||
|
if (!this.dayOverlay) {
|
||||||
|
this.dayOverlay = $("<div class='fc-cell-overlay' style='position:absolute;display:none'/>")
|
||||||
|
.appendTo(this.element);
|
||||||
|
}
|
||||||
|
var o = this.element.offset();
|
||||||
|
this.dayOverlay
|
||||||
|
.css({
|
||||||
|
top: props.top - o.top,
|
||||||
|
left: props.left - o.left,
|
||||||
|
width: props.width,
|
||||||
|
height: props.height
|
||||||
|
})
|
||||||
|
.show();
|
||||||
|
},
|
||||||
|
|
||||||
|
hideOverlay: function() {
|
||||||
|
if (this.dayOverlay) {
|
||||||
|
this.dayOverlay.hide();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// event rendering utilities
|
||||||
|
|
||||||
|
sliceSegs: function(events, start, end) {
|
||||||
|
var segs = [],
|
||||||
|
i, len=events.length, event,
|
||||||
|
eventStart, eventEnd,
|
||||||
|
segStart, segEnd,
|
||||||
|
isStart, isEnd;
|
||||||
|
for (i=0; i<len; i++) {
|
||||||
|
event = events[i];
|
||||||
|
eventStart = event.start;
|
||||||
|
eventEnd = this.visEventEnd(event);
|
||||||
|
if (eventEnd > start && eventStart < end) {
|
||||||
|
if (eventStart < start) {
|
||||||
|
segStart = cloneDate(start);
|
||||||
|
isStart = false;
|
||||||
|
}else{
|
||||||
|
segStart = eventStart;
|
||||||
|
isStart = true;
|
||||||
|
}
|
||||||
|
if (eventEnd > end) {
|
||||||
|
segEnd = cloneDate(end);
|
||||||
|
isEnd = false;
|
||||||
|
}else{
|
||||||
|
segEnd = eventEnd;
|
||||||
|
isEnd = true;
|
||||||
|
}
|
||||||
|
segs.push({
|
||||||
|
event: event,
|
||||||
|
start: segStart,
|
||||||
|
end: segEnd,
|
||||||
|
isStart: isStart,
|
||||||
|
isEnd: isEnd,
|
||||||
|
msLength: segEnd - segStart
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return segs.sort(segCmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// more event rendering utilities
|
||||||
|
|
||||||
|
function stackSegs(segs) {
|
||||||
|
var levels = [],
|
||||||
|
i, len = segs.length, seg,
|
||||||
|
j, collide, k;
|
||||||
|
for (i=0; i<len; i++) {
|
||||||
|
seg = segs[i];
|
||||||
|
j = 0; // the level index where seg should belong
|
||||||
|
while (true) {
|
||||||
|
collide = false;
|
||||||
|
if (levels[j]) {
|
||||||
|
for (k=0; k<levels[j].length; k++) {
|
||||||
|
if (seg.end > levels[j][k].start && seg.start < levels[j][k].end) {
|
||||||
|
collide = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (collide) {
|
||||||
|
j++;
|
||||||
|
}else{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (levels[j]) {
|
||||||
|
levels[j].push(seg);
|
||||||
|
}else{
|
||||||
|
levels[j] = [seg];
|
||||||
|
}
|
||||||
|
seg.after = 0;
|
||||||
|
}
|
||||||
|
return levels;
|
||||||
|
}
|
||||||
|
|
||||||
|
function segAfters(levels) { // TODO: put in agenda.js
|
||||||
|
var i, j, k, level, seg, seg2;
|
||||||
|
for (i=levels.length-1; i>0; i--) {
|
||||||
|
level = levels[i];
|
||||||
|
for (j=0; j<level.length; j++) {
|
||||||
|
seg = level[j];
|
||||||
|
for (k=0; k<segLevels[i-1].length; k++) {
|
||||||
|
seg2 = segLevels[i-1][k];
|
||||||
|
if (segsCollide(seg, seg2)) {
|
||||||
|
seg2.after = Math.max(seg2.after, seg.after+1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function segCmp(a, b) {
|
||||||
|
return (b.msLength - a.msLength) * 100 + (a.event.start - b.event.start);
|
||||||
|
}
|
||||||
|
|
||||||
|
function segsCollide(seg1, seg2) {
|
||||||
|
return seg1.end > seg2.start && seg1.start < seg2.end;
|
||||||
|
}
|
133
test/new.html
Executable file
|
@ -0,0 +1,133 @@
|
||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<link rel='stylesheet' type='text/css' href='redmond/theme.css' />
|
||||||
|
<link rel='stylesheet' type='text/css' href='../src/css/main.css' />
|
||||||
|
<link rel='stylesheet' type='text/css' href='../src/css/grid.css' />
|
||||||
|
<link rel='stylesheet' type='text/css' href='../src/css/agenda.css' />
|
||||||
|
|
||||||
|
<script type='text/javascript' src='../src/jquery/jquery.js'></script>
|
||||||
|
<script type='text/javascript' src='../src/jquery/ui.core.js'></script>
|
||||||
|
<script type='text/javascript' src='../src/jquery/ui.draggable.js'></script>
|
||||||
|
<script type='text/javascript' src='../src/jquery/ui.resizable.js'></script>
|
||||||
|
|
||||||
|
<script type='text/javascript' src='../src/main.js'></script>
|
||||||
|
<script type='text/javascript' src='../src/grid.js'></script>
|
||||||
|
<script type='text/javascript' src='../src/view.js'></script>
|
||||||
|
<script type='text/javascript' src='../src/util.js'></script>
|
||||||
|
<script type='text/javascript' src='../src/gcal.js'></script>
|
||||||
|
<script type='text/javascript'>
|
||||||
|
|
||||||
|
var d = new Date();
|
||||||
|
var y = d.getFullYear();
|
||||||
|
var m = d.getMonth();
|
||||||
|
|
||||||
|
$(document).ready(function() {
|
||||||
|
$('#calendar').fullCalendar({
|
||||||
|
windowResize: function() {
|
||||||
|
//alert('resize');
|
||||||
|
},
|
||||||
|
theme: false,
|
||||||
|
isRTL: false,
|
||||||
|
weekStart: 1,
|
||||||
|
weekMode: 'fixed',
|
||||||
|
//defaultView: 'dayBasic',
|
||||||
|
viewDisplay: function(date, view) {
|
||||||
|
//console.log(date + ', ' + view.name);
|
||||||
|
},
|
||||||
|
dayClick: function(date, view) {
|
||||||
|
//console.log(date + ', ' + view.name);
|
||||||
|
},
|
||||||
|
eventRender: function(event, element) {
|
||||||
|
//console.log(event.title + ' RENDER');
|
||||||
|
},
|
||||||
|
eventMouseover: function(event) {
|
||||||
|
//console.log('OVER ' + event.title);
|
||||||
|
},
|
||||||
|
eventMouseout: function(event) {
|
||||||
|
//console.log('OUT ' + event.title);
|
||||||
|
},
|
||||||
|
eventClick: function(event) {
|
||||||
|
//console.log('CLICK ' + event.title + ' /// ' + this.className);
|
||||||
|
//return false;
|
||||||
|
},
|
||||||
|
eventDragStart: function(event) {
|
||||||
|
//console.log('DRAG START ' + event.title);
|
||||||
|
},
|
||||||
|
eventDragStop: function(event) {
|
||||||
|
//console.log('DRAG STOP ' + event.title);
|
||||||
|
},
|
||||||
|
eventDrop: function(event, dayDelta, minuteDelta) {
|
||||||
|
//console.log(dayDelta + ' ' + minuteDelta + ' --- ' + event.title);
|
||||||
|
},
|
||||||
|
eventResizeStart: function(event) {
|
||||||
|
//console.log('resize START');
|
||||||
|
},
|
||||||
|
eventResizeStop: function(event) {
|
||||||
|
//console.log('resize STOP');
|
||||||
|
},
|
||||||
|
eventResize: function(event, dayDelta, minuteDelta) {
|
||||||
|
//console.log(dayDelta + ' ' + minuteDelta + ' --- ' + event.title);
|
||||||
|
},
|
||||||
|
editable: true,
|
||||||
|
eventSources: [
|
||||||
|
$.fullCalendar.gcalFeed('http://www.google.com/calendar/feeds/usa__en%40holiday.calendar.google.com/public/basic')
|
||||||
|
],
|
||||||
|
events: [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
title: "Long Event",
|
||||||
|
start: new Date(y, m, 6),
|
||||||
|
end: new Date(y, m, 10)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
title: "Repeating",
|
||||||
|
start: new Date(y, m, 2)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
title: "Repeating",
|
||||||
|
start: new Date(y, m, 9)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
title: "Meeting",
|
||||||
|
start: new Date(y, m, 20, 9, 0),
|
||||||
|
hasTime: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 4,
|
||||||
|
title: "Click for Facebook",
|
||||||
|
start: new Date(y, m, 27),
|
||||||
|
end: new Date(y, m, 28),
|
||||||
|
url: "http://facebook.com/"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 5,
|
||||||
|
title: "timed event1",
|
||||||
|
start: new Date (y, m, 31, 17, 30),
|
||||||
|
hasTime: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 6,
|
||||||
|
title: "timed event1",
|
||||||
|
start: new Date (y, m+1, 2, 14, 15),
|
||||||
|
hasTime: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 7,
|
||||||
|
title: "timed event1",
|
||||||
|
start: new Date (y, m+1, 4, 15, 00),
|
||||||
|
end: new Date(y, m+1, 4, 17, 00),
|
||||||
|
hasTime: true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body style='font-size:12px'>
|
||||||
|
<div id='calendar' style='width:900px;margin:20px auto 0;font-family:arial'></div>
|
||||||
|
</body>
|
BIN
test/redmond/images/ui-bg_flat_0_aaaaaa_40x100.png
Executable file
After Width: | Height: | Size: 180 B |
BIN
test/redmond/images/ui-bg_flat_55_fbec88_40x100.png
Executable file
After Width: | Height: | Size: 213 B |
BIN
test/redmond/images/ui-bg_glass_75_d0e5f5_1x400.png
Executable file
After Width: | Height: | Size: 124 B |
BIN
test/redmond/images/ui-bg_glass_85_dfeffc_1x400.png
Executable file
After Width: | Height: | Size: 123 B |
BIN
test/redmond/images/ui-bg_glass_95_fef1ec_1x400.png
Executable file
After Width: | Height: | Size: 119 B |
BIN
test/redmond/images/ui-bg_gloss-wave_55_5c9ccc_500x100.png
Executable file
After Width: | Height: | Size: 3.4 KiB |
BIN
test/redmond/images/ui-bg_inset-hard_100_f5f8f9_1x100.png
Executable file
After Width: | Height: | Size: 104 B |
BIN
test/redmond/images/ui-bg_inset-hard_100_fcfdfd_1x100.png
Executable file
After Width: | Height: | Size: 88 B |
BIN
test/redmond/images/ui-icons_217bc0_256x240.png
Executable file
After Width: | Height: | Size: 4.3 KiB |
BIN
test/redmond/images/ui-icons_2e83ff_256x240.png
Executable file
After Width: | Height: | Size: 4.3 KiB |
BIN
test/redmond/images/ui-icons_469bdd_256x240.png
Executable file
After Width: | Height: | Size: 4.3 KiB |
BIN
test/redmond/images/ui-icons_6da8d5_256x240.png
Executable file
After Width: | Height: | Size: 4.3 KiB |
BIN
test/redmond/images/ui-icons_cd0a0a_256x240.png
Executable file
After Width: | Height: | Size: 4.3 KiB |
BIN
test/redmond/images/ui-icons_d8e7f3_256x240.png
Executable file
After Width: | Height: | Size: 4.3 KiB |
BIN
test/redmond/images/ui-icons_f9bd01_256x240.png
Executable file
After Width: | Height: | Size: 5.2 KiB |
406
test/redmond/theme.css
Executable file
|
@ -0,0 +1,406 @@
|
||||||
|
/*
|
||||||
|
* jQuery UI CSS Framework
|
||||||
|
* Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
|
||||||
|
* Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Layout helpers
|
||||||
|
----------------------------------*/
|
||||||
|
.ui-helper-hidden { display: none; }
|
||||||
|
.ui-helper-hidden-accessible { position: absolute; left: -99999999px; }
|
||||||
|
.ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; }
|
||||||
|
.ui-helper-clearfix:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; }
|
||||||
|
.ui-helper-clearfix { display: inline-block; }
|
||||||
|
/* required comment for clearfix to work in Opera \*/
|
||||||
|
* html .ui-helper-clearfix { height:1%; }
|
||||||
|
.ui-helper-clearfix { display:block; }
|
||||||
|
/* end clearfix */
|
||||||
|
.ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); }
|
||||||
|
|
||||||
|
|
||||||
|
/* Interaction Cues
|
||||||
|
----------------------------------*/
|
||||||
|
.ui-state-disabled { cursor: default !important; }
|
||||||
|
|
||||||
|
|
||||||
|
/* Icons
|
||||||
|
----------------------------------*/
|
||||||
|
|
||||||
|
/* states and images */
|
||||||
|
.ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; }
|
||||||
|
|
||||||
|
|
||||||
|
/* Misc visuals
|
||||||
|
----------------------------------*/
|
||||||
|
|
||||||
|
/* Overlays */
|
||||||
|
.ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* jQuery UI CSS Framework
|
||||||
|
* Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
|
||||||
|
* Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses.
|
||||||
|
* To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Lucida%20Grande,%20Lucida%20Sans,%20Arial,%20sans-serif&fwDefault=bold&fsDefault=1.1em&cornerRadius=5px&bgColorHeader=5c9ccc&bgTextureHeader=12_gloss_wave.png&bgImgOpacityHeader=55&borderColorHeader=4297d7&fcHeader=ffffff&iconColorHeader=d8e7f3&bgColorContent=fcfdfd&bgTextureContent=06_inset_hard.png&bgImgOpacityContent=100&borderColorContent=a6c9e2&fcContent=222222&iconColorContent=469bdd&bgColorDefault=dfeffc&bgTextureDefault=02_glass.png&bgImgOpacityDefault=85&borderColorDefault=c5dbec&fcDefault=2e6e9e&iconColorDefault=6da8d5&bgColorHover=d0e5f5&bgTextureHover=02_glass.png&bgImgOpacityHover=75&borderColorHover=79b7e7&fcHover=1d5987&iconColorHover=217bc0&bgColorActive=f5f8f9&bgTextureActive=06_inset_hard.png&bgImgOpacityActive=100&borderColorActive=79b7e7&fcActive=e17009&iconColorActive=f9bd01&bgColorHighlight=fbec88&bgTextureHighlight=01_flat.png&bgImgOpacityHighlight=55&borderColorHighlight=fad42e&fcHighlight=363636&iconColorHighlight=2e83ff&bgColorError=fef1ec&bgTextureError=02_glass.png&bgImgOpacityError=95&borderColorError=cd0a0a&fcError=cd0a0a&iconColorError=cd0a0a&bgColorOverlay=aaaaaa&bgTextureOverlay=01_flat.png&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=01_flat.png&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/* Component containers
|
||||||
|
----------------------------------*/
|
||||||
|
.ui-widget { font-family: Lucida Grande, Lucida Sans, Arial, sans-serif; font-size: 1.1em; }
|
||||||
|
.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Lucida Grande, Lucida Sans, Arial, sans-serif; font-size: 1em; }
|
||||||
|
.ui-widget-content { border: 1px solid #a6c9e2; background: #fcfdfd url(images/ui-bg_inset-hard_100_fcfdfd_1x100.png) 50% bottom repeat-x; color: #222222; }
|
||||||
|
.ui-widget-content a { color: #222222; }
|
||||||
|
.ui-widget-header { border: 1px solid #4297d7; background: #5c9ccc url(images/ui-bg_gloss-wave_55_5c9ccc_500x100.png) 50% 50% repeat-x; color: #ffffff; font-weight: bold; }
|
||||||
|
.ui-widget-header a { color: #ffffff; }
|
||||||
|
|
||||||
|
/* Interaction states
|
||||||
|
----------------------------------*/
|
||||||
|
.ui-state-default, .ui-widget-content .ui-state-default { border: 1px solid #c5dbec; background: #dfeffc url(images/ui-bg_glass_85_dfeffc_1x400.png) 50% 50% repeat-x; font-weight: bold; color: #2e6e9e; outline: none; }
|
||||||
|
.ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #2e6e9e; text-decoration: none; outline: none; }
|
||||||
|
.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus { border: 1px solid #79b7e7; background: #d0e5f5 url(images/ui-bg_glass_75_d0e5f5_1x400.png) 50% 50% repeat-x; font-weight: bold; color: #1d5987; outline: none; }
|
||||||
|
.ui-state-hover a, .ui-state-hover a:hover { color: #1d5987; text-decoration: none; outline: none; }
|
||||||
|
.ui-state-active, .ui-widget-content .ui-state-active { border: 1px solid #79b7e7; background: #f5f8f9 url(images/ui-bg_inset-hard_100_f5f8f9_1x100.png) 50% 50% repeat-x; font-weight: bold; color: #e17009; outline: none; }
|
||||||
|
.ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #e17009; outline: none; text-decoration: none; }
|
||||||
|
|
||||||
|
/* Interaction Cues
|
||||||
|
----------------------------------*/
|
||||||
|
.ui-state-highlight, .ui-widget-content .ui-state-highlight {border: 1px solid #fad42e; background: #fbec88 url(images/ui-bg_flat_55_fbec88_40x100.png) 50% 50% repeat-x; color: #363636; }
|
||||||
|
.ui-state-highlight a, .ui-widget-content .ui-state-highlight a { color: #363636; }
|
||||||
|
.ui-state-error, .ui-widget-content .ui-state-error {border: 1px solid #cd0a0a; background: #fef1ec url(images/ui-bg_glass_95_fef1ec_1x400.png) 50% 50% repeat-x; color: #cd0a0a; }
|
||||||
|
.ui-state-error a, .ui-widget-content .ui-state-error a { color: #cd0a0a; }
|
||||||
|
.ui-state-error-text, .ui-widget-content .ui-state-error-text { color: #cd0a0a; }
|
||||||
|
.ui-state-disabled, .ui-widget-content .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; }
|
||||||
|
.ui-priority-primary, .ui-widget-content .ui-priority-primary { font-weight: bold; }
|
||||||
|
.ui-priority-secondary, .ui-widget-content .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; }
|
||||||
|
|
||||||
|
/* Icons
|
||||||
|
----------------------------------*/
|
||||||
|
|
||||||
|
/* states and images */
|
||||||
|
.ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_469bdd_256x240.png); }
|
||||||
|
.ui-widget-content .ui-icon {background-image: url(images/ui-icons_469bdd_256x240.png); }
|
||||||
|
.ui-widget-header .ui-icon {background-image: url(images/ui-icons_d8e7f3_256x240.png); }
|
||||||
|
.ui-state-default .ui-icon { background-image: url(images/ui-icons_6da8d5_256x240.png); }
|
||||||
|
.ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_217bc0_256x240.png); }
|
||||||
|
.ui-state-active .ui-icon {background-image: url(images/ui-icons_f9bd01_256x240.png); }
|
||||||
|
.ui-state-highlight .ui-icon {background-image: url(images/ui-icons_2e83ff_256x240.png); }
|
||||||
|
.ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_cd0a0a_256x240.png); }
|
||||||
|
|
||||||
|
/* positioning */
|
||||||
|
.ui-icon-carat-1-n { background-position: 0 0; }
|
||||||
|
.ui-icon-carat-1-ne { background-position: -16px 0; }
|
||||||
|
.ui-icon-carat-1-e { background-position: -32px 0; }
|
||||||
|
.ui-icon-carat-1-se { background-position: -48px 0; }
|
||||||
|
.ui-icon-carat-1-s { background-position: -64px 0; }
|
||||||
|
.ui-icon-carat-1-sw { background-position: -80px 0; }
|
||||||
|
.ui-icon-carat-1-w { background-position: -96px 0; }
|
||||||
|
.ui-icon-carat-1-nw { background-position: -112px 0; }
|
||||||
|
.ui-icon-carat-2-n-s { background-position: -128px 0; }
|
||||||
|
.ui-icon-carat-2-e-w { background-position: -144px 0; }
|
||||||
|
.ui-icon-triangle-1-n { background-position: 0 -16px; }
|
||||||
|
.ui-icon-triangle-1-ne { background-position: -16px -16px; }
|
||||||
|
.ui-icon-triangle-1-e { background-position: -32px -16px; }
|
||||||
|
.ui-icon-triangle-1-se { background-position: -48px -16px; }
|
||||||
|
.ui-icon-triangle-1-s { background-position: -64px -16px; }
|
||||||
|
.ui-icon-triangle-1-sw { background-position: -80px -16px; }
|
||||||
|
.ui-icon-triangle-1-w { background-position: -96px -16px; }
|
||||||
|
.ui-icon-triangle-1-nw { background-position: -112px -16px; }
|
||||||
|
.ui-icon-triangle-2-n-s { background-position: -128px -16px; }
|
||||||
|
.ui-icon-triangle-2-e-w { background-position: -144px -16px; }
|
||||||
|
.ui-icon-arrow-1-n { background-position: 0 -32px; }
|
||||||
|
.ui-icon-arrow-1-ne { background-position: -16px -32px; }
|
||||||
|
.ui-icon-arrow-1-e { background-position: -32px -32px; }
|
||||||
|
.ui-icon-arrow-1-se { background-position: -48px -32px; }
|
||||||
|
.ui-icon-arrow-1-s { background-position: -64px -32px; }
|
||||||
|
.ui-icon-arrow-1-sw { background-position: -80px -32px; }
|
||||||
|
.ui-icon-arrow-1-w { background-position: -96px -32px; }
|
||||||
|
.ui-icon-arrow-1-nw { background-position: -112px -32px; }
|
||||||
|
.ui-icon-arrow-2-n-s { background-position: -128px -32px; }
|
||||||
|
.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }
|
||||||
|
.ui-icon-arrow-2-e-w { background-position: -160px -32px; }
|
||||||
|
.ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
|
||||||
|
.ui-icon-arrowstop-1-n { background-position: -192px -32px; }
|
||||||
|
.ui-icon-arrowstop-1-e { background-position: -208px -32px; }
|
||||||
|
.ui-icon-arrowstop-1-s { background-position: -224px -32px; }
|
||||||
|
.ui-icon-arrowstop-1-w { background-position: -240px -32px; }
|
||||||
|
.ui-icon-arrowthick-1-n { background-position: 0 -48px; }
|
||||||
|
.ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
|
||||||
|
.ui-icon-arrowthick-1-e { background-position: -32px -48px; }
|
||||||
|
.ui-icon-arrowthick-1-se { background-position: -48px -48px; }
|
||||||
|
.ui-icon-arrowthick-1-s { background-position: -64px -48px; }
|
||||||
|
.ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
|
||||||
|
.ui-icon-arrowthick-1-w { background-position: -96px -48px; }
|
||||||
|
.ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
|
||||||
|
.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }
|
||||||
|
.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }
|
||||||
|
.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
|
||||||
|
.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
|
||||||
|
.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
|
||||||
|
.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
|
||||||
|
.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
|
||||||
|
.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
|
||||||
|
.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
|
||||||
|
.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
|
||||||
|
.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
|
||||||
|
.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
|
||||||
|
.ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
|
||||||
|
.ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
|
||||||
|
.ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
|
||||||
|
.ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
|
||||||
|
.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
|
||||||
|
.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
|
||||||
|
.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
|
||||||
|
.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
|
||||||
|
.ui-icon-arrow-4 { background-position: 0 -80px; }
|
||||||
|
.ui-icon-arrow-4-diag { background-position: -16px -80px; }
|
||||||
|
.ui-icon-extlink { background-position: -32px -80px; }
|
||||||
|
.ui-icon-newwin { background-position: -48px -80px; }
|
||||||
|
.ui-icon-refresh { background-position: -64px -80px; }
|
||||||
|
.ui-icon-shuffle { background-position: -80px -80px; }
|
||||||
|
.ui-icon-transfer-e-w { background-position: -96px -80px; }
|
||||||
|
.ui-icon-transferthick-e-w { background-position: -112px -80px; }
|
||||||
|
.ui-icon-folder-collapsed { background-position: 0 -96px; }
|
||||||
|
.ui-icon-folder-open { background-position: -16px -96px; }
|
||||||
|
.ui-icon-document { background-position: -32px -96px; }
|
||||||
|
.ui-icon-document-b { background-position: -48px -96px; }
|
||||||
|
.ui-icon-note { background-position: -64px -96px; }
|
||||||
|
.ui-icon-mail-closed { background-position: -80px -96px; }
|
||||||
|
.ui-icon-mail-open { background-position: -96px -96px; }
|
||||||
|
.ui-icon-suitcase { background-position: -112px -96px; }
|
||||||
|
.ui-icon-comment { background-position: -128px -96px; }
|
||||||
|
.ui-icon-person { background-position: -144px -96px; }
|
||||||
|
.ui-icon-print { background-position: -160px -96px; }
|
||||||
|
.ui-icon-trash { background-position: -176px -96px; }
|
||||||
|
.ui-icon-locked { background-position: -192px -96px; }
|
||||||
|
.ui-icon-unlocked { background-position: -208px -96px; }
|
||||||
|
.ui-icon-bookmark { background-position: -224px -96px; }
|
||||||
|
.ui-icon-tag { background-position: -240px -96px; }
|
||||||
|
.ui-icon-home { background-position: 0 -112px; }
|
||||||
|
.ui-icon-flag { background-position: -16px -112px; }
|
||||||
|
.ui-icon-calendar { background-position: -32px -112px; }
|
||||||
|
.ui-icon-cart { background-position: -48px -112px; }
|
||||||
|
.ui-icon-pencil { background-position: -64px -112px; }
|
||||||
|
.ui-icon-clock { background-position: -80px -112px; }
|
||||||
|
.ui-icon-disk { background-position: -96px -112px; }
|
||||||
|
.ui-icon-calculator { background-position: -112px -112px; }
|
||||||
|
.ui-icon-zoomin { background-position: -128px -112px; }
|
||||||
|
.ui-icon-zoomout { background-position: -144px -112px; }
|
||||||
|
.ui-icon-search { background-position: -160px -112px; }
|
||||||
|
.ui-icon-wrench { background-position: -176px -112px; }
|
||||||
|
.ui-icon-gear { background-position: -192px -112px; }
|
||||||
|
.ui-icon-heart { background-position: -208px -112px; }
|
||||||
|
.ui-icon-star { background-position: -224px -112px; }
|
||||||
|
.ui-icon-link { background-position: -240px -112px; }
|
||||||
|
.ui-icon-cancel { background-position: 0 -128px; }
|
||||||
|
.ui-icon-plus { background-position: -16px -128px; }
|
||||||
|
.ui-icon-plusthick { background-position: -32px -128px; }
|
||||||
|
.ui-icon-minus { background-position: -48px -128px; }
|
||||||
|
.ui-icon-minusthick { background-position: -64px -128px; }
|
||||||
|
.ui-icon-close { background-position: -80px -128px; }
|
||||||
|
.ui-icon-closethick { background-position: -96px -128px; }
|
||||||
|
.ui-icon-key { background-position: -112px -128px; }
|
||||||
|
.ui-icon-lightbulb { background-position: -128px -128px; }
|
||||||
|
.ui-icon-scissors { background-position: -144px -128px; }
|
||||||
|
.ui-icon-clipboard { background-position: -160px -128px; }
|
||||||
|
.ui-icon-copy { background-position: -176px -128px; }
|
||||||
|
.ui-icon-contact { background-position: -192px -128px; }
|
||||||
|
.ui-icon-image { background-position: -208px -128px; }
|
||||||
|
.ui-icon-video { background-position: -224px -128px; }
|
||||||
|
.ui-icon-script { background-position: -240px -128px; }
|
||||||
|
.ui-icon-alert { background-position: 0 -144px; }
|
||||||
|
.ui-icon-info { background-position: -16px -144px; }
|
||||||
|
.ui-icon-notice { background-position: -32px -144px; }
|
||||||
|
.ui-icon-help { background-position: -48px -144px; }
|
||||||
|
.ui-icon-check { background-position: -64px -144px; }
|
||||||
|
.ui-icon-bullet { background-position: -80px -144px; }
|
||||||
|
.ui-icon-radio-off { background-position: -96px -144px; }
|
||||||
|
.ui-icon-radio-on { background-position: -112px -144px; }
|
||||||
|
.ui-icon-pin-w { background-position: -128px -144px; }
|
||||||
|
.ui-icon-pin-s { background-position: -144px -144px; }
|
||||||
|
.ui-icon-play { background-position: 0 -160px; }
|
||||||
|
.ui-icon-pause { background-position: -16px -160px; }
|
||||||
|
.ui-icon-seek-next { background-position: -32px -160px; }
|
||||||
|
.ui-icon-seek-prev { background-position: -48px -160px; }
|
||||||
|
.ui-icon-seek-end { background-position: -64px -160px; }
|
||||||
|
.ui-icon-seek-first { background-position: -80px -160px; }
|
||||||
|
.ui-icon-stop { background-position: -96px -160px; }
|
||||||
|
.ui-icon-eject { background-position: -112px -160px; }
|
||||||
|
.ui-icon-volume-off { background-position: -128px -160px; }
|
||||||
|
.ui-icon-volume-on { background-position: -144px -160px; }
|
||||||
|
.ui-icon-power { background-position: 0 -176px; }
|
||||||
|
.ui-icon-signal-diag { background-position: -16px -176px; }
|
||||||
|
.ui-icon-signal { background-position: -32px -176px; }
|
||||||
|
.ui-icon-battery-0 { background-position: -48px -176px; }
|
||||||
|
.ui-icon-battery-1 { background-position: -64px -176px; }
|
||||||
|
.ui-icon-battery-2 { background-position: -80px -176px; }
|
||||||
|
.ui-icon-battery-3 { background-position: -96px -176px; }
|
||||||
|
.ui-icon-circle-plus { background-position: 0 -192px; }
|
||||||
|
.ui-icon-circle-minus { background-position: -16px -192px; }
|
||||||
|
.ui-icon-circle-close { background-position: -32px -192px; }
|
||||||
|
.ui-icon-circle-triangle-e { background-position: -48px -192px; }
|
||||||
|
.ui-icon-circle-triangle-s { background-position: -64px -192px; }
|
||||||
|
.ui-icon-circle-triangle-w { background-position: -80px -192px; }
|
||||||
|
.ui-icon-circle-triangle-n { background-position: -96px -192px; }
|
||||||
|
.ui-icon-circle-arrow-e { background-position: -112px -192px; }
|
||||||
|
.ui-icon-circle-arrow-s { background-position: -128px -192px; }
|
||||||
|
.ui-icon-circle-arrow-w { background-position: -144px -192px; }
|
||||||
|
.ui-icon-circle-arrow-n { background-position: -160px -192px; }
|
||||||
|
.ui-icon-circle-zoomin { background-position: -176px -192px; }
|
||||||
|
.ui-icon-circle-zoomout { background-position: -192px -192px; }
|
||||||
|
.ui-icon-circle-check { background-position: -208px -192px; }
|
||||||
|
.ui-icon-circlesmall-plus { background-position: 0 -208px; }
|
||||||
|
.ui-icon-circlesmall-minus { background-position: -16px -208px; }
|
||||||
|
.ui-icon-circlesmall-close { background-position: -32px -208px; }
|
||||||
|
.ui-icon-squaresmall-plus { background-position: -48px -208px; }
|
||||||
|
.ui-icon-squaresmall-minus { background-position: -64px -208px; }
|
||||||
|
.ui-icon-squaresmall-close { background-position: -80px -208px; }
|
||||||
|
.ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
|
||||||
|
.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
|
||||||
|
.ui-icon-grip-solid-vertical { background-position: -32px -224px; }
|
||||||
|
.ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
|
||||||
|
.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
|
||||||
|
.ui-icon-grip-diagonal-se { background-position: -80px -224px; }
|
||||||
|
|
||||||
|
|
||||||
|
/* Misc visuals
|
||||||
|
----------------------------------*/
|
||||||
|
|
||||||
|
/* Corner radius */
|
||||||
|
.ui-corner-tl { -moz-border-radius-topleft: 5px; -webkit-border-top-left-radius: 5px; }
|
||||||
|
.ui-corner-tr { -moz-border-radius-topright: 5px; -webkit-border-top-right-radius: 5px; }
|
||||||
|
.ui-corner-bl { -moz-border-radius-bottomleft: 5px; -webkit-border-bottom-left-radius: 5px; }
|
||||||
|
.ui-corner-br { -moz-border-radius-bottomright: 5px; -webkit-border-bottom-right-radius: 5px; }
|
||||||
|
.ui-corner-top { -moz-border-radius-topleft: 5px; -webkit-border-top-left-radius: 5px; -moz-border-radius-topright: 5px; -webkit-border-top-right-radius: 5px; }
|
||||||
|
.ui-corner-bottom { -moz-border-radius-bottomleft: 5px; -webkit-border-bottom-left-radius: 5px; -moz-border-radius-bottomright: 5px; -webkit-border-bottom-right-radius: 5px; }
|
||||||
|
.ui-corner-right { -moz-border-radius-topright: 5px; -webkit-border-top-right-radius: 5px; -moz-border-radius-bottomright: 5px; -webkit-border-bottom-right-radius: 5px; }
|
||||||
|
.ui-corner-left { -moz-border-radius-topleft: 5px; -webkit-border-top-left-radius: 5px; -moz-border-radius-bottomleft: 5px; -webkit-border-bottom-left-radius: 5px; }
|
||||||
|
.ui-corner-all { -moz-border-radius: 5px; -webkit-border-radius: 5px; }
|
||||||
|
|
||||||
|
/* Overlays */
|
||||||
|
.ui-widget-overlay { background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); }
|
||||||
|
.ui-widget-shadow { margin: -8px 0 0 -8px; padding: 8px; background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); -moz-border-radius: 8px; -webkit-border-radius: 8px; }/* Accordion
|
||||||
|
----------------------------------*/
|
||||||
|
.ui-accordion .ui-accordion-header { cursor: pointer; position: relative; margin-top: 1px; zoom: 1; }
|
||||||
|
.ui-accordion .ui-accordion-li-fix { display: inline; }
|
||||||
|
.ui-accordion .ui-accordion-header-active { border-bottom: 0 !important; }
|
||||||
|
.ui-accordion .ui-accordion-header a { display: block; font-size: 1em; padding: .5em .5em .5em 2.2em; }
|
||||||
|
.ui-accordion .ui-accordion-header .ui-icon { position: absolute; left: .5em; top: 50%; margin-top: -8px; }
|
||||||
|
.ui-accordion .ui-accordion-content { padding: 1em 2.2em; border-top: 0; margin-top: -2px; position: relative; top: 1px; margin-bottom: 2px; overflow: auto; display: none; }
|
||||||
|
.ui-accordion .ui-accordion-content-active { display: block; }/* Datepicker
|
||||||
|
----------------------------------*/
|
||||||
|
.ui-datepicker { width: 17em; padding: .2em .2em 0; }
|
||||||
|
.ui-datepicker .ui-datepicker-header { position:relative; padding:.2em 0; }
|
||||||
|
.ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { position:absolute; top: 2px; width: 1.8em; height: 1.8em; }
|
||||||
|
.ui-datepicker .ui-datepicker-prev-hover, .ui-datepicker .ui-datepicker-next-hover { top: 1px; }
|
||||||
|
.ui-datepicker .ui-datepicker-prev { left:2px; }
|
||||||
|
.ui-datepicker .ui-datepicker-next { right:2px; }
|
||||||
|
.ui-datepicker .ui-datepicker-prev-hover { left:1px; }
|
||||||
|
.ui-datepicker .ui-datepicker-next-hover { right:1px; }
|
||||||
|
.ui-datepicker .ui-datepicker-prev span, .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px; }
|
||||||
|
.ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; }
|
||||||
|
.ui-datepicker .ui-datepicker-title select { float:left; font-size:1em; margin:1px 0; }
|
||||||
|
.ui-datepicker select.ui-datepicker-month-year {width: 100%;}
|
||||||
|
.ui-datepicker select.ui-datepicker-month,
|
||||||
|
.ui-datepicker select.ui-datepicker-year { width: 49%;}
|
||||||
|
.ui-datepicker .ui-datepicker-title select.ui-datepicker-year { float: right; }
|
||||||
|
.ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; }
|
||||||
|
.ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0; }
|
||||||
|
.ui-datepicker td { border: 0; padding: 1px; }
|
||||||
|
.ui-datepicker td span, .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; }
|
||||||
|
.ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0; }
|
||||||
|
.ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; }
|
||||||
|
.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; }
|
||||||
|
|
||||||
|
/* with multiple calendars */
|
||||||
|
.ui-datepicker.ui-datepicker-multi { width:auto; }
|
||||||
|
.ui-datepicker-multi .ui-datepicker-group { float:left; }
|
||||||
|
.ui-datepicker-multi .ui-datepicker-group table { width:95%; margin:0 auto .4em; }
|
||||||
|
.ui-datepicker-multi-2 .ui-datepicker-group { width:50%; }
|
||||||
|
.ui-datepicker-multi-3 .ui-datepicker-group { width:33.3%; }
|
||||||
|
.ui-datepicker-multi-4 .ui-datepicker-group { width:25%; }
|
||||||
|
.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; }
|
||||||
|
.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; }
|
||||||
|
.ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; }
|
||||||
|
.ui-datepicker-row-break { clear:both; width:100%; }
|
||||||
|
|
||||||
|
/* RTL support */
|
||||||
|
.ui-datepicker-rtl { direction: rtl; }
|
||||||
|
.ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; }
|
||||||
|
.ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; }
|
||||||
|
.ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; }
|
||||||
|
.ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; }
|
||||||
|
.ui-datepicker-rtl .ui-datepicker-buttonpane { clear:right; }
|
||||||
|
.ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; }
|
||||||
|
.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { float:right; }
|
||||||
|
.ui-datepicker-rtl .ui-datepicker-group { float:right; }
|
||||||
|
.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
|
||||||
|
.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
|
||||||
|
|
||||||
|
/* IE6 IFRAME FIX (taken from datepicker 1.5.3 */
|
||||||
|
.ui-datepicker-cover {
|
||||||
|
display: none; /*sorry for IE5*/
|
||||||
|
display/**/: block; /*sorry for IE5*/
|
||||||
|
position: absolute; /*must have*/
|
||||||
|
z-index: -1; /*must have*/
|
||||||
|
filter: mask(); /*must have*/
|
||||||
|
top: -4px; /*must have*/
|
||||||
|
left: -4px; /*must have*/
|
||||||
|
width: 200px; /*must have*/
|
||||||
|
height: 200px; /*must have*/
|
||||||
|
}/* Dialog
|
||||||
|
----------------------------------*/
|
||||||
|
.ui-dialog { position: relative; padding: .2em; width: 300px; }
|
||||||
|
.ui-dialog .ui-dialog-titlebar { padding: .5em .3em .3em 1em; position: relative; }
|
||||||
|
.ui-dialog .ui-dialog-title { float: left; margin: .1em 0 .2em; }
|
||||||
|
.ui-dialog .ui-dialog-titlebar-close { position: absolute; right: .3em; top: 50%; width: 19px; margin: -10px 0 0 0; padding: 1px; height: 18px; }
|
||||||
|
.ui-dialog .ui-dialog-titlebar-close span { display: block; margin: 1px; }
|
||||||
|
.ui-dialog .ui-dialog-titlebar-close:hover, .ui-dialog .ui-dialog-titlebar-close:focus { padding: 0; }
|
||||||
|
.ui-dialog .ui-dialog-content { border: 0; padding: .5em 1em; background: none; overflow: auto; zoom: 1; }
|
||||||
|
.ui-dialog .ui-dialog-buttonpane { text-align: left; border-width: 1px 0 0 0; background-image: none; margin: .5em 0 0 0; padding: .3em 1em .5em .4em; }
|
||||||
|
.ui-dialog .ui-dialog-buttonpane button { float: right; margin: .5em .4em .5em 0; cursor: pointer; padding: .2em .6em .3em .6em; line-height: 1.4em; width:auto; overflow:visible; }
|
||||||
|
.ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; }
|
||||||
|
.ui-draggable .ui-dialog-titlebar { cursor: move; }
|
||||||
|
/* Progressbar
|
||||||
|
----------------------------------*/
|
||||||
|
.ui-progressbar { height:2em; text-align: left; }
|
||||||
|
.ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; }/* Resizable
|
||||||
|
----------------------------------*/
|
||||||
|
.ui-resizable { position: relative;}
|
||||||
|
.ui-resizable-handle { position: absolute;font-size: 0.1px;z-index: 99999; display: block;}
|
||||||
|
.ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; }
|
||||||
|
.ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0px; }
|
||||||
|
.ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0px; }
|
||||||
|
.ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0px; height: 100%; }
|
||||||
|
.ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0px; height: 100%; }
|
||||||
|
.ui-resizable-se { cursor: se-resize; width: 12px; height: 12px; right: 1px; bottom: 1px; }
|
||||||
|
.ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: -5px; bottom: -5px; }
|
||||||
|
.ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: -5px; top: -5px; }
|
||||||
|
.ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;}/* Slider
|
||||||
|
----------------------------------*/
|
||||||
|
.ui-slider { position: relative; text-align: left; }
|
||||||
|
.ui-slider .ui-slider-handle { position: absolute; z-index: 2; width: 1.2em; height: 1.2em; cursor: default; }
|
||||||
|
.ui-slider .ui-slider-range { position: absolute; z-index: 1; font-size: .7em; display: block; border: 0; }
|
||||||
|
|
||||||
|
.ui-slider-horizontal { height: .8em; }
|
||||||
|
.ui-slider-horizontal .ui-slider-handle { top: -.3em; margin-left: -.6em; }
|
||||||
|
.ui-slider-horizontal .ui-slider-range { top: 0; height: 100%; }
|
||||||
|
.ui-slider-horizontal .ui-slider-range-min { left: 0; }
|
||||||
|
.ui-slider-horizontal .ui-slider-range-max { right: 0; }
|
||||||
|
|
||||||
|
.ui-slider-vertical { width: .8em; height: 100px; }
|
||||||
|
.ui-slider-vertical .ui-slider-handle { left: -.3em; margin-left: 0; margin-bottom: -.6em; }
|
||||||
|
.ui-slider-vertical .ui-slider-range { left: 0; width: 100%; }
|
||||||
|
.ui-slider-vertical .ui-slider-range-min { bottom: 0; }
|
||||||
|
.ui-slider-vertical .ui-slider-range-max { top: 0; }/* Tabs
|
||||||
|
----------------------------------*/
|
||||||
|
.ui-tabs { padding: .2em; zoom: 1; }
|
||||||
|
.ui-tabs .ui-tabs-nav { list-style: none; position: relative; padding: .2em .2em 0; }
|
||||||
|
.ui-tabs .ui-tabs-nav li { position: relative; float: left; border-bottom-width: 0 !important; margin: 0 .2em -1px 0; padding: 0; }
|
||||||
|
.ui-tabs .ui-tabs-nav li a { float: left; text-decoration: none; padding: .5em 1em; }
|
||||||
|
.ui-tabs .ui-tabs-nav li.ui-tabs-selected { padding-bottom: 1px; border-bottom-width: 0; }
|
||||||
|
.ui-tabs .ui-tabs-nav li.ui-tabs-selected a, .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-state-processing a { cursor: text; }
|
||||||
|
.ui-tabs .ui-tabs-nav li a, .ui-tabs.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-selected a { cursor: pointer; } /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */
|
||||||
|
.ui-tabs .ui-tabs-panel { padding: 1em 1.4em; display: block; border-width: 0; background: none; }
|
||||||
|
.ui-tabs .ui-tabs-hide { display: none !important; }
|