Skip to content

Instantly share code, notes, and snippets.

@abtris
Created January 29, 2012 10:38
Show Gist options
  • Save abtris/1698216 to your computer and use it in GitHub Desktop.
Save abtris/1698216 to your computer and use it in GitHub Desktop.
mapy.cz
/**
* 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