Created
January 29, 2012 10:38
-
-
Save abtris/1698216 to your computer and use it in GitHub Desktop.
mapy.cz
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Input type - address with autocomplete and reverse geocoding using Seznam maps API. | |
*/ | |
angular.inputType('address', function(element) { | |
var scope = this; | |
// full address data from geocoder for angular model | |
var address = {}; | |
// parse input value and set into model | |
this.$parseView = function() { | |
this.$modelValue = address; | |
// valid by address number | |
this.$emit(address.number ? '$valid' : '$invalid', 'NUMBER'); | |
} | |
// set input value from model | |
this.$parseModel = function() { | |
this.$viewValue = (this.$modelValue && this.$modelValue.label ? this.$modelValue.label : ''); | |
} | |
// initialize geomap | |
var geomap = $('#' + element.attr('data-geomap')).data('control'); | |
// bind map control events | |
$(geomap).bind({ | |
// when coords geocoding is finished | |
geocodeCoords: function(event, data) { | |
// set input value | |
element.val(data.label); | |
// emit input $viewChange event | |
scope.$apply(function() { | |
address = data; | |
scope.$emit('$viewChange', data.label); | |
}); | |
} | |
}); | |
// bind autocomplete | |
var spinner = $('#' + element.attr('data-spinner')); | |
element.autocomplete({ | |
delay: 500, | |
source: function(request, response) { | |
spinner.show(); | |
geomap.geocodeQuery(request.term, function(results) { | |
scope.$apply(function() { | |
scope.$emit(results.length ? '$valid' : '$invalid', 'FOUND'); | |
}); | |
response(results); | |
spinner.hide(); | |
}); | |
}, | |
select: function(event, ui) { | |
spinner.show(); | |
geomap.geocodeCoords(ui.item.coords, function(data) { | |
geomap.setCenter(data.coords, { | |
zoom: true, | |
card: data.label | |
}); | |
spinner.hide(); | |
}); | |
return false; | |
} | |
}); | |
}); | |
/** | |
* Widget - geomap | |
*/ | |
angular.widget('ng:lmc-geomap', function(compiledElement) { | |
compiledElement.css('display', 'block'); | |
var Geomap = {}; | |
// Seznam mapy.cz (api4) | |
Geomap.Seznam = function(wrapper) { | |
var self = this; | |
// api cache | |
var cache = { | |
coords: {}, | |
query: {} | |
}; | |
// initialize map | |
var map, card, markerLayer; | |
this.init = function() { | |
map = new SMap(wrapper); | |
map.addDefaultLayer(SMap.DEF_BASE).enable(); | |
map.addDefaultControls(); | |
// card | |
card = new SMap.Card(230); | |
$(card.getBody()).css('padding-right', '18px'); | |
// marker layer | |
markerLayer = new SMap.Layer.Marker(); | |
map.addLayer(markerLayer); | |
markerLayer.enable(); | |
// bind map-click event on control click event | |
map.getSignals().addListener(window, 'map-click', function(signal) { | |
$(self).triggerHandler('click', [SMap.Coords.fromEvent(signal.data.event, map)]); | |
}); | |
} | |
// geocode by query | |
var geocoder = null; | |
this.geocodeQuery = function(query, callback) { | |
// cached | |
if (cache.query[query]) { | |
callback(cache.query[query]); | |
// query api | |
} else { | |
// abort previous request | |
if (geocoder) { | |
geocoder.abort(); | |
} | |
geocoder = new SMap.Geocoder(query, function(geocoder) { | |
var results = geocoder.getResults(); | |
results = (results[0] && results[0].results && results[0].results.length ? results[0].results : []); | |
cache.query[query] = results; | |
callback(results); | |
}); | |
} | |
}; | |
// (reverse) geocode by coords | |
this.geocodeCoords = function(coords, callback) { | |
// array of coords => SMap.Coords | |
if (typeof(coords) == 'object' && !coords.toWGS84) { | |
coords = SMap.Coords.fromWGS84(coords[0], coords[1]); | |
} | |
// onfinish callbacks | |
function callbacks(data) { | |
// trigger callback | |
if (callback) { | |
callback(data); | |
} | |
// trigger global 'geocodeCoords' event | |
$(self).triggerHandler('geocodeCoords', [data]); | |
} | |
// cached | |
var ckey = coords.x + '-' + coords.y; | |
if (cache.coords[ckey]) { | |
callbacks(cache.coords[ckey]); | |
// reverse geocode | |
} else { | |
new SMap.Geocoder.Reverse(coords, function(geocoder) { | |
var results = geocoder.getResults(); | |
var coords = results.coords.toWGS84(); | |
// result data | |
var data = { | |
coords: [coords[0], coords[1]] | |
}; | |
// create address fields from items[] | |
var fields = { | |
'stre': { key: 'street', filter: '^ulice ' }, | |
'addr': { key: 'number', filter: '^č\.p\. ' }, | |
'muni': { key: 'city' }, | |
'dist': { key: 'district', filter: '^okres ' }, | |
'regi': { key: 'region', filter: '^kraj ' }, | |
'ward': { key: 'ward', filter: '^(čtvrť|část obce) ' }, | |
'coun': { key: 'country' } | |
} | |
for (var i in results.items) { | |
var item = results.items[i]; | |
var field = fields[item.type]; | |
if (field) { | |
var value = item.name; | |
// apply filter | |
if (field.filter) { | |
value = value.replace(new RegExp(field.filter, 'i'), ''); | |
} | |
data[field.key] = value; | |
} | |
} | |
// zip code is not included in items, try parse it from place (label) | |
if (data.city) { | |
try { | |
var match = new RegExp(', ([0-9]{3}) ([0-9]{2}) ' + data.city).exec(results.label); | |
if (match) data.zip = match[1] + ' ' + match[2]; | |
} catch (e) {} | |
} | |
// create label | |
if (data.number) { | |
data.label = (data.street ? data.street : data.ward) + ' ' + data.number; | |
if (data.city) data.label += ', ' + (data.zip ? data.zip + ' ' : '') + data.city; | |
if (data.country) data.label += ', ' + data.country; | |
} else { | |
data.label = results.label; | |
} | |
cache.coords[ckey] = data; | |
callbacks(data); | |
}); | |
} | |
}, | |
// sets map center with additional actions (zoom, marker, card) | |
this.setCenter = function(coords, options) { | |
if (!coords) { | |
return; | |
} | |
coords = SMap.Coords.fromWGS84(coords[0], coords[1]); | |
// zoom into coords | |
if (options.zoom) { | |
map.setCenterZoom(coords, (options.zoom === true ? 15 : options.zoom)); | |
} else { | |
map.setCenter(coords); | |
} | |
// add marker | |
if (options.marker) { | |
markerLayer.removeAll(); | |
markerLayer.addMarker(new SMap.Marker(coords, 'marker')); | |
} | |
// add card with label | |
if (options.card) { | |
map.addCard(card, coords); | |
card.getBody().innerHTML = options.card; | |
} | |
} | |
} | |
// create map control and assign to element data | |
var control = new Geomap.Seznam($(compiledElement)[0]); | |
$(compiledElement).data('control', control); | |
return function(linkElement) { | |
// initialize map | |
control.init(); | |
// when model supplied, setup watcher | |
var model = linkElement.attr('model'); | |
if (model) { | |
this.$watch(model, function(scope, value) { | |
if (value) { | |
// set center with marker | |
control.setCenter(value.coords, { | |
zoom: true, | |
marker: true | |
}); | |
} | |
}); | |
} | |
} | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment