oxjs/source/Ox.UI/js/Map/Ox.ListMap.js

678 lines
20 KiB
JavaScript
Raw Normal View History

2011-04-23 16:45:50 +00:00
// vim: et:ts=4:sw=4:sts=4:ft=js
2011-05-16 08:24:46 +00:00
/*@
Ox.ListMap <f:Ox.Element> ListMap Object
() -> <f> ListMap Object
(options) -> <f> ListMap Object
(options, self) -> <f> ListMap Object
options <o> Options object
2011-05-16 10:49:48 +00:00
height <n|256>
labels <b|false>
places <f|null>
selected <a|[]>
width <n|256>
2011-05-16 08:24:46 +00:00
self <o> shared private variable
@*/
2011-04-22 22:03:10 +00:00
Ox.ListMap = function(options, self) {
var self = self || {},
2011-05-21 17:56:15 +00:00
that = Ox.Element({}, self)
2011-04-22 22:03:10 +00:00
.defaults({
height: 256,
labels: false,
2011-05-29 10:42:38 +00:00
pageLength: 100,
2011-04-22 22:03:10 +00:00
places: null,
selected: [],
2011-05-29 10:42:38 +00:00
sort: [{key: 'geoname', operator: '+'}],
2011-04-22 22:03:10 +00:00
width: 256
})
.addClass('OxListMap')
.options(options || {})
.css({
width: self.options.width + 'px',
height: self.options.height + 'px'
});
2011-05-29 10:42:38 +00:00
self.isAsync = Ox.isFunction(self.options.places);
2011-04-22 22:03:10 +00:00
self.columns = [
{
addable: false, // fixme: implement
id: 'id',
2011-05-24 16:08:52 +00:00
title: 'Id',
2011-04-22 22:03:10 +00:00
unique: true,
2011-05-24 16:08:52 +00:00
visible: false,
width: 64
2011-04-22 22:03:10 +00:00
},
{
format: function(value) {
return $('<img>')
.attr({
// fixme: not the right place to do this
src: Ox.PATH + 'Ox.Geo/png/icons/16/' + (value || 'NTHH') + '.png'
})
.css({
width: '14px',
2011-05-22 17:12:21 +00:00
height: '14px',
marginLeft: '-3px',
marginTop: 0
});
/*
.css({
width: '21px',
height: '14px'
2011-04-22 22:03:10 +00:00
})
.load(function() {
var $this = $(this);
Ox.print($this.width() / $this.height())
$this.css({
width: Math.round(14 * $this.width() / $this.height()) + 'px',
2011-04-22 22:03:10 +00:00
height: '14px',
padding: '1px 0 0 1px'
});
2011-04-22 22:03:10 +00:00
});
*/
2011-04-22 22:03:10 +00:00
},
id: 'countryCode',
2011-05-22 17:12:21 +00:00
resizable: false, // fixme: implement
title: '<img src="' + Ox.UI.getImagePath('symbolFlag.svg') +
'" style="width: 10px; height: 10px; padding: 3px 1px 1px 3px"/>',
visible: true,
width: 16
},
{
editable: true,
id: 'name',
operator: '+',
removable: false,
title: 'Name',
visible: true,
width: 144
},
2011-05-24 10:44:34 +00:00
{
editable: false,
format: function(value) {
return value.join('; ');
},
id: 'alternativeNames',
removable: false,
operator: '+',
title: 'Alternative Names',
visible: true,
width: 144
},
2011-05-22 17:12:21 +00:00
{
editable: true,
id: 'geoname',
removable: false,
2011-05-24 12:50:16 +00:00
map: function(v) {
2011-05-28 08:46:39 +00:00
var names = v.split(', ');
if (!Ox.getCountryByGeoname(names[names.length - 1])) {
names.push('~');
}
return names.reverse().join(', ')
2011-05-22 17:12:21 +00:00
},
2011-05-24 12:50:16 +00:00
operator: '+',
2011-05-22 17:12:21 +00:00
title: 'Geoname',
2011-04-22 22:03:10 +00:00
visible: true,
2011-05-22 17:12:21 +00:00
width: 192
2011-04-22 22:03:10 +00:00
},
{
align: 'right',
format: toFixed,
2011-05-24 11:43:27 +00:00
id: 'south',
2011-04-22 22:03:10 +00:00
operator: '+',
2011-05-24 11:43:27 +00:00
title: 'South',
visible: false,
2011-04-22 22:03:10 +00:00
width: 96
},
{
align: 'right',
2011-05-24 11:43:27 +00:00
id: 'west',
2011-04-22 22:03:10 +00:00
operator: '+',
2011-05-24 11:43:27 +00:00
title: 'West',
visible: false,
2011-04-22 22:03:10 +00:00
width: 96
},
{
align: 'right',
format: toFixed,
2011-05-24 11:43:27 +00:00
id: 'north',
2011-04-22 22:03:10 +00:00
operator: '+',
2011-05-24 11:43:27 +00:00
title: 'North',
2011-04-22 22:03:10 +00:00
visible: false,
width: 96
},
{
align: 'right',
2011-05-24 11:43:27 +00:00
format: toFixed,
id: 'east',
2011-04-22 22:03:10 +00:00
operator: '+',
2011-05-24 11:43:27 +00:00
title: 'East',
2011-04-22 22:03:10 +00:00
visible: false,
width: 96
},
{
align: 'right',
format: toFixed,
2011-05-24 11:43:27 +00:00
id: 'lat',
2011-04-22 22:03:10 +00:00
operator: '+',
2011-05-24 11:43:27 +00:00
title: 'Latitude',
visible: true,
2011-04-22 22:03:10 +00:00
width: 96
},
{
align: 'right',
format: toFixed,
2011-05-24 11:43:27 +00:00
id: 'lng',
2011-04-22 22:03:10 +00:00
operator: '+',
2011-05-24 11:43:27 +00:00
title: 'Longitude',
visible: true,
2011-04-22 22:03:10 +00:00
width: 96
},
2011-05-24 11:43:27 +00:00
{
align: 'right',
format: {type: 'area', args: [0]},
id: 'area',
operator: '-',
title: 'Area',
visible: true,
width: 128
},
2011-04-22 22:03:10 +00:00
{
id: 'user',
operator: '+',
title: 'User',
visible: false,
width: 96
},
{
format: 'date',
id: 'created',
operator: '-',
title: 'Date Created',
visible: false,
width: 96,
},
{
format: 'date',
id: 'modified',
operator: '-',
title: 'Date Modified',
visible: false,
width: 96,
},
{
align: 'right',
id: 'matches',
operator: '-',
title: 'Matches',
visible: false,
width: 96,
}
];
2011-05-21 17:56:15 +00:00
self.$listToolbar = Ox.Bar({
2011-04-22 22:03:10 +00:00
size: 24
});
2011-05-21 17:56:15 +00:00
self.$findElement = Ox.FormElementGroup({
2011-04-22 22:03:10 +00:00
elements: [
2011-05-21 17:56:15 +00:00
self.$findSelect = Ox.Select({
2011-04-22 22:03:10 +00:00
items: [
{id: 'all', title: 'Find: All'},
{id: 'name', title: 'Find: Name'},
{id: 'alternativeNames', title: 'Find: Alternative Names'},
{id: 'geoname', title: 'Find: Geoname'}
2011-04-22 22:03:10 +00:00
],
overlap: 'right',
type: 'image'
2011-04-22 22:03:10 +00:00
}),
2011-05-21 17:56:15 +00:00
self.$findInput = Ox.Input({
2011-04-22 22:03:10 +00:00
clear: true,
placeholder: 'Find in List',
width: 234
2011-04-22 22:03:10 +00:00
})
]
})
.css({float: 'right', margin: '4px'})
2011-05-21 17:56:15 +00:00
.appendTo(self.$listToolbar)
2011-04-22 22:03:10 +00:00
2011-05-21 17:56:15 +00:00
self.$list = Ox.TextList({
2011-04-22 22:03:10 +00:00
columns: self.columns,
columnsRemovable: true,
columnsVisible: true,
2011-05-24 20:00:25 +00:00
//items: Ox.clone(self.options.places),
items: self.options.places,
2011-05-29 10:42:38 +00:00
pageLength: self.options.pageLength,
2011-04-22 22:03:10 +00:00
scrollbarVisible: true,
2011-05-29 10:42:38 +00:00
sort: self.options.sort
2011-04-22 22:03:10 +00:00
})
.bindEvent({
'delete': removeItem,
init: initList,
2011-05-24 14:51:40 +00:00
// fixme: do we need 0/shift-0? return already zooms to place
key_0: function() {
self.$map.panToPlace();
},
key_equal: function() {
self.$map.zoom(1);
},
key_minus: function() {
self.$map.zoom(-1);
},
key_shift_0: function() {
self.$map.zoomToPlace();
},
2011-04-22 22:03:10 +00:00
load: function() {
that.triggerEvent('loadlist');
},
open: openItem,
select: selectItem
});
2011-05-21 17:56:15 +00:00
self.$listStatusbar = Ox.Bar({
size: 16
});
self.$status = Ox.Element()
.css({paddingTop: '2px', margin: 'auto', fontSize: '9px', textAlign: 'center'})
.appendTo(self.$listStatusbar);
2011-05-29 12:22:54 +00:00
self.$map = Ox.Map({
clickable: true,
editable: true,
findPlaceholder: 'Find on Map',
height: self.options.height,
places: self.options.places,
//statusbar: true,
toolbar: true,
width: self.options.width - 514,//self.mapResize[1],
zoombar: true
})
.bindEvent({
/*
2011-05-29 12:22:54 +00:00
addplace: function(event, data) {
that.triggerEvent('addplace', data);
},
*/
2011-05-29 12:22:54 +00:00
changeplace: function(event, data) {
self.$placeForm.values(Ox.map(data, function(val, key) {
// fixme: no size key anymore
return key == 'size' ? Ox.formatArea(val) : val;
})).show();
},
geocode: function(event, data) {
that.triggerEvent('geocode', data);
},
resize: function() {
self.$map.resizeMap(); // fixme: don't need event
},
selectplace: selectPlace
});
2011-05-21 17:56:15 +00:00
2011-05-22 17:12:21 +00:00
self.$placeTitlebar = Ox.Bar({
2011-05-21 17:56:15 +00:00
size: 24
});
2011-05-24 06:15:44 +00:00
self.$placeTitle = $('<div>')
.hide()
.appendTo(self.$placeTitlebar.$element)
2011-05-22 17:12:21 +00:00
self.$placeTitleFlag = $('<img>')
.addClass('OxFlag')
.attr({
2011-05-24 16:22:37 +00:00
src: Ox.getImageByGeoname('icon', 16, '')
2011-05-22 17:12:21 +00:00
})
.css({float: 'left', margin: '4px 0 0 4px'})
2011-05-24 06:15:44 +00:00
.appendTo(self.$placeTitle);
2011-05-22 17:12:21 +00:00
self.$placeTitleName = Ox.Label({
title: '',
width: 228
2011-05-21 17:56:15 +00:00
})
.css({float: 'left', margin: '4px'})
2011-05-24 06:15:44 +00:00
.appendTo(self.$placeTitle);
2011-05-21 17:56:15 +00:00
self.$placeFormItems = Ox.merge([
Ox.Input({
id: 'name',
label: 'Name',
labelWidth: 64,
width: 240
2011-05-24 06:15:44 +00:00
}).bindEvent({
change: function(data) {
2011-05-24 16:08:52 +00:00
var isResult = self.selectedPlace[0] == '_';
2011-05-24 06:15:44 +00:00
Ox.getObjectById(self.options.places, self.selectedPlace).name = data.value;
2011-05-24 16:08:52 +00:00
!isResult && self.$list.value(self.selectedPlace, 'name', data.value);
2011-05-24 06:15:44 +00:00
self.$map.value(self.selectedPlace, 'name', data.value);
}
2011-05-21 17:56:15 +00:00
}),
Ox.Input({
id: 'geoname',
label: 'Geoname',
labelWidth: 64,
width: 240
2011-05-24 06:15:44 +00:00
}).bindEvent({
change: function(data) {
2011-05-24 16:08:52 +00:00
var geoname = data.value,
country = Ox.getCountryByGeoname(geoname),
2011-05-24 16:22:37 +00:00
countryCode = country ? country.code : '',
2011-05-24 16:08:52 +00:00
isResult = self.selectedPlace[0] == '_';
2011-05-24 16:22:37 +00:00
Ox.print('IS RESULT?', isResult, self.selectedPlace)
if (!isResult) {
self.$list.value(self.selectedPlace, 'geoname', geoname);
self.$list.value(self.selectedPlace, 'countryCode', countryCode);
}
2011-05-24 16:08:52 +00:00
//self.$map.value(self.selectedPlace, 'geoname', geoname);
self.$placeTitleFlag.attr({
2011-05-24 16:22:37 +00:00
src: Ox.getImageByGeoname('icon', 16, geoname)
2011-05-24 06:15:44 +00:00
});
2011-05-24 16:08:52 +00:00
self.$placeTitleName.options({title: geoname});
2011-05-24 06:15:44 +00:00
}
2011-05-21 17:56:15 +00:00
}),
Ox.ArrayInput({
id: 'alternativeNames',
label: 'Alternative Names',
max: 10,
//sort: true,
values: [],
width: 240
2011-05-24 10:44:34 +00:00
}).bindEvent({
change: function(data) {
Ox.print('CHANGE........', data)
}
2011-05-21 17:56:15 +00:00
}),
2011-05-22 12:39:57 +00:00
], ['South', 'West', 'North', 'East', 'Latitude', 'Longitude'].map(function(v) {
var id = (
2011-05-21 17:56:15 +00:00
v == 'Latitude' ? 'lat' : v == 'Longitude' ? 'lng' : v
).toLowerCase(),
max = ['Latitude', 'South', 'North'].indexOf(v) > -1 ? Ox.MAX_LATITUDE : 180;
return Ox.Input({
decimals: 8,
2011-05-22 12:39:57 +00:00
disabled: ['Latitude', 'Longitude'].indexOf(v) > -1,
id: id,
2011-05-21 17:56:15 +00:00
label: v,
labelWidth: 80,
min: -max,
max: max,
type: 'float',
width: 240
2011-05-24 06:15:44 +00:00
}).bindEvent({
focus: function() {
Ox.print('---- FOCUS ----')
}
2011-04-22 22:03:10 +00:00
});
2011-05-22 12:39:57 +00:00
}), [
2011-05-24 10:44:34 +00:00
self.$areaInput = Ox.Input({
2011-05-22 12:39:57 +00:00
disabled: true,
2011-05-24 10:44:34 +00:00
id: 'area',
label: 'Area',
2011-05-22 12:39:57 +00:00
labelWidth: 80,
textAlign: 'right',
2011-05-24 11:43:27 +00:00
type: 'float',
2011-05-22 12:39:57 +00:00
width: 240
})
]);
2011-05-21 17:56:15 +00:00
self.$placeForm = Ox.Form({
items: self.$placeFormItems,
width: 240
})
2011-05-24 06:15:44 +00:00
.css({margin: '8px'})
.hide();
2011-04-22 22:03:10 +00:00
2011-05-21 17:56:15 +00:00
self.$placeStatusbar = Ox.Bar({
2011-05-24 06:15:44 +00:00
size: 24
});
2011-05-24 10:44:34 +00:00
self.$placeButton = Ox.Button({
2011-05-24 08:40:17 +00:00
title: 'New Place',
width: 96
2011-05-24 06:15:44 +00:00
})
2011-05-24 10:44:34 +00:00
.css({float: 'left', margin: '4px 2px 4px 4px'})
2011-05-24 08:40:17 +00:00
.bindEvent({
click: function() {
2011-05-24 10:44:34 +00:00
var title = self.$placeButton.options('title');
2011-05-24 16:08:52 +00:00
// fixme: these should be separate functions
2011-05-24 10:44:34 +00:00
if (title == 'New Place') {
self.$map.newPlace();
self.$placeButton.options({title: 'Add Place'})
} else if (title == 'Add Place') {
addPlace();
2011-05-24 10:44:34 +00:00
} else if (title == 'Remove Place') {
removePlace();
2011-05-24 10:44:34 +00:00
}
2011-05-24 08:40:17 +00:00
}
})
2011-05-24 06:15:44 +00:00
.appendTo(self.$placeStatusbar);
2011-05-24 10:44:34 +00:00
self.$revertButton = Ox.Button({
2011-05-24 06:15:44 +00:00
title: 'Revert',
2011-05-24 08:40:17 +00:00
width: 96
2011-05-24 06:15:44 +00:00
})
2011-05-24 10:44:34 +00:00
.css({float: 'right', margin: '4px 4px 4px 2px'})
2011-05-24 08:40:17 +00:00
.hide()
2011-05-21 17:56:15 +00:00
.appendTo(self.$placeStatusbar);
/*
2011-04-22 22:03:10 +00:00
self.mapResize = [
Math.round(self.options.width * 0.25),
Math.round(self.options.width * 0.5),
Math.round(self.options.width * 0.75)
];
2011-05-21 17:56:15 +00:00
*/
2011-04-22 22:03:10 +00:00
/*
2011-05-29 10:42:38 +00:00
if (!self.isAsync) {
2011-05-29 12:22:54 +00:00
self.placesLength = self.options.places.length;
setStatus();
2011-04-22 22:03:10 +00:00
} else {
self.options.places({}, function(results) {
self.placesLength = results.data.items;
2011-05-29 12:22:54 +00:00
setStatus();
2011-04-22 22:03:10 +00:00
});
}
*/
2011-04-22 22:03:10 +00:00
2011-05-29 12:22:54 +00:00
that.$element.replaceWith(
that.$element = Ox.SplitPanel({
elements: [
{
element: Ox.SplitPanel({
elements: [
{
element: self.$listToolbar,
size: 24
},
{
element: self.$list
},
{
element: self.$listStatusbar,
size: 16
}
],
orientation: 'vertical'
}),
resizable: true,
resize: [256, 384, 512],
size: 256
},
2011-05-29 12:22:54 +00:00
{
element: self.$map,
2011-04-22 22:03:10 +00:00
},
2011-05-29 12:22:54 +00:00
{
collapsible: true,
element: Ox.SplitPanel({
elements: [
{
element: self.$placeTitlebar,
size: 24
},
{
element: self.$placeForm
},
{
element: self.$placeStatusbar,
size: 24
2011-05-22 12:39:57 +00:00
}
2011-05-29 12:22:54 +00:00
],
orientation: 'vertical'
})
.bindEvent({
resize: function(foo, size) {
self.$placeTitleName.options({width: size - 28});
// fixme: pass width through form
self.$placeFormItems.forEach(function($item) {
$item.options({width: size - 16});
});
}
}),
resizable: true,
resize: [204, 256, 384],
size: 256
}
],
orientation: 'horizontal'
}).$element
);
2011-04-22 22:03:10 +00:00
function addPlace() {
var place = self.$placeForm.values(),
country = Ox.getCountryByGeoname(place.geoname);
place.countryCode = country ? country.code : '';
self.selectedPlace = self.selectedPlace.substr(1); // fixme: safe?
place.id = self.selectedPlace;
if (!self.isAsync) {
self.options.places.push(place);
self.$list.options({
items: Ox.clone(self.options.places),
selected: [place.id]
});
//setStatus();
}
self.$map.addPlace(place);
self.$placeButton.options({title: 'Remove Place'});
that.triggerEvent('addplace', {place: place});
if (self.isAsync) {
self.$list.reloadList().options({selected: [place.id]});
}
}
function removePlace() {
var index = Ox.getPositionById(self.options.places, self.selectedPlace);
if (!self.isAsync) {
self.options.places.splice(index, 1);
self.$list.options({items: Ox.clone(self.options.places)});
//setStatus();
}
self.$map.removePlace();
self.$placeButton.options({title: 'Add Place'});
that.triggerEvent('removeplace', {id: self.selectedPlace});
if (self.isAsync) {
self.$list.options({selected: []}).reloadList(true);
}
}
function initList(data) {
self.$status.html(
Ox.formatNumber(data.items) + ' Place' + (
data.items == 1 ? '' : 's'
)
);
2011-04-22 22:03:10 +00:00
}
function openItem(event, data) {
selectItem(event, data);
self.$map.zoomToPlace(data.ids[0]);
}
function removeItem(event, data) {
var id = data.ids[0];
that.triggerEvent('removeplace', {id: id});
self.$map.removePlace(id);
}
function selectItem(event, data) {
Ox.print('selectItem', data.ids[0])
var id = data.ids.length ? data.ids[0] : null;
self.$map.options({selected: id});
id && self.$map.panToPlace();
}
2011-05-22 17:12:21 +00:00
function selectPlace(place) {
2011-05-24 06:15:44 +00:00
if (place.id) {
2011-05-24 08:40:17 +00:00
isResult = place.id[0] == '_';
2011-05-24 16:08:52 +00:00
//isResult && self.options.places.push(place);
2011-05-24 06:15:44 +00:00
self.selectedPlace = place.id;
place.id[0] != '_' && self.$list.options({
selected: place.id ? [place.id] : []
});
self.$placeTitleFlag.attr({
2011-05-24 16:22:37 +00:00
src: Ox.getImageByGeoname('icon', 16, place.geoname)
2011-05-24 06:15:44 +00:00
});
self.$placeTitleName.options({title: place.geoname || ''});
self.$placeTitle.show();
self.$placeForm.values(Ox.map(place, function(val, key) {
return key == 'size' ? Ox.formatArea(val) : val;
})).show();
2011-05-24 10:44:34 +00:00
self.$placeButton.options({title: isResult ? 'Add Place' : 'Remove Place'});
self.$revertButton.options({disabled: true}).show();
2011-05-24 06:15:44 +00:00
} else {
self.selectedPlace = null;
self.$placeTitle.hide();
self.$placeForm.hide();
2011-05-24 10:44:34 +00:00
self.$placeButton.options({title: 'New Place'});
self.$revertButton.hide();
2011-05-24 06:15:44 +00:00
}
2011-04-22 22:03:10 +00:00
}
function toFixed(val) {
2011-05-24 10:44:34 +00:00
return Ox.isNumber(val) ? val.toFixed(8) : val; // fixme: why can a string be passed ??
2011-04-22 22:03:10 +00:00
}
2011-05-16 10:49:48 +00:00
/*@
setOption <f> setOption
@*/
2011-04-29 12:40:51 +00:00
self.setOption = function(key, value) {
2011-04-22 22:03:10 +00:00
Ox.print('ONCHANGE')
if (key == 'height' || key == 'width') {
Ox.print('ONCHANGE...')
self.$map.options({
height: self.options.height,
width: self.options.width
})
} else if (key == 'selected') {
self.$list.options({selected: value});
}
}
2011-05-16 10:49:48 +00:00
/*@
focusList <f> focusList
@*/
2011-04-22 22:03:10 +00:00
that.focusList = function() {
self.$list.gainFocus();
return that;
}
2011-05-16 10:49:48 +00:00
/*@
reloadList <f> reloadList
@*/
2011-04-22 22:03:10 +00:00
that.reloadList = function() {
self.$list.reloadList();
return that;
}
2011-05-16 10:49:48 +00:00
/*@
resizeMap <f> resizeMap
@*/
2011-04-22 22:03:10 +00:00
that.resizeMap = function() {
Ox.print('Ox.ListMap.resizeMap()')
self.$map.resizeMap();
return that;
};
return that;
};