diff --git a/static/djangocms_googlemap/js/.aldryn-folder b/static/djangocms_googlemap/js/.aldryn-folder
new file mode 100644
index 0000000..e69de29
diff --git a/static/djangocms_googlemap/js/djangocms.googlemap.js b/static/djangocms_googlemap/js/djangocms.googlemap.js
new file mode 100644
index 0000000..5048b45
--- /dev/null
+++ b/static/djangocms_googlemap/js/djangocms.googlemap.js
@@ -0,0 +1,308 @@
+'use strict';
+/*
+ * Copyright https://github.com/divio/djangocms-googlemap
+ */
+
+(function () {
+ var GoogleMap = (function () {
+ /**
+ * Helper function that retrieves a data-attribute value.
+ *
+ * @function getAttr
+ * @param {HTMLElement} element single document node
+ * @param {String} data data-attribute to retrieve
+ * @return {String} value returns the value from the data-attribute
+ */
+ function getAttr(element, data) {
+ var value = element.getAttribute('data-' + data);
+
+ // true/false values need to be parsed from string to boolean
+ // from the attributes data
+ if (value === 'true') {
+ return true;
+ } else if (value === 'false') {
+ return false;
+ }
+ return value;
+ }
+
+ /**
+ * Initiates the GoogleMap plugin inside the ``djangocms-googlemap-container`` container.
+ *
+ *
+ *
+ * @class GoogleMap
+ * @constructor
+ * @param {HTMLElement} container single document node
+ */
+ function GoogleMapConstructor(container) {
+ this.container = container;
+ this.markers = [];
+ this.bounds = new google.maps.LatLngBounds();
+ this.settings = {
+ zoom: parseInt(getAttr(container, 'zoom')),
+ styles: JSON.parse(getAttr(container, 'style') || false),
+ zoomControl: getAttr(container, 'zoom-control'),
+ streetViewControl: getAttr(container, 'street-view-control'),
+ rotateControl: getAttr(container, 'rotate-control'),
+ scaleControl: getAttr(container, 'scale-control'),
+ fullscreenControl: getAttr(container, 'fullscreen-control'),
+ panControl: getAttr(container, 'pan-control'),
+ disableDoubleClickZoom: getAttr(container, 'double-click-zoom') === false,
+ draggable: getAttr(container, 'draggable'),
+ keyboardShortcuts: getAttr(container, 'keyboard-shortcuts'),
+ scrollwheel: getAttr(container, 'scrollwheel'),
+ mapTypeId: google.maps.MapTypeId[getAttr(container, 'map-type-control')],
+ center: {
+ lat: parseFloat(getAttr(container, 'lat')) || 0,
+ lng: parseFloat(getAttr(container, 'lng')) || 0
+ }
+ };
+ var mapContainer = container.getElementsByClassName('js-djangocms-googlemap-container');
+ var markers = container.getElementsByClassName('js-djangocms-googlemap-marker');
+ var routes = container.getElementsByClassName('js-djangocms-googlemap-route');
+
+ // create iterable arrays
+ markers = [].slice.call(markers);
+ routes = [].slice.call(routes);
+
+ // init the map
+ this.map = new google.maps.Map(mapContainer[0], this.settings);
+
+ // the markers and routes need to be loaded after the map has been
+ // initialised as we need to access ``this.map``
+ if (markers.length) {
+ this.addMarkers(markers);
+ }
+ if (routes.length) {
+ this.addRoutes(routes);
+ }
+ }
+
+ // attach methods
+ GoogleMapConstructor.prototype = {
+ /**
+ * Processes a collection of markers and passes to ``addMarker``.
+ *
+ * @method addMarkers
+ * @param {Array} markers collection of marker nodes
+ */
+ addMarkers: function addMarkers(markers) {
+ var list = markers.map(function (marker) {
+ return {
+ admin: getAttr(marker, 'admin'),
+ title: getAttr(marker, 'title'),
+ address: getAttr(marker, 'address'),
+ lat: getAttr(marker, 'lat'),
+ lng: getAttr(marker, 'lng'),
+ icon: getAttr(marker, 'icon'),
+ showContent: getAttr(marker, 'show-content'),
+ content: marker.innerHTML,
+ animation: google.maps.Animation.DROP
+ }
+ }, this);
+
+ list.forEach(function (marker) {
+ this.addMarker(marker);
+ }, this);
+ },
+
+ /**
+ * Processes a single marker and attaches to ``this.map``.
+ *
+ * @method addMarker
+ * @param {HTMLElement} marker single marker node
+ */
+ addMarker: function addMarker(marker) {
+ var that = this;
+ var latLng = {
+ lat: parseFloat(marker.lat),
+ lng: parseFloat(marker.lng)
+ };
+ var geocoder = new google.maps.Geocoder();
+ var pin;
+ var coords;
+
+ // if there is no manual latlng defined, start geocoder
+ if (!latLng.lat || !latLng.lng) {
+ geocoder.geocode({ address: marker.address }, function (results, status) {
+ if (status === google.maps.GeocoderStatus.OK) {
+ coords = results[0].geometry.location;
+ marker.lat = coords.lat();
+ marker.lng = coords.lng();
+ that.addMarker(marker);
+ }
+ });
+ } else {
+ // marker data is ready, add to map
+ marker.position = latLng;
+ marker.map = this.map;
+ pin = new google.maps.Marker(marker);
+ // updated related components
+ pin.setMap(this.map);
+ this.markers.push(pin);
+ this.bounds.extend(pin.position);
+ this._addInfoWindow(pin);
+ this._addEditing(pin);
+ }
+
+ // call update every time a new marker has been added
+ if (this.map) {
+ this.update();
+ }
+ },
+
+ /**
+ * Update map position and bounds.
+ *
+ * @method update
+ */
+ update: function update() {
+ google.maps.event.addListenerOnce(this.map, 'bounds_changed',
+ function () {
+ if (this.map.getZoom() > this.settings.zoom) {
+ this.map.setZoom(this.settings.zoom);
+ }
+ }.bind(this));
+ this.map.fitBounds(this.bounds);
+ },
+
+ /**
+ * Processes a collection of routes and passes to ``addRoute``.
+ * Only one route can be displayed by the default Google Maps
+ * interface. Feel free to use this functionality to enhance the
+ * default UI with more route options.
+ *
+ * @method addRoutes
+ * @param {Array} routes collection of route nodes
+ */
+ addRoutes: function addRoutes(routes) {
+ routes.forEach(function (route) {
+ this.addRoute(route);
+ }, this);
+ },
+
+ /**
+ * Processes a single route and attaches to ``this.map``.
+ *
+ * @method addRoute
+ * @param {HTMLElement} route single route node
+ */
+ addRoute: function addRoute(route) {
+ var that = this;
+ var el = 'js-djangocms-googlemap-direction';
+ var directions = route.getElementsByClassName(el);
+ var title = getAttr(route, 'title');
+ var request = {
+ origin: getAttr(route, 'origin'),
+ destination: getAttr(route, 'destination'),
+ travelMode: getAttr(route, 'travel-mode')
+ };
+
+ this.directionsDisplay = new google.maps.DirectionsRenderer();
+ this.directionsService = new google.maps.DirectionsService();
+
+ this.directionsDisplay.setPanel(directions[0]);
+ this.directionsDisplay.setMap(this.map);
+
+ // if origin is not provided ask for your location
+ if (!request.origin && 'geolocation' in navigator) {
+ navigator.geolocation.getCurrentPosition(function(position) {
+ request.origin = position.coords.latitude + ',' + position.coords.longitude;
+ that.setDirection(request);
+ });
+ } else {
+ that.setDirection(request);
+ }
+ },
+
+ /**
+ * Adds the direction to the ``djangocms-googlemap-direction``dom node.
+ *
+ * @method setDirection
+ * @param {Object} request request to be passed to the ``directionsService``
+ */
+ setDirection: function setDirection(request) {
+ var that = this;
+
+ this.directionsService.route(request, function(result, status) {
+ if (status === 'OK') {
+ that.directionsDisplay.setDirections(result);
+ }
+ });
+ },
+
+ /**
+ * Attaches the GoogleMap info window to the marker pin.
+ *
+ * @method _addInfoWindow
+ * @private
+ * @param {Object} marker google map marker node
+ */
+ _addInfoWindow: function _addInfoWindow(marker) {
+ if (marker.content.trim() === '') {
+ return false;
+ }
+ var that = this;
+ var infoWindow = new google.maps.InfoWindow({
+ disableAutoPan: true,
+ content: marker.content
+ });
+
+ google.maps.event.addListener(marker, 'click', function () {
+ infoWindow.open(that.map, marker);
+ marker.setAnimation(google.maps.Animation.BOUNCE);
+ // stop animation after a certain timeframe
+ setTimeout(function () {
+ marker.setAnimation(null);
+ }, 750);
+ });
+
+ if (marker.showContent) {
+ infoWindow.open(this.map, marker);
+ }
+ },
+
+ /**
+ * Adds double-clock to edit on the google map pin.
+ *
+ * @method _addEditing
+ * @private
+ * @param {Object} marker google map marker node
+ */
+ _addEditing: function _addEditing(marker) {
+ // attach double-click to edit for markers
+ if (window.CMS && window.CMS.Modal) {
+ google.maps.event.addListener(marker, 'dblclick', function (e) {
+ // the native event in google.maps is stored in e.xa
+ // there's no need to continue if google decides to rename it
+ if (!e.xa) {
+ return false;
+ }
+ e.xa.stopPropagation();
+
+ var modal = new CMS.Modal();
+
+ modal.open({
+ url: marker.admin
+ });
+ });
+ }
+ }
+ };
+
+ return GoogleMapConstructor;
+ })();
+
+ // make sure google maps is loaded after our dom is ready
+ window.addEventListener('load', function () {
+ var elements = document.getElementsByClassName('js-djangocms-googlemap');
+
+ elements = [].slice.call(elements);
+ elements.forEach(function (element) {
+ new GoogleMap(element);
+ }, this);
+ });
+})();
diff --git a/templates/djangocms_googlemap/default/.aldryn-folder b/templates/djangocms_googlemap/default/.aldryn-folder
new file mode 100644
index 0000000..e69de29
diff --git a/templates/djangocms_googlemap/default/map.html b/templates/djangocms_googlemap/default/map.html
new file mode 100644
index 0000000..ff28e55
--- /dev/null
+++ b/templates/djangocms_googlemap/default/map.html
@@ -0,0 +1,51 @@
+{% load i18n staticfiles sekizai_tags cms_tags %}
+
+
+
+ {% for plugin in instance.child_plugin_instances %}
+ {% render_plugin plugin %}
+ {% endfor %}
+
+
+{% addtoblock "js" %}{% endaddtoblock %}
+{% addtoblock "js" %}{% endaddtoblock %}
+
+{% comment %}
+ {{ googlemap_key }}
+
+ {{ instance.title }}
+ {{ instance.width }}
+ {{ instance.height }}
+ {{ instance.zoom }}
+ {{ instance.style }}
+
+ {{ instance.map_type_control }}
+ {{ instance.zoom_control }}
+ {{ instance.street_view_control }}
+ {{ instance.rotate_control }}
+ {{ instance.scale_control }}
+ {{ instance.fullscreen_control }}
+ {{ instance.pan_control }}
+ {{ instance.double_click_zoom }}
+ {{ instance.draggable }}
+ {{ instance.keyboard_shortcuts }}
+ {{ instance.scrollwheel }}
+{% endcomment %}
diff --git a/templates/djangocms_googlemap/default/marker.html b/templates/djangocms_googlemap/default/marker.html
new file mode 100644
index 0000000..7324d2c
--- /dev/null
+++ b/templates/djangocms_googlemap/default/marker.html
@@ -0,0 +1,24 @@
+{% load cms_tags %}
+
+
+ {{ instance.info_content|safe }}
+
+
+{% comment %}
+ {{ instance.title }}
+ {{ instance.address }}
+ {{ instance.lat }}
+ {{ instance.lng }}
+ {{ instance.icon }}
+ {{ instance.show_content }}
+ {{ instance.info_content }}
+{% endcomment %}
diff --git a/templates/djangocms_googlemap/default/route.html b/templates/djangocms_googlemap/default/route.html
new file mode 100644
index 0000000..86fa6b5
--- /dev/null
+++ b/templates/djangocms_googlemap/default/route.html
@@ -0,0 +1,15 @@
+
+
+{% comment %}
+ {{ instance.title }}
+ {{ instance.origin }}
+ {{ instance.destination }}
+ {{ instance.travel_mode }}
+{% endcomment %}