From d7507ee5aba95ecccd61410d75918a49f26f3a4d Mon Sep 17 00:00:00 2001 From: rlx <0x0073@0x2620.org> Date: Mon, 10 Oct 2011 08:39:20 +0000 Subject: [PATCH 01/17] update calendar css --- source/Ox.UI/css/Ox.UI.css | 31 +++++++++------------ source/Ox.UI/themes/classic/css/classic.css | 6 ++++ source/Ox.UI/themes/modern/css/modern.css | 6 ++++ 3 files changed, 25 insertions(+), 18 deletions(-) diff --git a/source/Ox.UI/css/Ox.UI.css b/source/Ox.UI/css/Ox.UI.css index 9efcb18b..f594ab98 100644 --- a/source/Ox.UI/css/Ox.UI.css +++ b/source/Ox.UI/css/Ox.UI.css @@ -212,6 +212,7 @@ Calendar white-space: nowrap; } .OxCalendar .OxLine > .OxEvent { + //box-shadow: inset 0 0 1px rgba(0, 0, 0, 0.5); border-radius: 4px; } .OxCalendar .OxLine > .OxEvent.OxCurrent { @@ -219,30 +220,24 @@ Calendar border-bottom-right-radius: 0; } .OxCalendar .OxLine > .OxEvent.OxDate { - background: -moz-linear-gradient(top, rgba(192, 0, 0, 0.9), rgba(160, 0, 0, 0.9)); - background: -o-linear-gradient(top, rgba(192, 0, 0, 0.9), rgba(160, 0, 0, 0.9)); - background: -webkit-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(96, 96, 192, 0.9), rgba(64, 64, 160, 0.9)); + background: -webkit-linear-gradient(top, rgba(96, 96, 192, 0.9), rgba(64, 64, 160, 0.9)); } .OxCalendar .OxLine > .OxEvent.OxPlace { - background: -moz-linear-gradient(top, rgba(255, 192, 0, 0.9), rgba(224, 160, 0, 0.9)); - background: -o-linear-gradient(top, rgba(255, 192, 0, 0.9), rgba(224, 160, 0, 0.9)); - background: -webkit-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(0, 128, 96, 0.9), rgba(0, 96, 64, 0.9)); + background: -webkit-linear-gradient(top, rgba(0, 128, 96, 0.9), rgba(0, 96, 64, 0.9)); } .OxCalendar .OxLine > .OxEvent.OxPerson { - background: -moz-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, 80, 0, 0.9)); - background: -webkit-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, 64, 0, 0.9)); + background: -webkit-linear-gradient(top, rgba(255, 96, 0, 0.9), rgba(224, 64, 0, 0.9)); } .OxCalendar .OxLine > .OxEvent.OxOther { - background: -moz-linear-gradient(top, rgba(255, 0, 0, 0.9), rgba(224, 0, 0, 0.9)); - background: -o-linear-gradient(top, rgba(255, 0, 0, 0.9), rgba(224, 0, 0, 0.9)); - background: -webkit-linear-gradient(top, rgba(255, 0, 0, 0.9), rgba(224, 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)); + background: -moz-linear-gradient(top, rgba(192, 32, 32, 0.9), rgba(160, 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(192, 32, 32, 0.9), rgba(160, 0, 0, 0.9)); } .OxCalendar .OxTimeline { diff --git a/source/Ox.UI/themes/classic/css/classic.css b/source/Ox.UI/themes/classic/css/classic.css index 42761923..17a383e7 100644 --- a/source/Ox.UI/themes/classic/css/classic.css +++ b/source/Ox.UI/themes/classic/css/classic.css @@ -111,6 +111,12 @@ Calendar .OxThemeClassic .OxCalendar .OxLine > .OxEvent { 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) { border-top: 1px solid rgba(0, 0, 0, 0.5); diff --git a/source/Ox.UI/themes/modern/css/modern.css b/source/Ox.UI/themes/modern/css/modern.css index 3e4f3750..6af8e43e 100644 --- a/source/Ox.UI/themes/modern/css/modern.css +++ b/source/Ox.UI/themes/modern/css/modern.css @@ -110,6 +110,12 @@ Calendar .OxThemeModern .OxCalendar .OxLine > .OxEvent { 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) { border-top: 1px solid rgba(255, 255, 255, 0.5); From 96d03fc3860b9f621f4c55f5c04b29546947c8f5 Mon Sep 17 00:00:00 2001 From: rlx <0x0073@0x2620.org> Date: Mon, 10 Oct 2011 09:43:07 +0000 Subject: [PATCH 02/17] allow for selection of calendar events that are outside the current view --- source/Ox.UI/js/Calendar/Ox.Calendar.js | 31 ++++++++++++++++++------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/source/Ox.UI/js/Calendar/Ox.Calendar.js b/source/Ox.UI/js/Calendar/Ox.Calendar.js index b1dd7ab1..2c63b77f 100644 --- a/source/Ox.UI/js/Calendar/Ox.Calendar.js +++ b/source/Ox.UI/js/Calendar/Ox.Calendar.js @@ -633,14 +633,23 @@ Ox.Calendar = function(options, self) { 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() { self.lineEvents = []; self.$content.find('.OxLine').remove(); self.options.events.filter(function(event) { // 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 - /*&& overlaps(event, calendarEvent)*/; + return self.options.showTypes.indexOf(event.type) > -1; }).sort(function(a, b) { // sort events (dates first, people last, longer before shorter) if (a.type == 'date' && b.type != 'date') { @@ -858,16 +867,17 @@ Ox.Calendar = function(options, self) { marginLeft: -delta / getScrollbarFactor() + 'px' }, ms); if (!Ox.isUndefined(line)) { - scrollTo(line * 16 + 8 - self.$container.height() / 2, true); + scrollTo((line + 1) * 16 - self.$container.height() / 2, true); } }; function panToSelected() { // fixme: '0' should zoom to selected if selected is already centered // (both horizontally and vertically, the latter is a bit more work) + var event = getSelectedEvent(); self.options.selected !== '' && panTo( - getEventCenter(getSelectedEvent()), - getSelectedEventElement().data('line') + getEventCenter(event), + getEventLine(event.id) ); } @@ -900,7 +910,7 @@ Ox.Calendar = function(options, self) { event.id == self.options.selected || overlaps(event, calendarEvent) ) { - getEventElement(event).data({line: line}).appendTo(self.$lines[line]); + getEventElement(event).appendTo(self.$lines[line]); } }); }); @@ -978,7 +988,12 @@ Ox.Calendar = function(options, self) { self.$content.find('.OxSelected').removeClass('OxSelected'); if (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' that.triggerEvent('select', Ox.getObjectById(self.options.events, id)); } else { From d2972cd5268f68282c4bf32c8f1d7574465f240b Mon Sep 17 00:00:00 2001 From: rlx <0x0073@0x2620.org> Date: Mon, 10 Oct 2011 12:38:54 +0000 Subject: [PATCH 03/17] more functionality for ListCalendar --- source/Ox.UI/js/Calendar/Ox.Calendar.js | 4 +- source/Ox.UI/js/Calendar/Ox.ListCalendar.js | 102 ++++++++++---------- source/Ox.UI/js/List/Ox.List.js | 2 +- source/Ox.UI/js/Map/Ox.ListMap.js | 4 +- source/Ox/js/Format.js | 2 + 5 files changed, 61 insertions(+), 53 deletions(-) diff --git a/source/Ox.UI/js/Calendar/Ox.Calendar.js b/source/Ox.UI/js/Calendar/Ox.Calendar.js index 2c63b77f..5afb8db4 100644 --- a/source/Ox.UI/js/Calendar/Ox.Calendar.js +++ b/source/Ox.UI/js/Calendar/Ox.Calendar.js @@ -586,7 +586,7 @@ Ox.Calendar = function(options, self) { event.rangeText = Ox.formatDateRange(event.start, event.end, true); event.durationText = Ox.formatDateRangeDuration(event.start, event.end, true); if (event.current) { - event.rangeText = event.rangeText.split(' - ').shift() + ' - ...'; + event.rangeText = event.rangeText.split(' - ').shift() + ' - now'; } return event; } @@ -1068,6 +1068,7 @@ Ox.Calendar = function(options, self) { that.addEvent = function(event) { Ox.print('CALENDAR ADD EVENT', event) + event = getEventData(event); self.options.events.push(event); getLines(); renderCalendar(); @@ -1106,6 +1107,7 @@ Ox.Calendar = function(options, self) { if ($element) { getLines(); renderCalendar(); + panToSelected(); } }); return that; diff --git a/source/Ox.UI/js/Calendar/Ox.ListCalendar.js b/source/Ox.UI/js/Calendar/Ox.ListCalendar.js index a7dee2cf..99c0a1e5 100644 --- a/source/Ox.UI/js/Calendar/Ox.ListCalendar.js +++ b/source/Ox.UI/js/Calendar/Ox.ListCalendar.js @@ -29,14 +29,6 @@ Ox.ListCalendar = function(options, self) { Ox.print('EVENT[0]', self.options.events[0]) self.columns = [ - { - addable: false, // fixme: implement - id: 'id', - title: 'Id', - unique: true, - visible: false, - width: 64 - }, { id: 'name', operator: '+', @@ -67,25 +59,48 @@ Ox.ListCalendar = function(options, self) { width: 64 }, { + /* + format: function(value, data) { + return Ox.formatDateRange(data.start, data.end, true).split(' - ')[0]; + }, + */ id: 'start', + map: function(value) { + return Ox.parseDate(value); + }, operator: '-', title: 'Start', visible: true, width: 144 }, { + /* + format: function(value, data) { + return Ox.formatDateRange(data.start, data.end, true).split(' - ')[1]; + }, + */ id: 'end', + map: function(value) { + return Ox.parseDate(value); + }, operator: '-', title: 'End', visible: true, width: 144 }, { - id: 'duration', + format: function(value, data) { + return Ox.formatDateRangeDuration(data.start, data.end, true); + }, + id: 'id', + map: function(value, data) { + return Ox.parseDate(data.end) - Ox.parseDate(data.start); + }, operator: '-', title: 'Duration', + unique: true, visible: true, - width: 144 + width: 256 }, { id: 'user', @@ -172,14 +187,16 @@ Ox.ListCalendar = function(options, self) { columns: self.columns, columnsRemovable: true, columnsVisible: true, - //items: Ox.clone(self.options.places), - items: self.options.events, + // we have to clone so that when self.options.events changes, + // self.$list.options({items: self.options.events}) still + // registers as a change + items: Ox.clone(self.options.events, true), pageLength: self.options.pageLength, scrollbarVisible: true, sort: self.options.sort }) .bindEvent({ - 'delete': removeItem, + 'delete': removeEvent, init: initList, // fixme: won't fire from static list key_0: function() { self.$calendar.panToEvent(); @@ -215,7 +232,7 @@ Ox.ListCalendar = function(options, self) { self.$calendar = Ox.Calendar({ date: new Date(0), - events: self.options.events, + events: Ox.clone(self.options.events, true), height: self.options.height, width: self.options.width - 514, zoom: 4 @@ -446,6 +463,8 @@ Ox.ListCalendar = function(options, self) { Ox.print('ADD', self.$calendar.getBounds()) var bounds = self.$calendar.getBounds(), middle = +self.$calendar.options('date'), + startTime = +new Date((+bounds.startTime + middle) / 2), + endTime = +new Date((+bounds.endTime + middle) / 2), event = {}, i = 1; event.name = 'Untitled'; @@ -454,32 +473,25 @@ Ox.ListCalendar = function(options, self) { }; event.alternativeNames = []; event.type = 'other'; - event.startTime = +new Date((+bounds.startTime + middle) / 2); - event.endTime = +new Date((+bounds.endTime + middle) / 2); - 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); + event.start = Ox.formatDate(startTime, '%Y-%m-%d %H:%M:%S', true); + event.end = Ox.formatDate(endTime, '%Y-%m-%d %H:%M:%S', true); Ox.print(event); self.options.addEvent(event, function(result) { event.id = result.data.id; self.options.events.push(event); - self.$list.options({ - items: Ox.clone(self.options.events), - selected: [event.id] - }); + self.$list.options({items: Ox.clone(self.options.events, true)}); self.$calendar.addEvent(event); - // fixme: duplicated - self.selectedEvent = event.id; - self.$eventName.options({title: event.name}); - self.$eventTitle.show(); - self.$eventForm.values(Ox.extend({}, event, { - end: event.current ? '' : event.end - })).show(); - self.$removeEventButton.show(); + selectEvent(event); }); } function editEvent(key, value) { - var data = {id: self.selectedEvent}; + var id = self.selectedEvent, + index = Ox.getPositionById(self.options.events, id), + data = {id: id}; + self.options.events[index][key] = value; + //Ox.print('EQUAL?', Ox.isEqual(self.$list.options('items'), self.options.events)); + //alert(self.options.events[index][key] + '\n' + self.$list.options('items')[index][key]); data[key] = value; if (['start', 'end'].indexOf(key) > -1) { self.$durationInput.options({ @@ -491,8 +503,9 @@ Ox.ListCalendar = function(options, self) { ) }); } + self.$list.options({items: Ox.clone(self.options.events, true)}); if (['name', 'type', 'start', 'end'].indexOf(key) > -1) { - self.$calendar.editEvent(self.selectedEvent, key, value); + self.$calendar.editEvent(id, key, value); } self.options.editEvent(data, function(result) { // ... @@ -528,26 +541,17 @@ Ox.ListCalendar = function(options, self) { } function removeEvent() { - self.options.removeEvent({id: self.selectedEvent}, function(result) { - var index = Ox.getPositionById(self.options.events, self.selectedEvent); - self.options.events.splice(index, 1); - self.$list.options({items: Ox.clone(self.options.events)}); - self.$calendar.removeEvent(); - // fixme: duplicated - self.selectedEvent = null; - self.$eventTitle.hide(); - self.$eventForm.hide(); - self.$removeEventButton.hide(); + var id = self.selectedEvent, + index = Ox.getPositionById(self.options.events, id); + self.options.events.splice(index, 1); + self.$list.options({items: Ox.clone(self.options.events, true)}); + self.$calendar.removeEvent(); + selectEvent({}); + self.options.removeEvent({id: id}, function(result) { + // ... }); } - 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) { self.$list.options({ selected: event.id ? [event.id] : [] diff --git a/source/Ox.UI/js/List/Ox.List.js b/source/Ox.UI/js/List/Ox.List.js index c1670dad..d9b9bd74 100644 --- a/source/Ox.UI/js/List/Ox.List.js +++ b/source/Ox.UI/js/List/Ox.List.js @@ -1345,7 +1345,7 @@ Ox.List = function(options, self) { if (!self.isAsync) { selectedIds = getSelectedIds(); 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) { var aValue = sort[a.id], diff --git a/source/Ox.UI/js/Map/Ox.ListMap.js b/source/Ox.UI/js/Map/Ox.ListMap.js index c4143566..7ec45eff 100644 --- a/source/Ox.UI/js/Map/Ox.ListMap.js +++ b/source/Ox.UI/js/Map/Ox.ListMap.js @@ -92,8 +92,8 @@ Ox.ListMap = function(options, self) { }, { id: 'geoname', - map: function(v) { - var names = v.split(', '); + map: function(value) { + var names = value.split(', '); if (!Ox.getCountryByGeoname(names[names.length - 1])) { names.push('~'); } diff --git a/source/Ox/js/Format.js b/source/Ox/js/Format.js index 2ff2e914..839e59d8 100644 --- a/source/Ox/js/Format.js +++ b/source/Ox/js/Format.js @@ -279,6 +279,7 @@ Ox.formatDateRange Formats a date range as a string 'Sun, Jan 1, 50 BC, 00:00:00 - 23:59:59' @*/ Ox.formatDateRange = function(start, end, utc) { + end = end || Ox.formatDate(new Date(), '%Y-%m-%d'); var isOneUnit = false, range = [start, end], strings, @@ -370,6 +371,7 @@ Ox.formatDateRangeDuration Formats the duration of a date range as a string '1 month' @*/ Ox.formatDateRangeDuration = function(start, end, utc) { + end = end || Ox.formatDate(new Date(), '%Y-%m-%d'); var date = Ox.parseDate(start, utc), dates = [start, end].map(function(str) { return Ox.parseDate(str, utc); From 46ef208be2357ee837d11ef4b52fc3b8ed47e3e5 Mon Sep 17 00:00:00 2001 From: rlx <0x0073@0x2620.org> Date: Mon, 10 Oct 2011 14:09:13 +0000 Subject: [PATCH 04/17] fix a bug that would slow down reload of static lists when passing a new items array --- source/Ox.UI/js/List/Ox.List.js | 1 - 1 file changed, 1 deletion(-) diff --git a/source/Ox.UI/js/List/Ox.List.js b/source/Ox.UI/js/List/Ox.List.js index d9b9bd74..2ad27914 100644 --- a/source/Ox.UI/js/List/Ox.List.js +++ b/source/Ox.UI/js/List/Ox.List.js @@ -1383,7 +1383,6 @@ Ox.List = function(options, self) { if (Ox.isArray(value)) { updateSelected(); updateSort(); - loadItems(); } else { updateQuery(); } From ccece375c025958ce9bf733b49afcf16c32da80a Mon Sep 17 00:00:00 2001 From: rlx <0x0073@0x2620.org> Date: Mon, 10 Oct 2011 17:00:01 +0000 Subject: [PATCH 05/17] fix a corner case in Ox.formatDateRangeDuration() --- source/Ox.UI/js/Calendar/Ox.Calendar.js | 6 +++--- source/Ox.UI/js/Calendar/Ox.ListCalendar.js | 15 ++++++++------- source/Ox.UI/js/Form/Ox.Select.js | 3 +++ source/Ox/js/Format.js | 16 ++++++++++++++-- 4 files changed, 28 insertions(+), 12 deletions(-) diff --git a/source/Ox.UI/js/Calendar/Ox.Calendar.js b/source/Ox.UI/js/Calendar/Ox.Calendar.js index 5afb8db4..3fee5e62 100644 --- a/source/Ox.UI/js/Calendar/Ox.Calendar.js +++ b/source/Ox.UI/js/Calendar/Ox.Calendar.js @@ -46,9 +46,6 @@ Ox.Calendar = function(options, self) { //height: self.options.height + 'px' }) .bindEvent({ - anyclick: function(e) { - !$(e.target).is('.OxInput') && that.gainFocus(); - }, key_0: function() { panToSelected(); }, @@ -81,6 +78,9 @@ Ox.Calendar = function(options, self) { }, key_up: function() { scrollBy(-1); + }, + mousedown: function(e) { + !$(e.target).is('.OxInput') && that.gainFocus(); } }); diff --git a/source/Ox.UI/js/Calendar/Ox.ListCalendar.js b/source/Ox.UI/js/Calendar/Ox.ListCalendar.js index 99c0a1e5..dcb3a3f1 100644 --- a/source/Ox.UI/js/Calendar/Ox.ListCalendar.js +++ b/source/Ox.UI/js/Calendar/Ox.ListCalendar.js @@ -490,10 +490,14 @@ Ox.ListCalendar = function(options, self) { index = Ox.getPositionById(self.options.events, id), data = {id: id}; self.options.events[index][key] = value; - //Ox.print('EQUAL?', Ox.isEqual(self.$list.options('items'), self.options.events)); - //alert(self.options.events[index][key] + '\n' + self.$list.options('items')[index][key]); data[key] = value; - if (['start', 'end'].indexOf(key) > -1) { + self.$list.options({items: Ox.clone(self.options.events, true)}); + 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'), @@ -503,10 +507,7 @@ Ox.ListCalendar = function(options, self) { ) }); } - self.$list.options({items: Ox.clone(self.options.events, true)}); - if (['name', 'type', 'start', 'end'].indexOf(key) > -1) { - self.$calendar.editEvent(id, key, value); - } + self.options.editEvent(data, function(result) { // ... }); diff --git a/source/Ox.UI/js/Form/Ox.Select.js b/source/Ox.UI/js/Form/Ox.Select.js index cc2dd4b9..c115aad6 100644 --- a/source/Ox.UI/js/Form/Ox.Select.js +++ b/source/Ox.UI/js/Form/Ox.Select.js @@ -177,6 +177,7 @@ Ox.Select = function(options, self) { self.setOption = function(key, value) { if (key == 'value') { + Ox.print('SETTING VALUE OPTION', value) that.selectItem(value); } }; @@ -223,6 +224,8 @@ Ox.Select = function(options, self) { //Ox.print('selected::', that.selected()) return that.selected()[0].id; } else { + that.selectItem(arguments[0]); + return that; /* Ox.print('ELSE'); that.selectItem(arguments[0]); diff --git a/source/Ox/js/Format.js b/source/Ox/js/Format.js index 839e59d8..ca0fef5a 100644 --- a/source/Ox/js/Format.js +++ b/source/Ox/js/Format.js @@ -382,19 +382,31 @@ Ox.formatDateRangeDuration = function(start, end, utc) { Ox.forEach(keys, function(key, i) { while (true) { 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.getDate(date, utc), + day, Ox.getDaysInMonth( Ox.getFullYear(date, utc), - Ox.getMonth(date, utc) + 2 + Ox.getMonth(date, utc) + 2, + utc ) ), utc); } + // advance the date by one unit Ox['set' + parts[i]](date, Ox['get' + parts[i]](date, utc) + 1, utc); + Ox.print(key, '.....', date) if (date <= dates[1]) { + // still within the range, add one unit values[i] = (values[i] || 0) + 1; } else { + // outside the range, rewind the date by one unit 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; } } From 5948d2c2ce9ccdd668bc2f775183c8a27b2e19ee Mon Sep 17 00:00:00 2001 From: rlx <0x0073@0x2620.org> Date: Mon, 10 Oct 2011 20:48:35 +0000 Subject: [PATCH 06/17] fix a bug with doubleclicking on a calendar to zoom in --- source/Ox.UI/js/Calendar/Ox.Calendar.js | 2 +- source/Ox/js/Format.js | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/source/Ox.UI/js/Calendar/Ox.Calendar.js b/source/Ox.UI/js/Calendar/Ox.Calendar.js index 3fee5e62..1e449121 100644 --- a/source/Ox.UI/js/Calendar/Ox.Calendar.js +++ b/source/Ox.UI/js/Calendar/Ox.Calendar.js @@ -423,7 +423,7 @@ Ox.Calendar = function(options, self) { } else { if (self.options.zoom < self.maxZoom) { self.options.date = new Date( - (+self.options.date + +getMouseDate(e)) / 2 + (+self.options.date + +getMouseDate(data)) / 2 ); self.options.zoom++; } diff --git a/source/Ox/js/Format.js b/source/Ox/js/Format.js index ca0fef5a..14a549e9 100644 --- a/source/Ox/js/Format.js +++ b/source/Ox/js/Format.js @@ -396,7 +396,6 @@ Ox.formatDateRangeDuration = function(start, end, utc) { } // advance the date by one unit Ox['set' + parts[i]](date, Ox['get' + parts[i]](date, utc) + 1, utc); - Ox.print(key, '.....', date) if (date <= dates[1]) { // still within the range, add one unit values[i] = (values[i] || 0) + 1; From 527f75b009368cd1d69f34811ee2afc2def933db Mon Sep 17 00:00:00 2001 From: rlx <0x0073@0x2620.org> Date: Tue, 11 Oct 2011 06:32:20 +0000 Subject: [PATCH 07/17] slightly faster text list construction for cells that don't have tooltips; make calendar layout deterministic for events that have the same time span --- source/Ox.UI/js/Calendar/Ox.Calendar.js | 14 ++++--- source/Ox.UI/js/Calendar/Ox.ListCalendar.js | 8 +++- source/Ox.UI/js/List/Ox.List.js | 6 +++ source/Ox.UI/js/List/Ox.TextList.js | 42 +++++++++++---------- 4 files changed, 44 insertions(+), 26 deletions(-) diff --git a/source/Ox.UI/js/Calendar/Ox.Calendar.js b/source/Ox.UI/js/Calendar/Ox.Calendar.js index 1e449121..8806c1fe 100644 --- a/source/Ox.UI/js/Calendar/Ox.Calendar.js +++ b/source/Ox.UI/js/Calendar/Ox.Calendar.js @@ -583,6 +583,7 @@ Ox.Calendar = function(options, self) { event.id = Ox.isUndefined(event.id) ? Ox.uid() : event.id; event.startTime = Ox.parseDate(event.start, true); event.endTime = Ox.parseDate(event.end, true); + event.durationTime = event.endTime - event.startTime; event.rangeText = Ox.formatDateRange(event.start, event.end, true); event.durationText = Ox.formatDateRangeDuration(event.start, event.end, true); if (event.current) { @@ -651,7 +652,8 @@ Ox.Calendar = function(options, self) { // filter out events with types not shown return self.options.showTypes.indexOf(event.type) > -1; }).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') { return -1; } else if (a.type != 'date' && b.type == 'date') { @@ -660,10 +662,12 @@ Ox.Calendar = function(options, self) { return 1; } else if (a.type != 'person' && b.type == 'person') { return -1; - } else if ((b.endTime - b.startTime) != (a.endTime - a.startTime)) { - return (b.endTime - b.startTime) - (a.endTime - a.startTime); - } else /*if (a.startTime < b.startTime || a.startTime > b.startTime)*/ { + } else if (a.durationTime != b.durationTime) { + return b.durationTime - a.durationTime; + } else if (+a.startTime != +b.startTime) { return a.startTime - b.startTime; + } else { + return a.name < b.name ? -1 : 1; } }).forEach(function(event, i) { var line = self.lineEvents.length; @@ -1124,7 +1128,7 @@ Ox.Calendar = function(options, self) { that.removeEvent = function() { 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); getLines(); renderCalendar(); diff --git a/source/Ox.UI/js/Calendar/Ox.ListCalendar.js b/source/Ox.UI/js/Calendar/Ox.ListCalendar.js index dcb3a3f1..70908959 100644 --- a/source/Ox.UI/js/Calendar/Ox.ListCalendar.js +++ b/source/Ox.UI/js/Calendar/Ox.ListCalendar.js @@ -479,7 +479,9 @@ Ox.ListCalendar = function(options, self) { self.options.addEvent(event, function(result) { event.id = result.data.id; self.options.events.push(event); + var time0 = +new Date() self.$list.options({items: Ox.clone(self.options.events, true)}); + Ox.print('TIME TO SET LIST OPTIONS:', +new Date() - time0); self.$calendar.addEvent(event); selectEvent(event); }); @@ -491,7 +493,9 @@ Ox.ListCalendar = function(options, self) { data = {id: id}; self.options.events[index][key] = value; data[key] = value; + var time0 = +new Date(); self.$list.options({items: Ox.clone(self.options.events, true)}); + Ox.print('TIME TO SET LIST OPTIONS:', +new Date() - time0); if (['name', 'type', 'start', 'end'].indexOf(key) > -1) { self.$calendar.editEvent(id, key, value); } @@ -507,11 +511,9 @@ Ox.ListCalendar = function(options, self) { ) }); } - self.options.editEvent(data, function(result) { // ... }); - } function initList(data) { @@ -545,7 +547,9 @@ Ox.ListCalendar = function(options, self) { var id = self.selectedEvent, index = Ox.getPositionById(self.options.events, id); self.options.events.splice(index, 1); + var time0 = +new Date(); self.$list.options({items: Ox.clone(self.options.events, true)}); + Ox.print('TIME TO SET LIST OPTIONS:', +new Date() - time0); self.$calendar.removeEvent(); selectEvent({}); self.options.removeEvent({id: id}, function(result) { diff --git a/source/Ox.UI/js/List/Ox.List.js b/source/Ox.UI/js/List/Ox.List.js index 2ad27914..fe06a264 100644 --- a/source/Ox.UI/js/List/Ox.List.js +++ b/source/Ox.UI/js/List/Ox.List.js @@ -687,18 +687,24 @@ Ox.List = function(options, self) { function loadItems() { self.$page.empty(); self.$items = []; + var timeC = 0, timeA = 0; self.options.items.forEach(function(item, pos) { // fixme: duplicated + var time0 = +new Date(); self.$items[pos] = Ox.ListItem({ construct: self.options.construct, data: item, position: pos, unique: self.options.unique }); + timeC += +new Date() - time0; isSelected(pos) && self.$items[pos].addClass('OxSelected'); + var time0 = +new Date(); self.$items[pos].appendTo(self.$page); + timeA += +new Date() - time0; }); self.selected.length && scrollToPosition(self.selected[0]); + Ox.print('CONSTRUCT:', timeC, 'APPEND:', timeA); // that.triggerEvent('init', {items: self.options.items.length}); // fixme: do sync lists need to trigger init? // will this only be reached in sync lists? diff --git a/source/Ox.UI/js/List/Ox.TextList.js b/source/Ox.UI/js/List/Ox.TextList.js index 512bcd45..befe04cb 100644 --- a/source/Ox.UI/js/List/Ox.TextList.js +++ b/source/Ox.UI/js/List/Ox.TextList.js @@ -404,30 +404,35 @@ Ox.TextList = function(options, self) { self.visibleColumns.forEach(function(v, i) { var clickable = Ox.isBoolean(v.clickable) ? v.clickable : v.clickable(data), editable = Ox.isBoolean(v.editable) ? v.editable : v.editable(data), + $cell; + if (v.tooltip) { $cell = Ox.Element({ - tooltip: v.tooltip ? function() { - return self.options.selected.indexOf(data[self.unique]) > -1 - ? (Ox.isString(v.tooltip) ? v.tooltip : v.tooltip(data)) : ''; - } : null - }) - .addClass( - 'OxCell OxColumn' + Ox.toTitleCase(v.id) + - (clickable ? ' OxClickable' : '') + - (editable ? ' OxEditable' : '') - ) - .css({ - width: (self.columnWidths[i] - (self.options.columnsVisible ? 9 : 8)) + 'px', - borderRightWidth: (self.options.columnsVisible ? 1 : 0) + 'px', - textAlign: v.align - }) - .html(v.id in data ? formatValue(v.id, data[v.id], data) : '') - .appendTo($item); + tooltip: function() { + return self.options.selected.indexOf(data[self.unique]) > -1 + ? (Ox.isString(v.tooltip) ? v.tooltip : v.tooltip(data)) : ''; + } + }); + } else { + $cell = $('
'); + } + $cell.addClass( + 'OxCell OxColumn' + Ox.toTitleCase(v.id) + + (clickable ? ' OxClickable' : '') + + (editable ? ' OxEditable' : '') + ) + .css({ + width: (self.columnWidths[i] - (self.options.columnsVisible ? 9 : 8)) + 'px', + 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; } function dragstartColumn(id, e) { - //Ox.print(that.$body.scrollLeft(), '??') self.drag = { columnOffsets: getColumnOffsets(), listOffset: that.$element.offset().left - that.$body.scrollLeft(), @@ -440,7 +445,6 @@ Ox.TextList = function(options, self) { self.$heads[self.drag.startPos].addClass('OxDrag').css({ // fixme: why does the class not work? cursor: 'move' }); - //Ox.print('columnOffsets', self.drag.columnOffsets) } function dragColumn(id, e) { From 3fc1611803b4d7b455b95baabf0f0d477a1261b7 Mon Sep 17 00:00:00 2001 From: rlx <0x0073@0x2620.org> Date: Tue, 11 Oct 2011 06:50:02 +0000 Subject: [PATCH 08/17] in listcalendar, when editing, set list item value instead of reloading list --- source/Ox.UI/js/Calendar/Ox.ListCalendar.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/source/Ox.UI/js/Calendar/Ox.ListCalendar.js b/source/Ox.UI/js/Calendar/Ox.ListCalendar.js index 70908959..853f1858 100644 --- a/source/Ox.UI/js/Calendar/Ox.ListCalendar.js +++ b/source/Ox.UI/js/Calendar/Ox.ListCalendar.js @@ -493,9 +493,7 @@ Ox.ListCalendar = function(options, self) { data = {id: id}; self.options.events[index][key] = value; data[key] = value; - var time0 = +new Date(); - self.$list.options({items: Ox.clone(self.options.events, true)}); - Ox.print('TIME TO SET LIST OPTIONS:', +new Date() - time0); + self.$list.value(id, key, value); if (['name', 'type', 'start', 'end'].indexOf(key) > -1) { self.$calendar.editEvent(id, key, value); } From 718ec32e442905cce744dcd49666bc127407ee05 Mon Sep 17 00:00:00 2001 From: rlx <0x0073@0x2620.org> Date: Tue, 11 Oct 2011 07:05:45 +0000 Subject: [PATCH 09/17] in listcalendar, cache formatted duration strings --- source/Ox.UI/js/Calendar/Ox.ListCalendar.js | 69 ++++++++++----------- source/Ox.UI/js/List/Ox.TextList.js | 1 + 2 files changed, 33 insertions(+), 37 deletions(-) diff --git a/source/Ox.UI/js/Calendar/Ox.ListCalendar.js b/source/Ox.UI/js/Calendar/Ox.ListCalendar.js index 853f1858..f4d0c034 100644 --- a/source/Ox.UI/js/Calendar/Ox.ListCalendar.js +++ b/source/Ox.UI/js/Calendar/Ox.ListCalendar.js @@ -26,6 +26,8 @@ Ox.ListCalendar = function(options, self) { height: self.options.height + 'px' }); + self.durationCache = {}; + Ox.print('EVENT[0]', self.options.events[0]) self.columns = [ @@ -59,11 +61,6 @@ Ox.ListCalendar = function(options, self) { width: 64 }, { - /* - format: function(value, data) { - return Ox.formatDateRange(data.start, data.end, true).split(' - ')[0]; - }, - */ id: 'start', map: function(value) { return Ox.parseDate(value); @@ -74,11 +71,6 @@ Ox.ListCalendar = function(options, self) { width: 144 }, { - /* - format: function(value, data) { - return Ox.formatDateRange(data.start, data.end, true).split(' - ')[1]; - }, - */ id: 'end', map: function(value) { return Ox.parseDate(value); @@ -90,7 +82,12 @@ Ox.ListCalendar = function(options, self) { }, { format: function(value, data) { - return Ox.formatDateRangeDuration(data.start, data.end, true); + // 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) { @@ -491,26 +488,25 @@ Ox.ListCalendar = function(options, self) { var id = self.selectedEvent, index = Ox.getPositionById(self.options.events, id), data = {id: id}; - self.options.events[index][key] = value; - data[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 - ) - }); - } self.options.editEvent(data, function(result) { - // ... + self.options.events[index][key] = value; + data[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 + ) + }); + } }); } @@ -544,14 +540,13 @@ Ox.ListCalendar = function(options, self) { function removeEvent() { var id = self.selectedEvent, index = Ox.getPositionById(self.options.events, id); - self.options.events.splice(index, 1); - var time0 = +new Date(); - self.$list.options({items: Ox.clone(self.options.events, true)}); - Ox.print('TIME TO SET LIST OPTIONS:', +new Date() - time0); - self.$calendar.removeEvent(); - selectEvent({}); self.options.removeEvent({id: id}, function(result) { - // ... + self.options.events.splice(index, 1); + var time0 = +new Date(); + self.$list.options({items: Ox.clone(self.options.events, true)}); + Ox.print('TIME TO SET LIST OPTIONS:', +new Date() - time0); + self.$calendar.removeEvent(); + selectEvent({}); }); } diff --git a/source/Ox.UI/js/List/Ox.TextList.js b/source/Ox.UI/js/List/Ox.TextList.js index befe04cb..b8f79e47 100644 --- a/source/Ox.UI/js/List/Ox.TextList.js +++ b/source/Ox.UI/js/List/Ox.TextList.js @@ -413,6 +413,7 @@ Ox.TextList = function(options, self) { } }); } else { + // this is faster $cell = $('
'); } $cell.addClass( From 5a04e4fb8e18394c6d9f34dc3b92d766e6ef9004 Mon Sep 17 00:00:00 2001 From: rlx <0x0073@0x2620.org> Date: Tue, 11 Oct 2011 07:30:01 +0000 Subject: [PATCH 10/17] update calendar css --- source/Ox.UI/css/Ox.UI.css | 4 ++-- source/Ox.UI/themes/classic/css/classic.css | 6 +++--- source/Ox.UI/themes/modern/css/modern.css | 6 +++--- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/source/Ox.UI/css/Ox.UI.css b/source/Ox.UI/css/Ox.UI.css index f594ab98..81003973 100644 --- a/source/Ox.UI/css/Ox.UI.css +++ b/source/Ox.UI/css/Ox.UI.css @@ -222,7 +222,7 @@ Calendar .OxCalendar .OxLine > .OxEvent.OxDate { background: -moz-linear-gradient(top, rgba(96, 96, 192, 0.9), rgba(64, 64, 160, 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(96, 96, 192, 0.9), rgba(64, 64, 160, 0.9)); + background: -webkit-linear-gradient(top, rgba(96, 96, 255, 0.9), rgba(64, 64, 224, 0.9)); } .OxCalendar .OxLine > .OxEvent.OxPlace { background: -moz-linear-gradient(top, rgba(0, 128, 96, 0.9), rgba(0, 96, 64, 0.9)); @@ -263,7 +263,7 @@ Calendar cursor: ew-resize; } .OxCalendar .OxOverlay div:nth-child(even) { - height: 14px; + border-radius: 4px; } .OxCalendar .OxRange .OxArrow { diff --git a/source/Ox.UI/themes/classic/css/classic.css b/source/Ox.UI/themes/classic/css/classic.css index 17a383e7..8fdc9a49 100644 --- a/source/Ox.UI/themes/classic/css/classic.css +++ b/source/Ox.UI/themes/classic/css/classic.css @@ -119,11 +119,11 @@ Calendar } .OxThemeClassic .OxCalendar .OxOverlay div:nth-child(even) { - border-top: 1px solid rgba(0, 0, 0, 0.5); - border-bottom: 1px solid rgba(0, 0, 0, 0.5); + background-color: rgba(0, 0, 0, 0.25); + box-shadow: inset 0 0 2px rgb(0, 0, 0); } .OxThemeClassic .OxCalendar .OxOverlay div:nth-child(odd) { - background-color: rgba(255, 255, 255, 0.5); + background-color: rgba(255, 255, 255, 0.25); } /* diff --git a/source/Ox.UI/themes/modern/css/modern.css b/source/Ox.UI/themes/modern/css/modern.css index 6af8e43e..6bcd4784 100644 --- a/source/Ox.UI/themes/modern/css/modern.css +++ b/source/Ox.UI/themes/modern/css/modern.css @@ -118,11 +118,11 @@ Calendar } .OxThemeModern .OxCalendar .OxOverlay div:nth-child(even) { - border-top: 1px solid rgba(255, 255, 255, 0.5); - border-bottom: 1px solid rgba(255, 255, 255, 0.5); + background-color: rgba(255, 255, 255, 0.25); + box-shadow: inset 0 0 2px rgb(255, 255, 255); } .OxThemeModern .OxCalendar .OxOverlay div:nth-child(odd) { - background-color: rgba(0, 0, 0, 0.5); + background-color: rgba(0, 0, 0, 0.25); } From 9fb30bf1af7a3151cc87c156b6cba22f4c6f1296 Mon Sep 17 00:00:00 2001 From: rlx <0x0073@0x2620.org> Date: Tue, 11 Oct 2011 09:09:20 +0000 Subject: [PATCH 11/17] make find work in listcalendar; fill first page in static text lists with few items; listen to width/height changes in listmap and listcalendar; fix a bug where maps would load without zoombar --- source/Ox.UI/js/Calendar/Ox.ListCalendar.js | 39 +++++++++++++-------- source/Ox.UI/js/List/Ox.List.js | 10 ++++-- source/Ox.UI/js/Map/Ox.ListMap.js | 12 +++---- source/Ox.UI/js/Map/Ox.Map.js | 24 +++++++------ source/Ox.UI/js/Window/Ox.Dialog.js | 4 +++ 5 files changed, 55 insertions(+), 34 deletions(-) diff --git a/source/Ox.UI/js/Calendar/Ox.ListCalendar.js b/source/Ox.UI/js/Calendar/Ox.ListCalendar.js index f4d0c034..f041269a 100644 --- a/source/Ox.UI/js/Calendar/Ox.ListCalendar.js +++ b/source/Ox.UI/js/Calendar/Ox.ListCalendar.js @@ -578,24 +578,35 @@ Ox.ListCalendar = function(options, self) { } function updateList(key, value) { - var query = { - conditions: Ox.merge( + var events; + if (value === '') { + events = Ox.clone(self.options.events); + } else { + events = []; + self.options.events.forEach(function(event) { + if (( ['all', 'name'].indexOf(key) > -1 - ? [{key: 'name', value: value, operator: '='}] : [], + && event.name.toLowerCase().indexOf(value) > -1 + ) || ( ['all', 'alternativeNames'].indexOf(key) > -1 - ? [{key: 'alternativeNames', value: value, operator: '='}] : [] - ), - operator: key == 'all' ? '|' : '&' - }; - self.$list.options({ - items: function(data, callback) { - return pandora.api.findEvents(Ox.extend(data, { - query: query - }), callback); - } - }); + && event.alternativeNames.join('\n').toLowerCase().indexOf(value) > -1 + )) { + events.push(event) + } + }); + } + self.$list.options({items: events}); } + self.setOption = function(key, value) { + if (key == 'height') { + // fixme: should be .resizeList + self.$list.size(); + } else if (key == 'width') { + self.$calendar.resizeCalendar(); + } + }; + return that; }; \ No newline at end of file diff --git a/source/Ox.UI/js/List/Ox.List.js b/source/Ox.UI/js/List/Ox.List.js index fe06a264..3aa38bba 100644 --- a/source/Ox.UI/js/List/Ox.List.js +++ b/source/Ox.UI/js/List/Ox.List.js @@ -192,7 +192,8 @@ Ox.List = function(options, self) { } if (!self.isAsync) { - self.$page = Ox.Element() + self.$pages = []; + self.$pages[0] = Ox.Element() .addClass('OxPage') .css({ left: self.listMargin / 2 + 'px', @@ -426,6 +427,7 @@ Ox.List = function(options, self) { var height = getHeight(), lastItemHeight = height % self.options.itemHeight || self.options.itemHeight, visibleItems = Math.ceil(height / self.options.itemHeight); + Ox.print('FILL', self.listLength, visibleItems); if (self.listLength < visibleItems) { Ox.range(self.listLength, visibleItems).forEach(function(v) { var $item = Ox.ListItem({ @@ -685,7 +687,7 @@ Ox.List = function(options, self) { } function loadItems() { - self.$page.empty(); + self.$pages[0].empty(); self.$items = []; var timeC = 0, timeA = 0; self.options.items.forEach(function(item, pos) { @@ -700,9 +702,10 @@ Ox.List = function(options, self) { timeC += +new Date() - time0; isSelected(pos) && self.$items[pos].addClass('OxSelected'); var time0 = +new Date(); - self.$items[pos].appendTo(self.$page); + self.$items[pos].appendTo(self.$pages[0]); timeA += +new Date() - time0; }); + fillFirstPage(); self.selected.length && scrollToPosition(self.selected[0]); Ox.print('CONSTRUCT:', timeC, 'APPEND:', timeA); // that.triggerEvent('init', {items: self.options.items.length}); @@ -1387,6 +1390,7 @@ Ox.List = function(options, self) { // fixme: this could be used to change the list // from sync to async or vice versa, which wouldn't work if (Ox.isArray(value)) { + self.listLength = value.length; updateSelected(); updateSort(); } else { diff --git a/source/Ox.UI/js/Map/Ox.ListMap.js b/source/Ox.UI/js/Map/Ox.ListMap.js index 7ec45eff..92fcd7d0 100644 --- a/source/Ox.UI/js/Map/Ox.ListMap.js +++ b/source/Ox.UI/js/Map/Ox.ListMap.js @@ -824,15 +824,13 @@ Ox.ListMap = function(options, self) { setOption setOption @*/ self.setOption = function(key, value) { - Ox.print('ONCHANGE') - if (key == 'height' || key == 'width') { - Ox.print('ONCHANGE...') - self.$map.options({ - height: self.options.height, - width: self.options.width - }) + if (key == 'height') { + self.$list.size(); + self.$map.resizeMap(); } else if (key == 'selected') { self.$list.options({selected: value}); + } else if (key == 'width') { + self.$map.resizeMap(); } } diff --git a/source/Ox.UI/js/Map/Ox.Map.js b/source/Ox.UI/js/Map/Ox.Map.js index 78ce7a42..dbc8f8db 100644 --- a/source/Ox.UI/js/Map/Ox.Map.js +++ b/source/Ox.UI/js/Map/Ox.Map.js @@ -743,14 +743,12 @@ Ox.Map = function(options, self) { Ox.print('init', mapBounds.getSouthWest(), mapBounds.getNorthEast(), mapBounds.getCenter()) - updateFormElements(); - self.elevationService = new google.maps.ElevationService(); self.geocoder = new google.maps.Geocoder(); self.maxZoomService = new google.maps.MaxZoomService(); 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], { center: self.center, disableDefaultUI: true, @@ -772,12 +770,14 @@ Ox.Map = function(options, self) { selectPlace(self.options.selected, true); } else { mapBounds && self.map.fitBounds(mapBounds); - ///* if (self.map.getZoom() < self.minZoom) { self.map.setZoom(self.minZoom); } - //*/ } + updateFormElements(); + + // fixme: this is just guessing + // setTimeout(updateFormElements, 2500); self.places = []; if (!self.isAsync) { @@ -1239,7 +1239,12 @@ Ox.Map = function(options, self) { function updateFormElements() { var width = that.width(); - self.$zoomInput && constructZoomInput(); + if (self.options.zoombar) { + getMaxZoom(function(zoom) { + self.maxZoom = zoom; + constructZoomInput(); + }); + } if (self.options.statusbar) { self.$placeNameInput.options({ width: Math.floor((width - 132) / 2) @@ -1275,9 +1280,9 @@ Ox.Map = function(options, self) { } self.setOption = function(key, value) { - /*if (key == 'height' || key == 'width') { - resizeMap(); - } else */if (key == 'places') { + if (key == 'height' || key == 'width') { + that.resizeMap(); + } else if (key == 'places') { //fixme: should zoom to new bounds zoom(0); } else if (key == 'selected') { @@ -1385,7 +1390,6 @@ Ox.Map = function(options, self) { self.options.width = that.$element.width(); self.mapHeight = getMapHeight(); self.minZoom = getMinZoom(); - Ox.print('map w/h', self.options.width, self.options.height) self.$map.css({ height: self.mapHeight + 'px', width: self.options.width + 'px' diff --git a/source/Ox.UI/js/Window/Ox.Dialog.js b/source/Ox.UI/js/Window/Ox.Dialog.js index aa33acbd..f5afbcf5 100644 --- a/source/Ox.UI/js/Window/Ox.Dialog.js +++ b/source/Ox.UI/js/Window/Ox.Dialog.js @@ -512,6 +512,10 @@ Ox.Dialog = function(options, self) { function resizeend() { that.unwrap(); + that.triggerEvent('resizeend', { + width: self.options.width, + height: self.options.height + }); } function setButtons() { From db25eec98b0d57f57e70085526dc0723502a3ff5 Mon Sep 17 00:00:00 2001 From: rlx <0x0073@0x2620.org> Date: Tue, 11 Oct 2011 09:48:24 +0000 Subject: [PATCH 12/17] fix a bug where edited places would not be updated correctly --- source/Ox.UI/js/Calendar/Ox.ListCalendar.js | 20 ++++++++++++-------- source/Ox.UI/js/List/Ox.List.js | 1 + 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/source/Ox.UI/js/Calendar/Ox.ListCalendar.js b/source/Ox.UI/js/Calendar/Ox.ListCalendar.js index f041269a..4a0f1342 100644 --- a/source/Ox.UI/js/Calendar/Ox.ListCalendar.js +++ b/source/Ox.UI/js/Calendar/Ox.ListCalendar.js @@ -474,13 +474,17 @@ Ox.ListCalendar = function(options, self) { event.end = Ox.formatDate(endTime, '%Y-%m-%d %H:%M:%S', true); Ox.print(event); self.options.addEvent(event, function(result) { - event.id = result.data.id; - self.options.events.push(event); - var time0 = +new Date() - self.$list.options({items: Ox.clone(self.options.events, true)}); - Ox.print('TIME TO SET LIST OPTIONS:', +new Date() - time0); - self.$calendar.addEvent(event); - selectEvent(event); + if (result.status.code == '200') { + event.id = result.data.id; + self.options.events.push(event); + var time0 = +new Date() + self.$list.options({items: Ox.clone(self.options.events, true)}); + Ox.print('TIME TO SET LIST OPTIONS:', +new Date() - time0); + self.$calendar.addEvent(event); + selectEvent(event); + } else { + alert(result.status.code) + } }); } @@ -488,9 +492,9 @@ Ox.ListCalendar = function(options, self) { var id = self.selectedEvent, index = Ox.getPositionById(self.options.events, id), data = {id: id}; + data[key] = value; self.options.editEvent(data, function(result) { self.options.events[index][key] = value; - data[key] = value; self.$list.value(id, key, value); if (['name', 'type', 'start', 'end'].indexOf(key) > -1) { self.$calendar.editEvent(id, key, value); diff --git a/source/Ox.UI/js/List/Ox.List.js b/source/Ox.UI/js/List/Ox.List.js index 3aa38bba..3c085dd6 100644 --- a/source/Ox.UI/js/List/Ox.List.js +++ b/source/Ox.UI/js/List/Ox.List.js @@ -1178,6 +1178,7 @@ Ox.List = function(options, self) { // fixme: no case where callback is set // note: can't use selectNone here, // since it'd trigger a select event + Ox.print('SET SELECTED', ids) var counter = 0; self.$items.forEach(function($item, pos) { if (isSelected(pos)) { From c7d268a7aaf5e04a831eaa4bcdac741bb0f43168 Mon Sep 17 00:00:00 2001 From: rlx <0x0073@0x2620.org> Date: Tue, 11 Oct 2011 10:19:44 +0000 Subject: [PATCH 13/17] when adding an event, set focus to its name input field --- build/Ox.UI/themes/classic/css/classic.css | 12 +++++++++--- build/Ox.UI/themes/modern/css/modern.css | 12 +++++++++--- source/Ox.UI/js/Calendar/Ox.ListCalendar.js | 1 + 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/build/Ox.UI/themes/classic/css/classic.css b/build/Ox.UI/themes/classic/css/classic.css index 42761923..8fdc9a49 100644 --- a/build/Ox.UI/themes/classic/css/classic.css +++ b/build/Ox.UI/themes/classic/css/classic.css @@ -111,13 +111,19 @@ Calendar .OxThemeClassic .OxCalendar .OxLine > .OxEvent { 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) { - border-top: 1px solid rgba(0, 0, 0, 0.5); - border-bottom: 1px solid rgba(0, 0, 0, 0.5); + background-color: rgba(0, 0, 0, 0.25); + box-shadow: inset 0 0 2px rgb(0, 0, 0); } .OxThemeClassic .OxCalendar .OxOverlay div:nth-child(odd) { - background-color: rgba(255, 255, 255, 0.5); + background-color: rgba(255, 255, 255, 0.25); } /* diff --git a/build/Ox.UI/themes/modern/css/modern.css b/build/Ox.UI/themes/modern/css/modern.css index 3e4f3750..6bcd4784 100644 --- a/build/Ox.UI/themes/modern/css/modern.css +++ b/build/Ox.UI/themes/modern/css/modern.css @@ -110,13 +110,19 @@ Calendar .OxThemeModern .OxCalendar .OxLine > .OxEvent { 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) { - border-top: 1px solid rgba(255, 255, 255, 0.5); - border-bottom: 1px solid rgba(255, 255, 255, 0.5); + background-color: rgba(255, 255, 255, 0.25); + box-shadow: inset 0 0 2px rgb(255, 255, 255); } .OxThemeModern .OxCalendar .OxOverlay div:nth-child(odd) { - background-color: rgba(0, 0, 0, 0.5); + background-color: rgba(0, 0, 0, 0.25); } diff --git a/source/Ox.UI/js/Calendar/Ox.ListCalendar.js b/source/Ox.UI/js/Calendar/Ox.ListCalendar.js index 4a0f1342..7b7b60c4 100644 --- a/source/Ox.UI/js/Calendar/Ox.ListCalendar.js +++ b/source/Ox.UI/js/Calendar/Ox.ListCalendar.js @@ -482,6 +482,7 @@ Ox.ListCalendar = function(options, self) { Ox.print('TIME TO SET LIST OPTIONS:', +new Date() - time0); self.$calendar.addEvent(event); selectEvent(event); + self.$nameInput.focusInput(); } else { alert(result.status.code) } From e5d0c3fd20a454168d7bc0c88b4cd99c16d81718 Mon Sep 17 00:00:00 2001 From: rlx <0x0073@0x2620.org> Date: Tue, 11 Oct 2011 10:34:02 +0000 Subject: [PATCH 14/17] make dialog fire resize events after maximize and reset --- source/Ox.UI/js/Calendar/Ox.Calendar.js | 1 - source/Ox.UI/js/Window/Ox.Dialog.js | 8 ++++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/source/Ox.UI/js/Calendar/Ox.Calendar.js b/source/Ox.UI/js/Calendar/Ox.Calendar.js index 8806c1fe..8a61f1cf 100644 --- a/source/Ox.UI/js/Calendar/Ox.Calendar.js +++ b/source/Ox.UI/js/Calendar/Ox.Calendar.js @@ -1139,7 +1139,6 @@ Ox.Calendar = function(options, self) { self.options.width = that.width(); self.options.height = that.height(); self.$zoomInput.options({size: self.options.width}); - getLines(); renderCalendar(); return that; }; diff --git a/source/Ox.UI/js/Window/Ox.Dialog.js b/source/Ox.UI/js/Window/Ox.Dialog.js index f5afbcf5..aced2e53 100644 --- a/source/Ox.UI/js/Window/Ox.Dialog.js +++ b/source/Ox.UI/js/Window/Ox.Dialog.js @@ -297,6 +297,10 @@ Ox.Dialog = function(options, self) { height: self.options.maxHeight }, true); self.maximized = !self.maximized; + that.triggerEvent('resize', { + width: self.options.width, + height: self.options.height + }); } function mousedownLayer() { @@ -331,6 +335,10 @@ Ox.Dialog = function(options, self) { left: left, top: top }), animate); + that.triggerEvent('resize', { + width: self.options.width, + height: self.options.height + }); } function resizestart(event) { From f43122f795cb8e275d06288299b5ced3ce8b5b98 Mon Sep 17 00:00:00 2001 From: rlx <0x0073@0x2620.org> Date: Tue, 11 Oct 2011 11:22:16 +0000 Subject: [PATCH 15/17] workaround for select values not getting updated correctly when updating form values --- source/Ox.UI/js/Calendar/Ox.ListCalendar.js | 54 ++++++++++++--------- source/Ox.UI/js/Form/Ox.Form.js | 1 + source/Ox.UI/js/Form/Ox.Select.js | 6 ++- source/Ox.UI/js/Window/Ox.Dialog.js | 2 + 4 files changed, 39 insertions(+), 24 deletions(-) diff --git a/source/Ox.UI/js/Calendar/Ox.ListCalendar.js b/source/Ox.UI/js/Calendar/Ox.ListCalendar.js index 7b7b60c4..1b44358b 100644 --- a/source/Ox.UI/js/Calendar/Ox.ListCalendar.js +++ b/source/Ox.UI/js/Calendar/Ox.ListCalendar.js @@ -484,7 +484,7 @@ Ox.ListCalendar = function(options, self) { selectEvent(event); self.$nameInput.focusInput(); } else { - alert(result.status.code) + alert(result.status.text); } }); } @@ -495,22 +495,26 @@ Ox.ListCalendar = function(options, self) { data = {id: id}; data[key] = value; self.options.editEvent(data, function(result) { - 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 - ) - }); + 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); } }); } @@ -546,12 +550,16 @@ Ox.ListCalendar = function(options, self) { var id = self.selectedEvent, index = Ox.getPositionById(self.options.events, id); self.options.removeEvent({id: id}, function(result) { - self.options.events.splice(index, 1); - var time0 = +new Date(); - self.$list.options({items: Ox.clone(self.options.events, true)}); - Ox.print('TIME TO SET LIST OPTIONS:', +new Date() - time0); - self.$calendar.removeEvent(); - selectEvent({}); + if (result.status.code == '200') { + self.options.events.splice(index, 1); + var time0 = +new Date(); + self.$list.options({items: Ox.clone(self.options.events, true)}); + Ox.print('TIME TO SET LIST OPTIONS:', +new Date() - time0); + self.$calendar.removeEvent(); + selectEvent({}); + } else { + alert(result.status.text); + } }); } diff --git a/source/Ox.UI/js/Form/Ox.Form.js b/source/Ox.UI/js/Form/Ox.Form.js index dd713141..bd6635bf 100644 --- a/source/Ox.UI/js/Form/Ox.Form.js +++ b/source/Ox.UI/js/Form/Ox.Form.js @@ -138,6 +138,7 @@ Ox.Form = function(options, self) { //Ox.print('VALUES', values) return values; } else { + Ox.print('SET FORM VALUES', arguments[0]) Ox.forEach(arguments[0], function(value, key) { var index = getItemIndexById(key); //index > -1 && Ox.print(':::::::', key, value) diff --git a/source/Ox.UI/js/Form/Ox.Select.js b/source/Ox.UI/js/Form/Ox.Select.js index c115aad6..e13f2472 100644 --- a/source/Ox.UI/js/Form/Ox.Select.js +++ b/source/Ox.UI/js/Form/Ox.Select.js @@ -43,11 +43,12 @@ Ox.Select = function(options, self) { size: 'medium', title: '', type: 'text', // can be 'text' or 'image' - value: [], + value: '', width: 'auto' }) // fixme: make default selection restorable // or allow for extra action items below options + // fixme: passing value has no effect .options(options) .addClass( 'OxSelect Ox' + Ox.toTitleCase(self.options.size) + ( @@ -148,6 +149,7 @@ Ox.Select = function(options, self) { function changeMenu(data) { //Ox.print('clickMenu: ', self.options.id, data) self.checked = self.optionGroup.checked(); + self.options.value = data.checked[0].id; self.$title && self.$title.html( self.options.title ? self.options.title : data.checked[0].title @@ -182,6 +184,8 @@ Ox.Select = function(options, self) { } }; + // FIXME: selected() _and_ selectItem() _and_ value() ??? + /*@ selected gets selected item () -> returns object of selected items with id, title diff --git a/source/Ox.UI/js/Window/Ox.Dialog.js b/source/Ox.UI/js/Window/Ox.Dialog.js index aced2e53..a106d0ae 100644 --- a/source/Ox.UI/js/Window/Ox.Dialog.js +++ b/source/Ox.UI/js/Window/Ox.Dialog.js @@ -335,10 +335,12 @@ Ox.Dialog = function(options, self) { left: left, top: top }), animate); + /* that.triggerEvent('resize', { width: self.options.width, height: self.options.height }); + */ } function resizestart(event) { From 7ac16acbf176756771261596638c418fa0acadd4 Mon Sep 17 00:00:00 2001 From: rlx <0x0073@0x2620.org> Date: Tue, 11 Oct 2011 16:00:58 +0000 Subject: [PATCH 16/17] fix a bug with adding/removing columns of synchronous textlists --- source/Ox.UI/js/List/Ox.List.js | 19 ++++++++++++++----- source/Ox.UI/js/Map/Ox.ListMap.js | 5 ++++- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/source/Ox.UI/js/List/Ox.List.js b/source/Ox.UI/js/List/Ox.List.js index 3c085dd6..7eb6aadd 100644 --- a/source/Ox.UI/js/List/Ox.List.js +++ b/source/Ox.UI/js/List/Ox.List.js @@ -1548,11 +1548,20 @@ Ox.List = function(options, self) { () -> the list @*/ that.reloadPages = function() { - var page = self.page; - clear(); - self.page = page - that.$content.empty(); - loadPages(self.page); + // this is called by TextList when the column layout changes + var page, scrollLeft, scrollTop; + if (!self.isAsync) { + scrollLeft = that.scrollLeft(); + 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; }; diff --git a/source/Ox.UI/js/Map/Ox.ListMap.js b/source/Ox.UI/js/Map/Ox.ListMap.js index 92fcd7d0..fab4defa 100644 --- a/source/Ox.UI/js/Map/Ox.ListMap.js +++ b/source/Ox.UI/js/Map/Ox.ListMap.js @@ -65,10 +65,13 @@ Ox.ListMap = function(options, self) { }, id: 'countryCode', resizable: false, // fixme: implement + /* + // fixme: why does this not work? it does in folderBrowserList title: $('').attr({ src: Ox.UI.getImageURL('symbolFlag') - // fixme: why does this not work? it does in folderBrowserList }), + */ + title: '\u2691', visible: true, width: 16 }, From 687db7d957b84ab073c0361e9ff7914c609ade53 Mon Sep 17 00:00:00 2001 From: rlx <0x0073@0x2620.org> Date: Tue, 11 Oct 2011 17:27:46 +0000 Subject: [PATCH 17/17] make ESC work when editing text list cells --- source/Ox.UI/js/List/Ox.TextList.js | 1 + 1 file changed, 1 insertion(+) diff --git a/source/Ox.UI/js/List/Ox.TextList.js b/source/Ox.UI/js/List/Ox.TextList.js index b8f79e47..0ed389b5 100644 --- a/source/Ox.UI/js/List/Ox.TextList.js +++ b/source/Ox.UI/js/List/Ox.TextList.js @@ -829,6 +829,7 @@ Ox.TextList = function(options, self) { width: width }) .bind({ + blur: submit, mousedown: function(e) { // keep mousedown from reaching list e.stopPropagation();