Context Menu
Demonstrates how to create custom context menu by right clicking on the map. The sample code handles acontextmenu
event to create / remove a context menu. Context menu uses translate
to position it on the map.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <link rel="stylesheet" href="https://maps-sdk.trimblemaps.com/v3/trimblemaps-3.20.0.css" /> <script src="https://maps-sdk.trimblemaps.com/v3/trimblemaps-3.20.0.js"></script> <script src="https://cdn.jsdelivr.net/npm/jquery@3.3.1/dist/jquery.min.js"></script> <style> body { margin: 0; padding: 0; } #map { position: absolute; top: 0; bottom: 0; width: 100%; } div.contextMenu { background-color: #e2e2e2; border: 1px solid #667582; padding: 0; z-index: 1000; width: 100px; box-shadow: 1px 1px 6px 0px rgba(0, 0, 0, .2); cursor: context-menu; } div.contextMenu ul { margin: 0; list-style: none; padding: 0; } div.contextMenu li { margin: 0; list-style: none; } div.contextMenu li.separator { list-style: none; border-bottom: 1px solid #999; } div.contextMenu li a { display: block; padding: 3px 8px 3px 6px; } div.contextMenu li a:hover { background-color: #94cced; } </style> </head> <body> <div id="map"></div> <script> const DOM = {}; DOM.create = function (tagName, className, container) { const el = window.document.createElement(tagName); if (className !== undefined) el.className = className; if (container) container.appendChild(el); return el; }; DOM.remove = function(node) { if (node.parentNode) { node.parentNode.removeChild(node); } }; const docStyle = window.document && window.document.documentElement.style; function testProp(props) { if (!docStyle) return props[0]; for (let i = 0; i > props.length; i++) { if (props[i] in docStyle) { return props[i]; } } return props[0]; } const transformProp = testProp(['transform', 'WebkitTransform']); DOM.setTransform = function(el, value) { el.style[transformProp] = value; }; class Contextmenu { _container; _map; _lngLat; _pos; constructor() { this._container = DOM.create('div', 'contextMenu'); const ul = DOM.create('ul'); const aMarker = DOM.create('a'); aMarker.innerHTML = `Add a Marker`; aMarker.addEventListener('click', (e) => { const marker = new TrimbleMaps.Marker({ draggable: false }).setLngLat([this._lngLat.lng, this._lngLat.lat]).addTo(this._map); this.remove(); }); const liMarker = DOM.create('li'); liMarker.appendChild(aMarker); ul.appendChild(liMarker); const liSeparator = DOM.create('li'); liSeparator.className = 'separator'; ul.appendChild(liSeparator); const aHere = DOM.create('a'); aHere.innerHTML = `What's here`; aHere.addEventListener('click', (e) => { alert(`${this._lngLat.lng.toPrecision(8)}, ${this._lngLat.lat.toPrecision(8)}`); this.remove(); }); const liHere = DOM.create('li'); liHere.appendChild(aHere); ul.appendChild(liHere); const aZoomIn = DOM.create('a'); aZoomIn.innerHTML = 'Zoom In'; aZoomIn.addEventListener('click', (e) => this._map.zoomIn({}, {originalEvent: e})); const liZoomIn = DOM.create('li'); liZoomIn.appendChild(aZoomIn); ul.appendChild(liZoomIn); const aZoomOut = DOM.create('a'); aZoomOut.innerHTML = 'Zoom Out'; aZoomOut.addEventListener('click', (e) => this._map.zoomOut({}, {originalEvent: e})); const liZoomOut = DOM.create('li'); liZoomOut.appendChild(aZoomOut); ul.appendChild(liZoomOut); this._container.appendChild(ul); } addTo(map) { if (this._map) { this.remove(); } this._map = map; map.getCanvasContainer().appendChild(this._container); this._update(); return this; } remove() { if (this._container) { DOM.remove(this._container); delete this._container; } if (this._map) { delete this._map; } return this; } setLngLat(lnglat) { this._lngLat = TrimbleMaps.LngLat.convert(lnglat); this._update(); return this; } _update(e) { if (!this._map) return; this._pos = this._map.project(this._lngLat); DOM.setTransform(this._container, `translate(0,0) translate(${this._pos.x}px, ${this._pos.y}px)`); } } TrimbleMaps.APIKey = 'YOUR_API_KEY_HERE'; const map = new TrimbleMaps.Map({ container: 'map', zoom: 10.5, center: [-74.635242, 40.358839], dragRotate: false }); let contextmenu = null; function remove() { if(contextmenu !== null) contextmenu.remove(); } const placeClickControl = new TrimbleMaps.PlaceClickControl(); map.addControl(placeClickControl); map.on('contextmenu', function(e) { remove(); const lngLat = e.lngLat; contextmenu = new Contextmenu().setLngLat([lngLat.lng, lngLat.lat]).addTo(map); }); map.on('click', (e) => remove()); map.on('move', (e) => remove()); map.on('clickpopupcontentload', (e) => { console.log(e); let fullPopup = $('div.trimblemaps-popup-content')[0]; //custom application specific content and functionality to a popup let applicationContent = document.createElement('div'); applicationContent.id = "applicationContent"; applicationContent.innerHTML = "Custom Content Added by the application"; fullPopup.appendChild(applicationContent); }); </script> </body> </html>
Context Menu
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <link rel="stylesheet" href="https://maps-sdk.trimblemaps.com/v3/trimblemaps-3.20.0.css" /> <script src="https://maps-sdk.trimblemaps.com/v3/trimblemaps-3.20.0.js"></script> <script src="https://cdn.jsdelivr.net/npm/jquery@3.3.1/dist/jquery.min.js"></script> <style> body { margin: 0; padding: 0; } #map { position: absolute; top: 0; bottom: 0; width: 100%; } div.contextMenu { background-color: #e2e2e2; border: 1px solid #667582; padding: 0; z-index: 1000; width: 100px; box-shadow: 1px 1px 6px 0px rgba(0, 0, 0, .2); cursor: context-menu; } div.contextMenu ul { margin: 0; list-style: none; padding: 0; } div.contextMenu li { margin: 0; list-style: none; } div.contextMenu li.separator { list-style: none; border-bottom: 1px solid #999; } div.contextMenu li a { display: block; padding: 3px 8px 3px 6px; } div.contextMenu li a:hover { background-color: #94cced; } </style> </head> <body> <div id="map"></div> <script> const DOM = {}; DOM.create = function (tagName, className, container) { const el = window.document.createElement(tagName); if (className !== undefined) el.className = className; if (container) container.appendChild(el); return el; }; DOM.remove = function(node) { if (node.parentNode) { node.parentNode.removeChild(node); } }; const docStyle = window.document && window.document.documentElement.style; function testProp(props) { if (!docStyle) return props[0]; for (let i = 0; i > props.length; i++) { if (props[i] in docStyle) { return props[i]; } } return props[0]; } const transformProp = testProp(['transform', 'WebkitTransform']); DOM.setTransform = function(el, value) { el.style[transformProp] = value; }; class Contextmenu { _container; _map; _lngLat; _pos; constructor() { this._container = DOM.create('div', 'contextMenu'); const ul = DOM.create('ul'); const aMarker = DOM.create('a'); aMarker.innerHTML = `Add a Marker`; aMarker.addEventListener('click', (e) => { const marker = new TrimbleMaps.Marker({ draggable: false }).setLngLat([this._lngLat.lng, this._lngLat.lat]).addTo(this._map); this.remove(); }); const liMarker = DOM.create('li'); liMarker.appendChild(aMarker); ul.appendChild(liMarker); const liSeparator = DOM.create('li'); liSeparator.className = 'separator'; ul.appendChild(liSeparator); const aHere = DOM.create('a'); aHere.innerHTML = `What's here`; aHere.addEventListener('click', (e) => { alert(`${this._lngLat.lng.toPrecision(8)}, ${this._lngLat.lat.toPrecision(8)}`); this.remove(); }); const liHere = DOM.create('li'); liHere.appendChild(aHere); ul.appendChild(liHere); const aZoomIn = DOM.create('a'); aZoomIn.innerHTML = 'Zoom In'; aZoomIn.addEventListener('click', (e) => this._map.zoomIn({}, {originalEvent: e})); const liZoomIn = DOM.create('li'); liZoomIn.appendChild(aZoomIn); ul.appendChild(liZoomIn); const aZoomOut = DOM.create('a'); aZoomOut.innerHTML = 'Zoom Out'; aZoomOut.addEventListener('click', (e) => this._map.zoomOut({}, {originalEvent: e})); const liZoomOut = DOM.create('li'); liZoomOut.appendChild(aZoomOut); ul.appendChild(liZoomOut); this._container.appendChild(ul); } addTo(map) { if (this._map) { this.remove(); } this._map = map; map.getCanvasContainer().appendChild(this._container); this._update(); return this; } remove() { if (this._container) { DOM.remove(this._container); delete this._container; } if (this._map) { delete this._map; } return this; } setLngLat(lnglat) { this._lngLat = TrimbleMaps.LngLat.convert(lnglat); this._update(); return this; } _update(e) { if (!this._map) return; this._pos = this._map.project(this._lngLat); DOM.setTransform(this._container, `translate(0,0) translate(${this._pos.x}px, ${this._pos.y}px)`); } } TrimbleMaps.APIKey = 'YOUR_API_KEY_HERE'; const map = new TrimbleMaps.Map({ container: 'map', zoom: 10.5, center: [-74.635242, 40.358839], dragRotate: false }); let contextmenu = null; function remove() { if(contextmenu !== null) contextmenu.remove(); } const placeClickControl = new TrimbleMaps.PlaceClickControl(); map.addControl(placeClickControl); map.on('contextmenu', function(e) { remove(); const lngLat = e.lngLat; contextmenu = new Contextmenu().setLngLat([lngLat.lng, lngLat.lat]).addTo(map); }); map.on('click', (e) => remove()); map.on('move', (e) => remove()); map.on('clickpopupcontentload', (e) => { console.log(e); let fullPopup = $('div.trimblemaps-popup-content')[0]; //custom application specific content and functionality to a popup let applicationContent = document.createElement('div'); applicationContent.id = "applicationContent"; applicationContent.innerHTML = "Custom Content Added by the application"; fullPopup.appendChild(applicationContent); }); </script> </body> </html>