calendar improvements (api, css, utc)
This commit is contained in:
parent
fda007f00d
commit
b18500d133
5 changed files with 253 additions and 194 deletions
|
|
@ -133,7 +133,7 @@ Calendar
|
|||
position: absolute;
|
||||
}
|
||||
|
||||
.OxCalendar .OxDate {
|
||||
.OxCalendar .OxEvent {
|
||||
position: absolute;
|
||||
height: 16px;
|
||||
text-overflow: ellipsis;
|
||||
|
|
@ -141,9 +141,15 @@ Calendar
|
|||
white-space: nowrap;
|
||||
cursor: pointer;
|
||||
}
|
||||
.OxCalendar .OxLine > .OxDate {
|
||||
background: -moz-linear-gradient(top, rgba(255, 64, 64, 0.75), rgba(255, 0, 0, 0.75));
|
||||
background: -webkit-gradient(linear, left top, left bottom, from(rgba(255, 32, 32, 1)), to(rgba(224, 0, 0, 1)));
|
||||
.OxCalendar .OxLine > .OxEvent {
|
||||
border-radius: 2px;
|
||||
background: -moz-linear-gradient(top, rgba(255, 32, 32, 0.9), rgba(224, 0, 0, 0.9));
|
||||
background: -webkit-linear-gradient(top, rgba(255, 32, 32, 0.9), rgba(224, 0, 0, 0.9));
|
||||
color: rgb(255, 255, 255);
|
||||
}
|
||||
.OxCalendar .OxLine > .OxEvent.OxSelected {
|
||||
background: -moz-linear-gradient(top, rgba(128, 128, 255, 0.9), rgba(112, 112, 224, 0.9));
|
||||
background: -webkit-linear-gradient(top, rgba(128, 128, 255, 0.9), rgba(112, 112, 224, 0.9));
|
||||
}
|
||||
|
||||
.OxCalendar .OxTimeline {
|
||||
|
|
@ -152,7 +158,7 @@ Calendar
|
|||
//overflow: hidden;
|
||||
}
|
||||
|
||||
.OxCalendar .OxTimeline .OxDate {
|
||||
.OxCalendar .OxTimeline .OxEvent {
|
||||
position: absolute;
|
||||
border-radius: 0;
|
||||
cursor: ew-resize;
|
||||
|
|
|
|||
|
|
@ -7,21 +7,23 @@ Ox.Calendar <f:Ox.Element> Basic calendar object
|
|||
(options, self) -> <f> Calendar object
|
||||
options <o> Options object
|
||||
date <d|new Date()> UTC Date on which the calendar is centered
|
||||
dates <[o]|[]> Date objects to be displayed
|
||||
end <s> End of the event (UTC Date, as string)
|
||||
name <s> Name of the event
|
||||
start <s> Start of the event (UTC Date, as string)
|
||||
type <s> Type of the event (like "person")
|
||||
events <[o]|[]> Event objects to be displayed
|
||||
alternativeNames <[s]> Array of alternative names
|
||||
end <s> End of the event (UTC Date, as string)
|
||||
id <s> Id of the event
|
||||
name <s> Name of the event
|
||||
start <s> Start of the event (UTC Date, as string)
|
||||
type <s> Type of the event (like "person")
|
||||
height <n|256> Height in px
|
||||
range <[n]|[100, 5101]> Start and end year of the calendar
|
||||
selected <s|''> Id of the selected event
|
||||
width <n|256> Width in px
|
||||
zoom <n|8> Initial zoom level
|
||||
self <o> Shared private variable
|
||||
@*/
|
||||
|
||||
// Fixme: switch to UTC
|
||||
// Fixme: in options.dates, replace "stop" with "end"
|
||||
// Fixme: create a variable-resolution date type (with end that is _inclusive_)
|
||||
// Fixme: create a variable-resolution event type (with end that is _inclusive_)
|
||||
|
||||
Ox.Calendar = function(options, self) {
|
||||
|
||||
|
|
@ -29,9 +31,10 @@ Ox.Calendar = function(options, self) {
|
|||
var that = new Ox.Element({}, self)
|
||||
.defaults({
|
||||
date: new Date(),
|
||||
dates: [],
|
||||
events: [],
|
||||
height: 256,
|
||||
range: [1000, 3000],
|
||||
selected: '',
|
||||
width: 256,
|
||||
zoom: 8
|
||||
})
|
||||
|
|
@ -42,6 +45,12 @@ Ox.Calendar = function(options, self) {
|
|||
height: self.options.height + 'px'
|
||||
});
|
||||
|
||||
self.options.events.forEach(function(event) {
|
||||
event.id = Ox.isUndefined(event.id) ? Ox.uid() : event.id;
|
||||
event.start = Ox.parseDate(event.start, true);
|
||||
event.end = Ox.parseDate(event.end, true);
|
||||
});
|
||||
|
||||
self.maxZoom = 32;
|
||||
self.minLabelWidth = 80;
|
||||
self.overlayWidths = [Math.round(self.options.width / 16)];
|
||||
|
|
@ -346,7 +355,7 @@ Ox.Calendar = function(options, self) {
|
|||
}
|
||||
|
||||
function doubleclick(event, e) {
|
||||
if ($(e.target).is(':not(.OxLine > .OxDate)')) {
|
||||
if ($(e.target).is(':not(.OxLine > .OxEvent)')) {
|
||||
if (self.options.zoom < self.maxZoom) {
|
||||
self.options.date = new Date(
|
||||
(+self.options.date + +getMouseDate(e)) / 2
|
||||
|
|
@ -358,7 +367,7 @@ Ox.Calendar = function(options, self) {
|
|||
}
|
||||
|
||||
function dragstart(event, e) {
|
||||
if ($(e.target).is(':not(.OxLine > .OxDate)')) {
|
||||
if ($(e.target).is(':not(.OxLine > .OxEvent)')) {
|
||||
self.drag = {x: e.clientX};
|
||||
}
|
||||
}
|
||||
|
|
@ -446,61 +455,67 @@ Ox.Calendar = function(options, self) {
|
|||
renderCalendar();
|
||||
}
|
||||
|
||||
function formatDate(date) {
|
||||
var isFullDays = Ox.formatDate(date.start, '%H:%M:%S') == '00:00:00' &&
|
||||
Ox.formatDate(date.stop, '%H:%M:%S') == '00:00:00',
|
||||
isOneDay = isFullDays && date.stop - date.start == 86400000, // fixme: wrong, DST
|
||||
isSameDay = Ox.formatDate(date.start, '%Y-%m-%d') ==
|
||||
Ox.formatDate(date.stop, '%Y-%m-%d'),
|
||||
isSameYear = date.start.getFullYear() == date.stop.getFullYear(),
|
||||
function formatEvent(event) {
|
||||
var isFullDays = Ox.formatDate(event.start, '%H:%M:%S', true) == '00:00:00' &&
|
||||
Ox.formatDate(event.end, '%H:%M:%S', true) == '00:00:00',
|
||||
isOneDay = isFullDays && event.end - event.start == 86400000, // fixme: wrong, DST
|
||||
isSameDay = Ox.formatDate(event.start, '%Y-%m-%d', true) ==
|
||||
Ox.formatDate(event.end, '%Y-%m-%d', true),
|
||||
isSameYear = event.start.getUTCFullYear() == event.end.getUTCFullYear(),
|
||||
timeFormat = isFullDays ? '' : ', %H:%M:%S',
|
||||
str = Ox.formatDate(date.start, '%a, %b %e');
|
||||
str = Ox.formatDate(event.start, '%a, %b %e', true);
|
||||
if (isOneDay || isSameDay || !isSameYear) {
|
||||
str += Ox.formatDate(date.start, ', %Y' + timeFormat);
|
||||
str += Ox.formatDate(event.start, ', %Y' + timeFormat, true);
|
||||
}
|
||||
if (!isOneDay && !isSameDay) {
|
||||
str += Ox.formatDate(date.stop, ' - %a, %b %e, %Y' + timeFormat);
|
||||
str += Ox.formatDate(event.end, ' - %a, %b %e, %Y' + timeFormat, true);
|
||||
}
|
||||
if (isSameDay) {
|
||||
str += Ox.formatDate(date.stop, ' - ' + timeFormat.replace(', ', ''));
|
||||
str += Ox.formatDate(event.end, ' - ' + timeFormat.replace(', ', ''), true);
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
function getCalendarDate() {
|
||||
function getCalendarEvent() {
|
||||
var ms = self.options.width * getSecondsPerPixel() * 1000;
|
||||
return {
|
||||
start: new Date(+self.options.date - ms / 2),
|
||||
stop: new Date(+self.options.date + ms / 2)
|
||||
end: new Date(+self.options.date + ms / 2)
|
||||
};
|
||||
}
|
||||
|
||||
function getDateByName(name) {
|
||||
var date = {};
|
||||
Ox.forEach(self.options.dates, function(v) {
|
||||
if (v.name == name) {
|
||||
date = v;
|
||||
function getEventById(id) {
|
||||
var event = null;
|
||||
Ox.forEach(self.options.events, function(v) {
|
||||
if (v.id == id) {
|
||||
event = v;
|
||||
return false;
|
||||
}
|
||||
});
|
||||
return date;
|
||||
return event;
|
||||
}
|
||||
|
||||
function getDateElement(date, zoom) {
|
||||
var left = getPosition(date.start, zoom),
|
||||
width = Math.max(getPosition(date.stop, zoom) - left, 1);
|
||||
function getEventElement(event, zoom) {
|
||||
var left = getPosition(event.start, zoom),
|
||||
width = Math.max(getPosition(event.end, zoom) - left, 1);
|
||||
return new Ox.Element()
|
||||
.addClass('OxDate')
|
||||
.addClass('OxEvent' + (
|
||||
event.id == self.options.selected ? ' OxSelected' : ''
|
||||
))
|
||||
.css({
|
||||
left: left + 'px',
|
||||
width: width + 'px'
|
||||
})
|
||||
.data({
|
||||
name: date.name
|
||||
id: event.id
|
||||
})
|
||||
.html(' ' + date.name);
|
||||
.html(' ' + event.name);
|
||||
}
|
||||
|
||||
function getEventElementById(id) {
|
||||
|
||||
};
|
||||
|
||||
function getMouseDate(e) {
|
||||
return new Date(+self.options.date + (
|
||||
e.clientX - that.offset().left - self.options.width / 2 - 1
|
||||
|
|
@ -557,10 +572,10 @@ Ox.Calendar = function(options, self) {
|
|||
n = Math.ceil(self.options.width * 1.5/* * 16*/ / width);
|
||||
Ox.loop(-n, n + 1, function(i) {
|
||||
$elements.push(
|
||||
getDateElement({
|
||||
getEventElement({
|
||||
name: unit.name(value + i),
|
||||
start: new Date(unit.date(value + i)),
|
||||
stop: new Date(unit.date(value + i + 1))
|
||||
end: new Date(unit.date(value + i + 1))
|
||||
}, zoom)
|
||||
.addClass(Ox.mod(value + i, 2) == 0 ? 'even' : 'odd')
|
||||
);
|
||||
|
|
@ -592,11 +607,11 @@ Ox.Calendar = function(options, self) {
|
|||
|
||||
function mousemove(e) {
|
||||
var $target = $(e.target),
|
||||
date, title;
|
||||
if ($target.is('.OxLine > .OxDate')) {
|
||||
date = getDateByName($target.data('name'));
|
||||
title = '<span class="OxBright">' + date.name + '</span><br/>' +
|
||||
formatDate(date);
|
||||
event, title;
|
||||
if ($target.is('.OxLine > .OxEvent')) {
|
||||
event = getEventById($target.data('id'));
|
||||
title = '<span class="OxBright">' + event.name + '</span><br/>' +
|
||||
formatEvent(event);
|
||||
} else {
|
||||
title = Ox.formatDate(getMouseDate(e), '%a, %b %e, %Y, %H:%M:%S');
|
||||
}
|
||||
|
|
@ -630,20 +645,20 @@ Ox.Calendar = function(options, self) {
|
|||
}, 250);
|
||||
}
|
||||
|
||||
function overlaps(date0, date1) {
|
||||
function overlaps(eventA, eventB) {
|
||||
return (
|
||||
date0.start >= date1.start && date0.start < date1.stop
|
||||
eventA.start >= eventB.start && eventA.start < eventB.end
|
||||
) || (
|
||||
date1.start >= date0.start && date1.start < date0.stop
|
||||
eventB.start >= eventA.start && eventB.start < eventA.end
|
||||
);
|
||||
}
|
||||
|
||||
function renderCalendar() {
|
||||
$('.OxBackground').empty();
|
||||
$('.OxDate').remove();
|
||||
$('.OxEvent').remove();
|
||||
renderBackground();
|
||||
renderTimelines();
|
||||
renderDates();
|
||||
renderEvents();
|
||||
self.$statusbar.html(
|
||||
Ox.formatDate(self.options.date, '%a, %b %e, %Y, %H:%M:%S (%s)', true)
|
||||
);
|
||||
|
|
@ -655,24 +670,24 @@ Ox.Calendar = function(options, self) {
|
|||
});
|
||||
}
|
||||
|
||||
function renderDates() {
|
||||
var calendarDate = getCalendarDate();
|
||||
lineDates = [];
|
||||
self.options.dates.filter(function(date) {
|
||||
// filter out dates outside the visible area
|
||||
return overlaps(date, calendarDate);
|
||||
function renderEvents() {
|
||||
var calendarEvent = getCalendarEvent();
|
||||
lineEvents = [];
|
||||
self.options.events.filter(function(event) {
|
||||
// filter out events outside the visible area
|
||||
return overlaps(event, calendarEvent);
|
||||
}).sort(function(a, b) {
|
||||
// sort dates by duration, descending
|
||||
return (b.stop - b.start) - (a.stop - a.start);
|
||||
}).forEach(function(date, i) {
|
||||
var line = lineDates.length;
|
||||
// sort events by duration, descending
|
||||
return (b.end - b.start) - (a.end - a.start);
|
||||
}).forEach(function(event, i) {
|
||||
var line = lineEvents.length;
|
||||
// traverse lines
|
||||
Ox.forEach(lineDates, function(dates, line_) {
|
||||
Ox.forEach(lineEvents, function(events, line_) {
|
||||
var fits = true;
|
||||
// traverse dates in line
|
||||
Ox.forEach(dates, function(date_) {
|
||||
// traverse events in line
|
||||
Ox.forEach(events, function(event_) {
|
||||
// if overlaps, check next line
|
||||
if (overlaps(date, date_)) {
|
||||
if (overlaps(event, event_)) {
|
||||
fits = false;
|
||||
return false;
|
||||
}
|
||||
|
|
@ -682,24 +697,24 @@ Ox.Calendar = function(options, self) {
|
|||
return false;
|
||||
}
|
||||
});
|
||||
if (line == lineDates.length) {
|
||||
lineDates[line] = [];
|
||||
if (line == lineEvents.length) {
|
||||
lineEvents[line] = [];
|
||||
}
|
||||
lineDates[line].push(date);
|
||||
lineEvents[line].push(event);
|
||||
});
|
||||
$('.OxLine').remove();
|
||||
lineDates.forEach(function(dates, line) {
|
||||
lineEvents.forEach(function(events, line) {
|
||||
var $line = new Ox.Element()
|
||||
.addClass('OxLine')
|
||||
.css({
|
||||
top: ((line + 1) * 16) + 'px'
|
||||
})
|
||||
.appendTo(self.$content);
|
||||
dates.sort(function(a, b) {
|
||||
// sort dates by start, ascending
|
||||
events.sort(function(a, b) {
|
||||
// sort events by start, ascending
|
||||
return a.start - b.start;
|
||||
}).forEach(function(date) {
|
||||
getDateElement(date).appendTo($line);
|
||||
}).forEach(function(event) {
|
||||
getEventElement(event).appendTo($line);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
@ -714,8 +729,21 @@ Ox.Calendar = function(options, self) {
|
|||
});
|
||||
}
|
||||
|
||||
function selectEvent(id) {
|
||||
}
|
||||
|
||||
function singleclick(event, e) {
|
||||
if ($(e.target).is(':not(.OxLine > .OxDate)')) {
|
||||
var $target = $(e.target),
|
||||
id = $target.data('id');
|
||||
if ($target.is('.OxLine > .OxEvent')) {
|
||||
self.options.selected = id;
|
||||
self.$content.find('.OxSelected').removeClass('OxSelected');
|
||||
$target.addClass('OxSelected');
|
||||
// fixme: map event should also be 'select', not 'selectplace'
|
||||
that.triggerEvent('select', {
|
||||
id: id
|
||||
});
|
||||
} else {
|
||||
self.options.date = getMouseDate(e);
|
||||
renderCalendar();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ Ox.CalendarDate <f> CalendarDate
|
|||
start <d> start date
|
||||
stop <d> stop date
|
||||
@*/
|
||||
// fixme: unused
|
||||
Ox.CalendarDate = function(options) {
|
||||
|
||||
var self = {},
|
||||
|
|
|
|||
21
source/Ox.js
21
source/Ox.js
|
|
@ -1445,6 +1445,27 @@ Ox.makeYear = function(date, utc) {
|
|||
return Ox.isDate(date) ? Ox.getFullYear(date, utc) : parseInt(date);
|
||||
};
|
||||
|
||||
|
||||
/*@
|
||||
Ox.parseDate(f) Takes a string ('YYYY-MM-DD HH:MM:SS') and returns a date
|
||||
str <s> string
|
||||
utc <b|false> If true, Date is UTC
|
||||
> +Ox.parseDate('1970', true)
|
||||
0
|
||||
@*/
|
||||
Ox.parseDate = function(str, utc) {
|
||||
var def = [, 1, 1, 0, 0, 0];
|
||||
val = /(\d+)-?(\d+)?-?(\d+)? ?(\d+)?:?(\d+)?:?(\d+)?/(str);
|
||||
val.shift();
|
||||
val = val.map(function(v, i) {
|
||||
return v || def[i];
|
||||
});
|
||||
val[1]--;
|
||||
return utc
|
||||
? new Date(Date.UTC(val[0], val[1], val[2], val[3], val[4], val[5]))
|
||||
: new Date(val[0], val[1], val[2], val[3], val[4], val[5])
|
||||
};
|
||||
|
||||
//@ Ox.setDate <f> Set the day of a date, optionally UTC
|
||||
// see Ox.setSeconds for source code
|
||||
//@ Ox.setDay <f> Set the weekday of a date, optionally UTC
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue