1L.Polyline.polylineEditor = L.Polyline.extend({ 2 _prepareMapIfNeeded: function() { 3 var that = this; 4 that._changed = false; 5 6 if(this._map._editablePolylines != null) { 7 return 8 } 9 10 // Container for all editable polylines on this map: 11 this._map._editablePolylines = []; 12 this._map._editablePolylinesEnabled = true; 13 14 // Click anywhere on map to add a new point-polyline: 15 if(this._options.newPolylines) { 16 console.log('click na map'); 17 that._map.on('dblclick', function(event) { 18 console.log('click, target=' + (event.target == that._map) + ' type=' + event.type); 19 if(that._map.isEditablePolylinesBusy()) 20 return; 21 22 var latLng = event.latlng; 23 if(that._options.newPolylineConfirmMessage) 24 if(!confirm(that._options.newPolylineConfirmMessage)) 25 return 26 27 var contexts = [{'originalPolylineNo': null, 'originalPointNo': null}]; 28 L.Polyline.PolylineEditor([latLng], that._options, contexts).addTo(that._map); 29 30 that._showBoundMarkers(); 31 that._changed = true; 32 }); 33 } 34 35 /** 36 * Check if there is *any* busy editable polyline on this map. 37 */ 38 this._map.isEditablePolylinesBusy = function() { 39 var map = this; 40 for(var i = 0; i < map._editablePolylines.length; i++) 41 if(map._editablePolylines[i]._isBusy()) 42 return true; 43 44 return false; 45 }; 46 47 /** 48 * Enable/disable editing. 49 */ 50 this._map.setEditablePolylinesEnabled = function(enabled) { 51 var map = this; 52 map._editablePolylinesEnabled = enabled; 53 for(var i = 0; i < map._editablePolylines.length; i++) { 54 var polyline = map._editablePolylines[i]; 55 if(enabled) { 56 polyline._showBoundMarkers(); 57 } else { 58 polyline._hideAll(); 59 } 60 } 61 }; 62 63 /* 64 * Utility method added to this map to retreive editable 65 * polylines. 66 */ 67 this._map.getEditablePolylines = function() { 68 var map = this; 69 return map._editablePolylines; 70 } 71 72 this._map.fixAroundEditablePoint = function(marker) { 73 var map = this; 74 for(var i = 0; i < map._editablePolylines.length; i++) { 75 var polyline = map._editablePolylines[i]; 76 polyline._reloadPolyline(marker); 77 } 78 } 79 }, 80 /** 81 * Will add all needed methods to this polyline. 82 */ 83 _addMethods: function() { 84 var that = this; 85 86 this._init = function(options, contexts) { 87 this._prepareMapIfNeeded(); 88 89 /** 90 * Since all point editing is done by marker events, markers 91 * will be the main holder of the polyline points locations. 92 * Every marker contains a reference to the newPointMarker 93 * *before* him (=> the first marker has newPointMarker=null). 94 */ 95 this._parseOptions(options); 96 97 this._markers = []; 98 var points = this.getLatLngs(); 99 var length = points.length; 100 for(var i = 0; i < length; i++) { 101 var marker = this._addMarkers(i, points[i]); 102 if(! ('context' in marker)) { 103 marker.context = {} 104 if(that._contexts != null) { 105 marker.context = contexts[i]; 106 } 107 } 108 109 if(marker.context && ! ('originalPointNo' in marker.context)) 110 marker.context.originalPointNo = i; 111 if(marker.context && ! ('originalPolylineNo' in marker.context)) 112 marker.context.originalPolylineNo = that._map._editablePolylines.length; 113 } 114 115 // Map move => show different editable markers: 116 var map = this._map; 117 this._map.on("zoomend", function(e) { 118 that._showBoundMarkers(); 119 }); 120 this._map.on("moveend", function(e) { 121 that._showBoundMarkers(); 122 }); 123 124 if(this._desiredPolylineNo && this._desiredPolylineNo != null) { 125 this._map._editablePolylines.splice(this._desiredPolylineNo, 0, this); 126 } else { 127 this._map._editablePolylines.push(this); 128 } 129 }; 130 131 /** 132 * Check if is busy adding/moving new nodes. Note, there may be 133 * *other* editable polylines on the same map which *are* busy. 134 */ 135 this._isBusy = function() { 136 return that._busy; 137 }; 138 139 this._setBusy = function(busy) { 140 that._busy = busy; 141 }; 142 143 /** 144 * Get markers for this polyline. 145 */ 146 this.getPoints = function() { 147 return this._markers; 148 }; 149 150 this.isChanged = function() { 151 return this._changed; 152 } 153 154 this._parseOptions = function(options) { 155 if(!options) 156 options = {}; 157
158 // Do not show edit markers if more than maxMarkers would be shown: 159 if(!('maxMarkers' in options)) 160 options.maxMarkers = 100; 161 if(!('newPolylines' in options)) 162 options.newPolylines = false; 163 if(!('newPolylineConfirmMessage' in options)) 164 options.newPolylineConfirmMessage = ''; 165 if(!('addFirstLastPointEvent' in options)) 166 options.addFirstLastPointEvent = 'click'; 167 if(!('customPointListeners' in options)) 168 options.customPointListeners = {}; 169 if(!('customNewPointListeners' in options)) 170 options.customNewPointListeners = {}; 171 172 this._options = options; 173 }; 174 175 /** 176 * Show only markers in current map bounds *is* there are only a certain 177 * number of markers. This method is called on eventy that change map 178 * bounds. 179 */ 180 this._showBoundMarkers = function() { 181 if (!that._map) { 182 return; 183 } 184 185 this._setBusy(false); 186 187 if(!that._map._editablePolylinesEnabled) { 188 console.log('Do not show because editing is disabled'); 189 return; 190 } 191 192 var bounds = that._map.getBounds(); 193 var found = 0; 194 for(var polylineNo in that._map._editablePolylines) { 195 var polyline = that._map._editablePolylines[polylineNo]; 196 for(var markerNo in polyline._markers) { 197 var marker = polyline._markers[markerNo]; 198 if(bounds.contains(marker.getLatLng())) 199 found += 1; 200 } 201 } 202 203 for(var polylineNo in that._map._editablePolylines) { 204 var polyline = that._map._editablePolylines[polylineNo]; 205 for(var markerNo in polyline._markers) { 206 var marker = polyline._markers[markerNo]; 207 if(found < that._options.maxMarkers) { 208 that._setMarkerVisible(marker, bounds.contains(marker.getLatLng())); 209 that._setMarkerVisible(marker.newPointMarker, markerNo > 0 && bounds.contains(marker.getLatLng())); 210 } else { 211 that._setMarkerVisible(marker, false); 212 that._setMarkerVisible(marker.newPointMarker, false); 213 } 214 } 215 } 216 }; 217 218 /** 219 * Used when adding/moving points in order to disable the user to mess 220 * with other markers (+ easier to decide where to put the point 221 * without too many markers). 222 */ 223 this._hideAll = function(except) { 224 this._setBusy(true); 225 for(var polylineNo in that._map._editablePolylines) { 226 console.log("hide " + polylineNo + " markers"); 227 var polyline = that._map._editablePolylines[polylineNo]; 228 for(var markerNo in polyline._markers) { 229 var marker = polyline._markers[markerNo]; 230 if(except == null || except != marker) 231 polyline._setMarkerVisible(marker, false); 232 if(except == null || except != marker.newPointMarker) 233 polyline._setMarkerVisible(marker.newPointMarker, false); 234 } 235 } 236 } 237 238 /** 239 * Show/hide marker. 240 */ 241 this._setMarkerVisible = function(marker, show) { 242 if(!marker) 243 return; 244 245 var map = this._map; 246 if(show) { 247 if(!marker._visible) { 248 if(!marker._map) { // First show for this marker: 249 marker.addTo(map); 250 } else { // Marker was already shown and hidden: 251 map.addLayer(marker); 252 } 253 marker._map = map; 254 } 255 marker._visible = true; 256 } else { 257 if(marker._visible) { 258 map.removeLayer(marker); 259 } 260 marker._visible = false;
261 } 262 }; 263 264 /** 265 * Reload polyline. If it is busy, then the bound markers will not be 266 * shown. 267 */ 268 this._reloadPolyline = function(fixAroundPointNo) { 269 that.setLatLngs(that._getMarkerLatLngs()); 270 if(fixAroundPointNo != null) 271 that._fixAround(fixAroundPointNo); 272 that._showBoundMarkers(); 273 that._changed = true; 274 } 275 276 /** 277 * Add two markers (a point marker and his newPointMarker) for a 278 * single point. 279 * 280 * Markers are not added on the map here, the marker.addTo(map) is called 281 * only later when needed first time because of performance issues. 282 */ 283 this._addMarkers = function(pointNo, latLng, fixNeighbourPositions) { 284 var that = this; 285 var points = this.getLatLngs(); 286 var marker = L.marker(latLng, {draggable: true, icon: this._options.pointIcon}); 287 288 marker.newPointMarker = null; 289 marker.on('dragstart', function(event) { 290 var pointNo = that._getPointNo(event.target); 291 var previousPoint = pointNo && pointNo > 0 ? that._markers[pointNo - 1].getLatLng() : null; 292 var nextPoint = pointNo < that._markers.length - 1 ? that._markers[pointNo + 1].getLatLng() : null; 293 that._setupDragLines(marker, previousPoint, nextPoint); 294 that._hideAll(marker); 295 }); 296 marker.on('dragend', function(event) { 297 var marker = event.target; 298 var pointNo = that._getPointNo(event.target); 299 setTimeout(function() { 300 that._reloadPolyline(pointNo); 301 }, 25); 302 }); 303 marker.on('contextmenu', function(event) { 304 var marker = event.target; 305 var pointNo = that._getPointNo(event.target); 306 that._map.removeLayer(marker); 307 that._map.removeLayer(newPointMarker); 308 that._markers.splice(pointNo, 1); 309 that._reloadPolyline(pointNo); 310 }); 311 marker.on(that._options.addFirstLastPointEvent, function(event) { 312 313 console.log('click on marker'); 314 var marker = event.target; 315 var pointNo = that._getPointNo(event.target); 316 console.log('pointNo=' + pointNo + ' that._markers.length=' + that._markers.length); 317 event.dont; 318 if(pointNo == 0 || pointNo == that._markers.length - 1) { 319 console.log('first or last'); 320 that._prepareForNewPoint(marker, pointNo == 0 ? 0 : pointNo + 1); 321 } else { 322 console.log('not first or last'); 323 } 324 }); 325 326 var previousPoint = points[pointNo == 0 ? pointNo : pointNo - 1]; 327 var newPointMarker = L.marker([(latLng.lat + previousPoint.lat) / 2., 328 (latLng.lng + previousPoint.lng) / 2.], 329 {draggable: true, icon: this._options.newPointIcon}); 330 marker.newPointMarker = newPointMarker; 331 newPointMarker.on('dragstart', function(event) { 332 var pointNo = that._getPointNo(event.target); 333 var previousPoint = that._markers[pointNo - 1].getLatLng(); 334 var nextPoint = that._markers[pointNo].getLatLng(); 335 that._setupDragLines(marker.newPointMarker, previousPoint, nextPoint); 336 337 that._hideAll(marker.newPointMarker); 338 }); 339 newPointMarker.on('dragend', function(event) { 340 var marker = event.target; 341 var pointNo = that._getPointNo(event.target); 342 that._addMarkers(pointNo, marker.getLatLng(), true); 343 setTimeout(function() { 344 that._reloadPolyline(); 345 }, 25); 346 }); 347 newPointMarker.on('contextmenu', function(event) { 348 if (!confirm(edit_translation.slicing)) 349 return; 350 // 1. Remove this polyline from map 351 var marker = event.target; 352 var pointNo = that._getPointNo(marker); 353 var markers = that.getPoints(); 354 that._hideAll(); 355 356 var secondPartMarkers = that._markers.slice(pointNo, pointNo.length); 357 that._markers.splice(pointNo, that._markers.length - pointNo); 358 359 that._reloadPolyline(); 360 361 var points = []; 362 var contexts = []; 363 for(var i = 0; i < secondPartMarkers.length; i++) { 364 var marker = secondPartMarkers[i]; 365 points.push(marker.getLatLng()); 366 contexts.push(marker.context); 367 } 368 369 console.log('points:' + points); 370 console.log('contexts:' + contexts); 371 372 // Need to know the current polyline order numbers, because 373 // the splitted one need to be inserted immediately after: 374 var originalPolylineNo = that._map._editablePolylines.indexOf(that); 375 376 L.Polyline.PolylineEditor(points, that._options, contexts, originalPolylineNo + 1) 377 .addTo(that._map); 378 379 that._showBoundMarkers(); 380 }); 381 382 this._markers.splice(pointNo, 0, marker); 383 384 // User-defined custom event listeners: 385 if(that._options.customPointListeners) 386 for(var eventName in that._options.customPointListeners) 387 marker.on(eventName, that._options.customPointListeners[eventName]); 388 if(that._options.customNewPointListeners) 389 for(var eventName in that._options.customNewPointListeners) 390 newPointMarker.on(eventName, that._options.customNewPointListeners[eventName]); 391 392 if(fixNeighbourPositions) { 393 this._fixAround(pointNo); 394 } 395 396 return marker; 397 }; 398 399 /** 400 * Event handlers for first and last point. 401 */ 402 this._prepareForNewPoint = function(marker, pointNo) { 403 // This is slightly delayed to prevent the same propagated event 404 // to be catched here: 405 setTimeout( 406 function() { 407 that._hideAll(); 408 that._setupDragLines(marker, marker.getLatLng()); 409 that._map.once('click', function(event) { 410 if(that._markers.length == 1) { 411 pointNo += 1; 412 } 413 console.log('dodajemo na ' + pointNo + ' - ' + event.latlng); 414 that._addMarkers(pointNo, event.latlng, true); 415 that._reloadPolyline(); 416 }); 417 }, 418 100 419 ); 420 }; 421 422 /** 423 * Fix nearby new point markers when the new point is created. 424 */ 425 this._fixAround = function(pointNoOrMarker) { 426 if((typeof pointNoOrMarker) == 'number') 427 var pointNo = pointNoOrMarker; 428 else 429 var pointNo = that._markers.indexOf(pointNoOrMarker); 430 431 if(pointNo < 0) 432 return; 433 434 var previousMarker = pointNo == 0 ? null : that._markers[pointNo - 1]; 435 var marker = that._markers[pointNo]; 436 var nextMarker = pointNo < that._markers.length - 1 ? that._markers[pointNo + 1] : null; 437 if(marker && previousMarker) { 438 marker.newPointMarker.setLatLng([(previousMarker.getLatLng().lat + marker.getLatLng().lat) / 2., 439 (previousMarker.getLatLng().lng + marker.getLatLng().lng) / 2.]); 440 } 441 if(marker && nextMarker) { 442 nextMarker.newPointMarker.setLatLng([(marker.getLatLng().lat + nextMarker.getLatLng().lat) / 2., 443 (marker.getLatLng().lng + nextMarker.getLatLng().lng) / 2.]); 444 } 445 }; 446 447 /** 448 * Find the order number of the marker. 449 */ 450 this._getPointNo = function(marker) { 451 for(var i = 0; i < this._markers.length; i++) { 452 if(marker == this._markers[i] || marker == this._markers[i].newPointMarker) { 453 return i; 454 } 455 } 456 return -1; 457 }; 458 459 /** 460 * Get polyline latLngs based on marker positions. 461 */ 462 this._getMarkerLatLngs = function() { 463 var result = []; 464 for(var i = 0; i < this._markers.length; i++) 465 result.push(this._markers[i].getLatLng()); 466 return result; 467 }; 468 469 this._setupDragLines = function(marker, point1, point2) { 470 var line1 = null; 471 var line2 = null; 472 if(point1) line1 = L.polyline([marker.getLatLng(), point1], {dasharray: "5,
4721", weight: 1}) 473 .addTo(that._map); 474 if(point2) line2 = L.polyline([marker.getLatLng(), point2], {dasharray: "5,1", weight: 1}) 475 .addTo(that._map); 476 477 var moveHandler = function(event) { 478 if(line1) 479 line1.setLatLngs([event.latlng, point1]); 480 if(line2) 481 line2.setLatLngs([event.latlng, point2]); 482 }; 483 484 var stopHandler = function(event) { 485 if (that._map) { 486 that._map.off('mousemove', moveHandler); 487 marker.off('dragend', stopHandler); 488 if(line1) that._map.removeLayer(line1); 489 if(line2) that._map.removeLayer(line2); 490 console.log('STOPPED'); 491 if(event.target != that._map) { 492 that._map.fire('click', event); 493 } 494 } 495 }; 496 497 that._map.on('mousemove', moveHandler); 498 marker.on('dragend', stopHandler); 499 500 that._map.once('click', stopHandler); 501 marker.once('click', stopHandler); 502 if(line1) line1.once('click', stopHandler); 503 if(line2) line2.once('click', stopHandler); 504 } 505 } 506}); 507 508L.Polyline.polylineEditor.addInitHook(function () { 509 this.on('add', function(event) { 510 this._map = event.target._map; 511 this._addMethods(); 512 513 /** 514 * When addint a new point we must disable the user to mess with other 515 * markers. One way is to check everywhere if the user is busy. The 516 * other is to just remove other markers when the user is doing 517 * somethinng. 518 * 519 * TODO: Decide the right way to do this and then leave only _busy or 520 * _hideAll(). 521 */ 522 this._busy = false; 523 this._initialized = false; 524 525 this._init(this._options, this._contexts); 526 527 this._initialized = true; 528 529 return this; 530 }); 531 532 this.on('remove', function(event) { 533 var polyline = event.target; 534 var map = polyline._map; 535 var polylines = map.getEditablePolylines(); 536 var index = polylines.indexOf(polyline); 537 if (index > -1) { 538 polylines[index]._markers.forEach(function(marker) { 539 map.removeLayer(marker); 540 if(marker.newPointMarker) 541 map.removeLayer(marker.newPointMarker); 542 }); 543 polylines.splice(index, 1); 544 } 545 }); 546}); 547 548/** 549 * Construct a new editable polyline. 550 * 551 * latlngs ... a list of points (or two-element tuples with coordinates) 552 * options ... polyline options 553 * contexts ... custom contexts for every point in the polyline. Must have the 554 * same number of elements as latlngs and this data will be 555 * preserved when new points are added or polylines splitted. 556 * polylineNo ... insert this polyline in a specific order (used when splitting). 557 * 558 * More about contexts: 559 * This is an array of objects that will be kept as "context" for every 560 * point. Marker will keep this value as marker.context. New markers will 561 * have context set to null. 562 * 563 * Contexts must be the same size as the polyline size! 564 * 565 * By default, even without calling this method -- every marker will have 566 * context with one value: marker.context.originalPointNo with the 567 * original order number of this point. The order may change if some 568 * markers before this one are delted or new added. 569 */ 570L.Polyline.PolylineEditor = function(latlngs, options, contexts, polylineNo) { 571 // Since the app code may not be able to explicitly call the 572 // initialization of all editable polylines (if the user created a new 573 // one by splitting an existing), with this method you can control the 574 // options for new polylines: 575 576 if(options.prepareOptions) { 577 options.prepareOptions(options); 578 } 579 580 var result = new L.Polyline.polylineEditor(latlngs, options); 581 result._options = options; 582 result._contexts = contexts; 583 result._desiredPolylineNo = polylineNo 584 585 return result; 586};
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.