1
0
Fork 0
forked from 0x2620/oxjs

more calendar improvements (low zoom levels)

This commit is contained in:
rolux 2011-05-25 21:33:43 +02:00
commit 474d5f92cb
3 changed files with 127 additions and 85 deletions

View file

@ -15,7 +15,7 @@ Ox.Calendar <f:Ox.Element> Basic calendar object
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
range <[n]|[1000, 3000]> 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
@ -46,8 +46,8 @@ Ox.Calendar = function(options, self) {
height: self.options.height + 'px'
})
.bindEvent({
anyclick: function() {
that.gainFocus();
anyclick: function(e) {
!$(e.target).is('.OxInput') && that.gainFocus();
},
key_0: function() {
panToSelected();
@ -80,21 +80,19 @@ Ox.Calendar = function(options, self) {
self.maxZoom = 32;
self.minLabelWidth = 80;
self.overlayWidths = [Math.round(self.options.width / 16)];
self.overlayWidths = [
Math.floor((self.options.width - self.overlayWidths[0]) / 2),
self.overlayWidths[0],
Math.ceil((self.options.width - self.overlayWidths[0]) / 2),
];
self.units = [
{
id: 'millennium',
seconds: 365242.5 * 86400,
date: function(i) {
return '01/01/' + (i + 1) + '000 UTC';
var date = new Date(1970, 0, 1);
date.setUTCFullYear((i + 1) * 1000);
return date;
},
name: function(i) {
return Ox.formatOrdinal(i + 2) + ' millennium';
return i > -2
? Ox.formatOrdinal(i + 2) + ' millennium'
: Ox.formatOrdinal(-i - 1) + ' millennium BC'
},
value: function(date) {
return Math.floor(date.getUTCFullYear() / 1000) - 1;
@ -104,10 +102,14 @@ Ox.Calendar = function(options, self) {
id: 'century',
seconds: 36524.25 * 86400,
date: function(i) {
return '01/01/' + (i + 19) + '00 UTC';
var date = new Date(1970, 0, 1);
date.setUTCFullYear((i + 19) * 100);
return date;
},
name: function(i) {
return Ox.formatOrdinal(i + 20) + ' century';
return i > -20
? Ox.formatOrdinal(i + 20) + ' century'
: Ox.formatOrdinal(-i - 19) + ' century BC'
},
value: function(date) {
return Math.floor(date.getUTCFullYear() / 100) - 19;
@ -117,7 +119,9 @@ Ox.Calendar = function(options, self) {
id: 'decade',
seconds: 3652.425 * 86400,
date: function(i) {
return '01/01/' + (i + 197) + '0 UTC'
var date = new Date(1970, 0, 1);
date.setUTCFullYear((i + 197) * 10);
return date;
},
name: function(i) {
return (i + 197) + '0s'
@ -143,7 +147,9 @@ Ox.Calendar = function(options, self) {
id: 'month',
seconds: 365.2425 / 12 * 86400,
date: function(i) {
return (Ox.mod(i, 12) + 1) + '/01/' + (Math.floor(i / 12) + 1970) + ' UTC';
var date = new Date(1970, Ox.mod(i, 12), 1);
date.setUTCFullYear(Math.floor(i / 12) + 1970)
return date;
},
name: function(i) {
return Ox.SHORT_MONTHS[Ox.mod(i, 12)] + ' ' + Math.floor(i / 12 + 1970)
@ -156,7 +162,7 @@ Ox.Calendar = function(options, self) {
id: 'week',
seconds: 7 * 86400,
date: function(i) {
return (i * 7 - 3) * 86400000;
return new Date((i * 7 - 3) * 86400000);
},
name: function(i) {
return Ox.formatDate(new Date((i * 7 - 3) * 86400000), '%a, %b %e');
@ -169,7 +175,7 @@ Ox.Calendar = function(options, self) {
id: 'day',
seconds: 86400,
date: function(i) {
return i * 86400000;
return new Date(i * 86400000);
},
name: function(i) {
return Ox.formatDate(new Date(i * 86400000), '%b %e, %Y', true);
@ -182,7 +188,7 @@ Ox.Calendar = function(options, self) {
id: 'six_hours',
seconds: 21600,
date: function(i) {
return i * 21600000;
return new Date(i * 21600000);
},
name: function(i) {
return Ox.formatDate(new Date(i * 21600000), '%b %e, %H:00', true);
@ -195,7 +201,7 @@ Ox.Calendar = function(options, self) {
id: 'hour',
seconds: 3600,
date: function(i) {
return i * 3600000;
return new Date(i * 3600000);
},
name: function(i) {
return Ox.formatDate(new Date(i * 3600000), '%b %e, %H:00', true);
@ -208,7 +214,7 @@ Ox.Calendar = function(options, self) {
id: 'five_minutes',
seconds: 300,
date: function(i) {
return i * 300000;
return new Date(i * 300000);
},
name: function(i) {
return Ox.formatDate(new Date(i * 300000), '%b %e, %H:%M', true);
@ -221,7 +227,7 @@ Ox.Calendar = function(options, self) {
id: 'minute',
seconds: 60,
date: function(i) {
return i * 60000;
return new Date(i * 60000);
},
name: function(i) {
return Ox.formatDate(new Date(i * 60000), '%b %e, %H:%M', true);
@ -234,7 +240,7 @@ Ox.Calendar = function(options, self) {
id: 'five_seconds',
seconds: 5,
date: function(i) {
return i * 5000;
return new Date(i * 5000);
},
name: function(i) {
return Ox.formatDate(new Date(i * 5000), '%H:%M:%S', true);
@ -247,7 +253,7 @@ Ox.Calendar = function(options, self) {
id: 'second',
seconds: 1,
date: function(i) {
return i * 1000;
return new Date(i * 1000);
},
name: function(i) {
return Ox.formatDate(new Date(i * 1000), '%H:%M:%S', true);
@ -263,7 +269,6 @@ Ox.Calendar = function(options, self) {
})
.appendTo(that);
Ox.print(self.options.showTypes)
self.$typeSelect = Ox.Select({
items: [
{id: 'date', title: 'Dates', checked: self.options.showTypes.indexOf('date') > -1},
@ -276,7 +281,7 @@ Ox.Calendar = function(options, self) {
title: 'Show...',
width: 80
})
.css({margin: '4px'})
.css({float: 'left', margin: '4px'})
.bindEvent({
change: function(data) {
self.options.showTypes = data.selected.map(function(type) {
@ -287,11 +292,25 @@ Ox.Calendar = function(options, self) {
})
.appendTo(self.$toolbar);
self.$dateInput = Ox.Input({
clear: true,
//placeholder: 'Date',
value: Ox.formatDate(self.options.date, '%Y-%m-%d %H:%M:%S', true),
width: 160
})
.css({float: 'right', margin: '4px'})
.bindEvent({
change: function(data) {
panTo(Ox.parseDate(data.value, true))
}
})
.appendTo(self.$toolbar);
self.$container = new Ox.Element()
.addClass('OxCalendarContainer')
.css({
top: '24px',
bottom: '40px'
bottom: '16px'
})
.bind({
mouseleave: mouseleave,
@ -327,46 +346,18 @@ Ox.Calendar = function(options, self) {
.addClass('OxTimeline')
.css({
posision: 'absolute',
bottom: '40px'
})
.appendTo(that);
self.$overlay = new Ox.Element()
.addClass('OxOverlay')
.css({
bottom: '40px'
})
.append(
$('<div>').css({
width: self.overlayWidths[0] + 'px'
})
)
.append(
$('<div>').css({
left: self.overlayWidths[0] + 'px',
width: self.overlayWidths[1] + 'px'
})
)
.append(
$('<div>').css({
left: (self.overlayWidths[0] + self.overlayWidths[1]) + 'px',
width: self.overlayWidths[2] + 'px'
})
)
.bindEvent({
dragstart: dragstartScrollbar,
drag: dragScrollbar,
dragpause: dragpauseScrollbar,
dragend: dragendScrollbar
bottom: '16px'
})
.appendTo(that);
self.$zoombar = new Ox.Element()
.css({
position: 'absolute',
bottom: 24 + 'px',
bottom: 0,
height: '16px'
})
.appendTo(that);
self.$zoomInput = new Ox.Range({
arrows: true,
max: self.maxZoom,
@ -381,17 +372,6 @@ Ox.Calendar = function(options, self) {
})
.appendTo(self.$zoombar);
self.$statusbar = new Ox.Bar({
size: 24
})
.css({
// fixme: no need to set position absolute with map statusbar
position: 'absolute',
bottom: 0,
textAlign: 'center'
})
.appendTo(that);
self.$tooltip = new Ox.Tooltip({
animate: false
})
@ -423,9 +403,9 @@ Ox.Calendar = function(options, self) {
}
function dragstart(event, e) {
if ($(e.target).is(':not(.OxLine > .OxEvent)')) {
//if ($(e.target).is(':not(.OxLine > .OxEvent)')) {
self.drag = {x: e.clientX};
}
//}
}
function drag(event, e) {
@ -480,7 +460,7 @@ Ox.Calendar = function(options, self) {
function dragScrollbar(event, e) {
self.$content.css({
marginLeft: ((e.clientX - self.drag.x) * 16) + 'px'
marginLeft: ((e.clientX - self.drag.x) * getScrollbarFactor()) + 'px'
});
self.$scrollbar.css({
marginLeft: (e.clientX - self.drag.x) + 'px'
@ -556,7 +536,7 @@ Ox.Calendar = function(options, self) {
}
function getCalendarEvent(zoom) {
var ms = self.options.width * getSecondsPerPixel(zoom || self.options.zoom) * 1000;
var ms = self.options.width * getSecondsPerPixel(zoom) * 1000;
return {
start: new Date(+self.options.date - ms / 2),
end: new Date(+self.options.date + ms / 2)
@ -621,18 +601,33 @@ Ox.Calendar = function(options, self) {
) * getSecondsPerPixel() * 1000);
}
function getOverlayWidths() {
var width = Math.round(self.options.width / getScrollbarFactor());
return [
Math.floor((self.options.width - width) / 2),
width,
Math.ceil((self.options.width - width) / 2),
];
}
function getPixelsPerSecond(zoom) {
return Math.pow(2, (zoom || self.options.zoom) - (self.maxZoom - 4));
return Math.pow(2, (
!Ox.isUndefined(zoom) ? zoom : self.options.zoom
) - (self.maxZoom - 4));
}
function getPosition(date, zoom) {
return Math.round(
self.options.width / 2 +
(date - self.options.date) / 1000 *
getPixelsPerSecond(zoom || self.options.zoom)
getPixelsPerSecond(zoom)
);
}
function getScrollbarFactor() {
return Math.pow(2, Math.min(self.options.zoom, 4));
}
function getSecondsPerPixel(zoom) {
return 1 / getPixelsPerSecond(zoom);
}
@ -662,7 +657,7 @@ Ox.Calendar = function(options, self) {
u == 0 ? 'line' : Ox.mod(value + i, 2) == 0 ? 'even' : 'odd'
)
.css({
left: getPosition(new Date(unit.date(value + i)), zoom) + 'px',
left: getPosition(unit.date(value + i), zoom) + 'px',
width: (u == 0 ? 1 : width) + 'px'
})
);
@ -675,14 +670,15 @@ Ox.Calendar = function(options, self) {
var $elements = [],
unit = getUnits(zoom)[0],
value = unit.value(self.options.date),
width = unit.seconds * getPixelsPerSecond(zoom);
width = unit.seconds * getPixelsPerSecond(zoom),
n = Math.ceil(self.options.width * 1.5/* * 16*/ / width);
Ox.print(zoom, getUnits(zoom).map(function(u) {return u.name(value)}).join('/'))
Ox.loop(-n, n + 1, function(i) {
$elements.push(
getEventElement({
name: unit.name(value + i),
start: new Date(unit.date(value + i)),
end: new Date(unit.date(value + i + 1))
start: unit.date(value + i),
end: unit.date(value + i + 1)
}, zoom)
.addClass(Ox.mod(value + i, 2) == 0 ? 'even' : 'odd')
);
@ -696,7 +692,8 @@ Ox.Calendar = function(options, self) {
// units[1] for background
var pixelsPerSecond = getPixelsPerSecond(zoom),
units;
self.units = self.units.reverse();
Ox.print(zoom, 'ppsec', pixelsPerSecond)
self.units.reverse();
Ox.forEach(self.units, function(v, i) {
width = Math.round(v.seconds * pixelsPerSecond);
if (width >= self.minLabelWidth) {
@ -704,7 +701,7 @@ Ox.Calendar = function(options, self) {
return false;
}
});
self.units = self.units.reverse();
self.units.reverse();
return units;
}
@ -795,10 +792,11 @@ Ox.Calendar = function(options, self) {
$('.OxEvent').remove();
renderBackground();
renderTimelines();
renderOverlay();
renderEvents();
self.$statusbar.html(
Ox.formatDate(self.options.date, '%a, %b %e, %Y, %H:%M:%S (%s)', true)
);
self.$dateInput.options({
value: Ox.formatDate(self.options.date, '%Y-%m-%d %H:%M:%S', true)
});
}
function renderEvents() {
@ -842,7 +840,7 @@ Ox.Calendar = function(options, self) {
}
lineEvents[line].push(event);
});
$('.OxLine').remove();
self.$content.find('.OxLine').remove();
lineEvents.forEach(function(events, line) {
var $line = new Ox.Element()
.addClass('OxLine')
@ -859,6 +857,40 @@ Ox.Calendar = function(options, self) {
});
}
function renderOverlay() {
var widths = getOverlayWidths();
that.find('.OxOverlay').remove();
Ox.Element()
.addClass('OxOverlay')
.css({
bottom: '16px'
})
.append(
$('<div>').css({
width: widths[0] + 'px'
})
)
.append(
$('<div>').css({
left: widths[0] + 'px',
width: widths[1] + 'px'
})
)
.append(
$('<div>').css({
left: (widths[0] + widths[1]) + 'px',
width: widths[2] + 'px'
})
)
.bindEvent({
dragstart: dragstartScrollbar,
drag: dragScrollbar,
dragpause: dragpauseScrollbar,
dragend: dragendScrollbar
})
.appendTo(that);
}
function renderTimelines() {
Ox.print(self.options.zoom, Math.max(self.options.zoom - 4, 0))
getTimelineElements(self.options.zoom).forEach(function($element) {