Visual UGC Docs
Search
K

JavaScript API for Map Widget

Background

The Map plugin’s purpose is to provide a visualisation of where content is happening. This adds value when the location of content is as important as the content itself.
  • The Mapping Widget overlays geo-filtered content as Pins on a map;
  • The user sets the initial viewing area
  • The user can choose from various mapping providers – Google Maps, Mapzen, CartoDB and OpenStreetMap
  • They can customise the appearance of the Map based on which provider they choose
  • Each Pin reflects a Tile or a cluster (group) of Tiles
  • The Pin size is relative to the cluster size. The bigger the Pin, the more content that it represents.
  • The user can zoom in and out on the the map to see a more refined location of the Pins

Geohash

Tiles in the Maps Widget are grouped into clusters using geohash. Geohash is a string representation of coordinates.
Geohash is a geocoding system invented by Gustavo Niemeyer and placed into the public domain. It is a hierarchical spatial data structure which subdivides space into buckets of grid shape, which is one of the many applications of what is known as a Z-order curve, and generally space-filling curves.
Reference Wikipedia: Geohash

Execution flows

Map widget creation

  1. 1.
    MapWidget is created. var widget = new MapWidget()
  2. 2.
    Custom JS code is executed // custom javascript
  3. 3.
    Widget is initialized. widget.initialize()
    1. 1.
      Leaflet map is created. var map = widget.createMap()
    2. 2.
      Map layer is created. map.setLayer(widget.createLayer())

On map move

  1. 1.
    On move end is called. widget.handleMoveEnd()
    1. 1.
      Get all tile summaries for the current visible area. var summaries = widget.getAggregatedDataByBounds()
    2. 2.
      Render the fetched summaries. widget.renderSummaries(summaries)

On marker clicked

  1. 1.
    On marker click is called. widget.handleMarkerClick()

Methods

.initialize(options)

Initialize the map widget.
Parameters
Name
Type
Description
options
`Object`
Options
Return Promise A promise that resolves when initialization completes.

.createMap()

Creates a Leaflet Map object.
Return L.Map The created map object.

.createLayer(style)

Creates a Leaflet Map object.
Parameters
Name
Type
Description
style
`Object`
Style object
Return L.Layer The created map object.

.handleMarkerClick(event

Handles marker click. The default implementation is updates the content list if it is connected to a content widget. Otherwise, it only emits the ‘marker:click’ event which can be listen using .on
Parameters
Name
Type
Description
event
`Event`
Click event
Return void

Example usage

widget.handleMarkerClick = function (event) {
var $dom = $(event.originalEvent.target);
// do something
// call parent method (optional)
Widget.prototype.handleMarkerClick.call(widget, event);
};

.handleMoveEnd()

Handles map panning, resizing and zooming.
Return void

.createMarkerBySummary(summary)

Creates a Leaflet Map object.
Parameters
Name
Type
Description
summary
{
geohash:String,––
quantity:Integer,
avg_location:{
longitude:Float,
latitude:Float
}
} | Summary object |
Return L.Marker The marker object.

.on(eventName, handler)

Listens to an event.
Parameters
Name
Type
Description
eventName
`String`
Event name
handler
`Function(data:Object):void`
A handler function
Return MapWidget The current map widget object.

Example usage

// Event 'marker:click' might not emit if handleMoveEnd() or handleMarkerClick() is overrode.
widget.on('marker:click', function (summary) {
console.log('Geohash: ' + summary.geohash);
console.log('Quantity: ' + summary.quantity);
console.log('Average longitude: ' + summary.avg_location.longitude);
console.log('Average latitude: ' + summary.avg_location.latitude);
});

.getAggregatedDataByBounds(sw, ne, numGeohashPerView)

Listens to an event.
Parameters
Name
Type
Description
sw
`{lat:Float, lng:Float}`
South west coordinates
ne
`{lat:Float, lng:Float}`
North east coordinates
numGeohashPerView
`Integer`
(Optional) Max number of geohashes to generate in the given view. Default: `32`
Return Promise<Summary[]> A promise that resolves to summaries.

Exported methods

Exported methods can be called in parent window.

.getAggregatedDataByBounds(sw, ne, numGeohashPerView)

Example usage (own Google Maps)

var map; // Google Map instance
// get the map widget by ID
var mapWidget = Stackla.WidgetManager.getWidgetInstanceByWidgetId(1234);
map.addListener('bounds_changed', function () {
var bounds = map.getBounds();
var sw = bounds.getSouthWest();
var ne = bounds.getNorthEast();
mapWidget.getAggregatedDataByBounds(
{lat: sw.lat(), lng: sw.lng()},
{lat: ne.lat(), lng: ne.lng()},
16
).then(function (summaries) {
}).catch(function (ex) {
console.error(ex);
});
});

Customization examples

Add logic before/after map widget starts.

It is possible to add logic before and after the widget initializes. Below is an example using Promise.
widget.initialize = function (options) {
(new Promise(function (resolve, reject) {
try {
// perform necessary options before widget initialization starts.
// ...
// ...
// at the end, call resolve()
resolve();
} catch (ex) {
reject(ex);
}
}).then(function () {
return MapWidget.prototype.initialize.call(widget, options);
}).then(function () {
// then perform actions after widget initialization is completed.
}).catch(function (ex) {
// catch error/exception
console.error(ex);
});
};

Initialize Leaflet with custom options

// Leaflet options @see http://leafletjs.com/reference-1.0.0.html#map-factory
widget.createMap = function () {
var map = L.map('map', {
maxBounds: [
[-85.0, -180.0],
[85.0, 180.0]
],
scrollWheelZoom: false
});
return map;
};

Use a different map layer (e.g. Google Maps)

// You can create your own Google Map style here https://mapstyle.withgoogle.com/
widget.createLayer = function (style) {
return L.gridLayer.googleMutant({
styles: styles,
type: 'roadmap'
});
};