Ox.load('UI', { debug: true, hideScreen: true, showScreen: true, theme: 'modern' }, function() { Ox.load('Geo', function() { Ox.getJSON('json/cities50000.json', function(cities) { var places = cities.map(function(city, i) { var countryCode = city.country_code == 'XK' ? 'RS-KO' : city.country_code, marker = city.population > 10000000 ? {size: 24, color: [255, 0, 0]} : city.population > 5000000 ? {size: 22, color: [255, 32, 0]} : city.population > 2000000 ? {size: 20, color: [255, 64, 0]} : city.population > 1000000 ? {size: 18, color: [255, 96, 0]} : city.population > 500000 ? {size: 16, color: [255, 128, 0]} : city.population > 200000 ? {size: 14, color: [255, 160, 0]} : city.population > 100000 ? {size: 12, color: [255, 192, 0]} : city.population > 50000 ? {size: 10, color: [255, 224, 0]} : {size: 8, color: [255, 255, 0]}, area = Math.max(city.population, 1) * 100, latSize = Math.sqrt(area) / Ox.EARTH_CIRCUMFERENCE * 360, lngSize = Math.sqrt(area) * Ox.getDegreesPerMeter(city.latitude); return { alternativeNames: [], area: area, countryCode: countryCode, editable: true, flag: countryCode, geoname: city.name + ', ' + Ox.getCountryByCode(countryCode).name, geonameSort: getGeonameSort(city.name + ', ' + Ox.getCountryByCode(countryCode).name), id: Ox.encodeBase32(Ox.uid()), markerColor: marker.color, markerSize: marker.size, name: city.name, type: 'city', lat: city.latitude, lng: city.longitude, south: city.latitude - latSize / 2, west: city.longitude - lngSize / 2, north: city.latitude + latSize / 2, east: city.longitude + lngSize / 2 }; }); var $listmap = new Ox.ListMap({ addPlace: function(data, callback) { var id = Ox.encodeBase32(Ox.uid()); Ox.print('addplace', getGeonameSort(data.place.geoname)); places.push(Ox.extend(data.place, { geonameSort: getGeonameSort(data.place.geoname), id: id })); callback({ data: {id: id}, result: {code: 200, text: 'OK'} }); }, editPlace: function(data, callback) { var place = Ox.getObjectById(places, data.id); place = Ox.extend(place, data, { geonameSort: getGeonameSort(data.geoname) }); callback({ result: {code: 200, text: 'OK'} }); }, height: window.innerHeight, places: function(options, callback) { // this simulates a remote API Ox.print('OPTIONS', options) var data = {}; // query, sort, range, area if (Ox.isEmpty(options)) { data = { items: places.length, south: 90, west: 180, north: -90, east: -180 }; places.forEach(function(place) { ['south', 'west', 'north', 'east'].forEach(function(v) { if ( ((v == 'south' || v == 'west') && place[v] < data[v]) || ((v == 'north' || v == 'east') && place[v] > data[v]) ) { data[v] = place[v]; } }); }); } else { data.items = places; if (options.query) { // only case is key: 'id', value: ..., operator: '^$' data.items = data.items.filter(function(place) { return place[options.query.key] == options.query.value; }); } if (options.area) { data.items = data.items.filter(function(place) { // fixme: fails if crosses dateline return place.lat > options.area.south && place.lat < options.area.north && place.lng > options.area.west && place.lng < options.area.east; }).sort(function(a, b) { return b.area - a.area; }).filter(function(place, i) { return i < 100; }); } else { data.items.sort(function(a, b) { if (options.sort[0].key == 'geoname') { aValue = a.geonameSort; bValue = b.geonameSort; } else { aValue = a[options.sort[0].key]; bValue = b[options.sort[0].key]; } var ret = 0; if ( (options.sort[0].operator == '+' && aValue < bValue) || (options.sort[0].operator == '-' && aValue > bValue) ) { ret = -1; } else if ( (options.sort[0].operator == '+' && aValue > bValue) || (options.sort[0].operator == '-' && aValue < bValue) ) { ret = 1; } return ret; }); } if (options.ids) { data.positions = {}; data.items.forEach(function(place, i) { if (options.ids.indexOf(place.id) > -1) { data.positions[place.id] = i; } }); delete data.items; } else if (options.range) { data.items = data.items.filter(function(place, i) { return i >= options.range[0] && i < options.range[1]; }); } } Ox.print('DATA', data) callback({ data: data, result: {code: 200, text: 'OK'} }); }, removePlace: function(data, callback) { var i = Ox.getPositionById(places, data.id); places.splice(i, 1); callback(); }, width: window.innerWidth }) .bindEvent({ geocode: function(event, data) { Ox.print(event) Ox.print(JSON.stringify(data)) } }) .appendTo(Ox.UI.$body); $(window).resize(function() { Ox.print('RESIZE', window.innerHeight) $listmap.options({ height: window.innerHeight, width: window.innerWidth }); }); window.$listmap = $listmap; function getGeonameSort(geoname) { var names = geoname.split(', '); if (!Ox.getCountryByGeoname(names[names.length - 1])) { names.push('~'); } return names.reverse().join(', '); } }); }); });