From 258cfb9e0edbaa3607eae6ebb2e67d7e2acb9c08 Mon Sep 17 00:00:00 2001 From: Segun Date: Sun, 29 Jan 2023 23:07:13 +0100 Subject: [PATCH] Reconstruct Map from URL (#1339) * feature-reconstructMap * map reconstruction from url * update * update * update * update * update * moved code from library to examples folder * shareable integrated into archive * update * code transferred to archive.js * some codes to library * update * url reconstruction completed --- .eslintrc.js | 4 +- dist/leaflet.distortableimage.js | 846 +++++++++---------------------- examples/archive.html | 2 +- examples/js/archive.js | 113 ++++- src/DistortableCollection.js | 45 +- src/DistortableImageOverlay.js | 1 - 6 files changed, 381 insertions(+), 630 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index 46af44941..85e272987 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -11,7 +11,7 @@ module.exports = { SharedArrayBuffer: 'readonly', }, parserOptions: { - ecmaVersion: 6, + ecmaVersion: 8, }, rules: { /* @@ -47,7 +47,7 @@ module.exports = { 'overrides': [{ files: ['examples/js/*.js'], parserOptions: { - sourceType: "module" + sourceType: "module", } }], }, diff --git a/dist/leaflet.distortableimage.js b/dist/leaflet.distortableimage.js index 16bc00087..db4ac911b 100644 --- a/dist/leaflet.distortableimage.js +++ b/dist/leaflet.distortableimage.js @@ -194,6 +194,10 @@ ansiHTML.reset() \**************************************/ /***/ (function() { +function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); } +function _regeneratorRuntime() { "use strict"; /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */ _regeneratorRuntime = function _regeneratorRuntime() { return exports; }; var exports = {}, Op = Object.prototype, hasOwn = Op.hasOwnProperty, defineProperty = Object.defineProperty || function (obj, key, desc) { obj[key] = desc.value; }, $Symbol = "function" == typeof Symbol ? Symbol : {}, iteratorSymbol = $Symbol.iterator || "@@iterator", asyncIteratorSymbol = $Symbol.asyncIterator || "@@asyncIterator", toStringTagSymbol = $Symbol.toStringTag || "@@toStringTag"; function define(obj, key, value) { return Object.defineProperty(obj, key, { value: value, enumerable: !0, configurable: !0, writable: !0 }), obj[key]; } try { define({}, ""); } catch (err) { define = function define(obj, key, value) { return obj[key] = value; }; } function wrap(innerFn, outerFn, self, tryLocsList) { var protoGenerator = outerFn && outerFn.prototype instanceof Generator ? outerFn : Generator, generator = Object.create(protoGenerator.prototype), context = new Context(tryLocsList || []); return defineProperty(generator, "_invoke", { value: makeInvokeMethod(innerFn, self, context) }), generator; } function tryCatch(fn, obj, arg) { try { return { type: "normal", arg: fn.call(obj, arg) }; } catch (err) { return { type: "throw", arg: err }; } } exports.wrap = wrap; var ContinueSentinel = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} var IteratorPrototype = {}; define(IteratorPrototype, iteratorSymbol, function () { return this; }); var getProto = Object.getPrototypeOf, NativeIteratorPrototype = getProto && getProto(getProto(values([]))); NativeIteratorPrototype && NativeIteratorPrototype !== Op && hasOwn.call(NativeIteratorPrototype, iteratorSymbol) && (IteratorPrototype = NativeIteratorPrototype); var Gp = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(IteratorPrototype); function defineIteratorMethods(prototype) { ["next", "throw", "return"].forEach(function (method) { define(prototype, method, function (arg) { return this._invoke(method, arg); }); }); } function AsyncIterator(generator, PromiseImpl) { function invoke(method, arg, resolve, reject) { var record = tryCatch(generator[method], generator, arg); if ("throw" !== record.type) { var result = record.arg, value = result.value; return value && "object" == _typeof(value) && hasOwn.call(value, "__await") ? PromiseImpl.resolve(value.__await).then(function (value) { invoke("next", value, resolve, reject); }, function (err) { invoke("throw", err, resolve, reject); }) : PromiseImpl.resolve(value).then(function (unwrapped) { result.value = unwrapped, resolve(result); }, function (error) { return invoke("throw", error, resolve, reject); }); } reject(record.arg); } var previousPromise; defineProperty(this, "_invoke", { value: function value(method, arg) { function callInvokeWithMethodAndArg() { return new PromiseImpl(function (resolve, reject) { invoke(method, arg, resolve, reject); }); } return previousPromise = previousPromise ? previousPromise.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg(); } }); } function makeInvokeMethod(innerFn, self, context) { var state = "suspendedStart"; return function (method, arg) { if ("executing" === state) throw new Error("Generator is already running"); if ("completed" === state) { if ("throw" === method) throw arg; return doneResult(); } for (context.method = method, context.arg = arg;;) { var delegate = context.delegate; if (delegate) { var delegateResult = maybeInvokeDelegate(delegate, context); if (delegateResult) { if (delegateResult === ContinueSentinel) continue; return delegateResult; } } if ("next" === context.method) context.sent = context._sent = context.arg;else if ("throw" === context.method) { if ("suspendedStart" === state) throw state = "completed", context.arg; context.dispatchException(context.arg); } else "return" === context.method && context.abrupt("return", context.arg); state = "executing"; var record = tryCatch(innerFn, self, context); if ("normal" === record.type) { if (state = context.done ? "completed" : "suspendedYield", record.arg === ContinueSentinel) continue; return { value: record.arg, done: context.done }; } "throw" === record.type && (state = "completed", context.method = "throw", context.arg = record.arg); } }; } function maybeInvokeDelegate(delegate, context) { var methodName = context.method, method = delegate.iterator[methodName]; if (undefined === method) return context.delegate = null, "throw" === methodName && delegate.iterator.return && (context.method = "return", context.arg = undefined, maybeInvokeDelegate(delegate, context), "throw" === context.method) || "return" !== methodName && (context.method = "throw", context.arg = new TypeError("The iterator does not provide a '" + methodName + "' method")), ContinueSentinel; var record = tryCatch(method, delegate.iterator, context.arg); if ("throw" === record.type) return context.method = "throw", context.arg = record.arg, context.delegate = null, ContinueSentinel; var info = record.arg; return info ? info.done ? (context[delegate.resultName] = info.value, context.next = delegate.nextLoc, "return" !== context.method && (context.method = "next", context.arg = undefined), context.delegate = null, ContinueSentinel) : info : (context.method = "throw", context.arg = new TypeError("iterator result is not an object"), context.delegate = null, ContinueSentinel); } function pushTryEntry(locs) { var entry = { tryLoc: locs[0] }; 1 in locs && (entry.catchLoc = locs[1]), 2 in locs && (entry.finallyLoc = locs[2], entry.afterLoc = locs[3]), this.tryEntries.push(entry); } function resetTryEntry(entry) { var record = entry.completion || {}; record.type = "normal", delete record.arg, entry.completion = record; } function Context(tryLocsList) { this.tryEntries = [{ tryLoc: "root" }], tryLocsList.forEach(pushTryEntry, this), this.reset(!0); } function values(iterable) { if (iterable) { var iteratorMethod = iterable[iteratorSymbol]; if (iteratorMethod) return iteratorMethod.call(iterable); if ("function" == typeof iterable.next) return iterable; if (!isNaN(iterable.length)) { var i = -1, next = function next() { for (; ++i < iterable.length;) { if (hasOwn.call(iterable, i)) return next.value = iterable[i], next.done = !1, next; } return next.value = undefined, next.done = !0, next; }; return next.next = next; } } return { next: doneResult }; } function doneResult() { return { value: undefined, done: !0 }; } return GeneratorFunction.prototype = GeneratorFunctionPrototype, defineProperty(Gp, "constructor", { value: GeneratorFunctionPrototype, configurable: !0 }), defineProperty(GeneratorFunctionPrototype, "constructor", { value: GeneratorFunction, configurable: !0 }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, toStringTagSymbol, "GeneratorFunction"), exports.isGeneratorFunction = function (genFun) { var ctor = "function" == typeof genFun && genFun.constructor; return !!ctor && (ctor === GeneratorFunction || "GeneratorFunction" === (ctor.displayName || ctor.name)); }, exports.mark = function (genFun) { return Object.setPrototypeOf ? Object.setPrototypeOf(genFun, GeneratorFunctionPrototype) : (genFun.__proto__ = GeneratorFunctionPrototype, define(genFun, toStringTagSymbol, "GeneratorFunction")), genFun.prototype = Object.create(Gp), genFun; }, exports.awrap = function (arg) { return { __await: arg }; }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, asyncIteratorSymbol, function () { return this; }), exports.AsyncIterator = AsyncIterator, exports.async = function (innerFn, outerFn, self, tryLocsList, PromiseImpl) { void 0 === PromiseImpl && (PromiseImpl = Promise); var iter = new AsyncIterator(wrap(innerFn, outerFn, self, tryLocsList), PromiseImpl); return exports.isGeneratorFunction(outerFn) ? iter : iter.next().then(function (result) { return result.done ? result.value : iter.next(); }); }, defineIteratorMethods(Gp), define(Gp, toStringTagSymbol, "Generator"), define(Gp, iteratorSymbol, function () { return this; }), define(Gp, "toString", function () { return "[object Generator]"; }), exports.keys = function (val) { var object = Object(val), keys = []; for (var key in object) { keys.push(key); } return keys.reverse(), function next() { for (; keys.length;) { var key = keys.pop(); if (key in object) return next.value = key, next.done = !1, next; } return next.done = !0, next; }; }, exports.values = values, Context.prototype = { constructor: Context, reset: function reset(skipTempReset) { if (this.prev = 0, this.next = 0, this.sent = this._sent = undefined, this.done = !1, this.delegate = null, this.method = "next", this.arg = undefined, this.tryEntries.forEach(resetTryEntry), !skipTempReset) for (var name in this) { "t" === name.charAt(0) && hasOwn.call(this, name) && !isNaN(+name.slice(1)) && (this[name] = undefined); } }, stop: function stop() { this.done = !0; var rootRecord = this.tryEntries[0].completion; if ("throw" === rootRecord.type) throw rootRecord.arg; return this.rval; }, dispatchException: function dispatchException(exception) { if (this.done) throw exception; var context = this; function handle(loc, caught) { return record.type = "throw", record.arg = exception, context.next = loc, caught && (context.method = "next", context.arg = undefined), !!caught; } for (var i = this.tryEntries.length - 1; i >= 0; --i) { var entry = this.tryEntries[i], record = entry.completion; if ("root" === entry.tryLoc) return handle("end"); if (entry.tryLoc <= this.prev) { var hasCatch = hasOwn.call(entry, "catchLoc"), hasFinally = hasOwn.call(entry, "finallyLoc"); if (hasCatch && hasFinally) { if (this.prev < entry.catchLoc) return handle(entry.catchLoc, !0); if (this.prev < entry.finallyLoc) return handle(entry.finallyLoc); } else if (hasCatch) { if (this.prev < entry.catchLoc) return handle(entry.catchLoc, !0); } else { if (!hasFinally) throw new Error("try statement without catch or finally"); if (this.prev < entry.finallyLoc) return handle(entry.finallyLoc); } } } }, abrupt: function abrupt(type, arg) { for (var i = this.tryEntries.length - 1; i >= 0; --i) { var entry = this.tryEntries[i]; if (entry.tryLoc <= this.prev && hasOwn.call(entry, "finallyLoc") && this.prev < entry.finallyLoc) { var finallyEntry = entry; break; } } finallyEntry && ("break" === type || "continue" === type) && finallyEntry.tryLoc <= arg && arg <= finallyEntry.finallyLoc && (finallyEntry = null); var record = finallyEntry ? finallyEntry.completion : {}; return record.type = type, record.arg = arg, finallyEntry ? (this.method = "next", this.next = finallyEntry.finallyLoc, ContinueSentinel) : this.complete(record); }, complete: function complete(record, afterLoc) { if ("throw" === record.type) throw record.arg; return "break" === record.type || "continue" === record.type ? this.next = record.arg : "return" === record.type ? (this.rval = this.arg = record.arg, this.method = "return", this.next = "end") : "normal" === record.type && afterLoc && (this.next = afterLoc), ContinueSentinel; }, finish: function finish(finallyLoc) { for (var i = this.tryEntries.length - 1; i >= 0; --i) { var entry = this.tryEntries[i]; if (entry.finallyLoc === finallyLoc) return this.complete(entry.completion, entry.afterLoc), resetTryEntry(entry), ContinueSentinel; } }, catch: function _catch(tryLoc) { for (var i = this.tryEntries.length - 1; i >= 0; --i) { var entry = this.tryEntries[i]; if (entry.tryLoc === tryLoc) { var record = entry.completion; if ("throw" === record.type) { var thrown = record.arg; resetTryEntry(entry); } return thrown; } } throw new Error("illegal catch attempt"); }, delegateYield: function delegateYield(iterable, resultName, nextLoc) { return this.delegate = { iterator: values(iterable), resultName: resultName, nextLoc: nextLoc }, "next" === this.method && (this.arg = undefined), ContinueSentinel; } }, exports; } +function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } } +function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; } var arr = []; L.DistortableCollection = L.FeatureGroup.extend({ options: { @@ -213,16 +217,14 @@ L.DistortableCollection = L.FeatureGroup.extend({ onAdd: function onAdd(map) { L.FeatureGroup.prototype.onAdd.call(this, map); this._map = map; - if (this.editable) { this.editing.enable(); } + /** * although we have a DistortableCollection.Edit class that handles collection events to keep our code managable, * events that need to be added on individual images are kept here to do so through `layeradd`. */ - - this.on('layeradd', this._addEvents, this); this.on('layerremove', this._removeEvents, this); }, @@ -230,7 +232,6 @@ L.DistortableCollection = L.FeatureGroup.extend({ if (this.editing) { this.editing.disable(); } - this.off('layeradd', this._addEvents, this); this.off('layerremove', this._removeEvents, this); }, @@ -242,7 +243,6 @@ L.DistortableCollection = L.FeatureGroup.extend({ }, this); L.DomEvent.on(layer.getElement(), { mousedown: this._deselectOthers, - /* Enable longpress for multi select for touch devices. */ contextmenu: this._longPressMultiSelect }, this); @@ -260,21 +260,16 @@ L.DistortableCollection = L.FeatureGroup.extend({ }, _longPressMultiSelect: function _longPressMultiSelect(e) { var _this = this; - if (!this.editable) { return; } - e.preventDefault(); this.eachLayer(function (layer) { var edit = layer.editing; - if (layer.getElement() === e.target && edit.enabled()) { L.DomUtil.toggleClass(layer.getElement(), 'collected'); - if (_this.anyCollected()) { layer.deselect(); - _this.editing._addToolbar(); } else { _this.editing._removeToolbar(); @@ -293,13 +288,12 @@ L.DistortableCollection = L.FeatureGroup.extend({ if (e.shiftKey) { /* conditional prevents disabled images from flickering multi-select mode */ if (layer.editing.enabled()) { - L.DomUtil.toggleClass(e.target, 'collected'); // re-order layers by _leaflet_id to match their display order in UI + L.DomUtil.toggleClass(e.target, 'collected'); + // re-order layers by _leaflet_id to match their display order in UI // add new layer to right position and avoid repitition - var newArr = arr.every(function (each) { return each._leaflet_id !== layer._leaflet_id; }); - if (newArr) { arr.push(layer); } else { @@ -307,7 +301,6 @@ L.DistortableCollection = L.FeatureGroup.extend({ } } } - if (this.anyCollected()) { layer.deselect(); } else { @@ -316,11 +309,9 @@ L.DistortableCollection = L.FeatureGroup.extend({ }, _deselectOthers: function _deselectOthers(e) { var _this2 = this; - if (!this.editable) { return; } - this.eachLayer(function (layer) { if (layer.getElement() !== e.target) { layer.deselect(); @@ -328,7 +319,6 @@ L.DistortableCollection = L.FeatureGroup.extend({ _this2._toggleCollected(e, layer); } }); - if (e) { L.DomEvent.stopPropagation(e); } @@ -337,15 +327,12 @@ L.DistortableCollection = L.FeatureGroup.extend({ var overlay = e.target; var map = this._map; var i; - if (!this.isCollected(overlay)) { return; } - this.eachLayer(function (layer) { layer._dragStartPoints = {}; layer.deselect(); - for (i = 0; i < 4; i++) { var c = layer.getCorner(i); layer._dragStartPoints[i] = map.latLngToLayerPoint(c); @@ -355,20 +342,15 @@ L.DistortableCollection = L.FeatureGroup.extend({ _dragMultiple: function _dragMultiple(e) { var overlay = e.target; var map = this._map; - if (!this.isCollected(overlay)) { return; } - var topLeft = map.latLngToLayerPoint(overlay.getCorner(0)); - var delta = overlay._dragStartPoints[0].subtract(topLeft); - this._updateCollectionFromPoints(delta, overlay); }, _toRemove: function _toRemove() { var _this3 = this; - var layerArr = this.getLayers(); return layerArr.filter(function (layer) { var mode = layer.editing._mode; @@ -377,7 +359,6 @@ L.DistortableCollection = L.FeatureGroup.extend({ }, _toMove: function _toMove(overlay) { var _this4 = this; - var layerArr = this.getLayers(); return layerArr.filter(function (layer) { var mode = layer.editing._mode; @@ -386,16 +367,13 @@ L.DistortableCollection = L.FeatureGroup.extend({ }, _updateCollectionFromPoints: function _updateCollectionFromPoints(delta, overlay) { var layersToMove = this._toMove(overlay); - var p = new L.Transformation(1, -delta.x, 1, -delta.y); var i; layersToMove.forEach(function (layer) { var movedPoints = {}; - for (i = 0; i < 4; i++) { movedPoints[i] = p.transform(layer._dragStartPoints[i]); } - layer.setCornersFromPoints(movedPoints); }); }, @@ -405,18 +383,80 @@ L.DistortableCollection = L.FeatureGroup.extend({ }, 0); return reduce / imgs.length; }, - isJsonDetected: function isJsonDetected(currentURL) { - if (currentURL.includes('?json=')) { - startIndex = currentURL.lastIndexOf('.'); - fileExtension = currentURL.slice(startIndex + 1); - - if (fileExtension === 'json') { - console.log('JSON found in map shareable link'); - return true; - } - } - - return false; + // Connects to JSON file and fetches JSON data therein from remote source + fetchRemoteJson: function fetchRemoteJson(url) { + return _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee() { + var index, imgCollectionProps, response; + return _regeneratorRuntime().wrap(function _callee$(_context) { + while (1) { + switch (_context.prev = _context.next) { + case 0: + index = 0; + imgCollectionProps = []; + _context.prev = 2; + _context.next = 5; + return axios.get(url); + case 5: + response = _context.sent; + if (!(response.data.images.length > 1)) { + _context.next = 9; + break; + } + response.data.images.forEach(function (data) { + imgCollectionProps[index] = data; + index++; + }); + return _context.abrupt("return", { + avg_cm_per_pixel: response.data.avg_cm_per_pixel, + imgCollectionProps: imgCollectionProps + }); + case 9: + imgCollectionProps[index] = response.data.images; + return _context.abrupt("return", { + avg_cm_per_pixel: response.data.avg_cm_per_pixel, + imgCollectionProps: imgCollectionProps + }); + case 13: + _context.prev = 13; + _context.t0 = _context["catch"](2); + console.log('err', _context.t0); + case 16: + case "end": + return _context.stop(); + } + } + }, _callee, null, [[2, 13]]); + }))(); + }, + // expects url in this format: https://archive.org/download/segeotest/segeotest.json + recreateImagesFromJsonUrl: function recreateImagesFromJsonUrl(url) { + var _this5 = this; + return _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee2() { + var imageCollectionObj; + return _regeneratorRuntime().wrap(function _callee2$(_context2) { + while (1) { + switch (_context2.prev = _context2.next) { + case 0: + imageCollectionObj = {}; + if (!url) { + _context2.next = 6; + break; + } + _context2.next = 4; + return _this5.fetchRemoteJson(url); + case 4: + imageCollectionObj = _context2.sent; + return _context2.abrupt("return", imageCollectionObj); + case 6: + ; + return _context2.abrupt("return", imageCollectionObj); + case 8: + case "end": + return _context2.stop(); + } + } + }, _callee2); + }))(); }, generateExportJson: function generateExportJson() { var allImages = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; @@ -425,7 +465,6 @@ L.DistortableCollection = L.FeatureGroup.extend({ this.eachLayer(function (layer) { if (allImages || this.isCollected(layer)) { var sections = layer._image.src.split('/'); - var filename = sections[sections.length - 1]; var zc = layer.getCorners(); var corners = [{ @@ -457,7 +496,6 @@ L.DistortableCollection = L.FeatureGroup.extend({ return json; } }); - L.distortableCollection = function (id, options) { return new L.DistortableCollection(id, options); }; @@ -495,57 +533,44 @@ L.DistortableImageOverlay = L.ImageOverlay.extend({ }, onAdd: function onAdd(map) { var _this = this; - this._map = map; - if (!this.getElement()) { this._initImage(); } - map.on('viewreset', this._reset, this); - if (this.options.corners) { this._corners = this.options.corners; - if (map.options.zoomAnimation && L.Browser.any3d) { map.on('zoomanim', this._animateZoom, this); } - } // Have to wait for the image to load because need to access its w/h - + } + // Have to wait for the image to load because need to access its w/h L.DomEvent.on(this.getElement(), 'load', function () { _this.getPane().appendChild(_this.getElement()); - _this._initImageDimensions(); - if (_this.options.rotation) { var units = _this.options.rotation.deg >= 0 ? 'deg' : 'rad'; - _this.setAngle(_this.options.rotation[units], units); } else { _this.rotation = { deg: 0, rad: 0 }; - _this._reset(); } - /* Initialize default corners if not already set */ - + /* Initialize default corners if not already set */ if (!_this._corners) { if (map.options.zoomAnimation && L.Browser.any3d) { map.on('zoomanim', _this._animateZoom, _this); } } - /** if there is a featureGroup, only its editable option matters */ - + /** if there is a featureGroup, only its editable option matters */ var eventParents = _this._eventParents; - if (eventParents) { _this.eP = eventParents[Object.keys(eventParents)[0]]; - if (_this.eP.editable) { _this.editing.enable(); } @@ -553,7 +578,6 @@ L.DistortableImageOverlay = L.ImageOverlay.extend({ if (_this.editable) { _this.editing.enable(); } - _this.eP = null; } }); @@ -563,15 +587,14 @@ L.DistortableImageOverlay = L.ImageOverlay.extend({ singleclickoff: this._resetClickListeners, singleclick: this._singleClick }, this); + /** * custom events fired from DoubleClickLabels.js. Used to differentiate * single / dblclick to not deselect images on map dblclick. */ - if (!(map.doubleClickZoom.enabled() || map.doubleClickLabels.enabled())) { L.DomEvent.on(map, 'click', this.deselect, this); } - this.fire('add'); L.DomEvent.on(this.getElement(), 'mousemove', this.activateTooltip, this); L.DomEvent.on(this.getElement(), 'mouseout', this.closeTooltip, this); @@ -584,11 +607,9 @@ L.DistortableImageOverlay = L.ImageOverlay.extend({ singleclick: this._singleClick }, this); L.DomEvent.off(map, 'click', this.deselect, this); - if (this.editing) { this.editing.disable(); } - this.fire('remove'); L.ImageOverlay.prototype.onRemove.call(this, map); L.DomEvent.on(this.getElement(), 'mouseout', this.closeTooltip, this); @@ -603,13 +624,11 @@ L.DistortableImageOverlay = L.ImageOverlay.extend({ var imageWidth = parseInt(aspectRatio * imageHeight); var center = map.project(map.getCenter()); var offset = L.point(imageWidth, imageHeight).divideBy(2); - if (this.options.corners) { this._corners = this.options.corners; } else { this._corners = [map.unproject(center.subtract(offset)), map.unproject(center.add(L.point(offset.x, -offset.y))), map.unproject(center.add(L.point(-offset.x, offset.y))), map.unproject(center.add(offset))]; } - this._initialDimensions = { 'center': center, 'offset': offset, @@ -639,15 +658,11 @@ L.DistortableImageOverlay = L.ImageOverlay.extend({ }, deselect: function deselect() { var edit = this.editing; - if (!edit.enabled()) { return; } - edit._removeToolbar(); - edit._hideMarkers(); - this._selected = false; this.fire('deselect'); return this; @@ -655,31 +670,25 @@ L.DistortableImageOverlay = L.ImageOverlay.extend({ select: function select(e) { var edit = this.editing; var eP = this.eP; - if (!edit.enabled()) { return; } - if (e) { L.DomEvent.stopPropagation(e); - } // this ensures deselection of all other images, allowing us to keep collection group optional - + } + // this ensures deselection of all other images, allowing us to keep collection group optional this._programmaticGrouping(); - this._selected = true; - edit._addToolbar(); - edit._showMarkers(); + this.fire('select'); - this.fire('select'); // we run the selection logic 1st anyway because the collection group's _addToolbar method depends on it - + // we run the selection logic 1st anyway because the collection group's _addToolbar method depends on it if (eP && eP.anyCollected()) { this.deselect(); return; } - return this; }, _programmaticGrouping: function _programmaticGrouping() { @@ -694,11 +703,9 @@ L.DistortableImageOverlay = L.ImageOverlay.extend({ this._corners[corner] = latlng; this.setBounds(L.latLngBounds(this.getCorners())); this.fire('update'); - if (edit.toolbar && edit.toolbar instanceof L.DistortableImage.PopupBar) { edit._updateToolbarPos(); } - this.edited = true; return this; }, @@ -708,7 +715,6 @@ L.DistortableImageOverlay = L.ImageOverlay.extend({ } else { var exceedsTop; var exceedsBottom; - if (zoom === 0) { exceedsTop = map.project(corner).y < 2; exceedsBottom = map.project(corner).y >= 255; @@ -716,7 +722,6 @@ L.DistortableImageOverlay = L.ImageOverlay.extend({ exceedsTop = map.project(corner).y / zoom < 2; exceedsBottom = map.project(corner).y / Math.pow(2, zoom) >= 255; } - return exceedsTop || exceedsBottom; } }, @@ -737,8 +742,9 @@ L.DistortableImageOverlay = L.ImageOverlay.extend({ var map = this._map; var zoom = map.getZoom(); var edit = this.editing; - var i = 0; // this is to fix https://github.com/publiclab/Leaflet.DistortableImage/issues/402 + var i = 0; + // this is to fix https://github.com/publiclab/Leaflet.DistortableImage/issues/402 for (var k in latlngObj) { if (this._cornerExceedsMapLats(zoom, latlngObj[k], map)) { // calling reset / update w/ the same corners bc it prevents a marker flicker for rotate @@ -747,19 +753,15 @@ L.DistortableImageOverlay = L.ImageOverlay.extend({ return; } } - for (var _k in latlngObj) { this._corners[i] = latlngObj[_k]; i += 1; } - this.setBounds(L.latLngBounds(this.getCorners())); this.fire('update'); - if (edit.toolbar && edit.toolbar instanceof L.DistortableImage.PopupBar) { edit._updateToolbarPos(); } - this.edited = true; return this; }, @@ -768,10 +770,8 @@ L.DistortableImageOverlay = L.ImageOverlay.extend({ var zoom = map.getZoom(); var edit = this.editing; var i = 0; - for (var k in pointsObj) { var corner = map.layerPointToLatLng(pointsObj[k]); - if (this._cornerExceedsMapLats(zoom, corner, map)) { // calling reset / update w/ the same corners bc it prevents a marker flicker for rotate this.setBounds(L.latLngBounds(this.getCorners())); @@ -779,19 +779,15 @@ L.DistortableImageOverlay = L.ImageOverlay.extend({ return; } } - for (var _k2 in pointsObj) { this._corners[i] = map.layerPointToLatLng(pointsObj[_k2]); i += 1; } - this.setBounds(L.latLngBounds(this.getCorners())); this.fire('update'); - if (edit.toolbar && edit.toolbar instanceof L.DistortableImage.PopupBar) { edit._updateToolbarPos(); } - this.edited = true; return this; }, @@ -801,16 +797,13 @@ L.DistortableImageOverlay = L.ImageOverlay.extend({ var i; var p; var scaledCorners = {}; - if (scale === 0) { return; } - for (i = 0; i < 4; i++) { p = map.project(this.getCorner(i)).subtract(center).multiplyBy(scale).add(center); scaledCorners[i] = map.unproject(p); } - this.setCorners(scaledCorners); return this; }, @@ -823,15 +816,12 @@ L.DistortableImageOverlay = L.ImageOverlay.extend({ var row1y = matrix[5]; var determinant = row0x * row1y - row0y * row1x; var angle = L.TrigUtil.calcAngle(row0x, row0y, 'rad'); - if (determinant < 0) { angle += angle < 0 ? Math.PI : -Math.PI; } - if (angle < 0) { angle = 2 * Math.PI + angle; } - return unit === 'deg' ? Math.round(L.TrigUtil.radiansToDegrees(angle)) : L.Util.formatNum(angle, 2); }, setAngle: function setAngle(angle) { @@ -849,17 +839,14 @@ L.DistortableImageOverlay = L.ImageOverlay.extend({ var i; var p; var q; - if (unit === 'deg') { angle = L.TrigUtil.degreesToRadians(angle); } - for (i = 0; i < 4; i++) { p = map.project(this.getCorner(i)).subtract(center); q = L.point(Math.cos(angle) * p.x - Math.sin(angle) * p.y, Math.sin(angle) * p.x + Math.cos(angle) * p.y); corners[i] = map.unproject(q.add(center)); } - this.setCorners(corners); return this; }, @@ -869,12 +856,10 @@ L.DistortableImageOverlay = L.ImageOverlay.extend({ var p; var transCorners = {}; var delta = map.project(formerPoint).subtract(map.project(newPoint)); - for (i = 0; i < 4; i++) { p = map.project(this.getCorner(i)).subtract(delta); transCorners[i] = map.unproject(p); } - this.setCorners(transCorners); }, restore: function restore() { @@ -883,20 +868,16 @@ L.DistortableImageOverlay = L.ImageOverlay.extend({ var offset = this._initialDimensions.offset; var zoom = this._initialDimensions.zoom; var corners = [center.subtract(offset), center.add(L.point(offset.x, -offset.y)), center.add(L.point(-offset.x, offset.y)), center.add(offset)]; - for (var i = 0; i < 4; i++) { if (!map.unproject(corners[i], zoom).equals(this.getCorner(i))) { this.setCorner(i, map.unproject(corners[i], zoom)); } } - this.edited = false; this.fire('restore'); return this; }, - /* Copied from Leaflet v0.7 https://github.com/Leaflet/Leaflet/blob/66282f14bcb180ec87d9818d9f3c9f75afd01b30/src/dom/DomUtil.js#L189-L199 */ - /* since L.DomUtil.getTranslateString() is deprecated in Leaflet v1.0 */ _getTranslateString: function _getTranslateString(point) { // on WebKit browsers (Chrome/Safari/iOS Safari/Android) @@ -904,6 +885,7 @@ L.DistortableImageOverlay = L.ImageOverlay.extend({ // makes animation smoother as it ensures HW accel is used. // Firefox 13 doesn't care // (same speed either way), Opera 12 doesn't support translate3d + var is3d = L.Browser.webkit3d; var open = 'translate' + (is3d ? '3d' : '') + '('; var close = (is3d ? ',0' : '') + ')'; @@ -913,27 +895,22 @@ L.DistortableImageOverlay = L.ImageOverlay.extend({ var map = this._map; var image = this.getElement(); var latLngToLayerPoint = L.bind(map.latLngToLayerPoint, map); - var transformMatrix = this._calculateProjectiveTransform(latLngToLayerPoint); - var topLeft = latLngToLayerPoint(this.getCorner(0)); var warp = L.DomUtil.getMatrixString(transformMatrix); - var translation = this._getTranslateString(topLeft); - /* See L.DomUtil.setPosition. Mainly for the purposes of L.Draggable. */ - + /* See L.DomUtil.setPosition. Mainly for the purposes of L.Draggable. */ image._leaflet_pos = topLeft; image.style[L.DomUtil.TRANSFORM] = [translation, warp].join(' '); + /* Set origin to the upper-left corner rather than * the center of the image, which is the default. */ - image.style[L.DomUtil.TRANSFORM + '-origin'] = '0 0 0'; this.rotation.deg = this.getAngle(); this.rotation.rad = this.getAngle('rad'); }, - /* * Calculates the transform string that will be * correct *at the end* of zooming. @@ -943,20 +920,15 @@ L.DistortableImageOverlay = L.ImageOverlay.extend({ _animateZoom: function _animateZoom(event) { var map = this._map; var image = this.getElement(); - var latLngToNewLayerPoint = function latLngToNewLayerPoint(latlng) { return map._latLngToNewLayerPoint(latlng, event.zoom, event.center); }; - var transformMatrix = this._calculateProjectiveTransform(latLngToNewLayerPoint); - var topLeft = latLngToNewLayerPoint(this.getCorner(0)); var warp = L.DomUtil.getMatrixString(transformMatrix); - var translation = this._getTranslateString(topLeft); - /* See L.DomUtil.setPosition. Mainly for the purposes of L.Draggable. */ - + /* See L.DomUtil.setPosition. Mainly for the purposes of L.Draggable. */ image._leaflet_pos = topLeft; image.style[L.DomUtil.TRANSFORM] = [translation, warp].join(' '); }, @@ -984,10 +956,10 @@ L.DistortableImageOverlay = L.ImageOverlay.extend({ var c = []; var j; /* Convert corners to container points (i.e. cartesian coordinates). */ - for (j = 0; j < 4; j++) { c.push(latLngToCartesian(this.getCorner(j))._subtract(offset)); } + /* * This matrix describes the action of * the CSS transform on each corner of the image. @@ -999,16 +971,12 @@ L.DistortableImageOverlay = L.ImageOverlay.extend({ * says that the upper-left corner of the image * maps to the first latlng in this._corners. */ - - return L.MatrixUtil.general2DProjection(0, 0, c[0].x, c[0].y, w, 0, c[1].x, c[1].y, 0, h, c[2].x, c[2].y, w, h, c[3].x, c[3].y); } }); - L.distortableImageOverlay = function (id, options) { return new L.DistortableImageOverlay(id, options); }; - L.Map.addInitHook(function () { if (!L.DomUtil.hasClass(this.getContainer(), 'ldi')) { L.DomUtil.addClass(this.getContainer(), 'ldi'); @@ -1024,7 +992,6 @@ L.Map.addInitHook(function () { /***/ (function() { var _this = this; - L.DomUtil = L.DomUtil || {}; L.DistortableImage = L.DistortableImage || {}; L.distortableImage = L.DistortableImage; @@ -1041,9 +1008,7 @@ L.DistortableImage.Keymapper = L.Handler.extend({ this._container = this._buildContainer(); this._scrollWrapper = this._wrap(); this._toggler = this._createButton(); - this._setMapper(this._container, this._scrollWrapper, this._toggler); - L.DomEvent.on(this._toggler, 'click', this._toggleKeymapper, this); L.DomEvent.disableClickPropagation(this._container); L.DomEvent.disableScrollPropagation(this._container); @@ -1070,8 +1035,8 @@ L.DistortableImage.Keymapper = L.Handler.extend({ toggler.innerHTML = L.IconUtil.create('keyboard_open'); toggler.setAttribute('id', 'toggle-keymapper'); toggler.setAttribute('href', '#'); - toggler.setAttribute('title', 'Show keymap'); // Will force screen readers like VoiceOver to read this as "Show keymap - button" - + toggler.setAttribute('title', 'Show keymap'); + // Will force screen readers like VoiceOver to read this as "Show keymap - button" toggler.setAttribute('role', 'button'); toggler.setAttribute('aria-label', 'Show keymap'); return toggler; @@ -1086,18 +1051,14 @@ L.DistortableImage.Keymapper = L.Handler.extend({ this._keymapper = L.control({ position: this.options.position }); - this._keymapper.onAdd = function () { container.appendChild(wrap); - wrap.insertAdjacentHTML('beforeend', '' + '
' + - /* eslint-disable */ + wrap.insertAdjacentHTML('beforeend', '
' + '
' + /* eslint-disable */ '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '
Rotate Mode
R
RotateScale Mode
r
Scale Mode
s
Distort Mode
d
Drag Mode
D
Lock (Mode) / Unlock Image
l\xa0u
Stack up / down
q\xa0a
Add / Remove Image Border
b
Toggle Opacity
o
Deselect All
esc
Delete Image(s)
delete\xa0backspace
Export Image(s)
e
'); /* eslint-enable */ - container.appendChild(button); return container; }; - this._keymapper.addTo(this._map); }, _toggleKeymapper: function _toggleKeymapper(e) { @@ -1112,7 +1073,6 @@ L.DistortableImage.Keymapper = L.Handler.extend({ if (document.querySelector('#keymapper-iconset')) { return; } - var el = L.DomUtil.create('div', ''); el.id = 'keymapper-iconset'; el.setAttribute('hidden', 'hidden'); @@ -1122,15 +1082,13 @@ L.DistortableImage.Keymapper = L.Handler.extend({ } }); L.DistortableImage.Keymapper.addInitHook(function () { - L.DistortableImage.Keymapper.prototype._n = L.DistortableImage.Keymapper.prototype._n ? L.DistortableImage.Keymapper.prototype._n + 1 : 1; // dont enable keymapper for mobile - + L.DistortableImage.Keymapper.prototype._n = L.DistortableImage.Keymapper.prototype._n ? L.DistortableImage.Keymapper.prototype._n + 1 : 1; + // dont enable keymapper for mobile if (L.DistortableImage.Keymapper.prototype._n === 1 && !L.Browser.mobile) { _this.enable(); - _this._injectIconSet(); } }); - L.distortableImage.keymapper = function (map, options) { return new L.DistortableImage.Keymapper(map, options); }; @@ -1143,8 +1101,9 @@ L.distortableImage.keymapper = function (map, options) { \************************************************/ /***/ (function() { -L.DistortableImage = L.DistortableImage || {}; // this class holds the keybindings and toolbar API for an image collection instance +L.DistortableImage = L.DistortableImage || {}; +// this class holds the keybindings and toolbar API for an image collection instance L.DistortableCollection.Edit = L.Handler.extend({ options: { keymap: L.distortableImage.group_action_map @@ -1161,11 +1120,9 @@ L.DistortableCollection.Edit = L.Handler.extend({ this.editActions = this.options.actions; this.runExporter = L.bind(L.Utils.getNestedVal(this, '_exportOpts', 'exporter') || this.startExport, this); L.DomEvent.on(document, 'keydown', this._onKeyDown, this); - if (!(map.doubleClickZoom.enabled() || map.doubleClickLabels.enabled())) { L.DomEvent.on(map, 'click', this._decollectAll, this); } - L.DomEvent.on(map, { singleclickon: this._singleClickListeners, singleclickoff: this._resetClickListeners, @@ -1173,7 +1130,6 @@ L.DistortableCollection.Edit = L.Handler.extend({ boxcollectend: this._addCollections }, this); this._group.editable = true; - this._group.eachLayer(function (layer) { return layer.editing.enable(); }); @@ -1182,22 +1138,17 @@ L.DistortableCollection.Edit = L.Handler.extend({ var group = this._group; var map = group._map; L.DomEvent.off(document, 'keydown', this._onKeyDown, this); - if (!(map.doubleClickZoom.enabled() || map.doubleClickLabels.enabled())) { L.DomEvent.off(map, 'click', this._decollectAll, this); } - L.DomEvent.off(map, { singleclickon: this._singleClickListeners, singleclickoff: this._resetClickListeners, singleclick: this._singleClick, boxcollectend: this._addCollections }, this); - this._decollectAll(); - this._group.editable = false; - this._group.eachLayer(function (layer) { return layer.editing.disable(); }); @@ -1215,11 +1166,9 @@ L.DistortableCollection.Edit = L.Handler.extend({ _onKeyDown: function _onKeyDown(e) { var keymap = this.options.keymap; var handlerName = keymap[e.key]; - if (!this[handlerName]) { return; } - if (this._group.anyCollected()) { this[handlerName].call(this); } @@ -1243,7 +1192,6 @@ L.DistortableCollection.Edit = L.Handler.extend({ }, _decollectAll: function _decollectAll(e) { var oe; - if (e) { oe = e.originalEvent; } @@ -1251,113 +1199,86 @@ L.DistortableCollection.Edit = L.Handler.extend({ * prevents image deselection following the 'boxcollectend' event - note 'shift' must not be released until dragging is complete * also prevents deselection following a click on a disabled img by differentiating it from the map */ - - if (oe && (oe.shiftKey || oe.target instanceof HTMLImageElement)) { return; } - this._group.eachLayer(function (layer) { L.DomUtil.removeClass(layer.getElement(), 'collected'); layer.deselect(); }); - this._removeToolbar(); - if (e) { L.DomEvent.stopPropagation(e); } }, _unlockGroup: function _unlockGroup() { var _this = this; - if (!this.hasTool(L.UnlockAction)) { return; } - this._group.eachLayer(function (layer) { if (_this._group.isCollected(layer)) { var edit = layer.editing; - - edit._unlock(); // unlock updates the layer's handles; deselect to ensure they're hidden - - + edit._unlock(); + // unlock updates the layer's handles; deselect to ensure they're hidden layer.deselect(); } }); }, _lockGroup: function _lockGroup() { var _this2 = this; - if (!this.hasTool(L.LockAction)) { return; } - this._group.eachLayer(function (layer) { if (_this2._group.isCollected(layer)) { var edit = layer.editing; - - edit._lock(); // map.addLayer also deselects the image, so we reselect here - - + edit._lock(); + // map.addLayer also deselects the image, so we reselect here L.DomUtil.addClass(layer.getElement(), 'collected'); } }); }, _addCollections: function _addCollections(e) { var _this3 = this; - var box = e.boxCollectBounds; var map = this._group._map; - this._group.eachLayer(function (layer) { var edit = layer.editing; - if (layer.isSelected()) { layer.deselect(); } - var zoom = map.getZoom(); var center = map.getCenter(); var imgBounds = L.latLngBounds(layer.getCorner(2), layer.getCorner(1)); imgBounds = map._latLngBoundsToNewLayerBounds(imgBounds, zoom, center); - if (box.intersects(imgBounds) && edit.enabled()) { if (!_this3.toolbar) { _this3._addToolbar(); } - L.DomUtil.addClass(layer.getElement(), 'collected'); } }); }, _removeGroup: function _removeGroup(e) { var _this4 = this; - if (!this.hasTool(L.DeleteAction)) { return; } - var layersToRemove = this._group._toRemove(); - var n = layersToRemove.length; - if (n === 0) { return; } - var choice = L.DomUtil.confirmDeletes(n); - if (choice) { layersToRemove.forEach(function (layer) { _this4._group.removeLayer(layer); }); - if (!this._group.anyCollected()) { this._removeToolbar(); } } - if (e) { L.DomEvent.stopPropagation(e); } @@ -1366,17 +1287,14 @@ L.DistortableCollection.Edit = L.Handler.extend({ if (!this.customCollection) { this._exportOpts.collection = undefined; } - clearInterval(this.updateInterval); }, _addToolbar: function _addToolbar() { var group = this._group; var map = group._map; - if (group.options.suppressToolbar || this.toolbar) { return; } - this.toolbar = L.distortableImage.controlBar({ actions: this.editActions, position: 'topleft' @@ -1384,7 +1302,6 @@ L.DistortableCollection.Edit = L.Handler.extend({ }, _removeToolbar: function _removeToolbar() { var map = this._group._map; - if (this.toolbar) { map.removeLayer(this.toolbar); this.toolbar = false; @@ -1400,25 +1317,18 @@ L.DistortableCollection.Edit = L.Handler.extend({ addTool: function addTool(value) { if (value.baseClass === 'leaflet-toolbar-icon' && !this.hasTool(value)) { this._removeToolbar(); - this.editActions.push(value); - this._addToolbar(); } - return this; }, removeTool: function removeTool(value) { var _this5 = this; - this.editActions.some(function (item, idx) { if (_this5.editActions[idx] === value) { _this5._removeToolbar(); - _this5.editActions.splice(idx, 1); - _this5._addToolbar(); - return true; } else { return false; @@ -1428,54 +1338,51 @@ L.DistortableCollection.Edit = L.Handler.extend({ }, startExport: function startExport() { var _this6 = this; - if (!this.hasTool(L.ExportAction)) { return; } - return new Promise(function (resolve) { var opts = _this6._exportOpts; opts.resolve = resolve; // allow resolving promise in user-defined functions, to stop spinner on completion var statusUrl; - _this6.updateInterval = null; // this may be overridden to update the UI to show export progress or completion + _this6.updateInterval = null; + // this may be overridden to update the UI to show export progress or completion var _defaultUpdater = function _defaultUpdater(data) { - data = JSON.parse(data); // optimization: fetch status directly from google storage: - + data = JSON.parse(data); + // optimization: fetch status directly from google storage: if (data.status_url) { if (statusUrl !== data.status_url && data.status_url.match('.json')) { // if (data.status_url && data.status_url.substr(0,1) === "/") { // opts.statusUrl = opts.statusUrl + data.status_url; // } else { - statusUrl = data.status_url; // } + statusUrl = data.status_url; + // } } if (data.status === 'complete') { clearInterval(_this6.updateInterval); - if (!_this6.customCollection) { _this6._exportOpts.collection = undefined; } - resolve(); - if (data.jpg !== null) { alert('Export succeeded. ' + opts.exportUrl + data.jpg); } - } // TODO: update to clearInterval when status == "failed" if we update that in this file: - // https://github.com/publiclab/mapknitter-exporter/blob/main/lib/mapknitterExporter.rb - + } + // TODO: update to clearInterval when status == "failed" if we update that in this file: + // https://github.com/publiclab/mapknitter-exporter/blob/main/lib/mapknitterExporter.rb console.log(data); } - }; // receives the URL of status.json, and starts running the updater to repeatedly fetch from status.json; - // this may be overridden to integrate with any UI - + }; + // receives the URL of status.json, and starts running the updater to repeatedly fetch from status.json; + // this may be overridden to integrate with any UI var _defaultHandleStatusRes = function _defaultHandleStatusRes(data) { - statusUrl = opts.statusUrl + data; // repeatedly fetch the status.json - + statusUrl = opts.statusUrl + data; + // repeatedly fetch the status.json _this6.updateInterval = setInterval(function () { var reqOpts = { method: 'GET' @@ -1487,9 +1394,9 @@ L.DistortableCollection.Edit = L.Handler.extend({ } }).then(opts.updater); }, opts.frequency); - }; // initiate the export - + }; + // initiate the export var _defaultFetchStatusUrl = function _defaultFetchStatusUrl(mergedOpts) { var form = new FormData(); form.append('collection', JSON.stringify(mergedOpts.collection)); @@ -1505,18 +1412,15 @@ L.DistortableCollection.Edit = L.Handler.extend({ return res.text(); } }).then(mergedOpts.handleStatusRes); - }; // If the user has passed collection property - + }; + // If the user has passed collection property _this6.customCollection = !!opts.collection; - if (!_this6.customCollection) { opts.collection = _this6._group.generateExportJson().images; } - opts.frequency = opts.frequency || 3000; opts.scale = opts.scale || 100; // switch it to _getAvgCmPerPixel ! - opts.updater = opts.updater || _defaultUpdater; opts.handleStatusRes = opts.handleStatusRes || _defaultHandleStatusRes; opts.fetchStatusUrl = opts.fetchStatusUrl || _defaultFetchStatusUrl; @@ -1524,7 +1428,6 @@ L.DistortableCollection.Edit = L.Handler.extend({ }); } }); - L.distortableCollection.edit = function (group, options) { return new L.DistortableCollection.Edit(group, options); }; @@ -1537,8 +1440,9 @@ L.distortableCollection.edit = function (group, options) { \*******************************************/ /***/ (function() { -L.DistortableImage = L.DistortableImage || {}; // holds the keybindings & toolbar API for an individual image instance +L.DistortableImage = L.DistortableImage || {}; +// holds the keybindings & toolbar API for an individual image instance L.DistortableImage.Edit = L.Handler.extend({ options: { opacity: 0.7, @@ -1554,60 +1458,47 @@ L.DistortableImage.Edit = L.Handler.extend({ L.setOptions(this, options); L.distortableImage.action_map.Escape = '_deselect'; }, - - /* Run on image selection. */ - addHooks: function addHooks() { + /* Run on image selection. */addHooks: function addHooks() { var overlay = this._overlay; this.editActions = this.options.actions; - /* bring the selected image into view */ + /* bring the selected image into view */ overlay.bringToFront(); - this._initModes(); - this._initHandles(); - this._appendHandlesandDragable(); - if (overlay.isSelected() && !overlay.options.suppressToolbar) { this._addToolbar(); } - this.parentGroup = overlay.eP ? overlay.eP : false; L.DomEvent.on(overlay.getElement(), { dblclick: this.nextMode }, this); L.DomEvent.on(window, 'keydown', this._onKeyDown, this); }, - - /* Run on image deselection. */ - removeHooks: function removeHooks() { + /* Run on image deselection. */removeHooks: function removeHooks() { var overlay = this._overlay; - var eP = this.parentGroup; // First, check if dragging exists - it may be off due to locking + var eP = this.parentGroup; + // First, check if dragging exists - it may be off due to locking this._disableDragging(); - if (this.toolbar) { this._removeToolbar(); } - for (var handle in this._handles) { L.DomUtil.remove(handle); } + /** * ensures if you disable an image while it is multi-selected * additional deselection logic is run */ - - if (L.DomUtil.hasClass(overlay.getElement(), 'collected')) { L.DomUtil.removeClass(overlay.getElement(), 'collected'); } - if (eP && !eP.anyCollected() && eP.editing.toolbar) { eP.editing._removeToolbar(); } - L.DomEvent.off(overlay.getElement(), { dblclick: this.nextMode }, this); @@ -1617,27 +1508,24 @@ L.DistortableImage.Edit = L.Handler.extend({ if (!this._enabled) { return this; } - this._overlay.deselect(); - this._enabled = false; this.removeHooks(); return this; }, _initModes: function _initModes() { - this._modes = {}; // passed from L.DistortablImage.PopupBar. If the mode is one + this._modes = {}; + // passed from L.DistortablImage.PopupBar. If the mode is one // of the current toolbar actions, adds it to this._modes - for (var mode in L.DistortableImage.Edit.MODES) { var action = L.DistortableImage.Edit.MODES[mode]; - if (this.editActions.indexOf(action) !== -1) { this._modes[mode] = action; } - } // sets the current mode to the 1st available one if the one selected - // during initialization is not available - + } + // sets the current mode to the 1st available one if the one selected + // during initialization is not available if (!this._modes[this._mode]) { this._mode = Object.keys(this._modes)[0]; } @@ -1646,44 +1534,33 @@ L.DistortableImage.Edit = L.Handler.extend({ var overlay = this._overlay; var i; this._dragHandles = L.layerGroup(); - for (i = 0; i < 4; i++) { this._dragHandles.addLayer(L.dragHandle(overlay, i)); } - this._scaleHandles = L.layerGroup(); - for (i = 0; i < 4; i++) { this._scaleHandles.addLayer(L.scaleHandle(overlay, i)); } - this._distortHandles = L.layerGroup(); - for (i = 0; i < 4; i++) { this._distortHandles.addLayer(L.distortHandle(overlay, i)); } - this._rotateHandles = L.layerGroup(); // individual rotate - for (i = 0; i < 4; i++) { this._rotateHandles.addLayer(L.rotateHandle(overlay, i)); - } // handle includes rotate AND scale - + } + // handle includes rotate AND scale this._freeRotateHandles = L.layerGroup(); - for (i = 0; i < 4; i++) { this._freeRotateHandles.addLayer(L.freeRotateHandle(overlay, i)); } - this._lockHandles = L.layerGroup(); - for (i = 0; i < 4; i++) { this._lockHandles.addLayer(L.lockHandle(overlay, i, { draggable: false })); } - this._handles = { drag: this._dragHandles, scale: this._scaleHandles, @@ -1694,26 +1571,22 @@ L.DistortableImage.Edit = L.Handler.extend({ }; }, _appendHandlesandDragable: function _appendHandlesandDragable() { - var ov = this._overlay; // won't throw error if user adds 0 mode actions to toolbar + var ov = this._overlay; + // won't throw error if user adds 0 mode actions to toolbar if (!this._mode) { this._enableDragging(); - return; } - this._updateHandle(); - if (!ov.isSelected() && this.currentHandle) { this.currentHandle.eachLayer(function (handle) { handle.setOpacity(0); - if (handle.dragging) { handle.dragging.disable(); } }); } - if (!this.isMode('lock')) { this._enableDragging(); } @@ -1723,11 +1596,9 @@ L.DistortableImage.Edit = L.Handler.extend({ var handlerName = keymap[e.key]; var ov = this._overlay; var eP = this.parentGroup; - if (eP && eP.anyCollected()) { return; } - if (this[handlerName] !== undefined && !ov.options.suppressToolbar) { if (ov.isSelected() && this.toolbar) { this[handlerName].call(this); @@ -1736,29 +1607,22 @@ L.DistortableImage.Edit = L.Handler.extend({ }, replaceTool: function replaceTool(old, next) { var _this = this; - if (next.baseClass !== 'leaflet-toolbar-icon' || this.hasTool(next)) { return this; } - this.editActions.some(function (item, idx) { if (item === old) { _this._removeToolbar(); - _this.editActions[idx] = next; - _this._addToolbar(); - for (var mode in L.DistortableImage.Edit.MODES) { if (L.DistortableImage.Edit.MODES[mode] === old) { delete _this._modes[mode]; - _this._nextOrNone(mode); } else if (L.DistortableImage.Edit.MODES[mode] === next) { _this._modes[mode] = next; } } - return true; } }); @@ -1767,22 +1631,17 @@ L.DistortableImage.Edit = L.Handler.extend({ addTool: function addTool(value) { if (value.baseClass === 'leaflet-toolbar-icon' && !this.hasTool(value)) { this._removeToolbar(); - this.editActions.push(value); - this._addToolbar(); - for (var mode in L.DistortableImage.Edit.MODES) { if (L.DistortableImage.Edit.MODES[mode] === value) { this._modes[mode] = value; } } - if (!this._overlay.isSelected()) { this._removeToolbar(); } } - return this; }, hasTool: function hasTool(value) { @@ -1792,31 +1651,23 @@ L.DistortableImage.Edit = L.Handler.extend({ }, removeTool: function removeTool(value) { var _this2 = this; - this.editActions.some(function (item, idx) { if (item === value) { _this2._removeToolbar(); - _this2.editActions.splice(idx, 1); - _this2._addToolbar(); - for (var mode in L.DistortableImage.Edit.MODES) { if (L.DistortableImage.Edit.MODES[mode] === value) { delete _this2._modes[mode]; - _this2._nextOrNone(mode); } } - return true; } }); - if (!this._overlay.isSelected()) { this._removeToolbar(); } - return this; }, // set the mode to the next mode or if that was the last one set mode to '' @@ -1828,9 +1679,7 @@ L.DistortableImage.Edit = L.Handler.extend({ if (mode === 'lock') { this._enableDragging(); } - this._mode = ''; - this._updateHandle(); } } @@ -1838,7 +1687,6 @@ L.DistortableImage.Edit = L.Handler.extend({ _removeToolbar: function _removeToolbar() { var ov = this._overlay; var map = ov._map; - if (this.toolbar) { map.removeLayer(this.toolbar); this.toolbar = false; @@ -1846,43 +1694,36 @@ L.DistortableImage.Edit = L.Handler.extend({ }, _enableDragging: function _enableDragging() { var _this3 = this; - var overlay = this._overlay; var map = overlay._map; this.dragging = new L.Draggable(overlay.getElement()); this.dragging.enable(); - /* Hide toolbars and markers while dragging; click will re-show it */ + /* Hide toolbars and markers while dragging; click will re-show it */ this.dragging.on('dragstart', function () { overlay.fire('dragstart'); - _this3._removeToolbar(); }); + /* * Adjust default behavior of L.Draggable, which overwrites the CSS3 * distort transformations that we set when it calls L.DomUtil.setPosition. */ - this.dragging._updatePosition = function () { var topLeft = overlay.getCorner(0); - var delta = this._newPos.subtract(map.latLngToLayerPoint(topLeft)); - var currentPoint; var corners = {}; var i; this.fire('predrag'); - for (i = 0; i < 4; i++) { currentPoint = map.latLngToLayerPoint(overlay.getCorner(i)); corners[i] = map.layerPointToLatLng(currentPoint.add(delta)); } - overlay.setCorners(corners); overlay.fire('drag'); this.fire('drag'); }; - this.dragging.on('dragend', function () { overlay.fire('dragend'); }); @@ -1917,29 +1758,23 @@ L.DistortableImage.Edit = L.Handler.extend({ }, _toggleOpacity: function _toggleOpacity() { var image = this._overlay.getElement(); - if (!this.hasTool(L.OpacityAction)) { return; } - this._transparent = !this._transparent; var opacity = this._transparent ? this.options.opacity : 1; L.DomUtil.setOpacity(image, opacity); image.setAttribute('opacity', opacity); - this._refresh(); }, _toggleBorder: function _toggleBorder() { var image = this._overlay.getElement(); - if (!this.hasTool(L.BorderAction)) { return; } - this._outlined = !this._outlined; var outline = this._outlined ? this.options.outline : 'none'; image.style.outline = outline; - this._refresh(); }, // compare this to using overlay zIndex @@ -1953,19 +1788,14 @@ L.DistortableImage.Edit = L.Handler.extend({ _removeOverlay: function _removeOverlay() { var ov = this._overlay; var eP = this.parentGroup; - if (this.isMode('lock') || !this.hasTool(L.DeleteAction)) { return; } - var choice = L.DomUtil.confirmDelete(); - if (!choice) { return; } - this._removeToolbar(); - if (eP) { eP.removeLayer(ov); } else { @@ -1977,43 +1807,45 @@ L.DistortableImage.Edit = L.Handler.extend({ var overlay = this._overlay; var map = overlay._map; var img = overlay.getElement(); - if (!this.hasTool(L.ExportAction)) { return; - } // make a new image - + } + // make a new image var downloadable = new Image(); downloadable.id = downloadable.id || 'tempId12345'; document.body.appendChild(downloadable); - downloadable.onload = function onLoadDownloadableImage() { var height = downloadable.height; var width = downloadable.width; var nw = map.latLngToLayerPoint(overlay.getCorner(0)); var ne = map.latLngToLayerPoint(overlay.getCorner(1)); var sw = map.latLngToLayerPoint(overlay.getCorner(2)); - var se = map.latLngToLayerPoint(overlay.getCorner(3)); // I think this is to move the image to the upper left corner, + var se = map.latLngToLayerPoint(overlay.getCorner(3)); + + // I think this is to move the image to the upper left corner, // eslint-disable-next-line max-len // jywarren: i think we may need these or the image goes off the edge of the canvas // jywarren: but these seem to break the distortion math... + // jywarren: i think it should be rejiggered so it // finds the most negative values of x and y and then // adds those to all coordinates + // nw.x -= nw.x; // ne.x -= nw.x; // se.x -= nw.x; // sw.x -= nw.x; + // nw.y -= nw.y; // ne.y -= nw.y; // se.y -= nw.y; // sw.y -= nw.y; - // run once warping is complete + // run once warping is complete downloadable.onload = function () { L.DomUtil.remove(downloadable); }; - if (window && window.hasOwnProperty('warpWebGl')) { warpWebGl(downloadable.id, [0, 0, width, 0, width, height, 0, height], [nw.x, nw.y, ne.x, ne.y, se.x, se.y, sw.x, sw.y], true // trigger download ); @@ -2024,87 +1856,65 @@ L.DistortableImage.Edit = L.Handler.extend({ }, _stackUp: function _stackUp() { var t = this._toggledImage; - if (!t || !this.hasTool(L.StackAction)) { return; } - this._toggledImage = false; - this._overlay.bringToFront(); - this._refresh(); }, _stackDown: function _stackDown() { var t = this._toggledImage; - if (t || !this.hasTool(L.StackAction)) { return; } - this._toggledImage = true; - this._overlay.bringToBack(); - this._refresh(); }, _unlock: function _unlock() { var ov = this._overlay; var map = ov._map; var eP = this.parentGroup; - if (!this.isMode('lock')) { return; } - if (eP && !eP.isCollected(ov) || !eP) { if (!this.hasTool(L.LockAction)) { return; } } - if (this.currentHandle) { map.removeLayer(this.currentHandle); } - if (ov.options.mode === 'lock' || !this.hasMode(ov.options.mode)) { this._mode = ''; this.currentHandle = ''; } else { this._mode = ov.options.mode; } - this._updateHandle(); - this._enableDragging(); - this._refresh(); }, _lock: function _lock() { var ov = this._overlay; var map = ov._map; var eP = this.parentGroup; - if (this.isMode('lock')) { return; } - if (eP && !eP.isCollected(ov) || !eP) { if (!this.hasTool(L.LockAction)) { return; } } - if (this.currentHandle) { map.removeLayer(this.currentHandle); } - this._mode = 'lock'; - this._updateHandle(); - this._disableDragging(); - this._refresh(); }, _deselect: function _deselect() { @@ -2112,49 +1922,40 @@ L.DistortableImage.Edit = L.Handler.extend({ }, _showMarkers: function _showMarkers(e) { var eP = this.parentGroup; - if (!this.currentHandle) { return; - } // only markers we want in collect interface for now is lock - - + } + // only markers we want in collect interface for now is lock if (!this.isMode('lock') && eP && eP.anyCollected()) { return; } - this.currentHandle.eachLayer(function (handle) { handle.setOpacity(1); - if (handle.dragging) { handle.dragging.enable(); } - L.DomUtil.addClass(handle.getElement(), 'leaflet-interactive'); }); }, _hideMarkers: function _hideMarkers() { var ov = this._overlay; - var eP = this.parentGroup; // workaround for race condition w/ feature group + var eP = this.parentGroup; + // workaround for race condition w/ feature group if (!this._handles) { this._initHandles(); } - if (!this.currentHandle) { return; } - if (this.isMode('lock') && eP && eP.isCollected(ov)) { return; } - this.currentHandle.eachLayer(function (handle) { handle.setOpacity(0); - if (handle.dragging) { handle.dragging.disable(); } - L.DomUtil.removeClass(handle.getElement(), 'leaflet-interactive'); }); }, @@ -2162,13 +1963,10 @@ L.DistortableImage.Edit = L.Handler.extend({ var ov = this._overlay; var map = ov._map; var mode = this.getMode(); - if (this.currentHandle) { map.removeLayer(this.currentHandle); } - this.currentHandle = mode === '' ? '' : this._handles[mode]; - if (this.currentHandle !== '') { map.addLayer(this.currentHandle); } @@ -2176,28 +1974,24 @@ L.DistortableImage.Edit = L.Handler.extend({ _addToolbar: function _addToolbar() { var ov = this._overlay; var eP = this.parentGroup; - var map = ov._map; // Find the topmost point on the image. - + var map = ov._map; + // Find the topmost point on the image. var corners = ov.getCorners(); var maxLat = -Infinity; - if (eP && eP.anyCollected()) { eP.editing._addToolbar(); - return; } - if (ov.options.suppressToolbar || this.toolbar) { return; } - for (var i = 0; i < corners.length; i++) { if (corners[i].lat > maxLat) { maxLat = corners[i].lat; } - } // Longitude is based on the centroid of the image. - + } + // Longitude is based on the centroid of the image. var raisedPoint = ov.getCenter(); raisedPoint.lat = maxLat; this.toolbar = L.distortableImage.popupBar(raisedPoint, { @@ -2209,27 +2003,24 @@ L.DistortableImage.Edit = L.Handler.extend({ if (this.toolbar) { this._removeToolbar(); } - this._addToolbar(); }, _updateToolbarPos: function _updateToolbarPos() { - var overlay = this._overlay; // Find the topmost point on the image. - + var overlay = this._overlay; + // Find the topmost point on the image. var corners = overlay.getCorners(); var toolbar = this.toolbar; var maxLat = -Infinity; - if (toolbar && toolbar instanceof L.DistortableImage.PopupBar) { for (var i = 0; i < corners.length; i++) { if (corners[i].lat > maxLat) { maxLat = corners[i].lat; } - } // Longitude is based on the centroid of the image. - + } + // Longitude is based on the centroid of the image. var raisedPoint = overlay.getCenter(); raisedPoint.lat = maxLat; - if (!overlay.options.suppressToolbar) { this.toolbar.setLatLng(raisedPoint); } @@ -2242,7 +2033,6 @@ L.DistortableImage.Edit = L.Handler.extend({ if (!this.enabled()) { return; } - return this._mode; }, getModes: function getModes() { @@ -2252,43 +2042,32 @@ L.DistortableImage.Edit = L.Handler.extend({ if (!this.enabled()) { return false; } - return this._mode === mode; }, setMode: function setMode(newMode) { var ov = this._overlay; var eP = this.parentGroup; var mode = this.getMode(); - if (mode === newMode || !this.hasMode(newMode) || !this.enabled()) { return; } - if (this.toolbar) { this.toolbar.clickTool(newMode); } - if (this.isMode('lock') && !this.dragging) { this._enableDragging(); } - this._mode = newMode; - if (this.isMode('lock')) { this._disableDragging(); } - this._updateHandle(); - this._refresh(); - if (eP && eP.isCollected(ov)) { ov.deselect(); } - return this; }, - /** * need to attach a stop to img dblclick or it will propagate to * the map and fire the handler that shows map location labels on map dblclick. @@ -2300,19 +2079,15 @@ L.DistortableImage.Edit = L.Handler.extend({ var idx = modesArray.indexOf(mode); var nextIdx = (idx + 1) % modesArray.length; var newMode = modesArray[nextIdx]; - if (e) { if (eP && eP.anyCollected()) { return; } - L.DomEvent.stop(e); } - return this.setMode(newMode); } }); - L.distortableImage.edit = function (overlay, options) { return new L.DistortableImage.Edit(overlay, options); }; @@ -2331,7 +2106,6 @@ L.BorderAction = L.EditAction.extend({ var mode = edit._mode; var use; var tooltip; - if (edit._outlined) { use = 'border_outer'; tooltip = overlay.options.translation.removeBorder; @@ -2339,15 +2113,15 @@ L.BorderAction = L.EditAction.extend({ use = 'border_clear'; tooltip = overlay.options.translation.addBorder; } - options = options || {}; options.toolbarIcon = { svg: true, html: use, tooltip: tooltip, className: mode === 'lock' ? 'disabled' : '' - }; // conditional for disabling keybindings for this action when the image is locked. + }; + // conditional for disabling keybindings for this action when the image is locked. L.DistortableImage.action_map.b = mode === 'lock' ? '' : '_toggleBorder'; L.EditAction.prototype.initialize.call(this, map, overlay, options); }, @@ -2355,7 +2129,6 @@ L.BorderAction = L.EditAction.extend({ var edit = this._overlay.editing; L.IconUtil.toggleXlink(this._link, 'border_clear', 'border_outer'); L.IconUtil.toggleTitle(this._link, 'Remove Border', 'Add Border'); - edit._toggleBorder(); } }); @@ -2377,16 +2150,14 @@ L.DeleteAction = L.EditAction.extend({ * we can tell whether the overlay is an instance of `L.DistortableImageOverlay` or `L.DistortableCollection` bc only * the former should have `parentGroup` defined on it. From there we call the apporpriate keybindings and methods. */ - if (edit instanceof L.DistortableImage.Edit) { - tooltip = overlay.options.translation.deleteImage; // backspace windows / delete mac - + tooltip = overlay.options.translation.deleteImage; + // backspace windows / delete mac L.DistortableImage.action_map.Backspace = edit._mode === 'lock' ? '' : '_removeOverlay'; } else { tooltip = overlay.options.translation.deleteImages; L.DistortableImage.group_action_map.Backspace = edit._mode === 'lock' ? '' : '_removeGroup'; } - options = options || {}; options.toolbarIcon = { svg: true, @@ -2398,7 +2169,6 @@ L.DeleteAction = L.EditAction.extend({ }, addHooks: function addHooks() { var edit = this._overlay.editing; - if (edit instanceof L.DistortableImage.Edit) { edit._removeOverlay(); } else { @@ -2429,7 +2199,6 @@ L.DistortAction = L.EditAction.extend({ }, addHooks: function addHooks() { var edit = this._overlay.editing; - edit._distortMode(); } }); @@ -2456,7 +2225,6 @@ L.DragAction = L.EditAction.extend({ }, addHooks: function addHooks() { var edit = this._overlay.editing; - edit._dragMode(); } }); @@ -2486,64 +2254,51 @@ L.EditAction = L.Toolbar2.Action.extend({ this._map = map; L.setOptions(this, options); L.Toolbar2.Action.prototype.initialize.call(this, options); - this._injectIconSet(); }, _createIcon: function _createIcon(toolbar, container, args) { var _this = this; - var iconOptions = this.options.toolbarIcon; var className = iconOptions.className; var edit = this._overlay.editing; this.toolbar = toolbar; this._icon = L.DomUtil.create('li', '', container); this._link = L.DomUtil.create('a', '', this._icon); - if (iconOptions.svg) { this._link.innerHTML = L.IconUtil.create(iconOptions.html); } else { this._link.innerHTML = iconOptions.html; } - this._link.setAttribute('href', '#'); - this._link.setAttribute('title', iconOptions.tooltip); - this._link.setAttribute('role', 'button'); - L.DomUtil.addClass(this._link, this.constructor.baseClass); - if (className) { L.DomUtil.addClass(this._link, className); - if (className === 'disabled') { L.DomUtil.addClass(this._icon, className); } - if (className === edit._mode) { L.DomUtil.addClass(this._link, 'selected-mode'); } else { L.DomUtil.removeClass(this._link, 'selected-mode'); } } - L.DomEvent.on(this._link, 'click', this.enable, this); L.DomEvent.on(this._overlay, 'update', function () { var match = _this._link.innerHTML.match(/xlink:href="#restore"/); - if (match && match.length === 1) { _this._enableAction(); } }); - /* Add secondary toolbar */ + /* Add secondary toolbar */ this._addSubToolbar(toolbar, this._icon, args); }, _injectIconSet: function _injectIconSet() { if (document.querySelector('#iconset')) { return; } - var el = document.createElement('div'); el.id = 'iconset'; el.setAttribute('hidden', 'hidden'); @@ -2559,7 +2314,6 @@ L.EditAction = L.Toolbar2.Action.extend({ L.DomUtil.addClass(this._link, 'disabled'); } }); - L.editAction = function (map, overlay, options) { return new L.EditAction(map, overlay, options); }; @@ -2580,7 +2334,6 @@ L.ExportAction = L.EditAction.extend({ this.isExporting = false; this.mouseLeaveSkip = true; this.isHooksExecuted = false; - if (edit instanceof L.DistortableImage.Edit) { L.DistortableImage.action_map.e = '_getExport'; tooltip = overlay.options.translation.exportImage; @@ -2588,7 +2341,6 @@ L.ExportAction = L.EditAction.extend({ L.DistortableImage.group_action_map.e = 'runExporter'; tooltip = overlay.options.translation.exportImages; } - options = options || {}; options.toolbarIcon = { svg: true, @@ -2599,20 +2351,17 @@ L.ExportAction = L.EditAction.extend({ }, addHooks: function addHooks() { var edit = this._overlay.editing; - if (edit instanceof L.DistortableImage.Edit) { edit._getExport(); - return; - } // Make sure that addHooks is executed only once, event listeners will handle the rest - + } + // Make sure that addHooks is executed only once, event listeners will handle the rest if (this.isHooksExecuted) { return; } else { this.isHooksExecuted = true; } - var exportTool = this._link.parentElement; this.mouseEnterHandler = this.handleMouseEnter.bind(this); this.mouseLeaveHandler = this.handleMouseLeave.bind(this); @@ -2630,7 +2379,6 @@ L.ExportAction = L.EditAction.extend({ if (this.mouseLeaveSkip) { return; } - this.resetState(); this.detachMouseEventListeners(exportTool); edit.cancelExport(); @@ -2699,7 +2447,6 @@ L.FreeRotateAction = L.EditAction.extend({ }, addHooks: function addHooks() { var edit = this._overlay.editing; - edit._freeRotateMode(); } }); @@ -2726,7 +2473,6 @@ L.GeolocateAction = L.EditAction.extend({ }, addHooks: function addHooks() { var image = this._overlay.getElement(); - EXIF.getData(image, L.EXIF(image)); } }); @@ -2744,7 +2490,6 @@ L.LockAction = L.EditAction.extend({ var edit = overlay.editing; var use; var tooltip; - if (edit instanceof L.DistortableImage.Edit) { L.DistortableImage.action_map.u = '_unlock'; L.DistortableImage.action_map.l = '_lock'; @@ -2755,7 +2500,6 @@ L.LockAction = L.EditAction.extend({ tooltip = overlay.options.translation.lockImages; use = 'lock'; } - options = options || {}; options.toolbarIcon = { svg: true, @@ -2767,7 +2511,6 @@ L.LockAction = L.EditAction.extend({ }, addHooks: function addHooks() { var edit = this._overlay.editing; - if (edit instanceof L.DistortableImage.Edit) { edit._toggleLockMode(); } else { @@ -2790,7 +2533,6 @@ L.OpacityAction = L.EditAction.extend({ var mode = edit._mode; var use; var tooltip; - if (edit._transparent) { use = 'opacity_empty'; tooltip = overlay.options.translation.makeImageOpaque; @@ -2798,7 +2540,6 @@ L.OpacityAction = L.EditAction.extend({ use = 'opacity'; tooltip = overlay.options.translation.makeImageTransparent; } - options = options || {}; options.toolbarIcon = { svg: true, @@ -2814,7 +2555,6 @@ L.OpacityAction = L.EditAction.extend({ var link = this._link; L.IconUtil.toggleXlink(link, 'opacity', 'opacity_empty'); L.IconUtil.toggleTitle(link, 'Make Image Transparent', 'Make Image Opaque'); - edit._toggleOpacity(); } }); @@ -2872,7 +2612,6 @@ L.RotateAction = L.EditAction.extend({ }, addHooks: function addHooks() { var edit = this._overlay.editing; - edit._rotateMode(); } }); @@ -2899,7 +2638,6 @@ L.ScaleAction = L.EditAction.extend({ }, addHooks: function addHooks() { var edit = this._overlay.editing; - edit._scaleMode(); } }); @@ -2917,7 +2655,6 @@ L.StackAction = L.EditAction.extend({ var edit = overlay.editing; var use; var tooltip; - if (edit._toggledImage) { use = 'flip_to_back'; tooltip = overlay.options.translation.stackToFront; @@ -2925,7 +2662,6 @@ L.StackAction = L.EditAction.extend({ use = 'flip_to_front'; tooltip = overlay.options.translation.stackToBack; } - options = options || {}; options.toolbarIcon = { svg: true, @@ -2941,7 +2677,6 @@ L.StackAction = L.EditAction.extend({ var edit = this._overlay.editing; L.IconUtil.toggleXlink(this._link, 'flip_to_front', 'flip_to_back'); L.IconUtil.toggleTitle(this._link, 'Stack to Front', 'Stack to Back'); - edit._toggleOrder(); } }); @@ -2967,7 +2702,6 @@ L.UnlockAction = L.EditAction.extend({ }, addHooks: function addHooks() { var edit = this._overlay.editing; - edit._unlockGroup(); } }); @@ -2986,38 +2720,37 @@ L.EXIF = function getEXIFdata(img) { console.log(EXIF.getAllTags(img)); var GPS = EXIF.getAllTags(img); var altitude; - /* If the lat/lng is available. */ + /* If the lat/lng is available. */ if (typeof GPS.GPSLatitude !== 'undefined' && typeof GPS.GPSLongitude !== 'undefined') { // sadly, encoded in [degrees,minutes,seconds] // primitive value = GPS.GPSLatitude[x].numerator var lat = GPS.GPSLatitude[0] + GPS.GPSLatitude[1] / 60 + GPS.GPSLatitude[2] / 3600; var lng = GPS.GPSLongitude[0] + GPS.GPSLongitude[1] / 60 + GPS.GPSLongitude[2] / 3600; - if (GPS.GPSLatitudeRef !== 'N') { lat = lat * -1; } - if (GPS.GPSLongitudeRef === 'W') { lng = lng * -1; } - } // Attempt to use GPS compass heading; will require - // some trig to calc corner points, which you can find below: - + } - var angle = 0; // "T" refers to "True north", so -90. + // Attempt to use GPS compass heading; will require + // some trig to calc corner points, which you can find below: + var angle = 0; + // "T" refers to "True north", so -90. if (GPS.GPSImgDirectionRef === 'T') { - angle = Math.PI / 180 * (GPS.GPSImgDirection.numerator / GPS.GPSImgDirection.denominator - 90); // "M" refers to "Magnetic north" + angle = Math.PI / 180 * (GPS.GPSImgDirection.numerator / GPS.GPSImgDirection.denominator - 90); + // "M" refers to "Magnetic north" } else if (GPS.GPSImgDirectionRef === 'M') { angle = Math.PI / 180 * (GPS.GPSImgDirection.numerator / GPS.GPSImgDirection.denominator - 90); } else { console.log('No compass data found'); } - console.log('Orientation:', GPS.Orientation); - /* If there is orientation data -- i.e. landscape/portrait etc */ + /* If there is orientation data -- i.e. landscape/portrait etc */ if (GPS.Orientation === 6) { // CCW angle += Math.PI / 180 * -90; @@ -3028,9 +2761,8 @@ L.EXIF = function getEXIFdata(img) { // 180 angle += Math.PI / 180 * 180; } - /* If there is altitude data */ - + /* If there is altitude data */ if (typeof GPS.GPSAltitude !== 'undefined' && typeof GPS.GPSAltitudeRef !== 'undefined') { // Attempt to use GPS altitude: // (may eventually need to find EXIF field of view for correction) @@ -3057,7 +2789,8 @@ L.DistortHandle = L.EditHandle.extend({ options: { TYPE: 'distort', icon: L.icon({ - iconUrl: // eslint-disable-next-line max-len + iconUrl: + // eslint-disable-next-line max-len 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAklEQVR4AewaftIAAAChSURBVO3BIU4DURgGwNkvL2B6AkQTLBqP4QCoSm7DDXoBLBZHDbfgICAIZjEV3YTn9uVHdMZZtcnCfI13bIzxg0emg6Nm6QVbYz3jylEsXRrvwommb49X67jFkz80fR9Mb1YxTzqiWBSLYlEsikWxKBbFolgUi2JRLIpFsSgWxaJY03fHHOu40dH07bAzWCx9Ge/TiWbpHgdsjPGNB2f/yS+7xRCyiiZPJQAAAABJRU5ErkJggg==', iconSize: [32, 32], iconAnchor: [16, 16] @@ -3071,7 +2804,6 @@ L.DistortHandle = L.EditHandle.extend({ this.setLatLng(this._handled.getCorner(this._corner)); } }); - L.distortHandle = function (overlay, idx, options) { return new L.DistortHandle(overlay, idx, options); }; @@ -3104,7 +2836,6 @@ L.DragHandle = L.EditHandle.extend({ this.setLatLng(this._handled.getCorner(this._corner)); } }); - L.dragHandle = function (overlay, idx, options) { return new L.DragHandle(overlay, idx, options); }; @@ -3127,23 +2858,18 @@ L.EditHandle = L.Marker.extend({ draggable: true, zIndexOffset: 10 }; - if (options && options.hasOwnProperty('draggable')) { markerOptions.draggable = options.draggable; } - L.Marker.prototype.initialize.call(this, latlng, markerOptions); }, onAdd: function onAdd(map) { L.Marker.prototype.onAdd.call(this, map); - this._bindListeners(); - this.updateHandle(); }, onRemove: function onRemove(map) { this._unbindListeners(); - L.Marker.prototype.onRemove.call(this, map); }, _onHandleDragStart: function _onHandleDragStart() { @@ -3154,7 +2880,6 @@ L.EditHandle = L.Marker.extend({ }, _fireEdit: function _fireEdit() { this._handled.edited = true; - this._handled.fire('edit'); }, _bindListeners: function _bindListeners() { @@ -3164,9 +2889,7 @@ L.EditHandle = L.Marker.extend({ drag: this._onHandleDrag, dragend: this._onHandleDragEnd }, this); - this._handled._map.on('zoomend', this.updateHandle, this); - this._handled.on('update', this.updateHandle, this); }, _unbindListeners: function _unbindListeners() { @@ -3176,36 +2899,25 @@ L.EditHandle = L.Marker.extend({ drag: this._onHandleDrag, dragend: this._onHandleDragEnd }, this); - this._handled._map.off('zoomend', this.updateHandle, this); - this._handled.off('update', this.updateHandle, this); }, - - /* Takes two latlngs and calculates the scaling difference. */ - _calculateScalingFactor: function _calculateScalingFactor(latlngA, latlngB) { + /* Takes two latlngs and calculates the scaling difference. */_calculateScalingFactor: function _calculateScalingFactor(latlngA, latlngB) { var overlay = this._handled; var map = overlay._map; var centerPoint = map.latLngToLayerPoint(overlay.getCenter()); var formerPoint = map.latLngToLayerPoint(latlngA); var newPoint = map.latLngToLayerPoint(latlngB); - var formerRadiusSquared = this._d2(centerPoint, formerPoint); - var newRadiusSquared = this._d2(centerPoint, newPoint); - return Math.sqrt(newRadiusSquared / formerRadiusSquared); }, - - /* Distance between two points in cartesian space, squared (distance formula). */ - _d2: function _d2(a, b) { + /* Distance between two points in cartesian space, squared (distance formula). */_d2: function _d2(a, b) { var dx = a.x - b.x; var dy = a.y - b.y; return Math.pow(dx, 2) + Math.pow(dy, 2); }, - - /* Takes two latlngs and calculates the angle between them. */ - calculateAngleDelta: function calculateAngleDelta(latlngA, latlngB) { + /* Takes two latlngs and calculates the angle between them. */calculateAngleDelta: function calculateAngleDelta(latlngA, latlngB) { var overlay = this._handled; var map = overlay._map; var centerPoint = map.latLngToLayerPoint(overlay.getCenter()); @@ -3229,7 +2941,8 @@ L.FreeRotateHandle = L.EditHandle.extend({ options: { TYPE: 'freeRotate', icon: L.icon({ - iconUrl: // eslint-disable-next-line max-len + iconUrl: + // eslint-disable-next-line max-len 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAklEQVR4AewaftIAAAHiSURBVMXBa3HbShgA0PMp/1sCCo8oCEpgTaCXgIXAJiDzyCJoAUTm4UVQAns1Y8+snWnTvJyeE16hkjDgDrfoNTMKcpC9UPiLSo8JyetkjEHxjPCMyoS199kFoz8Iv1HpMaN3qWDCHoegOKkkRwnJpRmroHgiPFEZ8IBekzEGxQtUEhKSS/fB7Ew4U+lxcGkVZG9QWWPSFAxBcdK59KApuA+yNwp2uEdx1GN25sZJZULSfAtm77SlbNjju6MvG75u+WHRWVR6rDVjMPsgwYyVZl3pLTpHkyYHOx8syMiayaJzlDTZ9YyaZNFVkiYH2ZUEBcVJJXVImuz6Js3Qofe59pq7DoOTILu+g+a288mCouk7/1iH4qTS+2QdDppbV1ZJmrnDXnPnc5UOs2Z0fUmTuyBr+krvSioJyUmQO0dZM7mepMkWnaNRkyrJB6uskTSjxY3Fll8bvmJwlDb83FJ8gMqAB80uyBY3Trb82PAfvjj6vuHnluIdKgMeNXOwctK5NKBoHitrb1RJeHRp5Ux4ojLg0aWMHGQvUOkxIWkKVsHsTPiNSo8HDC5lZIsgO6n0uMUdRvQuFQxB8UR4RmXC2vvsgtEfhL+o9JiQvE7GGBTPCK9QSUjoMWgKDthjDrIX+h/k0I7gth6N5gAAAABJRU5ErkJggg==', iconSize: [32, 32], iconAnchor: [16, 16] @@ -3241,27 +2954,20 @@ L.FreeRotateHandle = L.EditHandle.extend({ var formerLatLng = overlay.getCorner(this._corner); var newLatLng = this.getLatLng(); var angle = this.calculateAngleDelta(formerLatLng, newLatLng); - var scale = this._calculateScalingFactor(formerLatLng, newLatLng); - if (angle !== 0) { overlay.rotateBy(angle, 'rad'); } - var edgeMinWidth = overlay.edgeMinWidth; - if (!edgeMinWidth) { edgeMinWidth = 50; - } - /* just in case */ - + } /* just in case */ var corner1 = map.latLngToContainerPoint(overlay.getCorner(0)); var corner2 = map.latLngToContainerPoint(overlay.getCorner(1)); var w = Math.abs(corner1.x - corner2.x); var h = Math.abs(corner1.y - corner2.y); var distance = Math.sqrt(w * w + h * h); - if (distance > edgeMinWidth || scale > 1) { overlay.scaleBy(scale); } else { @@ -3272,7 +2978,6 @@ L.FreeRotateHandle = L.EditHandle.extend({ this.setLatLng(this._handled.getCorner(this._corner)); } }); - L.freeRotateHandle = function (overlay, idx, options) { return new L.FreeRotateHandle(overlay, idx, options); }; @@ -3302,9 +3007,7 @@ L.LockHandle = L.EditHandle.extend({ }, _bindListeners: function _bindListeners() { var icon = this.getElement(); - L.EditHandle.prototype._bindListeners.call(this); - L.DomEvent.on(icon, { mousedown: this._tooltipOn, mouseup: this._tooltipOff @@ -3313,39 +3016,31 @@ L.LockHandle = L.EditHandle.extend({ }, _unbindListeners: function _unbindListeners() { var icon = this.getElement(); - L.EditHandle.prototype._bindListeners.call(this); - L.DomEvent.off(icon, { mousedown: this._tooltipOn, mouseup: this._tooltipOff }, this); L.DomEvent.off(document, 'pointerleave', this._tooltipOff, this); }, - - /* cannot be dragged */ - _onHandleDrag: function _onHandleDrag() {}, + /* cannot be dragged */_onHandleDrag: function _onHandleDrag() {}, updateHandle: function updateHandle() { this.setLatLng(this._handled.getCorner(this._corner)); }, _tooltipOn: function _tooltipOn(e) { var eP = this._handled.parentGroup; var edit = eP ? eP.editing : this._handled.editing; - if (e.shiftKey) { return; } - if (!this._handled.isSelected() && eP && !eP.isCollected(this._handled)) { return; } - var handlesArr = edit._lockHandles; this._timer = setTimeout(L.bind(function () { if (this._timeout) { clearTimeout(this._timeout); } - if (!this.getTooltip()) { this.bindTooltip('Locked!', { permanent: true @@ -3357,40 +3052,32 @@ L.LockHandle = L.EditHandle.extend({ } }); } - this.openTooltip(); }, this), 500); }, _tooltipOff: function _tooltipOff(e) { var eP = this._handled.parentGroup; var edit = eP ? eP.editing : this._handled.editing; - if (e.shiftKey) { return; } - if (!this._handled.isSelected() && eP && !eP.isCollected(this._handled)) { return; } - var handlesArr = edit._lockHandles; - if (e.currentTarget === document) { handlesArr.eachLayer(function (handle) { handle.closeTooltip(); }); } - if (this._timer) { clearTimeout(this._timer); } - this._timeout = setTimeout(L.bind(function () { this.closeTooltip(); }, this), 400); } }); - L.lockHandle = function (overlay, idx, options) { return new L.LockHandle(overlay, idx, options); }; @@ -3407,7 +3094,8 @@ L.RotateHandle = L.EditHandle.extend({ options: { TYPE: 'rotate', icon: L.icon({ - iconUrl: // eslint-disable-next-line max-len + iconUrl: + // eslint-disable-next-line max-len 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAklEQVR4AewaftIAAAHiSURBVMXBa3HbShgA0PMp/1sCCo8oCEpgTaCXgIXAJiDzyCJoAUTm4UVQAns1Y8+snWnTvJyeE16hkjDgDrfoNTMKcpC9UPiLSo8JyetkjEHxjPCMyoS199kFoz8Iv1HpMaN3qWDCHoegOKkkRwnJpRmroHgiPFEZ8IBekzEGxQtUEhKSS/fB7Ew4U+lxcGkVZG9QWWPSFAxBcdK59KApuA+yNwp2uEdx1GN25sZJZULSfAtm77SlbNjju6MvG75u+WHRWVR6rDVjMPsgwYyVZl3pLTpHkyYHOx8syMiayaJzlDTZ9YyaZNFVkiYH2ZUEBcVJJXVImuz6Js3Qofe59pq7DoOTILu+g+a288mCouk7/1iH4qTS+2QdDppbV1ZJmrnDXnPnc5UOs2Z0fUmTuyBr+krvSioJyUmQO0dZM7mepMkWnaNRkyrJB6uskTSjxY3Fll8bvmJwlDb83FJ8gMqAB80uyBY3Trb82PAfvjj6vuHnluIdKgMeNXOwctK5NKBoHitrb1RJeHRp5Ux4ojLg0aWMHGQvUOkxIWkKVsHsTPiNSo8HDC5lZIsgO6n0uMUdRvQuFQxB8UR4RmXC2vvsgtEfhL+o9JiQvE7GGBTPCK9QSUjoMWgKDthjDrIX+h/k0I7gth6N5gAAAABJRU5ErkJggg==', iconSize: [32, 32], iconAnchor: [16, 16] @@ -3418,18 +3106,17 @@ L.RotateHandle = L.EditHandle.extend({ var formerLatLng = overlay.getCorner(this._corner); var newLatLng = this.getLatLng(); var angle = this.calculateAngleDelta(formerLatLng, newLatLng); + /* * running rotation logic even for an angle delta of 0 * prevents a small, occasional marker flicker */ - overlay.rotateBy(angle, 'rad'); }, updateHandle: function updateHandle() { this.setLatLng(this._handled.getCorner(this._corner)); } }); - L.rotateHandle = function (overlay, idx, options) { return new L.RotateHandle(overlay, idx, options); }; @@ -3446,7 +3133,8 @@ L.ScaleHandle = L.EditHandle.extend({ options: { TYPE: 'scale', icon: L.icon({ - iconUrl: // eslint-disable-next-line max-len + iconUrl: + // eslint-disable-next-line max-len 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB2ZXJzaW9uPSIxLjEiIHdpZHRoPSI0NTkiIGhlaWdodD0iNDY0IiBlbmFibGUtYmFja2dyb3VuZD0ibmV3IDAgMCA1MTIgNTEyIiB4bWw6c3BhY2U9InByZXNlcnZlIiBzdHlsZT0iIj48cmVjdCBpZD0iYmFja2dyb3VuZHJlY3QiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIHg9IjAiIHk9IjAiIGZpbGw9Im5vbmUiIHN0cm9rZT0ibm9uZSIgY2xhc3M9IiIgc3R5bGU9IiIvPjxnIGNsYXNzPSJjdXJyZW50TGF5ZXIiIHN0eWxlPSIiPjx0aXRsZT5MYXllciAxPC90aXRsZT48cGF0aCBkPSJNNDU5LjA0OTE1OTUzMDQ3MTM0LDg2LjkyNjIzNDUxMjU1MDAyIFYwIGgtODUuNzE0NTczMzU2MzEyMDkgdjI3LjA0MzcxNzQwMzkwNDQ1MiBIODUuNzE0NTczMzU2MzEyMDMgVjAgSDAgdjg2LjkyNjIzNDUxMjU1MDAyIGgyNS43MTQzNzIwMDY4OTM2MjYgdjI4OS43NTQxMTUwNDE4MzM0IEgwIHY4Ni45MjYyMzQ1MTI1NTAwMiBoODUuNzE0NTczMzU2MzEyMDkgdi0yNy4wNDM3MTc0MDM5MDQ0NTIgaDI4NS43MTUyNDQ1MjEwNDAzIHYyNy4wNDM3MTc0MDM5MDQ0NTIgaDg1LjcxNDU3MzM1NjMxMjA5IHYtODYuOTI2MjM0NTEyNTUwMDIgaC0yMy44MDk2MDM3MTAwODY2OSBWODYuOTI2MjM0NTEyNTUwMDIgSDQ1OS4wNDkxNTk1MzA0NzEzNCB6TTM4NC43NjMxOTU5NTUwMDA5LDEyLjU1NjAxMTY1MTgxMjc4MSBoNjEuOTA0OTY5NjQ2MjI1Mzk2IHY2Mi43ODAwNTgyNTkwNjM5MSBoLTYxLjkwNDk2OTY0NjIyNTM5NiBWMTIuNTU2MDExNjUxODEyNzgxIHpNMTIuMzgwOTkzOTI5MjQ1MDUsMTIuNTU2MDExNjUxODEyNzgxIGg2MS45MDQ5Njk2NDYyMjUzOTYgdjYyLjc4MDA1ODI1OTA2MzkxIEgxMi4zODA5OTM5MjkyNDUwNSBWMTIuNTU2MDExNjUxODEyNzgxIHpNNzQuMjg1OTYzNTc1NDcwNTMsNDUxLjA1MDU3MjQxNTEyMDY2IEgxMi4zODA5OTM5MjkyNDUwNSB2LTYyLjc4MDA1ODI1OTA2MzkxIGg2MS45MDQ5Njk2NDYyMjUzOTYgVjQ1MS4wNTA1NzI0MTUxMjA2NiB6TTQ0NS43MTU3ODE0NTI4MjI3NCw0NTEuMDUwNTcyNDE1MTIwNjYgaC02Mi44NTczNTM3OTQ2Mjg4NjQgdi02Mi43ODAwNTgyNTkwNjM5MSBoNjIuODU3MzUzNzk0NjI4ODY0IFY0NTEuMDUwNTcyNDE1MTIwNjYgek00MDcuNjIwNDE1NTE2Njg0MjYsMzc2LjY4MDM0OTU1NDM4MzQ0IGgtMzYuMTkwNTk3NjM5MzMxNzcgdjMyLjgzODc5OTcwNDc0MTEyIEg4NS43MTQ1NzMzNTYzMTIwMyB2LTMyLjgzODc5OTcwNDc0MTEyIEg0OS41MjM5NzU3MTY5ODAzMiBWODYuOTI2MjM0NTEyNTUwMDIgaDM2LjE5MDU5NzYzOTMzMTc3IFY1MC4yMjQwNDY2MDcyNTExMjUgaDI4Ny42MjAwMTI4MTc4NDcyIHYzNi43MDIxODc5MDUyOTg5IGgzNC4yODU4MjkzNDI1MjQ4MzUgVjM3Ni42ODAzNDk1NTQzODM0NCB6IiBpZD0ic3ZnXzIiIGNsYXNzPSIiIGZpbGw9IiMxYTFhZWIiIGZpbGwtb3BhY2l0eT0iMSIvPjwvZz48L3N2Zz4=', iconSize: [32, 32], iconAnchor: [16, 16] @@ -3458,26 +3146,21 @@ L.ScaleHandle = L.EditHandle.extend({ var edgeMinWidth = overlay.edgeMinWidth; var formerLatLng = overlay.getCorner(this._corner); var newLatLng = this.getLatLng(); - var scale = this._calculateScalingFactor(formerLatLng, newLatLng); + /* * checks whether the "edgeMinWidth" property is set and tracks the minimum edge length; * this enables preventing scaling to zero, but we might also add an overall scale limit */ - if (!edgeMinWidth) { edgeMinWidth = 50; - } - /* just in case */ - - + } /* just in case */ var corner1 = map.latLngToLayerPoint(overlay.getCorner(0)); var corner2 = map.latLngToLayerPoint(overlay.getCorner(1)); var w = Math.abs(corner1.x - corner2.x); var h = Math.abs(corner1.y - corner2.y); var distance = Math.sqrt(w * w + h * h); - if (distance > edgeMinWidth || scale > 1) { overlay.scaleBy(scale); /* @@ -3492,7 +3175,6 @@ L.ScaleHandle = L.EditHandle.extend({ this.setLatLng(this._handled.getCorner(this._corner)); } }); - L.scaleHandle = function (overlay, idx, options) { return new L.ScaleHandle(overlay, idx, options); }; @@ -3509,17 +3191,16 @@ L.distortableImage = L.DistortableImage || {}; L.distortableImage = L.DistortableImage; L.DistortableImage.group_action_map = {}; L.DistortableImage.ControlBar = L.Toolbar2.Control.extend({}); - L.distortableImage.controlBar = function (options) { return new L.DistortableImage.ControlBar(options); }; -/** addInitHooks run before onAdd */ - +/** addInitHooks run before onAdd */ L.DistortableCollection.addInitHook(function () { /** Default actions */ - this.ACTIONS = [L.ExportAction, L.DeleteAction, L.LockAction, L.UnlockAction]; // all possible modes + this.ACTIONS = [L.ExportAction, L.DeleteAction, L.LockAction, L.UnlockAction]; + // all possible modes L.DistortableCollection.Edit.MODES = { lock: L.LockAction, unlock: L.UnlockAction @@ -3560,28 +3241,24 @@ L.DistortableImage.PopupBar = L.Toolbar2.Popup.extend({ }, clickTool: function clickTool(name) { var tools = this.tools(); - for (var i = 0; i < tools.length; i++) { var tool = tools.item(i).children[0]; - if (L.DomUtil.hasClass(tool, name)) { tool.click(); return tool; } } - return false; } }); - L.distortableImage.popupBar = function (latlng, options) { return new L.DistortableImage.PopupBar(latlng, options); }; - L.DistortableImageOverlay.addInitHook(function () { /** Default actions */ - this.ACTIONS = [L.DragAction, L.ScaleAction, L.DistortAction, L.RotateAction, L.FreeRotateAction, L.LockAction, L.OpacityAction, L.BorderAction, L.ExportAction, L.DeleteAction]; // all possible modes + this.ACTIONS = [L.DragAction, L.ScaleAction, L.DistortAction, L.RotateAction, L.FreeRotateAction, L.LockAction, L.OpacityAction, L.BorderAction, L.ExportAction, L.DeleteAction]; + // all possible modes L.DistortableImage.Edit.MODES = { drag: L.DragAction, scale: L.ScaleAction, @@ -3627,7 +3304,8 @@ L.IconSet = L.Class.extend({ /***/ (function() { L.KeymapperIconSet = L.IconSet.extend({ - _symbols: // eslint-disable-next-line max-len + _symbols: + // eslint-disable-next-line max-len '' }); @@ -3656,11 +3334,11 @@ L.Map.mergeOptions({ boxCollector: true, boxZoom: false }); + /** * primarily Leaflet 1.5.1 source code. Overriden so that it's a collection box used with * our `L.DistortableCollection` class instead of a zoom box. * */ - L.Map.BoxCollector = L.Map.BoxZoom.extend({ initialize: function initialize(map) { this._map = map; @@ -3695,14 +3373,12 @@ L.Map.BoxCollector = L.Map.BoxZoom.extend({ _onMouseDown: function _onMouseDown(e) { if (!e.shiftKey || e.which !== 1 && e.button !== 1) { return false; - } // Clear the deferred resetState if it hasn't executed yet, otherwise it - // will interrupt the interaction and orphan a box element in the container. - + } + // Clear the deferred resetState if it hasn't executed yet, otherwise it + // will interrupt the interaction and orphan a box element in the container. this._clearDeferredResetState(); - this._resetState(); - L.DomUtil.disableTextSelection(); L.DomUtil.disableImageDrag(); this._startPoint = this._map.mouseEventToContainerPoint(e); @@ -3717,15 +3393,11 @@ L.Map.BoxCollector = L.Map.BoxZoom.extend({ this._moved = true; this._box = L.DomUtil.create('div', 'leaflet-zoom-box', this._container); L.DomUtil.addClass(this._container, 'leaflet-crosshair'); - this._map.fire('boxzoomstart'); } - this._point = this._map.mouseEventToContainerPoint(e); this._bounds = L.bounds(this._startPoint, this._point); - var size = this._bounds.getSize(); - L.DomUtil.setPosition(this._box, this._bounds.min); this._box.style.width = size.x + 'px'; this._box.style.height = size.y + 'px'; @@ -3735,7 +3407,6 @@ L.Map.BoxCollector = L.Map.BoxZoom.extend({ L.DomUtil.remove(this._box); L.DomUtil.removeClass(this._container, 'leaflet-crosshair'); } - L.DomUtil.enableTextSelection(); L.DomUtil.enableImageDrag(); L.DomEvent.off(document, { @@ -3748,27 +3419,21 @@ L.Map.BoxCollector = L.Map.BoxZoom.extend({ if (e.which !== 1 && e.button !== 1) { return; } - this._finish(); - if (!this._moved) { return; - } // Postpone to next JS tick so internal click event handling - // still see it as "moved". - + } + // Postpone to next JS tick so internal click event handling + // still see it as "moved". this._clearDeferredResetState(); - this._resetStateTimeout = setTimeout(L.Util.bind(this._resetState, this), 0); var bounds = L.latLngBounds(this._map.containerPointToLatLng(this._bounds.getBottomLeft()), this._map.containerPointToLatLng(this._bounds.getTopRight())); - var zoom = this._map.getZoom(); + var center = this._map.getCenter(); - var center = this._map.getCenter(); // calls the `project` method but 1st updates the pixel origin - see https://github.com/publiclab/Leaflet.DistortableImage/pull/344 - - + // calls the `project` method but 1st updates the pixel origin - see https://github.com/publiclab/Leaflet.DistortableImage/pull/344 bounds = this._map._latLngBoundsToNewLayerBounds(bounds, zoom, center); - this._map.fire('boxcollectend', { boxCollectBounds: bounds }); @@ -3787,26 +3452,23 @@ L.Map.addInitHook('addHandler', 'boxCollector', L.Map.BoxCollector); L.Map.mergeOptions({ doubleClickLabels: true }); + /** * The `doubleClickLabels` handler replaces `doubleClickZoom` by default if `#addGoogleMutant` * is used unless the options 'labels: false' or 'doubleClickZoom: false` were passed to it. */ - L.Map.DoubleClickLabels = L.Map.DoubleClickZoom.extend({ enable: function enable() { var map = this._map; - if (this._enabled) { return this; - } // disable 'doubleClickZoom' if 'doubleClickLabels' is enabled. - + } + // disable 'doubleClickZoom' if 'doubleClickLabels' is enabled. if (map.doubleClickZoom.enabled()) { map.doubleClickZoom.disable(); } - this._map.fire('singleclickon'); - this._enabled = true; this.addHooks(); return this; @@ -3815,19 +3477,18 @@ L.Map.DoubleClickLabels = L.Map.DoubleClickZoom.extend({ if (!this._enabled) { return this; } - this._enabled = false; this.removeHooks(); return this; }, _fireIfSingle: function _fireIfSingle(e) { var map = this._map; - var oe = e.originalEvent; // prevents deselection in case of box selector + var oe = e.originalEvent; + // prevents deselection in case of box selector if (oe && oe.shiftKey) { return; } - map._clicked += 1; this._map._clickTimeout = setTimeout(function () { if (map._clicked === 1) { @@ -3850,11 +3511,9 @@ L.Map.DoubleClickLabels = L.Map.DoubleClickZoom.extend({ map._clicked = 0; clearTimeout(map._clickTimeout); }, 0); - if (!labels) { return; } - if (labels.options.opacity === 1) { labels.options.opacity = 0; labels.setOpacity(0); @@ -3895,18 +3554,17 @@ L.Map.DoubleClickZoom.include({ enable: function enable() { if (this._enabled) { return this; - } // don't enable 'doubleClickZoom' unless 'doubleClickLabels' is disabled first - + } + // don't enable 'doubleClickZoom' unless 'doubleClickLabels' is disabled first if (this._map.doubleClickLabels) { if (this._map.doubleClickLabels.enabled()) { return this; } - } // signify to collection/instance classes to turn on 'singleclick' listeners - + } + // signify to collection/instance classes to turn on 'singleclick' listeners this._map.fire('singleclickon'); - this._enabled = true; this.addHooks(); return this; @@ -3914,23 +3572,22 @@ L.Map.DoubleClickZoom.include({ disable: function disable() { if (!this._enabled) { return this; - } // signify to collection/instance safe to swap 'singleclick' listeners with 'click' listeners. - + } + // signify to collection/instance safe to swap 'singleclick' listeners with 'click' listeners. this._map.fire('singleclickoff'); - this._enabled = false; this.removeHooks(); return this; }, _fireIfSingle: function _fireIfSingle(e) { var map = this._map; - var oe = e.originalEvent; // prevents deselection in case of box selector + var oe = e.originalEvent; + // prevents deselection in case of box selector if (oe && oe.shiftKey) { return; } - map._clicked += 1; this._map._clickTimeout = setTimeout(function () { if (map._clicked === 1) { @@ -3956,15 +3613,12 @@ L.Map.DoubleClickZoom.include({ map._clicked = 0; clearTimeout(map._clickTimeout); }, 0); - if (!oe) { return false; } - var oldZoom = map.getZoom(); var delta = map.options.zoomDelta; var zoom = oe.shiftKey ? oldZoom - delta : oldZoom + delta; - if (map.options.doubleClickZoom === 'center') { map.setZoom(zoom); } else { @@ -3995,37 +3649,32 @@ L.Map.include({ labelOpacity: 1, doubleClickLabels: true }, opts); - if (!opts.labels) { this.mutantOptions = L.extend(this.mutantOptions, { labelOpacity: opts.labels ? 1 : undefined, doubleClickLabels: opts.labels ? true : undefined }); } - this._googleMutant = L.tileLayer(url, { maxZoom: opts.maxZoom, maxNativeZoom: opts.maxNativeZoom, minZoom: opts.minZoom, opacity: opts.mutantOpacity }).addTo(this); - if (opts.labels) { this._addLabels(opts); - } // shouldn't have this handler at all if there are no labels to toggle + } + // shouldn't have this handler at all if there are no labels to toggle else { this.doubleClickLabels = undefined; } - return this; }, _addLabels: function _addLabels(opts) { var url = 'https://stamen-tiles-{s}.a.ssl.fastly.net/toner-labels/{z}/{x}/{y}{r}.{ext}'; - if (opts.labelOpacity !== 0 && opts.labelOpacity !== 1) { opts.labelOpacity = 1; } - this._labels = L.tileLayer(url, { attribution: 'Map tiles by Stamen Design, CC BY 3.0 — Map data © OpenStreetMap contributors', subdomains: 'abcd', @@ -4036,16 +3685,14 @@ L.Map.include({ minZoom: opts.minZoom, ext: 'png' }).addTo(this); - if (this.mutantOptions.doubleClickLabels) { this.doubleClickLabels.enable(); } - return this; } -}); // start off with doubleClickZoom enabled, doubleClickLabels can later be enabled instead +}); +// start off with doubleClickZoom enabled, doubleClickLabels can later be enabled instead // during initialization - L.Map.addInitHook(function () { this.doubleClickLabels.disable(); this.doubleClickZoom.enable(); @@ -4065,6 +3712,7 @@ L.DomUtil = L.extend(L.DomUtil, { }, getMatrixString: function getMatrixString(m) { var is3d = L.Browser.webkit3d || L.Browser.gecko3d || L.Browser.ie3d; + /* * Since matrix3d takes a 4*4 matrix, we add in an empty row and column, * which act as the identity on the z-axis. @@ -4072,14 +3720,11 @@ L.DomUtil = L.extend(L.DomUtil, { * http://franklinta.com/2014/09/08/computing-css-matrix3d-transforms/ * https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function#M.C3.B6bius'_homogeneous_coordinates_in_projective_geometry */ - var matrix = [m[0], m[3], 0, m[6], m[1], m[4], 0, m[7], 0, 0, 1, 0, m[2], m[5], 0, m[8]]; var str = is3d ? 'matrix3d(' + matrix.join(',') + ')' : ''; - if (!is3d) { console.log('Your browser must support 3D CSS transforms' + 'in order to use DistortableImageOverlay.'); } - return str; }, toggleClass: function toggleClass(el, className) { @@ -4093,16 +3738,13 @@ L.DomUtil = L.extend(L.DomUtil, { if (n === 1) { return this.confirmDelete(); } - var translation = this.translation.confirmImagesDeletes; var warningMsg = ''; - if (typeof translation === 'function') { warningMsg = translation(n); } else { warningMsg = translation; } - return window.confirm(warningMsg); } }); @@ -4125,12 +3767,10 @@ L.IconUtil = { if (/^#/.test(ref)) { ref = ref.replace(/^#/, ''); } - return '' + '' + ''; }, addClassToSvg: function addClassToSvg(container, loader) { var svg = container.querySelector('svg'); - if (svg) { L.DomUtil.addClass(svg, loader); } @@ -4140,29 +3780,23 @@ L.IconUtil = { if (!/^#/.test(ref1)) { ref1 = '#' + ref1; } - if (!/^#/.test(ref2)) { ref2 = '#' + ref2; } - var use = container.querySelector('use'); - if (use) { var toggled = use.getAttribute('xlink:href') === ref1 ? ref2 : ref1; use.setAttribute('xlink:href', toggled); return toggled; } - return false; }, toggleTitle: function toggleTitle(container, title1, title2) { var toggled = container.getAttribute('title') === title1 ? title2 : title1; container.setAttribute('title', toggled); - if (container.hasAttribute('aria-label')) { container.setAttribute('aria-label', toggled); } - return toggled; } }; @@ -4200,19 +3834,15 @@ L.MatrixUtil = { multmm: function multmm(a, b) { var c = []; var i; - for (i = 0; i < 3; i++) { for (var j = 0; j < 3; j++) { var cij = 0; - for (var k = 0; k < 3; k++) { cij += a[3 * i + k] * b[3 * k + j]; } - c[3 * i + j] = cij; } } - return c; }, // multiply a 3*3 matrix and a 3-vector @@ -4222,11 +3852,9 @@ L.MatrixUtil = { // multiply a scalar and a 3*3 matrix multsm: function multsm(s, m) { var matrix = []; - for (var i = 0, l = m.length; i < l; i++) { matrix.push(s * m[i]); } - return matrix; }, basisToPoints: function basisToPoints(x1, y1, x2, y2, x3, y3, x4, y4) { @@ -4241,7 +3869,9 @@ L.MatrixUtil = { general2DProjection: function general2DProjection(x1s, y1s, x1d, y1d, x2s, y2s, x2d, y2d, x3s, y3s, x3d, y3d, x4s, y4s, x4d, y4d) { var s = L.MatrixUtil.basisToPoints(x1s, y1s, x2s, y2s, x3s, y3s, x4s, y4s); var d = L.MatrixUtil.basisToPoints(x1d, y1d, x2d, y2d, x3d, y3d, x4d, y4d); - var m = L.MatrixUtil.multmm(d, L.MatrixUtil.adj(s)); // Normalize to the unique matrix with m[8] == 1. + var m = L.MatrixUtil.multmm(d, L.MatrixUtil.adj(s)); + + // Normalize to the unique matrix with m[8] == 1. // See: http://franklinta.com/2014/09/08/computing-css-matrix3d-transforms/ return L.MatrixUtil.multsm(1 / m[8], m); @@ -4303,7 +3933,6 @@ L.Utils = { confirmImageDelete: 'Are you sure? This image will be permanently deleted from the map.', confirmImagesDeletes: 'Are you sure? These images will be permanently deleted from the map.' }; - if (!this.options.translation) { this.options.translation = translation; } else { @@ -4314,7 +3943,6 @@ L.Utils = { } } } - L.DomUtil.initTranslation(this.options.translation); }, getNestedVal: function getNestedVal(obj, key, nestedKey) { @@ -7300,7 +6928,7 @@ module.exports.formatError = function (err) { /******/ /******/ /* webpack/runtime/getFullHash */ /******/ !function() { -/******/ __webpack_require__.h = function() { return "e25f8be8eeb066dddf26"; } +/******/ __webpack_require__.h = function() { return "f548663938c12b88c6e0"; } /******/ }(); /******/ /******/ /* webpack/runtime/hasOwnProperty shorthand */ diff --git a/examples/archive.html b/examples/archive.html index 8dad92e53..f715fbebe 100644 --- a/examples/archive.html +++ b/examples/archive.html @@ -22,7 +22,7 @@ - + diff --git a/examples/js/archive.js b/examples/js/archive.js index b211e4574..9c86d5d6d 100644 --- a/examples/js/archive.js +++ b/examples/js/archive.js @@ -14,6 +14,8 @@ let imageCount = 0; let fetchedFrom; let fetchedImages; let currPagination; // currPagination is used to initiate the Paginator Class +let sidebarOpen = false; +let mapReconstructionMode = false; const setupMap = () => { map = L.map('map').setView([51.505, -0.09], 13); @@ -22,7 +24,12 @@ const setupMap = () => { map.addGoogleMutant(); map.whenReady(() => { - new bootstrap.Modal(welcomeModal).show(); + if (isJsonDetected(location.href)) { + new bootstrap.Modal(welcomeModal).hide(); + mapReconstructionMode = true; + return; + } + new bootstrap.Modal(welcomeModal).show(); }); }; @@ -155,6 +162,7 @@ function showImages(getUrl) { welcomeModal.addEventListener('hidden.bs.modal', (event) => { new bootstrap.Offcanvas(sidebar).show(); + sidebarOpen = true; }); restoreWelcomeModal.addEventListener('click', (event) => { @@ -164,10 +172,13 @@ restoreWelcomeModal.addEventListener('click', (event) => { mapToggle.addEventListener('click', (event) => { new bootstrap.Offcanvas(sidebar).show(); + sidebarOpen = true; }); tileMap.addEventListener('click', (event) => { - bootstrap.Offcanvas.getInstance(sidebar).hide(); + if (sidebarOpen) { + bootstrap.Offcanvas.getInstance(sidebar).hide(); + } }); function getImageName(imageURL) { @@ -178,16 +189,102 @@ function getImageName(imageURL) { return imageName; } +function extractJsonFromUrlParams(url) { + const startIndex = url.lastIndexOf('='); + const jsonDownloadURL = url.slice(startIndex + 1); + + return jsonDownloadURL; +} + +function isJsonDetected(url) { + if (url.includes('?json=')) { + const startIndex = url.lastIndexOf('.'); + const fileExtension = url.slice(startIndex + 1); + + if (fileExtension === 'json') { + console.log('JSON found in map shareable link'); // left here purposely + return true; + } + } + + return false; +} + +function placeImage (imageURL, options, newImage = false) { + let image; + + if (newImage) { + image = L.distortableImageOverlay( + imageURL, + {tooltipText: options.tooltipText} + ); + } else { + image = L.distortableImageOverlay( + imageURL, + { + height: options.height, + tooltipText: options.tooltipText, + // corners: options.corners, <== uncomment this to see the effect of the corners + } + ); + } + + map.imgGroup.addLayer(image); +}; + +// Reconstruct Map from JSON +document.addEventListener('DOMContentLoaded', async (event) => { + if (mapReconstructionMode) { + const url = location.href; + + if (isJsonDetected(url)) { + const jsonDownloadURL = extractJsonFromUrlParams(url); + + if (jsonDownloadURL) { + const imageCollectionObj = await map.imgGroup.recreateImagesFromJsonUrl(jsonDownloadURL); + const avg_cm_per_pixel = imageCollectionObj.avg_cm_per_pixel; // this is made available here for future use + + // creates multiple images - this applies where multiple images are to be reconstructed + if (imageCollectionObj.imgCollectionProps.length > 1) { + let imageURL; + let options; + + imageCollectionObj.imgCollectionProps.forEach((imageObj) => { + imageURL = imageObj.src; + options = { + height: imageObj.height, + tooltipText: imageObj.tooltipText, + corners: imageObj.nodes, + }; + placeImage(imageURL, options, false); + }); + + return; + } + + // creates single image - this applies where only one image is to be reconstructed + const imageObj = imageCollectionObj.imgCollectionProps[0]; + const imageURL = imageObj[0].src; + const options = { + height: imageObj[0].height, + tooltipText: imageObj[0].tooltipText, + corners: imageObj[0].nodes, + } + + placeImage(imageURL, options, false); + } + } + } +}); + document.addEventListener('click', (event) => { if (event.target.classList.contains('place-button')) { const imageURL = event.target.previousElementSibling.src; const imageTooltipText = getImageName(imageURL); + const options = {tooltipText: imageTooltipText}; - const image = L.distortableImageOverlay( - imageURL, - {tooltipText: imageTooltipText} - ); - map.imgGroup.addLayer(image); + placeImage(imageURL, options, true); + return; } }); @@ -203,4 +300,4 @@ saveMap.addEventListener('click', () => { a.download = fileName ? fileName + '.json' : 'MapknitterLite.json'; a.click(); } -}) +}); \ No newline at end of file diff --git a/src/DistortableCollection.js b/src/DistortableCollection.js index 66d279f10..8ec2e09fe 100644 --- a/src/DistortableCollection.js +++ b/src/DistortableCollection.js @@ -199,17 +199,44 @@ L.DistortableCollection = L.FeatureGroup.extend({ return reduce / imgs.length; }, - isJsonDetected(currentURL) { - if (currentURL.includes('?json=')) { - startIndex = currentURL.lastIndexOf('.'); - fileExtension = currentURL.slice(startIndex + 1); - - if (fileExtension === 'json') { - console.log('JSON found in map shareable link'); - return true; + // Connects to JSON file and fetches JSON data therein from remote source + async fetchRemoteJson(url) { + let index = 0; + const imgCollectionProps = []; + + try { + const response = await axios.get(url); + if (response.data.images.length > 1) { + response.data.images.forEach((data) => { + imgCollectionProps[index] = data; + index++; + }); + return { + avg_cm_per_pixel: response.data.avg_cm_per_pixel, + imgCollectionProps, + }; } + imgCollectionProps[index] = response.data.images; + + return { + avg_cm_per_pixel: response.data.avg_cm_per_pixel, + imgCollectionProps, + }; + } catch (err) { + console.log('err', err); } - return false; + }, + + // expects url in this format: https://archive.org/download/segeotest/segeotest.json + async recreateImagesFromJsonUrl(url) { + let imageCollectionObj = {}; + + if (url) { + imageCollectionObj = await this.fetchRemoteJson(url); + return imageCollectionObj; + }; + + return imageCollectionObj; }, generateExportJson(allImages = false) { diff --git a/src/DistortableImageOverlay.js b/src/DistortableImageOverlay.js index 29b3f9d71..a5c3c86a4 100644 --- a/src/DistortableImageOverlay.js +++ b/src/DistortableImageOverlay.js @@ -1,5 +1,4 @@ L.DistortableImageOverlay = L.ImageOverlay.extend({ - options: { height: 200, crossOrigin: true,