Commit ec2bbbc25b2833420c9c26f2386bcad6bf79f7c8

Authored by Igor Kulikov
1 parent c5d47bbe

UI: Widgets. Improve image map.

... ... @@ -78,7 +78,7 @@
78 78 "sizeY": 6.5,
79 79 "resources": [],
80 80 "templateHtml": "",
81   - "templateCss": ".error {\n color: red;\n}\n.tb-labels {\n color: #222;\n font: 12px/1.5 \"Helvetica Neue\", Arial, Helvetica, sans-serif;\n text-align: center;\n width: 200px;\n white-space: nowrap;\n}",
  81 + "templateCss": ".leaflet-zoom-box {\n\tz-index: 9;\n}\n\n.leaflet-pane { z-index: 4; }\n\n.leaflet-tile-pane { z-index: 2; }\n.leaflet-overlay-pane { z-index: 4; }\n.leaflet-shadow-pane { z-index: 5; }\n.leaflet-marker-pane { z-index: 6; }\n.leaflet-tooltip-pane { z-index: 7; }\n.leaflet-popup-pane { z-index: 8; }\n\n.leaflet-map-pane canvas { z-index: 1; }\n.leaflet-map-pane svg { z-index: 2; }\n\n.leaflet-control {\n\tz-index: 9;\n}\n.leaflet-top,\n.leaflet-bottom {\n\tz-index: 11;\n}\n\n.tb-marker-label {\n border: none;\n background: none;\n box-shadow: none;\n}\n\n.tb-marker-label:before {\n border: none;\n background: none;\n}\n",
