forked from 0x2620/oxjs
fix bugs in video editor; begin to implement new list map mode that allows for defining/clearing places
This commit is contained in:
parent
ae82696600
commit
3c94f44a99
15 changed files with 437 additions and 255 deletions
|
|
@ -10,8 +10,9 @@ Ox.ListMap <f:Ox.Element> ListMap object
|
|||
options <o> Options object
|
||||
height <n|256> Height in px
|
||||
labels <b|false> If true, show labels
|
||||
mode <s|'add'> Mode ('add' or 'define')
|
||||
places <a|f|null> Array of places, or function that returns places
|
||||
selected <a|[]> Selected places
|
||||
selected <s|''> Id of the selected place
|
||||
width <n|256> Width in px
|
||||
self <o> Shared private variable
|
||||
@*/
|
||||
|
|
@ -23,9 +24,11 @@ Ox.ListMap = function(options, self) {
|
|||
.defaults({
|
||||
addPlace: null,
|
||||
editPlace: null,
|
||||
collapsible: false,
|
||||
getMatches: null,
|
||||
height: 256,
|
||||
labels: false,
|
||||
mode: 'add',
|
||||
pageLength: 100,
|
||||
places: null,
|
||||
removePlace: null,
|
||||
|
|
@ -37,7 +40,6 @@ Ox.ListMap = function(options, self) {
|
|||
width: 256
|
||||
})
|
||||
.options(options || {})
|
||||
.addClass('OxListMap')
|
||||
.css({
|
||||
width: self.options.width + 'px',
|
||||
height: self.options.height + 'px'
|
||||
|
|
@ -45,6 +47,21 @@ Ox.ListMap = function(options, self) {
|
|||
|
||||
self.isAsync = Ox.isFunction(self.options.places);
|
||||
|
||||
// FIXME: duplicated, see MapMarker
|
||||
self.typeColor = {
|
||||
country: [64, 64, 255],
|
||||
region: [0, 192, 192],
|
||||
city: [255, 0, 0],
|
||||
borough: [255, 128, 0],
|
||||
street: [255, 255, 0],
|
||||
building: [255, 64, 128],
|
||||
feature: [0, 192, 0]
|
||||
};
|
||||
self.areaSize = {
|
||||
10000: 8, // 100 x 100 m
|
||||
10000000000: 10 // 100 x 100 km
|
||||
};
|
||||
|
||||
self.columns = [
|
||||
{
|
||||
addable: false, // fixme: implement
|
||||
|
|
@ -56,26 +73,78 @@ Ox.ListMap = function(options, self) {
|
|||
},
|
||||
{
|
||||
format: function(value, data) {
|
||||
return data.geoname ? $('<img>')
|
||||
.attr({
|
||||
src: Ox.getFlagByGeoname(data.geoname, 16)
|
||||
})
|
||||
.css({
|
||||
width: '14px',
|
||||
height: '14px',
|
||||
borderRadius: '4px',
|
||||
marginLeft: '-3px',
|
||||
marginTop: 0
|
||||
}) : '';
|
||||
return data.geoname
|
||||
? $('<img>')
|
||||
.attr({
|
||||
src: Ox.getFlagByGeoname(data.geoname, 16)
|
||||
})
|
||||
.css({
|
||||
width: '14px',
|
||||
height: '14px',
|
||||
borderRadius: '4px',
|
||||
marginLeft: '-3px',
|
||||
marginTop: 0
|
||||
})
|
||||
: '';
|
||||
},
|
||||
id: 'countryCode',
|
||||
map: function(value) {
|
||||
var names = value.split(', ');
|
||||
if (!Ox.getCountryByGeoname(names[names.length - 1])) {
|
||||
names.push('~');
|
||||
}
|
||||
return names.reverse().join(', ');
|
||||
},
|
||||
operator: '+',
|
||||
resizable: false, // fixme: implement
|
||||
title: 'Flag',
|
||||
titleImage: 'flag',
|
||||
tooltip: function(data) {
|
||||
return Ox.toTitleCase(data.geoname || '')
|
||||
},
|
||||
visible: true,
|
||||
width: 16
|
||||
},
|
||||
{
|
||||
format: function(value, data) {
|
||||
var iconSize = 6;
|
||||
Ox.forEach(self.areaSize, function(size, area) {
|
||||
if (data.area >= area) {
|
||||
iconSize = size;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
return data.type
|
||||
? $('<div>')
|
||||
.addClass('OxTypeIcon')
|
||||
.css({
|
||||
width: iconSize + 'px',
|
||||
height: iconSize + 'px',
|
||||
borderRadius: (iconSize + 4) / 2 + 'px',
|
||||
margin: [0, 0, 0, -3].map(function(v) {
|
||||
return v + (10 - iconSize) / 2 + 'px';
|
||||
}).join(' '),
|
||||
background: 'rgb(' + self.typeColor[data.type].join(', ') + ')'
|
||||
})
|
||||
: '';
|
||||
},
|
||||
id: 'type',
|
||||
operator: '+',
|
||||
title: 'Type',
|
||||
titleImage: 'icon',
|
||||
tooltip: function(data) {
|
||||
return Ox.toTitleCase(data.type || '');
|
||||
},
|
||||
visible: true,
|
||||
width: 16
|
||||
},
|
||||
{
|
||||
format: function(value, data) {
|
||||
return data.type
|
||||
? value
|
||||
: $('<span>').addClass('OxWarning').html(value)
|
||||
},
|
||||
id: 'name',
|
||||
operator: '+',
|
||||
removable: false,
|
||||
|
|
@ -99,21 +168,29 @@ Ox.ListMap = function(options, self) {
|
|||
var names = value.split(', ');
|
||||
if (!Ox.getCountryByGeoname(names[names.length - 1])) {
|
||||
names.push('~');
|
||||
}
|
||||
return names.reverse().join(', ');
|
||||
},
|
||||
operator: '+',
|
||||
title: 'Geoname',
|
||||
visible: true,
|
||||
width: 192
|
||||
}
|
||||
return names.reverse().join(', ');
|
||||
},
|
||||
operator: '+',
|
||||
title: 'Geoname',
|
||||
visible: false,
|
||||
width: 192
|
||||
},
|
||||
{
|
||||
format: function(value) {
|
||||
return Ox.toTitleCase(value);
|
||||
},
|
||||
id: 'type',
|
||||
align: 'right',
|
||||
format: toFixed,
|
||||
id: 'lat',
|
||||
operator: '+',
|
||||
title: 'Type',
|
||||
title: 'Latitude',
|
||||
visible: true,
|
||||
width: 64
|
||||
},
|
||||
{
|
||||
align: 'right',
|
||||
format: toFixed,
|
||||
id: 'lng',
|
||||
operator: '+',
|
||||
title: 'Longitude',
|
||||
visible: true,
|
||||
width: 64
|
||||
},
|
||||
|
|
@ -124,7 +201,7 @@ Ox.ListMap = function(options, self) {
|
|||
operator: '+',
|
||||
title: 'South',
|
||||
visible: false,
|
||||
width: 96
|
||||
width: 64
|
||||
},
|
||||
{
|
||||
align: 'right',
|
||||
|
|
@ -132,7 +209,7 @@ Ox.ListMap = function(options, self) {
|
|||
operator: '+',
|
||||
title: 'West',
|
||||
visible: false,
|
||||
width: 96
|
||||
width: 64
|
||||
},
|
||||
{
|
||||
align: 'right',
|
||||
|
|
@ -141,7 +218,7 @@ Ox.ListMap = function(options, self) {
|
|||
operator: '+',
|
||||
title: 'North',
|
||||
visible: false,
|
||||
width: 96
|
||||
width: 64
|
||||
},
|
||||
{
|
||||
align: 'right',
|
||||
|
|
@ -150,25 +227,7 @@ Ox.ListMap = function(options, self) {
|
|||
operator: '+',
|
||||
title: 'East',
|
||||
visible: false,
|
||||
width: 96
|
||||
},
|
||||
{
|
||||
align: 'right',
|
||||
format: toFixed,
|
||||
id: 'lat',
|
||||
operator: '+',
|
||||
title: 'Latitude',
|
||||
visible: true,
|
||||
width: 96
|
||||
},
|
||||
{
|
||||
align: 'right',
|
||||
format: toFixed,
|
||||
id: 'lng',
|
||||
operator: '+',
|
||||
title: 'Longitude',
|
||||
visible: true,
|
||||
width: 96
|
||||
width: 64
|
||||
},
|
||||
{
|
||||
align: 'right',
|
||||
|
|
@ -267,6 +326,7 @@ Ox.ListMap = function(options, self) {
|
|||
columnsVisible: true,
|
||||
//items: Ox.clone(self.options.places),
|
||||
items: self.options.places,
|
||||
keys: ['area', 'geoname'], // needed for icon and flag
|
||||
max: 1,
|
||||
min: 0,
|
||||
pageLength: self.options.pageLength,
|
||||
|
|
@ -353,7 +413,20 @@ Ox.ListMap = function(options, self) {
|
|||
});
|
||||
self.$placeTitle = $('<div>')
|
||||
.hide()
|
||||
.appendTo(self.$placeTitlebar)
|
||||
.appendTo(self.$placeTitlebar);
|
||||
if (self.options.mode == 'define') {
|
||||
self.$findPlaceButton = Ox.Button({
|
||||
title: 'find',
|
||||
tooltip: 'Find',
|
||||
type: 'image'
|
||||
})
|
||||
.css({float: 'left', margin: '4px'})
|
||||
.bindEvent({
|
||||
click: findPlace
|
||||
})
|
||||
.hide()
|
||||
.appendTo(self.$placeTitle);
|
||||
}
|
||||
self.$placeFlag = $('<img>')
|
||||
.addClass('OxFlag')
|
||||
.attr({
|
||||
|
|
@ -438,6 +511,7 @@ Ox.ListMap = function(options, self) {
|
|||
country = Ox.getCountryByGeoname(geoname),
|
||||
countryCode = country ? country.code : '',
|
||||
isResult = self.selectedPlace[0] == '_';
|
||||
Ox.print('CHANGE', geoname, country, countryCode, self.isAsync);
|
||||
self.$placeFlag.attr({
|
||||
src: Ox.getFlagByGeoname(geoname, 16)
|
||||
});
|
||||
|
|
@ -564,9 +638,9 @@ Ox.ListMap = function(options, self) {
|
|||
|
||||
self.$newPlaceButton = Ox.Button({
|
||||
title: 'New Place',
|
||||
width: 96
|
||||
width: 70
|
||||
})
|
||||
.css({float: 'left', margin: '4px 2px 4px 4px'})
|
||||
.css({float: 'left', margin: '4px'})
|
||||
.bindEvent({
|
||||
click: function() {
|
||||
self.$map.newPlace();
|
||||
|
|
@ -574,14 +648,14 @@ Ox.ListMap = function(options, self) {
|
|||
})
|
||||
.appendTo(self.$placeStatusbar);
|
||||
|
||||
self.$placeButton = Ox.Button({
|
||||
title: 'Add Place',
|
||||
width: 96
|
||||
self.$addPlaceButton = Ox.Button({
|
||||
tooltip: 'Add Place',
|
||||
width: 90
|
||||
})
|
||||
.css({float: 'right', margin: '4px 4px 4px 2px'})
|
||||
.css({float: 'right', margin: '4px'})
|
||||
.bindEvent({
|
||||
click: function() {
|
||||
if (self.$placeButton.options('title') == 'Add Place') {
|
||||
if (this.options('title') == 'Add Place') {
|
||||
addPlace();
|
||||
} else {
|
||||
removePlace();
|
||||
|
|
@ -591,6 +665,25 @@ Ox.ListMap = function(options, self) {
|
|||
.hide()
|
||||
.appendTo(self.$placeStatusbar);
|
||||
|
||||
if (self.options.mode == 'define') {
|
||||
self.$definePlaceButton = Ox.Button({
|
||||
title: 'Define Place',
|
||||
width: 80
|
||||
})
|
||||
.css({float: 'right', margin: '4px 0 4px 0'})
|
||||
.bindEvent({
|
||||
click: function() {
|
||||
if (this.options('title') == 'Define Place') {
|
||||
definePlace();
|
||||
} else {
|
||||
clearPlace();
|
||||
}
|
||||
}
|
||||
})
|
||||
.hide()
|
||||
.appendTo(self.$placeStatusbar);
|
||||
}
|
||||
|
||||
/*
|
||||
self.$revertButton = Ox.Button({
|
||||
title: 'Revert',
|
||||
|
|
@ -625,7 +718,7 @@ Ox.ListMap = function(options, self) {
|
|||
that.$element = Ox.SplitPanel({
|
||||
elements: [
|
||||
{
|
||||
collapsible: true,
|
||||
collapsible: self.options.collapsible,
|
||||
element: self.$listPanel = Ox.SplitPanel({
|
||||
elements: [
|
||||
{
|
||||
|
|
@ -647,10 +740,15 @@ Ox.ListMap = function(options, self) {
|
|||
size: 256
|
||||
},
|
||||
{
|
||||
element: self.$map,
|
||||
element: self.$map
|
||||
.bindEvent({
|
||||
resize: function() {
|
||||
self.$map.resizeMap();
|
||||
}
|
||||
}),
|
||||
},
|
||||
{
|
||||
collapsible: true,
|
||||
collapsible: self.options.collapsible,
|
||||
element: Ox.SplitPanel({
|
||||
elements: [
|
||||
{
|
||||
|
|
@ -674,15 +772,19 @@ Ox.ListMap = function(options, self) {
|
|||
self.$placeFormItems.forEach(function($item) {
|
||||
$item.options({width: data.size - 16});
|
||||
});
|
||||
self.$areaKmInput.options({width: data.size - 16});
|
||||
self.$matchesInput && self.$matchesInput.options({width: data.size - 16});
|
||||
}
|
||||
}),
|
||||
resizable: true,
|
||||
resize: [204, 256, 384],
|
||||
resize: [256, 384],
|
||||
size: 256
|
||||
}
|
||||
],
|
||||
orientation: 'horizontal'
|
||||
}).$element
|
||||
})
|
||||
.addClass('OxListMap')
|
||||
.$element
|
||||
);
|
||||
|
||||
function addPlace() {
|
||||
|
|
@ -698,19 +800,19 @@ Ox.ListMap = function(options, self) {
|
|||
selected: [place.id]
|
||||
});
|
||||
self.$map.addPlace(place);
|
||||
self.$placeButton.options({title: 'Remove Place'});
|
||||
self.$addPlaceButton.options({title: 'Remove Place'});
|
||||
//setStatus();
|
||||
}
|
||||
//that.triggerEvent('addplace', {place: place});
|
||||
if (self.isAsync) {
|
||||
self.$placeButton.options({disabled: true, title: 'Adding Place'});
|
||||
self.$addPlaceButton.options({disabled: true, title: 'Adding...'});
|
||||
self.options.addPlace(place, function(result) {
|
||||
if (result.status.code == 200) {
|
||||
place.id = result.data.id;
|
||||
self.selectedPlace = place.id;
|
||||
self.$list.reloadList().options({selected: [place.id]});
|
||||
self.$map.addPlace(place);
|
||||
self.$placeButton.options({disabled: false, title: 'Remove Place'});
|
||||
self.$addPlaceButton.options({disabled: false, title: 'Remove Place'});
|
||||
} else {
|
||||
if (result.data.names) {
|
||||
if (result.data.names.indexOf(self.$nameInput.value()) > -1) {
|
||||
|
|
@ -721,13 +823,37 @@ Ox.ListMap = function(options, self) {
|
|||
if (result.data.geoname) {
|
||||
self.$geonameInput.addClass('OxError');
|
||||
}
|
||||
self.$placeButton.options({disabled: false, title: 'Add Place'});
|
||||
self.$addPlaceButton.options({disabled: false, title: 'Add Place'});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function clearPlace() {
|
||||
var values = {
|
||||
id: self.selectedPlace,
|
||||
alternativeNames: [], geoname: '', type: '',
|
||||
latitude: null, longitude: null,
|
||||
south: null, west: null, north: null, east: null
|
||||
};
|
||||
self.$definePlaceButton.options({disabled: true, title: 'Clearing...'});
|
||||
self.options.editPlace(values, function() {
|
||||
self.$list.reloadList();
|
||||
self.$map.removePlace();
|
||||
self.$findPlaceButton.show();
|
||||
self.$placeFlag.hide();
|
||||
self.$placeForm.hide();
|
||||
self.$definePlaceButton.options({disabled: false, title: 'Define Place'})
|
||||
});
|
||||
}
|
||||
|
||||
function definePlace() {
|
||||
self.$map.newPlace();
|
||||
self.$definePlaceButton.options({title: 'Clear Place'})
|
||||
}
|
||||
|
||||
function editPlace(keys) {
|
||||
Ox.print('EDIT PLACE', keys, self.$placeForm.values())
|
||||
var values = Ox.filter(self.$placeForm.values(), function(values, key) {
|
||||
return keys.indexOf(key) > -1;
|
||||
});
|
||||
|
|
@ -749,6 +875,12 @@ Ox.ListMap = function(options, self) {
|
|||
}
|
||||
}
|
||||
|
||||
function findPlace() {
|
||||
self.$map.options({
|
||||
find: self.$list.value(self.selectedPlace).name
|
||||
});
|
||||
}
|
||||
|
||||
function initList(data) {
|
||||
self.$status.html(
|
||||
Ox.formatNumber(data.items) + ' Place' + (
|
||||
|
|
@ -777,52 +909,100 @@ Ox.ListMap = function(options, self) {
|
|||
index = Ox.getIndexById(self.options.places, self.selectedPlace);
|
||||
self.options.places.splice(index, 1);
|
||||
self.$list.options({items: Ox.clone(self.options.places)});
|
||||
self.$addPlaceButton.options({title: 'Add Place'});
|
||||
//setStatus();
|
||||
}
|
||||
// fixme: what is this? both options.removePlace and event removeplace??
|
||||
if (self.isAsync) {
|
||||
self.$addPlaceButton.options({disabled: true, title: 'Removing...'})
|
||||
self.options.removePlace({id: self.selectedPlace}, function() {
|
||||
self.$list.options({selected: []}).reloadList(true);
|
||||
self.$addPlaceButton.options({disabled: false, title: 'Add Place'})
|
||||
});
|
||||
}
|
||||
self.$map.removePlace();
|
||||
self.$placeButton.options({title: 'Add Place'});
|
||||
that.triggerEvent('removeplace', {id: self.selectedPlace});
|
||||
}
|
||||
|
||||
function selectItem(data) {
|
||||
var id = data.ids.length ? data.ids[0] : null;
|
||||
self.$map.options({selected: id});
|
||||
id && self.$map.panToPlace();
|
||||
// Select item in list
|
||||
var isUndefined, selectedPlace;
|
||||
self.options.selected = data.ids.length ? data.ids[0] : '';
|
||||
isUndefined = !!self.options.selected
|
||||
&& !self.$list.value(self.options.selected, 'type');
|
||||
selectedPlace = self.options.selected && !isUndefined
|
||||
? self.options.selected : null;
|
||||
self.$map.options({selected: selectedPlace});
|
||||
selectedPlace && self.$map.panToPlace();
|
||||
if (isUndefined) {
|
||||
self.selectedPlace = self.options.selected;
|
||||
self.$findPlaceButton.show();
|
||||
self.$placeFlag.hide();
|
||||
self.$placeName.options({
|
||||
title: self.$list.value(self.options.selected, 'name')
|
||||
});
|
||||
self.$placeTitle.show();
|
||||
self.$definePlaceButton.options({
|
||||
title: 'Define Place'
|
||||
}).show();
|
||||
self.$addPlaceButton.options({
|
||||
title: 'Remove Place'
|
||||
}).show();
|
||||
}
|
||||
}
|
||||
|
||||
function selectPlace(place) {
|
||||
var isResult = place.id && place.id[0] == '_';
|
||||
self.$list.options({
|
||||
selected: place.id && !isResult ? [place.id] : []
|
||||
});
|
||||
if (place.id) {
|
||||
//isResult && self.options.places.push(place);
|
||||
self.selectedPlace = place.id;
|
||||
self.$placeFlag.attr({
|
||||
src: Ox.getFlagByGeoname(place.geoname, 16)
|
||||
// Select place on map
|
||||
Ox.print('selectPlace', place)
|
||||
var isResult, isUndefined;
|
||||
self.selectedPlace = place.id || null;
|
||||
isResult = !!place.id && place.id[0] == '_';
|
||||
isUndefined = !!self.options.selected
|
||||
&& !self.$list.value(self.options.selected, 'type');
|
||||
Ox.print('isResult', isResult, 'isUndefined', isUndefined, self.options.selected)
|
||||
if (!isUndefined) {
|
||||
self.$list.options({
|
||||
selected: place.id && !isResult ? [place.id] : []
|
||||
});
|
||||
self.$placeName.options({title: place.geoname || ''});
|
||||
}
|
||||
if (place.id) {
|
||||
if (isResult && isUndefined) {
|
||||
place.name = self.$list.value(self.selectedPlace, 'name');
|
||||
}
|
||||
self.options.mode == 'define' && self.$findPlaceButton.hide();
|
||||
self.$placeFlag.attr({
|
||||
src: Ox.getFlagByGeoname(place.geoname || '', 16)
|
||||
}).show();
|
||||
self.$placeName.options({title: place.name || ''});
|
||||
self.$placeTitle.show();
|
||||
self.$areaKmInput.value(Ox.formatArea(place.area));
|
||||
self.$placeForm.values(place).show();
|
||||
self.$placeButton.options({title: isResult ? 'Add Place' : 'Remove Place'}).show();
|
||||
self.$areaKmInput.value(Ox.formatArea(place.area));
|
||||
updateMatches();
|
||||
self.options.mode == 'define' && self.$definePlaceButton.options({
|
||||
title: isUndefined && !isResult ? 'Define Place' : 'Clear Place'
|
||||
}).show();
|
||||
self.$addPlaceButton.options({
|
||||
title: isResult ? 'Add Place' : 'Remove Place'
|
||||
}).show();
|
||||
if (isResult && isUndefined) {
|
||||
Ox.print('???? s.o.s s.sP', self.options.selected, self.selectedPlace)
|
||||
self.selectedPlace = self.options.selected;
|
||||
editPlace([
|
||||
'geoname', 'type',
|
||||
'latitude', 'longitude',
|
||||
'south', 'west', 'north', 'east', 'area'
|
||||
]);
|
||||
}
|
||||
} else {
|
||||
self.selectedPlace = null;
|
||||
self.$placeTitle.hide();
|
||||
self.$placeForm.hide();
|
||||
self.$placeButton.hide();
|
||||
self.options.mode == 'define' && self.$definePlaceButton.hide();
|
||||
self.$addPlaceButton.hide();
|
||||
}
|
||||
}
|
||||
|
||||
function toFixed(val) {
|
||||
return Ox.isNumber(val) ? val.toFixed(8) : val; // fixme: why can a string be passed ??
|
||||
return Ox.isNumber(val) ? val.toFixed(3) : '';
|
||||
}
|
||||
|
||||
function toggleList() {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue