This commit is contained in:
rolux 2011-10-12 01:22:09 +02:00
commit 52fd8b9ad8
15 changed files with 312 additions and 182 deletions

View file

@ -111,13 +111,19 @@ Calendar
.OxThemeClassic .OxCalendar .OxLine > .OxEvent { .OxThemeClassic .OxCalendar .OxLine > .OxEvent {
color: rgb(0, 0, 0); color: rgb(0, 0, 0);
} }
.OxThemeClassic .OxCalendar .OxLine > .OxEvent.OxSelected {
box-shadow: inset 0 0 1px rgb(0, 0, 0),
inset 0 0 1px rgb(0, 0, 0),
inset 0 0 1px rgb(0, 0, 0),
inset 0 0 1px rgb(0, 0, 0);
}
.OxThemeClassic .OxCalendar .OxOverlay div:nth-child(even) { .OxThemeClassic .OxCalendar .OxOverlay div:nth-child(even) {
border-top: 1px solid rgba(0, 0, 0, 0.5); background-color: rgba(0, 0, 0, 0.25);
border-bottom: 1px solid rgba(0, 0, 0, 0.5); box-shadow: inset 0 0 2px rgb(0, 0, 0);
} }
.OxThemeClassic .OxCalendar .OxOverlay div:nth-child(odd) { .OxThemeClassic .OxCalendar .OxOverlay div:nth-child(odd) {
background-color: rgba(255, 255, 255, 0.5); background-color: rgba(255, 255, 255, 0.25);
} }
/* /*

View file

@ -110,13 +110,19 @@ Calendar
.OxThemeModern .OxCalendar .OxLine > .OxEvent { .OxThemeModern .OxCalendar .OxLine > .OxEvent {
color: rgb(255, 255, 255); color: rgb(255, 255, 255);
} }
.OxThemeModern .OxCalendar .OxLine > .OxEvent.OxSelected {
box-shadow: inset 0 0 1px rgb(255, 255, 255),
inset 0 0 1px rgb(255, 255, 255),
inset 0 0 1px rgb(255, 255, 255),
inset 0 0 1px rgb(255, 255, 255);
}
.OxThemeModern .OxCalendar .OxOverlay div:nth-child(even) { .OxThemeModern .OxCalendar .OxOverlay div:nth-child(even) {
border-top: 1px solid rgba(255, 255, 255, 0.5); background-color: rgba(255, 255, 255, 0.25);
border-bottom: 1px solid rgba(255, 255, 255, 0.5); box-shadow: inset 0 0 2px rgb(255, 255, 255);
} }
.OxThemeModern .OxCalendar .OxOverlay div:nth-child(odd) { .OxThemeModern .OxCalendar .OxOverlay div:nth-child(odd) {
background-color: rgba(0, 0, 0, 0.5); background-color: rgba(0, 0, 0, 0.25);
} }

View file

@ -212,6 +212,7 @@ Calendar
white-space: nowrap; white-space: nowrap;
} }
.OxCalendar .OxLine > .OxEvent { .OxCalendar .OxLine > .OxEvent {
//box-shadow: inset 0 0 1px rgba(0, 0, 0, 0.5);
border-radius: 4px; border-radius: 4px;
} }
.OxCalendar .OxLine > .OxEvent.OxCurrent { .OxCalendar .OxLine > .OxEvent.OxCurrent {
@ -219,30 +220,24 @@ Calendar
border-bottom-right-radius: 0; border-bottom-right-radius: 0;
} }
.OxCalendar .OxLine > .OxEvent.OxDate { .OxCalendar .OxLine > .OxEvent.OxDate {
background: -moz-linear-gradient(top, rgba(192, 0, 0, 0.9), rgba(160, 0, 0, 0.9)); background: -moz-linear-gradient(top, rgba(96, 96, 192, 0.9), rgba(64, 64, 160, 0.9));
background: -o-linear-gradient(top, rgba(192, 0, 0, 0.9), rgba(160, 0, 0, 0.9)); background: -o-linear-gradient(top, rgba(96, 96, 192, 0.9), rgba(64, 64, 160, 0.9));
background: -webkit-linear-gradient(top, rgba(192, 0, 0, 0.9), rgba(160, 0, 0, 0.9)); background: -webkit-linear-gradient(top, rgba(96, 96, 255, 0.9), rgba(64, 64, 224, 0.9));
} }
.OxCalendar .OxLine > .OxEvent.OxPlace { .OxCalendar .OxLine > .OxEvent.OxPlace {
background: -moz-linear-gradient(top, rgba(255, 192, 0, 0.9), rgba(224, 160, 0, 0.9)); background: -moz-linear-gradient(top, rgba(0, 128, 96, 0.9), rgba(0, 96, 64, 0.9));
background: -o-linear-gradient(top, rgba(255, 192, 0, 0.9), rgba(224, 160, 0, 0.9)); background: -o-linear-gradient(top, rgba(0, 128, 96, 0.9), rgba(0, 96, 64, 0.9));
background: -webkit-linear-gradient(top, rgba(255, 192, 0, 0.9), rgba(224, 160, 0, 0.9)); background: -webkit-linear-gradient(top, rgba(0, 128, 96, 0.9), rgba(0, 96, 64, 0.9));
} }
.OxCalendar .OxLine > .OxEvent.OxPerson { .OxCalendar .OxLine > .OxEvent.OxPerson {
background: -moz-linear-gradient(top, rgba(255, 96, 0, 0.9), rgba(224, 80, 0, 0.9)); background: -moz-linear-gradient(top, rgba(255, 96, 0, 0.9), rgba(224, 64, 0, 0.9));
background: -o-linear-gradient(top, rgba(255, 96, 0, 0.9), rgba(224, 80, 0, 0.9)); background: -o-linear-gradient(top, rgba(255, 96, 0, 0.9), rgba(224, 64, 0, 0.9));
background: -webkit-linear-gradient(top, rgba(255, 96, 0, 0.9), rgba(224, 80, 0, 0.9)); background: -webkit-linear-gradient(top, rgba(255, 96, 0, 0.9), rgba(224, 64, 0, 0.9));
} }
.OxCalendar .OxLine > .OxEvent.OxOther { .OxCalendar .OxLine > .OxEvent.OxOther {
background: -moz-linear-gradient(top, rgba(255, 0, 0, 0.9), rgba(224, 0, 0, 0.9)); background: -moz-linear-gradient(top, rgba(192, 32, 32, 0.9), rgba(160, 0, 0, 0.9));
background: -o-linear-gradient(top, rgba(255, 0, 0, 0.9), rgba(224, 0, 0, 0.9)); background: -o-linear-gradient(top, rgba(192, 32, 32, 0.9), rgba(160, 0, 0, 0.9));
background: -webkit-linear-gradient(top, rgba(255, 0, 0, 0.9), rgba(224, 0, 0, 0.9)); background: -webkit-linear-gradient(top, rgba(192, 32, 32, 0.9), rgba(160, 0, 0, 0.9));
}
.OxCalendar .OxLine > .OxEvent.OxSelected {
background: -moz-linear-gradient(top, rgba(128, 128, 255, 0.9), rgba(96, 96, 224, 0.9));
background: -o-linear-gradient(top, rgba(128, 128, 255, 0.9), rgba(96, 96, 224, 0.9));
background: -webkit-linear-gradient(top, rgba(128, 128, 255, 0.9), rgba(96, 96, 224, 0.9));
} }
.OxCalendar .OxTimeline { .OxCalendar .OxTimeline {
@ -268,7 +263,7 @@ Calendar
cursor: ew-resize; cursor: ew-resize;
} }
.OxCalendar .OxOverlay div:nth-child(even) { .OxCalendar .OxOverlay div:nth-child(even) {
height: 14px; border-radius: 4px;
} }
.OxCalendar .OxRange .OxArrow { .OxCalendar .OxRange .OxArrow {

View file

@ -46,9 +46,6 @@ Ox.Calendar = function(options, self) {
//height: self.options.height + 'px' //height: self.options.height + 'px'
}) })
.bindEvent({ .bindEvent({
anyclick: function(e) {
!$(e.target).is('.OxInput') && that.gainFocus();
},
key_0: function() { key_0: function() {
panToSelected(); panToSelected();
}, },
@ -81,6 +78,9 @@ Ox.Calendar = function(options, self) {
}, },
key_up: function() { key_up: function() {
scrollBy(-1); scrollBy(-1);
},
mousedown: function(e) {
!$(e.target).is('.OxInput') && that.gainFocus();
} }
}); });
@ -423,7 +423,7 @@ Ox.Calendar = function(options, self) {
} else { } else {
if (self.options.zoom < self.maxZoom) { if (self.options.zoom < self.maxZoom) {
self.options.date = new Date( self.options.date = new Date(
(+self.options.date + +getMouseDate(e)) / 2 (+self.options.date + +getMouseDate(data)) / 2
); );
self.options.zoom++; self.options.zoom++;
} }
@ -583,10 +583,11 @@ Ox.Calendar = function(options, self) {
event.id = Ox.isUndefined(event.id) ? Ox.uid() : event.id; event.id = Ox.isUndefined(event.id) ? Ox.uid() : event.id;
event.startTime = Ox.parseDate(event.start, true); event.startTime = Ox.parseDate(event.start, true);
event.endTime = Ox.parseDate(event.end, true); event.endTime = Ox.parseDate(event.end, true);
event.durationTime = event.endTime - event.startTime;
event.rangeText = Ox.formatDateRange(event.start, event.end, true); event.rangeText = Ox.formatDateRange(event.start, event.end, true);
event.durationText = Ox.formatDateRangeDuration(event.start, event.end, true); event.durationText = Ox.formatDateRangeDuration(event.start, event.end, true);
if (event.current) { if (event.current) {
event.rangeText = event.rangeText.split(' - ').shift() + ' - ...'; event.rangeText = event.rangeText.split(' - ').shift() + ' - now';
} }
return event; return event;
} }
@ -633,16 +634,26 @@ Ox.Calendar = function(options, self) {
return $element; return $element;
} }
function getEventLine(id) {
var line = -1;
Ox.forEach(self.lineEvents, function(events, line_) {
if (Ox.getPositionById(events, id) > -1) {
line = line_;
return false;
}
});
return line;
}
function getLines() { function getLines() {
self.lineEvents = []; self.lineEvents = [];
self.$content.find('.OxLine').remove(); self.$content.find('.OxLine').remove();
self.options.events.filter(function(event) { self.options.events.filter(function(event) {
// filter out events with types not shown // filter out events with types not shown
// and events outside the visible area <-- commented out to keep layout from changing return self.options.showTypes.indexOf(event.type) > -1;
return self.options.showTypes.indexOf(event.type) > -1
/*&& overlaps(event, calendarEvent)*/;
}).sort(function(a, b) { }).sort(function(a, b) {
// sort events (dates first, people last, longer before shorter) // sort events (dates first, people last, longer before shorter,
// earlier before later, otherwise alphabetically by name)
if (a.type == 'date' && b.type != 'date') { if (a.type == 'date' && b.type != 'date') {
return -1; return -1;
} else if (a.type != 'date' && b.type == 'date') { } else if (a.type != 'date' && b.type == 'date') {
@ -651,10 +662,12 @@ Ox.Calendar = function(options, self) {
return 1; return 1;
} else if (a.type != 'person' && b.type == 'person') { } else if (a.type != 'person' && b.type == 'person') {
return -1; return -1;
} else if ((b.endTime - b.startTime) != (a.endTime - a.startTime)) { } else if (a.durationTime != b.durationTime) {
return (b.endTime - b.startTime) - (a.endTime - a.startTime); return b.durationTime - a.durationTime;
} else /*if (a.startTime < b.startTime || a.startTime > b.startTime)*/ { } else if (+a.startTime != +b.startTime) {
return a.startTime - b.startTime; return a.startTime - b.startTime;
} else {
return a.name < b.name ? -1 : 1;
} }
}).forEach(function(event, i) { }).forEach(function(event, i) {
var line = self.lineEvents.length; var line = self.lineEvents.length;
@ -858,16 +871,17 @@ Ox.Calendar = function(options, self) {
marginLeft: -delta / getScrollbarFactor() + 'px' marginLeft: -delta / getScrollbarFactor() + 'px'
}, ms); }, ms);
if (!Ox.isUndefined(line)) { if (!Ox.isUndefined(line)) {
scrollTo(line * 16 + 8 - self.$container.height() / 2, true); scrollTo((line + 1) * 16 - self.$container.height() / 2, true);
} }
}; };
function panToSelected() { function panToSelected() {
// fixme: '0' should zoom to selected if selected is already centered // fixme: '0' should zoom to selected if selected is already centered
// (both horizontally and vertically, the latter is a bit more work) // (both horizontally and vertically, the latter is a bit more work)
var event = getSelectedEvent();
self.options.selected !== '' && panTo( self.options.selected !== '' && panTo(
getEventCenter(getSelectedEvent()), getEventCenter(event),
getSelectedEventElement().data('line') getEventLine(event.id)
); );
} }
@ -900,7 +914,7 @@ Ox.Calendar = function(options, self) {
event.id == self.options.selected event.id == self.options.selected
|| overlaps(event, calendarEvent) || overlaps(event, calendarEvent)
) { ) {
getEventElement(event).data({line: line}).appendTo(self.$lines[line]); getEventElement(event).appendTo(self.$lines[line]);
} }
}); });
}); });
@ -978,7 +992,12 @@ Ox.Calendar = function(options, self) {
self.$content.find('.OxSelected').removeClass('OxSelected'); self.$content.find('.OxSelected').removeClass('OxSelected');
if (id) { if (id) {
self.options.selected = id; self.options.selected = id;
($element || getEventElementById(id)).addClass('OxSelected'); $element = $element || getEventElementById(id);
if ($element) {
$element.addClass('OxSelected');
} else {
panToSelected();
}
// fixme: map event should also be 'select', not 'selectplace' // fixme: map event should also be 'select', not 'selectplace'
that.triggerEvent('select', Ox.getObjectById(self.options.events, id)); that.triggerEvent('select', Ox.getObjectById(self.options.events, id));
} else { } else {
@ -1053,6 +1072,7 @@ Ox.Calendar = function(options, self) {
that.addEvent = function(event) { that.addEvent = function(event) {
Ox.print('CALENDAR ADD EVENT', event) Ox.print('CALENDAR ADD EVENT', event)
event = getEventData(event);
self.options.events.push(event); self.options.events.push(event);
getLines(); getLines();
renderCalendar(); renderCalendar();
@ -1091,6 +1111,7 @@ Ox.Calendar = function(options, self) {
if ($element) { if ($element) {
getLines(); getLines();
renderCalendar(); renderCalendar();
panToSelected();
} }
}); });
return that; return that;
@ -1107,7 +1128,7 @@ Ox.Calendar = function(options, self) {
that.removeEvent = function() { that.removeEvent = function() {
Ox.print('REMOVE ... SELF.OPTIONS', self.options) Ox.print('REMOVE ... SELF.OPTIONS', self.options)
var index = Ox.getPositionById(self.options.events, self.selected); var index = Ox.getPositionById(self.options.events, self.options.selected);
self.options.events.splice(index, 1); self.options.events.splice(index, 1);
getLines(); getLines();
renderCalendar(); renderCalendar();
@ -1118,7 +1139,6 @@ Ox.Calendar = function(options, self) {
self.options.width = that.width(); self.options.width = that.width();
self.options.height = that.height(); self.options.height = that.height();
self.$zoomInput.options({size: self.options.width}); self.$zoomInput.options({size: self.options.width});
getLines();
renderCalendar(); renderCalendar();
return that; return that;
}; };

View file

@ -26,17 +26,11 @@ Ox.ListCalendar = function(options, self) {
height: self.options.height + 'px' height: self.options.height + 'px'
}); });
self.durationCache = {};
Ox.print('EVENT[0]', self.options.events[0]) Ox.print('EVENT[0]', self.options.events[0])
self.columns = [ self.columns = [
{
addable: false, // fixme: implement
id: 'id',
title: 'Id',
unique: true,
visible: false,
width: 64
},
{ {
id: 'name', id: 'name',
operator: '+', operator: '+',
@ -68,6 +62,9 @@ Ox.ListCalendar = function(options, self) {
}, },
{ {
id: 'start', id: 'start',
map: function(value) {
return Ox.parseDate(value);
},
operator: '-', operator: '-',
title: 'Start', title: 'Start',
visible: true, visible: true,
@ -75,17 +72,32 @@ Ox.ListCalendar = function(options, self) {
}, },
{ {
id: 'end', id: 'end',
map: function(value) {
return Ox.parseDate(value);
},
operator: '-', operator: '-',
title: 'End', title: 'End',
visible: true, visible: true,
width: 144 width: 144
}, },
{ {
id: 'duration', format: function(value, data) {
// return Ox.formatDateRangeDuration(data.start, data.end, true);
var key = data.start + ' - ' + data.end;
if (!self.durationCache[key]) {
self.durationCache[key] = Ox.formatDateRangeDuration(data.start, data.end, true);
}
return self.durationCache[key];
},
id: 'id',
map: function(value, data) {
return Ox.parseDate(data.end) - Ox.parseDate(data.start);
},
operator: '-', operator: '-',
title: 'Duration', title: 'Duration',
unique: true,
visible: true, visible: true,
width: 144 width: 256
}, },
{ {
id: 'user', id: 'user',
@ -172,14 +184,16 @@ Ox.ListCalendar = function(options, self) {
columns: self.columns, columns: self.columns,
columnsRemovable: true, columnsRemovable: true,
columnsVisible: true, columnsVisible: true,
//items: Ox.clone(self.options.places), // we have to clone so that when self.options.events changes,
items: self.options.events, // self.$list.options({items: self.options.events}) still
// registers as a change
items: Ox.clone(self.options.events, true),
pageLength: self.options.pageLength, pageLength: self.options.pageLength,
scrollbarVisible: true, scrollbarVisible: true,
sort: self.options.sort sort: self.options.sort
}) })
.bindEvent({ .bindEvent({
'delete': removeItem, 'delete': removeEvent,
init: initList, // fixme: won't fire from static list init: initList, // fixme: won't fire from static list
key_0: function() { key_0: function() {
self.$calendar.panToEvent(); self.$calendar.panToEvent();
@ -215,7 +229,7 @@ Ox.ListCalendar = function(options, self) {
self.$calendar = Ox.Calendar({ self.$calendar = Ox.Calendar({
date: new Date(0), date: new Date(0),
events: self.options.events, events: Ox.clone(self.options.events, true),
height: self.options.height, height: self.options.height,
width: self.options.width - 514, width: self.options.width - 514,
zoom: 4 zoom: 4
@ -446,6 +460,8 @@ Ox.ListCalendar = function(options, self) {
Ox.print('ADD', self.$calendar.getBounds()) Ox.print('ADD', self.$calendar.getBounds())
var bounds = self.$calendar.getBounds(), var bounds = self.$calendar.getBounds(),
middle = +self.$calendar.options('date'), middle = +self.$calendar.options('date'),
startTime = +new Date((+bounds.startTime + middle) / 2),
endTime = +new Date((+bounds.endTime + middle) / 2),
event = {}, event = {},
i = 1; i = 1;
event.name = 'Untitled'; event.name = 'Untitled';
@ -454,50 +470,53 @@ Ox.ListCalendar = function(options, self) {
}; };
event.alternativeNames = []; event.alternativeNames = [];
event.type = 'other'; event.type = 'other';
event.startTime = +new Date((+bounds.startTime + middle) / 2); event.start = Ox.formatDate(startTime, '%Y-%m-%d %H:%M:%S', true);
event.endTime = +new Date((+bounds.endTime + middle) / 2); event.end = Ox.formatDate(endTime, '%Y-%m-%d %H:%M:%S', true);
event.start = Ox.formatDate(event.startTime, '%Y-%m-%d %H:%M:%S', true);
event.end = Ox.formatDate(event.endTime, '%Y-%m-%d %H:%M:%S', true);
Ox.print(event); Ox.print(event);
self.options.addEvent(event, function(result) { self.options.addEvent(event, function(result) {
event.id = result.data.id; if (result.status.code == '200') {
self.options.events.push(event); event.id = result.data.id;
self.$list.options({ self.options.events.push(event);
items: Ox.clone(self.options.events), var time0 = +new Date()
selected: [event.id] self.$list.options({items: Ox.clone(self.options.events, true)});
}); Ox.print('TIME TO SET LIST OPTIONS:', +new Date() - time0);
self.$calendar.addEvent(event); self.$calendar.addEvent(event);
// fixme: duplicated selectEvent(event);
self.selectedEvent = event.id; self.$nameInput.focusInput();
self.$eventName.options({title: event.name}); } else {
self.$eventTitle.show(); alert(result.status.text);
self.$eventForm.values(Ox.extend({}, event, { }
end: event.current ? '' : event.end
})).show();
self.$removeEventButton.show();
}); });
} }
function editEvent(key, value) { function editEvent(key, value) {
var data = {id: self.selectedEvent}; var id = self.selectedEvent,
index = Ox.getPositionById(self.options.events, id),
data = {id: id};
data[key] = value; data[key] = value;
if (['start', 'end'].indexOf(key) > -1) {
self.$durationInput.options({
value: Ox.formatDateRangeDuration(
self.$startInput.options('value'),
self.$endInput.options('value')
|| Ox.formatDate(new Date(), '%Y-%m-%d %H%:%M:%S'),
true
)
});
}
if (['name', 'type', 'start', 'end'].indexOf(key) > -1) {
self.$calendar.editEvent(self.selectedEvent, key, value);
}
self.options.editEvent(data, function(result) { self.options.editEvent(data, function(result) {
// ... if (result.status.code == 200) {
self.options.events[index][key] = value;
self.$list.value(id, key, value);
if (['name', 'type', 'start', 'end'].indexOf(key) > -1) {
self.$calendar.editEvent(id, key, value);
}
if (key == 'name') {
self.$eventName.options({title: value});
} else if (['start', 'end'].indexOf(key) > -1) {
self.$durationInput.options({
value: Ox.formatDateRangeDuration(
self.$startInput.options('value'),
self.$endInput.options('value')
|| Ox.formatDate(new Date(), '%Y-%m-%d %H%:%M:%S'),
true
)
});
}
} else {
alert(result.status.text);
}
}); });
} }
function initList(data) { function initList(data) {
@ -528,26 +547,22 @@ Ox.ListCalendar = function(options, self) {
} }
function removeEvent() { function removeEvent() {
self.options.removeEvent({id: self.selectedEvent}, function(result) { var id = self.selectedEvent,
var index = Ox.getPositionById(self.options.events, self.selectedEvent); index = Ox.getPositionById(self.options.events, id);
self.options.events.splice(index, 1); self.options.removeEvent({id: id}, function(result) {
self.$list.options({items: Ox.clone(self.options.events)}); if (result.status.code == '200') {
self.$calendar.removeEvent(); self.options.events.splice(index, 1);
// fixme: duplicated var time0 = +new Date();
self.selectedEvent = null; self.$list.options({items: Ox.clone(self.options.events, true)});
self.$eventTitle.hide(); Ox.print('TIME TO SET LIST OPTIONS:', +new Date() - time0);
self.$eventForm.hide(); self.$calendar.removeEvent();
self.$removeEventButton.hide(); selectEvent({});
} else {
alert(result.status.text);
}
}); });
} }
function removeItem(data) {
var id = data.ids[0];
// fixme: events or callback functions??
that.triggerEvent('removeevent', {id: id});
self.$calendar.removeEvent(id);
}
function selectEvent(event) { function selectEvent(event) {
self.$list.options({ self.$list.options({
selected: event.id ? [event.id] : [] selected: event.id ? [event.id] : []
@ -576,24 +591,35 @@ Ox.ListCalendar = function(options, self) {
} }
function updateList(key, value) { function updateList(key, value) {
var query = { var events;
conditions: Ox.merge( if (value === '') {
events = Ox.clone(self.options.events);
} else {
events = [];
self.options.events.forEach(function(event) {
if ((
['all', 'name'].indexOf(key) > -1 ['all', 'name'].indexOf(key) > -1
? [{key: 'name', value: value, operator: '='}] : [], && event.name.toLowerCase().indexOf(value) > -1
) || (
['all', 'alternativeNames'].indexOf(key) > -1 ['all', 'alternativeNames'].indexOf(key) > -1
? [{key: 'alternativeNames', value: value, operator: '='}] : [] && event.alternativeNames.join('\n').toLowerCase().indexOf(value) > -1
), )) {
operator: key == 'all' ? '|' : '&' events.push(event)
}; }
self.$list.options({ });
items: function(data, callback) { }
return pandora.api.findEvents(Ox.extend(data, { self.$list.options({items: events});
query: query
}), callback);
}
});
} }
self.setOption = function(key, value) {
if (key == 'height') {
// fixme: should be .resizeList
self.$list.size();
} else if (key == 'width') {
self.$calendar.resizeCalendar();
}
};
return that; return that;
}; };

View file

@ -138,6 +138,7 @@ Ox.Form = function(options, self) {
//Ox.print('VALUES', values) //Ox.print('VALUES', values)
return values; return values;
} else { } else {
Ox.print('SET FORM VALUES', arguments[0])
Ox.forEach(arguments[0], function(value, key) { Ox.forEach(arguments[0], function(value, key) {
var index = getItemIndexById(key); var index = getItemIndexById(key);
//index > -1 && Ox.print(':::::::', key, value) //index > -1 && Ox.print(':::::::', key, value)

View file

@ -43,11 +43,12 @@ Ox.Select = function(options, self) {
size: 'medium', size: 'medium',
title: '', title: '',
type: 'text', // can be 'text' or 'image' type: 'text', // can be 'text' or 'image'
value: [], value: '',
width: 'auto' width: 'auto'
}) })
// fixme: make default selection restorable // fixme: make default selection restorable
// or allow for extra action items below options // or allow for extra action items below options
// fixme: passing value has no effect
.options(options) .options(options)
.addClass( .addClass(
'OxSelect Ox' + Ox.toTitleCase(self.options.size) + ( 'OxSelect Ox' + Ox.toTitleCase(self.options.size) + (
@ -148,6 +149,7 @@ Ox.Select = function(options, self) {
function changeMenu(data) { function changeMenu(data) {
//Ox.print('clickMenu: ', self.options.id, data) //Ox.print('clickMenu: ', self.options.id, data)
self.checked = self.optionGroup.checked(); self.checked = self.optionGroup.checked();
self.options.value = data.checked[0].id;
self.$title && self.$title.html( self.$title && self.$title.html(
self.options.title ? self.options.title : self.options.title ? self.options.title :
data.checked[0].title data.checked[0].title
@ -177,10 +179,13 @@ Ox.Select = function(options, self) {
self.setOption = function(key, value) { self.setOption = function(key, value) {
if (key == 'value') { if (key == 'value') {
Ox.print('SETTING VALUE OPTION', value)
that.selectItem(value); that.selectItem(value);
} }
}; };
// FIXME: selected() _and_ selectItem() _and_ value() ???
/*@ /*@
selected <f> gets selected item selected <f> gets selected item
() -> <o> returns object of selected items with id, title () -> <o> returns object of selected items with id, title
@ -223,6 +228,8 @@ Ox.Select = function(options, self) {
//Ox.print('selected::', that.selected()) //Ox.print('selected::', that.selected())
return that.selected()[0].id; return that.selected()[0].id;
} else { } else {
that.selectItem(arguments[0]);
return that;
/* /*
Ox.print('ELSE'); Ox.print('ELSE');
that.selectItem(arguments[0]); that.selectItem(arguments[0]);

View file

@ -192,7 +192,8 @@ Ox.List = function(options, self) {
} }
if (!self.isAsync) { if (!self.isAsync) {
self.$page = Ox.Element() self.$pages = [];
self.$pages[0] = Ox.Element()
.addClass('OxPage') .addClass('OxPage')
.css({ .css({
left: self.listMargin / 2 + 'px', left: self.listMargin / 2 + 'px',
@ -426,6 +427,7 @@ Ox.List = function(options, self) {
var height = getHeight(), var height = getHeight(),
lastItemHeight = height % self.options.itemHeight || self.options.itemHeight, lastItemHeight = height % self.options.itemHeight || self.options.itemHeight,
visibleItems = Math.ceil(height / self.options.itemHeight); visibleItems = Math.ceil(height / self.options.itemHeight);
Ox.print('FILL', self.listLength, visibleItems);
if (self.listLength < visibleItems) { if (self.listLength < visibleItems) {
Ox.range(self.listLength, visibleItems).forEach(function(v) { Ox.range(self.listLength, visibleItems).forEach(function(v) {
var $item = Ox.ListItem({ var $item = Ox.ListItem({
@ -685,20 +687,27 @@ Ox.List = function(options, self) {
} }
function loadItems() { function loadItems() {
self.$page.empty(); self.$pages[0].empty();
self.$items = []; self.$items = [];
var timeC = 0, timeA = 0;
self.options.items.forEach(function(item, pos) { self.options.items.forEach(function(item, pos) {
// fixme: duplicated // fixme: duplicated
var time0 = +new Date();
self.$items[pos] = Ox.ListItem({ self.$items[pos] = Ox.ListItem({
construct: self.options.construct, construct: self.options.construct,
data: item, data: item,
position: pos, position: pos,
unique: self.options.unique unique: self.options.unique
}); });
timeC += +new Date() - time0;
isSelected(pos) && self.$items[pos].addClass('OxSelected'); isSelected(pos) && self.$items[pos].addClass('OxSelected');
self.$items[pos].appendTo(self.$page); var time0 = +new Date();
self.$items[pos].appendTo(self.$pages[0]);
timeA += +new Date() - time0;
}); });
fillFirstPage();
self.selected.length && scrollToPosition(self.selected[0]); self.selected.length && scrollToPosition(self.selected[0]);
Ox.print('CONSTRUCT:', timeC, 'APPEND:', timeA);
// that.triggerEvent('init', {items: self.options.items.length}); // that.triggerEvent('init', {items: self.options.items.length});
// fixme: do sync lists need to trigger init? // fixme: do sync lists need to trigger init?
// will this only be reached in sync lists? // will this only be reached in sync lists?
@ -1169,6 +1178,7 @@ Ox.List = function(options, self) {
// fixme: no case where callback is set // fixme: no case where callback is set
// note: can't use selectNone here, // note: can't use selectNone here,
// since it'd trigger a select event // since it'd trigger a select event
Ox.print('SET SELECTED', ids)
var counter = 0; var counter = 0;
self.$items.forEach(function($item, pos) { self.$items.forEach(function($item, pos) {
if (isSelected(pos)) { if (isSelected(pos)) {
@ -1345,7 +1355,7 @@ Ox.List = function(options, self) {
if (!self.isAsync) { if (!self.isAsync) {
selectedIds = getSelectedIds(); selectedIds = getSelectedIds();
self.options.items.forEach(function(item) { self.options.items.forEach(function(item) {
sort[item.id] = map ? map(item[key]) : item[key]; sort[item.id] = map ? map(item[key], item) : item[key];
}); });
self.options.items.sort(function(a, b) { self.options.items.sort(function(a, b) {
var aValue = sort[a.id], var aValue = sort[a.id],
@ -1381,9 +1391,9 @@ Ox.List = function(options, self) {
// fixme: this could be used to change the list // fixme: this could be used to change the list
// from sync to async or vice versa, which wouldn't work // from sync to async or vice versa, which wouldn't work
if (Ox.isArray(value)) { if (Ox.isArray(value)) {
self.listLength = value.length;
updateSelected(); updateSelected();
updateSort(); updateSort();
loadItems();
} else { } else {
updateQuery(); updateQuery();
} }
@ -1538,11 +1548,20 @@ Ox.List = function(options, self) {
() -> <o> the list () -> <o> the list
@*/ @*/
that.reloadPages = function() { that.reloadPages = function() {
var page = self.page; // this is called by TextList when the column layout changes
clear(); var page, scrollLeft, scrollTop;
self.page = page if (!self.isAsync) {
that.$content.empty(); scrollLeft = that.scrollLeft();
loadPages(self.page); scrollTop = that.scrollTop();
loadItems();
that.scrollLeft(scrollLeft).scrollTop(scrollTop);
} else {
page = self.page;
clear();
self.page = page
that.$content.empty();
loadPages(self.page);
}
return that; return that;
}; };

View file

@ -404,30 +404,36 @@ Ox.TextList = function(options, self) {
self.visibleColumns.forEach(function(v, i) { self.visibleColumns.forEach(function(v, i) {
var clickable = Ox.isBoolean(v.clickable) ? v.clickable : v.clickable(data), var clickable = Ox.isBoolean(v.clickable) ? v.clickable : v.clickable(data),
editable = Ox.isBoolean(v.editable) ? v.editable : v.editable(data), editable = Ox.isBoolean(v.editable) ? v.editable : v.editable(data),
$cell;
if (v.tooltip) {
$cell = Ox.Element({ $cell = Ox.Element({
tooltip: v.tooltip ? function() { tooltip: function() {
return self.options.selected.indexOf(data[self.unique]) > -1 return self.options.selected.indexOf(data[self.unique]) > -1
? (Ox.isString(v.tooltip) ? v.tooltip : v.tooltip(data)) : ''; ? (Ox.isString(v.tooltip) ? v.tooltip : v.tooltip(data)) : '';
} : null }
}) });
.addClass( } else {
'OxCell OxColumn' + Ox.toTitleCase(v.id) + // this is faster
(clickable ? ' OxClickable' : '') + $cell = $('<div>');
(editable ? ' OxEditable' : '') }
) $cell.addClass(
.css({ 'OxCell OxColumn' + Ox.toTitleCase(v.id) +
width: (self.columnWidths[i] - (self.options.columnsVisible ? 9 : 8)) + 'px', (clickable ? ' OxClickable' : '') +
borderRightWidth: (self.options.columnsVisible ? 1 : 0) + 'px', (editable ? ' OxEditable' : '')
textAlign: v.align )
}) .css({
.html(v.id in data ? formatValue(v.id, data[v.id], data) : '') width: (self.columnWidths[i] - (self.options.columnsVisible ? 9 : 8)) + 'px',
.appendTo($item); borderRightWidth: (self.options.columnsVisible ? 1 : 0) + 'px',
textAlign: v.align
})
// if the column id is not in data, we're constructing an empty cell
.html(v.id in data ? formatValue(v.id, data[v.id], data) : '')
.appendTo($item);
}); });
return $item; return $item;
} }
function dragstartColumn(id, e) { function dragstartColumn(id, e) {
//Ox.print(that.$body.scrollLeft(), '??')
self.drag = { self.drag = {
columnOffsets: getColumnOffsets(), columnOffsets: getColumnOffsets(),
listOffset: that.$element.offset().left - that.$body.scrollLeft(), listOffset: that.$element.offset().left - that.$body.scrollLeft(),
@ -440,7 +446,6 @@ Ox.TextList = function(options, self) {
self.$heads[self.drag.startPos].addClass('OxDrag').css({ // fixme: why does the class not work? self.$heads[self.drag.startPos].addClass('OxDrag').css({ // fixme: why does the class not work?
cursor: 'move' cursor: 'move'
}); });
//Ox.print('columnOffsets', self.drag.columnOffsets)
} }
function dragColumn(id, e) { function dragColumn(id, e) {
@ -824,6 +829,7 @@ Ox.TextList = function(options, self) {
width: width width: width
}) })
.bind({ .bind({
blur: submit,
mousedown: function(e) { mousedown: function(e) {
// keep mousedown from reaching list // keep mousedown from reaching list
e.stopPropagation(); e.stopPropagation();

View file

@ -65,10 +65,13 @@ Ox.ListMap = function(options, self) {
}, },
id: 'countryCode', id: 'countryCode',
resizable: false, // fixme: implement resizable: false, // fixme: implement
/*
// fixme: why does this not work? it does in folderBrowserList
title: $('<img>').attr({ title: $('<img>').attr({
src: Ox.UI.getImageURL('symbolFlag') src: Ox.UI.getImageURL('symbolFlag')
// fixme: why does this not work? it does in folderBrowserList
}), }),
*/
title: '\u2691',
visible: true, visible: true,
width: 16 width: 16
}, },
@ -92,8 +95,8 @@ Ox.ListMap = function(options, self) {
}, },
{ {
id: 'geoname', id: 'geoname',
map: function(v) { map: function(value) {
var names = v.split(', '); var names = value.split(', ');
if (!Ox.getCountryByGeoname(names[names.length - 1])) { if (!Ox.getCountryByGeoname(names[names.length - 1])) {
names.push('~'); names.push('~');
} }
@ -824,15 +827,13 @@ Ox.ListMap = function(options, self) {
setOption <f> setOption setOption <f> setOption
@*/ @*/
self.setOption = function(key, value) { self.setOption = function(key, value) {
Ox.print('ONCHANGE') if (key == 'height') {
if (key == 'height' || key == 'width') { self.$list.size();
Ox.print('ONCHANGE...') self.$map.resizeMap();
self.$map.options({
height: self.options.height,
width: self.options.width
})
} else if (key == 'selected') { } else if (key == 'selected') {
self.$list.options({selected: value}); self.$list.options({selected: value});
} else if (key == 'width') {
self.$map.resizeMap();
} }
} }

View file

@ -743,14 +743,12 @@ Ox.Map = function(options, self) {
Ox.print('init', mapBounds.getSouthWest(), mapBounds.getNorthEast(), mapBounds.getCenter()) Ox.print('init', mapBounds.getSouthWest(), mapBounds.getNorthEast(), mapBounds.getCenter())
updateFormElements();
self.elevationService = new google.maps.ElevationService(); self.elevationService = new google.maps.ElevationService();
self.geocoder = new google.maps.Geocoder(); self.geocoder = new google.maps.Geocoder();
self.maxZoomService = new google.maps.MaxZoomService(); self.maxZoomService = new google.maps.MaxZoomService();
self.center = mapBounds ? mapBounds.getCenter() : new google.maps.LatLng(0, 0); self.center = mapBounds ? mapBounds.getCenter() : new google.maps.LatLng(0, 0);
self.zoom = 1; // fixme: should depend on height self.zoom = self.minZoom;
that.map = self.map = new google.maps.Map(self.$map.$element[0], { that.map = self.map = new google.maps.Map(self.$map.$element[0], {
center: self.center, center: self.center,
disableDefaultUI: true, disableDefaultUI: true,
@ -772,12 +770,14 @@ Ox.Map = function(options, self) {
selectPlace(self.options.selected, true); selectPlace(self.options.selected, true);
} else { } else {
mapBounds && self.map.fitBounds(mapBounds); mapBounds && self.map.fitBounds(mapBounds);
///*
if (self.map.getZoom() < self.minZoom) { if (self.map.getZoom() < self.minZoom) {
self.map.setZoom(self.minZoom); self.map.setZoom(self.minZoom);
} }
//*/
} }
updateFormElements();
// fixme: this is just guessing
// setTimeout(updateFormElements, 2500);
self.places = []; self.places = [];
if (!self.isAsync) { if (!self.isAsync) {
@ -1239,7 +1239,12 @@ Ox.Map = function(options, self) {
function updateFormElements() { function updateFormElements() {
var width = that.width(); var width = that.width();
self.$zoomInput && constructZoomInput(); if (self.options.zoombar) {
getMaxZoom(function(zoom) {
self.maxZoom = zoom;
constructZoomInput();
});
}
if (self.options.statusbar) { if (self.options.statusbar) {
self.$placeNameInput.options({ self.$placeNameInput.options({
width: Math.floor((width - 132) / 2) width: Math.floor((width - 132) / 2)
@ -1275,9 +1280,9 @@ Ox.Map = function(options, self) {
} }
self.setOption = function(key, value) { self.setOption = function(key, value) {
/*if (key == 'height' || key == 'width') { if (key == 'height' || key == 'width') {
resizeMap(); that.resizeMap();
} else */if (key == 'places') { } else if (key == 'places') {
//fixme: should zoom to new bounds //fixme: should zoom to new bounds
zoom(0); zoom(0);
} else if (key == 'selected') { } else if (key == 'selected') {
@ -1385,7 +1390,6 @@ Ox.Map = function(options, self) {
self.options.width = that.$element.width(); self.options.width = that.$element.width();
self.mapHeight = getMapHeight(); self.mapHeight = getMapHeight();
self.minZoom = getMinZoom(); self.minZoom = getMinZoom();
Ox.print('map w/h', self.options.width, self.options.height)
self.$map.css({ self.$map.css({
height: self.mapHeight + 'px', height: self.mapHeight + 'px',
width: self.options.width + 'px' width: self.options.width + 'px'

View file

@ -297,6 +297,10 @@ Ox.Dialog = function(options, self) {
height: self.options.maxHeight height: self.options.maxHeight
}, true); }, true);
self.maximized = !self.maximized; self.maximized = !self.maximized;
that.triggerEvent('resize', {
width: self.options.width,
height: self.options.height
});
} }
function mousedownLayer() { function mousedownLayer() {
@ -331,6 +335,12 @@ Ox.Dialog = function(options, self) {
left: left, left: left,
top: top top: top
}), animate); }), animate);
/*
that.triggerEvent('resize', {
width: self.options.width,
height: self.options.height
});
*/
} }
function resizestart(event) { function resizestart(event) {
@ -512,6 +522,10 @@ Ox.Dialog = function(options, self) {
function resizeend() { function resizeend() {
that.unwrap(); that.unwrap();
that.triggerEvent('resizeend', {
width: self.options.width,
height: self.options.height
});
} }
function setButtons() { function setButtons() {

View file

@ -111,13 +111,19 @@ Calendar
.OxThemeClassic .OxCalendar .OxLine > .OxEvent { .OxThemeClassic .OxCalendar .OxLine > .OxEvent {
color: rgb(0, 0, 0); color: rgb(0, 0, 0);
} }
.OxThemeClassic .OxCalendar .OxLine > .OxEvent.OxSelected {
box-shadow: inset 0 0 1px rgb(0, 0, 0),
inset 0 0 1px rgb(0, 0, 0),
inset 0 0 1px rgb(0, 0, 0),
inset 0 0 1px rgb(0, 0, 0);
}
.OxThemeClassic .OxCalendar .OxOverlay div:nth-child(even) { .OxThemeClassic .OxCalendar .OxOverlay div:nth-child(even) {
border-top: 1px solid rgba(0, 0, 0, 0.5); background-color: rgba(0, 0, 0, 0.25);
border-bottom: 1px solid rgba(0, 0, 0, 0.5); box-shadow: inset 0 0 2px rgb(0, 0, 0);
} }
.OxThemeClassic .OxCalendar .OxOverlay div:nth-child(odd) { .OxThemeClassic .OxCalendar .OxOverlay div:nth-child(odd) {
background-color: rgba(255, 255, 255, 0.5); background-color: rgba(255, 255, 255, 0.25);
} }
/* /*

View file

@ -110,13 +110,19 @@ Calendar
.OxThemeModern .OxCalendar .OxLine > .OxEvent { .OxThemeModern .OxCalendar .OxLine > .OxEvent {
color: rgb(255, 255, 255); color: rgb(255, 255, 255);
} }
.OxThemeModern .OxCalendar .OxLine > .OxEvent.OxSelected {
box-shadow: inset 0 0 1px rgb(255, 255, 255),
inset 0 0 1px rgb(255, 255, 255),
inset 0 0 1px rgb(255, 255, 255),
inset 0 0 1px rgb(255, 255, 255);
}
.OxThemeModern .OxCalendar .OxOverlay div:nth-child(even) { .OxThemeModern .OxCalendar .OxOverlay div:nth-child(even) {
border-top: 1px solid rgba(255, 255, 255, 0.5); background-color: rgba(255, 255, 255, 0.25);
border-bottom: 1px solid rgba(255, 255, 255, 0.5); box-shadow: inset 0 0 2px rgb(255, 255, 255);
} }
.OxThemeModern .OxCalendar .OxOverlay div:nth-child(odd) { .OxThemeModern .OxCalendar .OxOverlay div:nth-child(odd) {
background-color: rgba(0, 0, 0, 0.5); background-color: rgba(0, 0, 0, 0.25);
} }

View file

@ -279,6 +279,7 @@ Ox.formatDateRange <f> Formats a date range as a string
'Sun, Jan 1, 50 BC, 00:00:00 - 23:59:59' 'Sun, Jan 1, 50 BC, 00:00:00 - 23:59:59'
@*/ @*/
Ox.formatDateRange = function(start, end, utc) { Ox.formatDateRange = function(start, end, utc) {
end = end || Ox.formatDate(new Date(), '%Y-%m-%d');
var isOneUnit = false, var isOneUnit = false,
range = [start, end], range = [start, end],
strings, strings,
@ -370,6 +371,7 @@ Ox.formatDateRangeDuration <f> Formats the duration of a date range as a string
'1 month' '1 month'
@*/ @*/
Ox.formatDateRangeDuration = function(start, end, utc) { Ox.formatDateRangeDuration = function(start, end, utc) {
end = end || Ox.formatDate(new Date(), '%Y-%m-%d');
var date = Ox.parseDate(start, utc), var date = Ox.parseDate(start, utc),
dates = [start, end].map(function(str) { dates = [start, end].map(function(str) {
return Ox.parseDate(str, utc); return Ox.parseDate(str, utc);
@ -380,19 +382,30 @@ Ox.formatDateRangeDuration = function(start, end, utc) {
Ox.forEach(keys, function(key, i) { Ox.forEach(keys, function(key, i) {
while (true) { while (true) {
if (key == 'month') { if (key == 'month') {
// set the day to the same day in the next month,
// or to its last day if the next month is shorter
var day = Ox.getDate(date, utc);
Ox.setDate(date, Math.min( Ox.setDate(date, Math.min(
Ox.getDate(date, utc), day,
Ox.getDaysInMonth( Ox.getDaysInMonth(
Ox.getFullYear(date, utc), Ox.getFullYear(date, utc),
Ox.getMonth(date, utc) + 2 Ox.getMonth(date, utc) + 2,
utc
) )
), utc); ), utc);
} }
// advance the date by one unit
Ox['set' + parts[i]](date, Ox['get' + parts[i]](date, utc) + 1, utc); Ox['set' + parts[i]](date, Ox['get' + parts[i]](date, utc) + 1, utc);
if (date <= dates[1]) { if (date <= dates[1]) {
// still within the range, add one unit
values[i] = (values[i] || 0) + 1; values[i] = (values[i] || 0) + 1;
} else { } else {
// outside the range, rewind the date by one unit
Ox['set' + parts[i]](date, Ox['get' + parts[i]](date, utc) - 1, utc); Ox['set' + parts[i]](date, Ox['get' + parts[i]](date, utc) - 1, utc);
if (key == 'month') {
// and revert to original day
Ox.setDate(date, day, utc);
}
break; break;
} }
} }