82 82 "controllerScript": "self.onInit = function() {\n self.ctx.map = new TbMapWidgetV2('image-map', false, self.ctx);\n}\n\nself.onDataUpdated = function() {\n self.ctx.map.update();\n}\n\nself.onResize = function() {\n self.ctx.map.resize();\n}\n\nself.getSettingsSchema = function() {\n return TbMapWidgetV2.settingsSchema('image-map');\n}\n\nself.getDataKeySettingsSchema = function() {\n return TbMapWidgetV2.dataKeySettingsSchema('image-map');\n}\n\nself.actionSources = function() {\n return TbMapWidgetV2.actionSources();\n}\n\nself.onDestroy = function() {\n}\n",
83 83 "settingsSchema": "{}",
84 84 "dataKeySettingsSchema": "{}\n",
... ...
... ... @@ -224,7 +224,7 @@ export default class TbGoogleMap {
224 224 }
225 225
226 226 if (settings.displayTooltip) {
227   - this.createTooltip(marker, settings.tooltipPattern, settings.tooltipReplaceInfo, markerArgs);
  227 + this.createTooltip(marker, settings.tooltipPattern, settings.tooltipReplaceInfo, settings.autocloseTooltip, markerArgs);
228 228 }
229 229
230 230 if (onClickListener) {
... ... @@ -241,11 +241,17 @@ export default class TbGoogleMap {
241 241 /* eslint-enable no-undef */
242 242
243 243 /* eslint-disable no-undef */
244   - createTooltip(marker, pattern, replaceInfo, markerArgs) {
  244 + createTooltip(marker, pattern, replaceInfo, autoClose, markerArgs) {
245 245 var popup = new google.maps.InfoWindow({
246 246 content: ''
247 247 });
  248 + var map = this;
248 249 marker.addListener('click', function() {
  250 + if (autoClose) {
  251 + map.tooltips.forEach((tooltip) => {
  252 + tooltip.popup.close();
  253 + });
  254 + }
249 255 popup.open(this.map, marker);
250 256 });
251 257 this.tooltips.push( {
... ...
... ... @@ -14,15 +14,10 @@
14 14 * limitations under the License.
15 15 */
16 16
17   -import 'tooltipster/dist/css/tooltipster.bundle.min.css';
18   -import 'tooltipster/dist/js/tooltipster.bundle.min.js';
19   -import 'tooltipster/dist/css/plugins/tooltipster/sideTip/themes/tooltipster-sideTip-shadow.min.css';
  17 +import 'leaflet/dist/leaflet.css';
  18 +import L from 'leaflet/dist/leaflet';
20 19
21   -import './image-map.scss';
22   -
23   -const pinShape = '<path id="pin" d="m 12.033721,23.509909 c 0.165665,-3.220958 1.940547,-8.45243 4.512974,-11.745035 1.401507,-1.7940561 2.046337,-3.5425327 2.046337,-4.6032909 0,-3.6844827 -2.951858,-6.67149197 -6.592948,-6.67149197 l -1.68e-4,0 c -3.6412584,0 -6.5929483,2.98700927 -6.5929483,6.67149197 0,1.0607582 0.6448307,2.8092348 2.0463367,4.6032909 2.5724276,3.292605 4.3471416,8.524077 4.5129736,11.745035 l 0.06745,0 z" style="fill:#f2756a;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-opacity:1"/>';
24   -const circleShape = '<circle id="circle" fill-rule="evenodd" cy="6.9234" cx="12" clip-rule="evenodd" r="1.5"/>';
25   -const pinSvg = `<svg class="image-map-pin-image" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">${pinShape}${circleShape}</svg>`;
  20 +const maxZoom = 4;
26 21
27 22 export default class TbImageMap {
28 23
... ... @@ -31,10 +26,9 @@ export default class TbImageMap {
31 26 this.ctx = ctx;
32 27 this.tooltips = [];
33 28
34   - $containerElement.append('<div id="image-map-container"><div id="image-map"></div></div>');
  29 + this.$containerElement = $containerElement;
  30 + this.$containerElement.css('background', '#fff');
35 31
36   - this.imageMapContainer = angular.element('#image-map-container', $containerElement);
37   - this.imageMap = angular.element('#image-map', $containerElement);
38 32 this.aspect = 0;
39 33 this.width = 0;
40 34 this.height = 0;
... ... @@ -108,7 +102,7 @@ export default class TbImageMap {
108 102 if (keyData && keyData.data && keyData.data[0]) {
109 103 var attrValue = keyData.data[0][1];
110 104 if (attrValue && attrValue.length) {
111   - this.loadImage(attrValue, this.aspect > 0 ? null : this.initCallback);
  105 + this.loadImage(attrValue, this.aspect > 0 ? null : this.initCallback, true);
112 106 }
113 107 }
114 108 }
... ... @@ -117,72 +111,145 @@ export default class TbImageMap {
117 111 }
118 112 }
119 113
120   - loadImage(imageUrl, initCallback) {
  114 + loadImage(imageUrl, initCallback, updateImage) {
121 115 if (!imageUrl) {
122 116 imageUrl = 'data:image/svg+xml;base64,PHN2ZyBpZD0ic3ZnMiIgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMTAwIiB3aWR0aD0iMTAwIiB2ZXJzaW9uPSIxLjEiIHhtbG5zOmNjPSJodHRwOi8vY3JlYXRpdmVjb21tb25zLm9yZy9ucyMiIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIgdmlld0JveD0iMCAwIDEwMCAxMDAiPgogPGcgaWQ9ImxheWVyMSIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMCAtOTUyLjM2KSI+CiAgPHJlY3QgaWQ9InJlY3Q0Njg0IiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBoZWlnaHQ9Ijk5LjAxIiB3aWR0aD0iOTkuMDEiIHN0cm9rZT0iIzAwMCIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiB5PSI5NTIuODYiIHg9Ii40OTUwNSIgc3Ryb2tlLXdpZHRoPSIuOTkwMTAiIGZpbGw9IiNlZWUiLz4KICA8dGV4dCBpZD0idGV4dDQ2ODYiIHN0eWxlPSJ3b3JkLXNwYWNpbmc6MHB4O2xldHRlci1zcGFjaW5nOjBweDt0ZXh0LWFuY2hvcjptaWRkbGU7dGV4dC1hbGlnbjpjZW50ZXIiIGZvbnQtd2VpZ2h0PSJib2xkIiB4bWw6c3BhY2U9InByZXNlcnZlIiBmb250LXNpemU9IjEwcHgiIGxpbmUtaGVpZ2h0PSIxMjUlIiB5PSI5NzAuNzI4MDkiIHg9IjQ5LjM5NjQ3NyIgZm9udC1mYW1pbHk9IlJvYm90byIgZmlsbD0iIzY2NjY2NiI+PHRzcGFuIGlkPSJ0c3BhbjQ2OTAiIHg9IjUwLjY0NjQ3NyIgeT0iOTcwLjcyODA5Ij5JbWFnZSBiYWNrZ3JvdW5kIDwvdHNwYW4+PHRzcGFuIGlkPSJ0c3BhbjQ2OTIiIHg9IjQ5LjM5NjQ3NyIgeT0iOTgzLjIyODA5Ij5pcyBub3QgY29uZmlndXJlZDwvdHNwYW4+PC90ZXh0PgogIDxyZWN0IGlkPSJyZWN0NDY5NCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgaGVpZ2h0PSIxOS4zNiIgd2lkdGg9IjY5LjM2IiBzdHJva2U9IiMwMDAiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgeT0iOTkyLjY4IiB4PSIxNS4zMiIgc3Ryb2tlLXdpZHRoPSIuNjM5ODYiIGZpbGw9Im5vbmUiLz4KIDwvZz4KPC9zdmc+Cg==';
123 117 }
124   - this.imageMap.css({backgroundImage: 'url('+imageUrl+')'});
  118 + this.imageUrl = imageUrl;
125 119 var imageMap = this;
126 120 var testImage = document.createElement('img'); // eslint-disable-line
127 121 testImage.style.visibility = 'hidden';
128 122 testImage.onload = function() {
129 123 imageMap.aspect = testImage.width / testImage.height;
130 124 document.body.removeChild(testImage); //eslint-disable-line
131   - imageMap.onresize();
  125 + imageMap.onresize(updateImage);
132 126 if (initCallback) {
133 127 setTimeout(initCallback, 0); //eslint-disable-line
134   - } else {
135   - imageMap.onresize();
136 128 }
137 129 }
138 130 document.body.appendChild(testImage); //eslint-disable-line
139 131 testImage.src = imageUrl;
140 132 }
141 133
142   - onresize() {
  134 + onresize(updateImage) {
143 135 if (this.aspect > 0) {
144   - var width = this.imageMapContainer.width();
  136 + var width = this.$containerElement.width();
145 137 if (width > 0) {
146 138 var height = width / this.aspect;
147   - var imageMapHeight = this.imageMapContainer.height();
  139 + var imageMapHeight = this.$containerElement.height();
148 140 if (imageMapHeight > 0 && height > imageMapHeight) {
149 141 height = imageMapHeight;
150 142 width = height * this.aspect;
151 143 }
  144 + width *= maxZoom;
  145 + var prevWidth = this.width;
  146 + var prevHeight = this.height;
152 147 if (this.width !== width) {
153 148 this.width = width;
154 149 this.height = width / this.aspect;
155   - this.imageMap.css({width: this.width, height: this.height});
156   - this.markers.forEach((marker) => {
157   - this.updateMarkerDimensions(marker);
158   - });
  150 + if (!this.map) {
  151 + this.initMap(updateImage);
  152 + } else {
  153 + var lastCenterPos = this.latLngToPoint(this.map.getCenter());
  154 + lastCenterPos.x /= prevWidth;
  155 + lastCenterPos.y /= prevHeight;
  156 + this.updateBounds(updateImage, lastCenterPos);
  157 + this.map.invalidateSize(true);
  158 + this.updateMarkers();
  159 + }
159 160 }
160 161 }
161 162 }
162 163 }
163 164
  165 + initMap(updateImage) {
  166 + if (!this.map && this.aspect > 0) {
  167 + var center = this.pointToLatLng(this.width/2, this.height/2);
  168 + this.map = L.map(this.$containerElement[0], {
  169 + minZoom: 1,
  170 + maxZoom: maxZoom,
  171 + center: center,
  172 + zoom: 1,
  173 + crs: L.CRS.Simple,
  174 + attributionControl: false
  175 + });
  176 + this.updateBounds(updateImage);
  177 + this.updateMarkers();
  178 + }
  179 + }
  180 +
  181 + pointToLatLng(x, y) {
  182 + return L.CRS.Simple.pointToLatLng({x:x, y:y}, maxZoom-1);
  183 + }
  184 +
  185 + latLngToPoint(latLng) {
  186 + return L.CRS.Simple.latLngToPoint(latLng, maxZoom-1);
  187 + }
  188 +
164 189 inited() {
165   - return this.aspect > 0 ? true : false;
  190 + return angular.isDefined(this.map);
166 191 }
167 192
168   - updateMarkerLabel(marker, settings) {
169   - if (settings.showLabel) {
170   - marker.labelElement.css({color: settings.labelColor});
171   - marker.labelElement.html(`<b>${settings.labelText}</b>`);
  193 + updateBounds(updateImage, lastCenterPos) {
  194 + var w = this.width;
  195 + var h = this.height;
  196 + var southWest = this.pointToLatLng(0, h);
  197 + var northEast = this.pointToLatLng(w, 0);
  198 + var bounds = new L.LatLngBounds(southWest, northEast);
  199 +
  200 + if (updateImage && this.imageOverlay) {
  201 + this.imageOverlay.remove();
  202 + this.imageOverlay = null;
172 203 }
  204 +
  205 + if (this.imageOverlay) {
  206 + this.imageOverlay.setBounds(bounds);
  207 + } else {
  208 + this.imageOverlay = L.imageOverlay(this.imageUrl, bounds).addTo(this.map);
  209 + }
  210 + var padding = 200 * maxZoom;
  211 + southWest = this.pointToLatLng(-padding, h + padding);
  212 + northEast = this.pointToLatLng(w+padding, -padding);
  213 + var maxBounds = new L.LatLngBounds(southWest, northEast);
  214 + this.map.setMaxBounds(maxBounds);
  215 + if (lastCenterPos) {
  216 + lastCenterPos.x *= w;
  217 + lastCenterPos.y *= h;
  218 + var center = this.pointToLatLng(lastCenterPos.x, lastCenterPos.y);
  219 + this.ctx.$scope.$injector.get('$mdUtil').nextTick(() => {
  220 + this.map.panTo(center, {animate: false});
  221 + });
  222 + }
  223 + }
  224 +
  225 + updateMarkerLabel(marker, settings) {
  226 + marker.unbindTooltip();
  227 + marker.bindTooltip('<div style="color: '+ settings.labelColor +';"><b>'+settings.labelText+'</b></div>',
  228 + { className: 'tb-marker-label', permanent: true, direction: 'top', offset: marker.tooltipOffset });
173 229 }
174 230
175 231 updateMarkerColor(marker, color) {
176   - marker.pinSvgElement.css({fill: color});
  232 + var pinColor = color.substr(1);
  233 + var icon = L.icon({
  234 + iconUrl: 'https://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=%E2%80%A2|' + pinColor,
  235 + iconSize: [21, 34],
  236 + iconAnchor: [10, 34],
  237 + popupAnchor: [0, -34],
  238 + shadowUrl: 'https://chart.apis.google.com/chart?chst=d_map_pin_shadow',
  239 + shadowSize: [40, 37],
  240 + shadowAnchor: [12, 35]
  241 + });
  242 + marker.setIcon(icon);
177 243 }
178 244
179 245 updateMarkerImage(marker, settings, image, maxSize) {
180   - var testImage = new Image(); // eslint-disable-line no-undef
181   - var imageMap = this;
  246 + var testImage = document.createElement('img'); // eslint-disable-line
  247 + testImage.style.visibility = 'hidden';
182 248 testImage.onload = function() {
183 249 var width;
184 250 var height;
185 251 var aspect = testImage.width / testImage.height;
  252 + document.body.removeChild(testImage); //eslint-disable-line
186 253 if (aspect > 1) {
187 254 width = maxSize;
188 255 height = maxSize / aspect;
... ... @@ -190,74 +257,79 @@ export default class TbImageMap {
190 257 width = maxSize * aspect;
191 258 height = maxSize;
192 259 }
193   - var size = Math.max(width, height);
194   - marker.size = size;
195   - if (marker.imgElement) {
196   - marker.imgElement.remove();
  260 + var icon = L.icon({
  261 + iconUrl: image,
  262 + iconSize: [width, height],
  263 + iconAnchor: [marker.offsetX * width, marker.offsetY * height],
  264 + popupAnchor: [0, -height]
  265 + });
  266 + marker.setIcon(icon);
  267 + if (settings.showLabel) {
  268 + marker.unbindTooltip();
  269 + marker.tooltipOffset = [0, -height * marker.offsetY + 10];
  270 + marker.bindTooltip('<div style="color: '+ settings.labelColor +';"><b>'+settings.labelText+'</b></div>',
  271 + { className: 'tb-marker-label', permanent: true, direction: 'top', offset: marker.tooltipOffset });
197 272 }
198   - marker.imgElement = angular.element(`<img src="${image}" aria-label="pin" class="image-map-pin-image"/>`);
199   - var left = (size - width)/2;
200   - var top = (size - height)/2;
201   - marker.imgElement.css({width: width, height: height, left: left, top: top});
202   - marker.pinElement.append(marker.imgElement);
203   - imageMap.updateMarkerDimensions(marker);
204 273 }
  274 + document.body.appendChild(testImage); //eslint-disable-line
205 275 testImage.src = image;
206 276 }
207 277
208   - updateMarkerDimensions(marker) {
209   - var pinElement = marker.pinElement;
210   - pinElement.css({width: marker.size, height: marker.size});
211   - var left = marker.x * this.width - marker.size * marker.offsetX;
212   - var top = marker.y * this.height - marker.size * marker.offsetY;
213   - pinElement.css({left: left, top: top});
214   - }
215   -
216 278 createMarker(position, settings, onClickListener, markerArgs) {
217   - var marker = {
218   - size: 34,
219   - position: position
220   - };
  279 + var height = 34;
  280 + var pinColor = settings.color.substr(1);
  281 + var icon = L.icon({
  282 + iconUrl: 'https://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=%E2%80%A2|' + pinColor,
  283 + iconSize: [21, 34],
  284 + iconAnchor: [21 * settings.markerOffsetX, 34 * settings.markerOffsetY],
  285 + popupAnchor: [0, -34],
  286 + shadowUrl: 'https://chart.apis.google.com/chart?chst=d_map_pin_shadow',
  287 + shadowSize: [40, 37],
  288 + shadowAnchor: [12, 35]
  289 + });
  290 +
221 291 var pos = this.posFunction(position.x, position.y);
222   - marker.x = pos.x;
223   - marker.y = pos.y;
  292 + var x = pos.x * this.width;
  293 + var y = pos.y * this.height;
  294 + var location = this.pointToLatLng(x, y);
  295 + var marker = L.marker(location, {icon: icon}).addTo(this.map);
  296 + marker.position = position;
224 297 marker.offsetX = settings.markerOffsetX;
225 298 marker.offsetY = settings.markerOffsetY;
226   - marker.pinElement = angular.element('<div class="image-map-pin"></div>');
227 299
228 300 if (settings.showLabel) {
229   - marker.labelElement = angular.element(`<div class="image-map-pin-title"><b>${settings.labelText}</b></div>`);
230   - marker.labelElement.css({color: settings.labelColor});
231   - marker.pinElement.append(marker.labelElement);
  301 + marker.tooltipOffset = [0, -height * marker.offsetY + 10];
  302 + marker.bindTooltip('<div style="color: '+ settings.labelColor +';"><b>'+settings.labelText+'</b></div>',
  303 + { className: 'tb-marker-label', permanent: true, direction: 'top', offset: marker.tooltipOffset });
232 304 }
233 305
234   - marker.imgElement = angular.element(pinSvg);
235   - marker.pinSvgElement = marker.imgElement.find('#pin');
236   - marker.pinElement.append(marker.imgElement);
237   -
238   - marker.pinSvgElement.css({fill: settings.color});
239   -
240   - this.updateMarkerDimensions(marker);
241   -
242   - this.imageMap.append(marker.pinElement);
243   -
244 306 if (settings.useMarkerImage) {
245 307 this.updateMarkerImage(marker, settings, settings.markerImage, settings.markerImageSize || 34);
246 308 }
247 309
248 310 if (settings.displayTooltip) {
249   - this.createTooltip(marker, settings.tooltipPattern, settings.tooltipReplaceInfo, markerArgs);
  311 + this.createTooltip(marker, settings.tooltipPattern, settings.tooltipReplaceInfo, settings.autocloseTooltip, markerArgs);
250 312 }
251 313
252 314 if (onClickListener) {
253   - marker.pinElement.on('click', onClickListener);
  315 + marker.on('click', onClickListener);
254 316 }
255   -
256 317 this.markers.push(marker);
257 318 return marker;
258 319 }
259 320
  321 + updateMarkers() {
  322 + this.markers.forEach((marker) => {
  323 + this.updateMarkerLocation(marker);
  324 + });
  325 + }
  326 +
  327 + updateMarkerLocation(marker) {
  328 + this.setMarkerPosition(marker, marker.position);
  329 + }
  330 +
260 331 removeMarker(marker) {
  332 + this.map.removeLayer(marker);
261 333 var index = this.markers.indexOf(marker);
262 334 if (index > -1) {
263 335 marker.pinElement.remove();
... ... @@ -265,9 +337,10 @@ export default class TbImageMap {
265 337 }
266 338 }
267 339
268   - createTooltip(marker, pattern, replaceInfo, markerArgs) {
269   - var popup = new Popup(this.ctx, marker.pinElement);
  340 + createTooltip(marker, pattern, replaceInfo, autoClose, markerArgs) {
  341 + var popup = L.popup();
270 342 popup.setContent('');
  343 + marker.bindPopup(popup, {autoClose: autoClose, closeOnClick: false});
271 344 this.tooltips.push( {
272 345 markerArgs: markerArgs,
273 346 popup: popup,
... ... @@ -302,9 +375,10 @@ export default class TbImageMap {
302 375 setMarkerPosition(marker, position) {
303 376 marker.position = position;
304 377 var pos = this.posFunction(position.x, position.y);
305   - marker.x = pos.x;
306   - marker.y = pos.y;
307   - this.updateMarkerDimensions(marker);
  378 + var x = pos.x * this.width;
  379 + var y = pos.y * this.height;
  380 + var location = this.pointToLatLng(x, y);
  381 + marker.setLatLng(location);
308 382 }
309 383
310 384 getPolylineLatLngs(/*polyline*/) {
... ... @@ -340,38 +414,3 @@ class Position {
340 414 return loc && loc.x == this.x && loc.y == this.y;
341 415 }
342 416 }
343   -
344   -class Popup {
345   - constructor(ctx, anchor) {
346   - anchor.tooltipster(
347   - {
348   - theme: 'tooltipster-shadow',
349   - delay: 100,
350   - trigger: 'custom',
351   - triggerOpen: {
352   - click: true,
353   - tap: true
354   - },
355   - trackOrigin: true
356   - }
357   - );
358   - this.tooltip = anchor.tooltipster('instance');
359   - var contentElement = angular.element('<div class="image-map-pin-tooltip">' +
360   - '<a class="image-map-pin-tooltip-close-button" id="close" style="outline: none;">×</a>' +
361   - '<div id="tooltip-content">' +
362   - '</div>' +
363   - '</div>');
364   - var $compile = ctx.$scope.$injector.get('$compile');
365   - $compile(contentElement)(ctx.$scope);
366   - var popup = this;
367   - contentElement.find('#close').on('click', function() {
368   - popup.tooltip.close();
369   - });
370   - this.content = contentElement.find('#tooltip-content');
371   - this.tooltip.content(contentElement);
372   - }
373   -
374   - setContent(content) {
375   - this.content.html(content);
376   - }
377   -}
... ...
1   -/**
2   - * Copyright © 2016-2017 The Thingsboard Authors
3   - *
4   - * Licensed under the Apache License, Version 2.0 (the "License");
5   - * you may not use this file except in compliance with the License.
6   - * You may obtain a copy of the License at
7   - *
8   - * http://www.apache.org/licenses/LICENSE-2.0
9   - *
10   - * Unless required by applicable law or agreed to in writing, software
11   - * distributed under the License is distributed on an "AS IS" BASIS,
12   - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   - * See the License for the specific language governing permissions and
14   - * limitations under the License.
15   - */
16   -
17   -.image-map-pin-tooltip {
18   - pointer-events: all;
19   - padding: 5px;
20   - .image-map-pin-tooltip-close-button {
21   - cursor: pointer;
22   - position: absolute;
23   - top: 0;
24   - right: 0;
25   - padding: 6px 6px 0 0;
26   - border: none;
27   - text-align: center;
28   - width: 20px;
29   - height: 16px;
30   - font: 18px/16px Tahoma, Verdana, sans-serif;
31   - color: #b0b0b0;
32   - text-decoration: none;
33   - font-weight: bold;
34   - background: transparent;
35   - &:hover {
36   - color: #919191;
37   - }
38   - }
39   - #tooltip-content {
40   - line-height: normal;
41   - font-size: 13px;
42   - font-weight: 300;
43   - color: #333;
44   - }
45   -}
46   -
47   -#image-map-container {
48   - width: 100%;
49   - height: 100%;
50   - #image-map {
51   - color: rgba(0, 0, 0, 0.870588);
52   - position: relative;
53   - margin: auto;
54   - background: transparent no-repeat scroll 0 0;
55   - background-size: 100% 100%;
56   -
57   - &.is-pointer {
58   - cursor: pointer !important;
59   - }
60   -
61   - .movable {
62   - cursor: move;
63   - }
64   -
65   - .image-map-pin {
66   - outline: none;
67   - position: absolute;
68   - background: none;
69   - .image-map-pin-title {
70   - position: relative;
71   - white-space: nowrap;
72   - text-align: center;
73   - line-height: 1.5;
74   - font-size: 12px;
75   - font-weight: 400;
76   - top: -20px;
77   - &:before {
78   - content: "";
79   - margin-left: -100%;
80   - }
81   - &:after {
82   - content: "";
83   - margin-right: -100%;
84   - }
85   - }
86   - .image-map-pin-image {
87   - position: absolute;
88   - pointer-events: none;
89   - top: 0;
90   - bottom: 0;
91   - right: 0;
92   - left: 0;
93   - width: 100%;
94   - height: 100%;
95   - }
96   - }
97   - }
98   -}
... ... @@ -131,6 +131,7 @@ export default class TbMapWidgetV2 {
131 131
132 132 this.locationSettings.showLabel = this.ctx.settings.showLabel !== false;
133 133 this.locationSettings.displayTooltip = this.ctx.settings.showTooltip !== false;
  134 + this.locationSettings.autocloseTooltip = this.ctx.settings.autocloseTooltip !== false;
134 135 this.locationSettings.labelColor = this.ctx.widgetConfig.color || '#000000',
135 136 this.locationSettings.label = this.ctx.settings.label || "${entityName}";
136 137 this.locationSettings.color = this.ctx.settings.color ? tinycolor(this.ctx.settings.color).toHexString() : "#FE7569";
... ... @@ -586,6 +587,11 @@ const commonMapSettingsSchema =
586 587 "type":"boolean",
587 588 "default":true
588 589 },
  590 + "autocloseTooltip": {
  591 + "title": "Auto-close tooltips",
  592 + "type":"boolean",
  593 + "default":true
  594 + },
589 595 "tooltipPattern":{
590 596 "title":"Tooltip (for ex. 'Text ${keyName} units.' or <link-act name='my-action'>Link text</link-act>')",
591 597 "type":"string",
... ... @@ -641,6 +647,7 @@ const commonMapSettingsSchema =
641 647 "showLabel",
642 648 "label",
643 649 "showTooltip",
  650 + "autocloseTooltip",
644 651 {
645 652 "key": "tooltipPattern",
646 653 "type": "textarea"
... ... @@ -748,6 +755,11 @@ const imageMapSettingsSchema =
748 755 "type":"boolean",
749 756 "default":true
750 757 },
  758 + "autocloseTooltip": {
  759 + "title": "Auto-close tooltips",
  760 + "type":"boolean",
  761 + "default":true
  762 + },
751 763 "tooltipPattern":{
752 764 "title":"Tooltip (for ex. 'Text ${keyName} units.' or <link-act name='my-action'>Link text</link-act>')",
753 765 "type":"string",
... ... @@ -822,6 +834,7 @@ const imageMapSettingsSchema =
822 834 "showLabel",
823 835 "label",
824 836 "showTooltip",
  837 + "autocloseTooltip",
825 838 {
826 839 "key": "tooltipPattern",
827 840 "type": "textarea"
... ...
... ... @@ -118,7 +118,7 @@ export default class TbOpenStreetMap {
118 118 }
119 119
120 120 if (settings.displayTooltip) {
121   - this.createTooltip(marker, settings.tooltipPattern, settings.tooltipReplaceInfo, markerArgs);
  121 + this.createTooltip(marker, settings.tooltipPattern, settings.tooltipReplaceInfo, settings.autocloseTooltip, markerArgs);
122 122 }
123 123
124 124 if (onClickListener) {
... ... @@ -132,10 +132,10 @@ export default class TbOpenStreetMap {
132 132 this.map.removeLayer(marker);
133 133 }
134 134
135   - createTooltip(marker, pattern, replaceInfo, markerArgs) {
  135 + createTooltip(marker, pattern, replaceInfo, autoClose, markerArgs) {
136 136 var popup = L.popup();
137 137 popup.setContent('');
138   - marker.bindPopup(popup, {autoClose: false, closeOnClick: false});
  138 + marker.bindPopup(popup, {autoClose: autoClose, closeOnClick: false});
139 139 this.tooltips.push( {
140 140 markerArgs: markerArgs,
141 141 popup: popup,
... ...