New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

leaflet-distortableimage

Package Overview
Dependencies
Maintainers
2
Versions
56
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

leaflet-distortableimage - npm Package Compare versions

Comparing version 0.7.8 to 0.8.0

src/edit/actions/BorderAction.js

71

.eslintrc.js
module.exports = {
"env": {
"browser": true,
},
"extends": "google",
"globals": {
"Atomics": "readonly",
"SharedArrayBuffer": "readonly"
},
"parserOptions": {
"ecmaVersion": 2018
},
"rules": {
"env": {
"browser": true,
},
"extends": "google",
"globals": {
"Atomics": "readonly",
"SharedArrayBuffer": "readonly"
},
"parserOptions": {
"ecmaVersion": 2018
},
"rules": {
/*
* include rules you want to enforce/suppress/disable here
* they can be set to "off"(0) or "warn"(1) or "error"(2)
* for eg., "semi": "warn" or "semi": 1, that will display
* warnings for all snippets where semicolons aren't used
* but won't throw an error
*/
/*
* include rules you want to enforce/suppress/disable here
* they can be set to "off"(0) or "warn"(1) or "error"(2)
* for eg., "semi": "warn" or "semi": 1, that will display
* warnings for all snippets where semicolons aren't used
* but won't throw an error
*/
/*
* some rules have properties that can be modified for eg.,
* "quotes": ["error", "double"], i.e., display errors(2)
* (see above) ÿhen double quotes aren't used.
*/
/*
* some rules have properties that can be modified for eg.,
* "quotes": ["error", "double"], i.e., display errors(2)
* (see above) when double quotes aren't used.
*/
/* rules */
"curly": ["error", "multi-line"],
"brace-style": ["off", "1tbs", { "allowSingleLine": true }],
"block-spacing": ["error", "always"],
"no-var": 0,
"new-cap": 0,
"guard-for-in": 0,
"max-len": ["warn", { "ignoreComments": true }],
"prefer-const": 1,
"valid-jsdoc": 2
}
/* rules */
"curly": ["error", "multi-line"],
"brace-style": ["off", "1tbs", { "allowSingleLine": true }],
"block-spacing": ["error", "always"],
"no-var": 0,
"new-cap": 0,
"guard-for-in": 0,
"max-len": ["warn", { "ignoreComments": true }],
"prefer-const": 1,
"valid-jsdoc": 0
}
};

@@ -12,3 +12,3 @@ {

"name": "Launch Chrome against localhost",
"url": "http://127.0.0.1:5500",
"url": "http://127.0.0.1:5501",
"webRoot": "${workspaceFolder}",

@@ -15,0 +15,0 @@ "skipFiles": [

@@ -127,14 +127,11 @@ module.exports = function(grunt) {

'src/edit/getEXIFdata.js',
'src/edit/EditHandle.js',
'src/edit/LockHandle.js',
'src/edit/DistortHandle.js',
'src/edit/RotateScaleHandle.js',
'src/edit/RotateHandle.js',
'src/edit/ScaleHandle.js',
'src/edit/handles/EditHandle.js',
'src/edit/handles/*.js',
'src/iconsets/IconSet.js',
'src/iconsets/KeymapperIconSet.js',
'src/iconsets/ToolbarIconSet.js',
'src/edit/tools/EditAction.js',
'src/edit/tools/DistortableImage.PopupBar.js',
'src/edit/tools/DistortableImage.ControlBar.js',
'src/edit/actions/EditAction.js',
'src/edit/actions/*.js',
'src/edit/toolbars/DistortableImage.PopupBar.js',
'src/edit/toolbars/DistortableImage.ControlBar.js',
'src/edit/DistortableImage.Edit.js',

@@ -141,0 +138,0 @@ 'src/edit/DistortableCollection.Edit.js',

{
"name": "leaflet-distortableimage",
"version": "0.7.8",
"version": "0.8.0",
"description": "Leaflet plugin enabling image overlays to be distorted, stretched, and warped (built for Public Lab's MapKnitter: http://publiclab.org).",

@@ -36,3 +36,4 @@ "scripts": {

"leaflet-toolbar": "0.4.0-alpha.2",
"webgl-distort": "0.0.2"
"webgl-distort": "0.0.2",
"jquery": "~> 3.4.0"
},

@@ -52,4 +53,3 @@ "devDependencies": {

"husky": "^3.0.3",
"jquery": "~> 3.4.0",
"karma": "^4.1.0",
"karma": "^4.3.0",
"karma-coverage": "^2.0.1",

@@ -59,2 +59,3 @@ "karma-mocha": "^1.3.0",

"karma-phantomjs-launcher": "^1.0.4",
"karma-sinon": "^1.0.5",
"matchdep": "^2.0.0",

@@ -61,0 +62,0 @@ "mocha": "^6.0.0",

@@ -88,11 +88,11 @@ # Leaflet.DistortableImage

* `actions` (*optional*, default: [ToggleTransparency, ToggleOutline, ToggleLock, ToggleRotateScale, ToggleOrder, Revert, Export, Delete], value: *array*)
* `actions` (*optional*, default: [`L.ScaleAction`, `L.DistortAction`, `L.RotateAction`, `L.FreeRotateAction`, `L.LockAction`, `L.OpacityAction`, `L.BorderAction`, `L.ExportAction`, `L.DeleteAction`], value: *array*)
If you would like to overrwrite the default toolbar actions available for an individual image's `L.Popup` toolbar, pass an array with the actions you want. Reference the available values [here](#Single-Image-Interface).
For example, to overrwrite the toolbar to only include the `ToggleTransparency` and `Delete` actions, and also add on the additional `ToggleScale` action:
For example, to overrwrite the toolbar to only include `L.OpacityAction` and `L.DeleteAction` , and also add on an additional non-default like `L.RevertAction`:
```js
img = L.distortableImageOverlay('example.jpg', {
actions: [ToggleTransparency, ToggleScale, Delete],
actions: [L.OpacityAction, L.DeleteAction, L.RevertAction],
}).addTo(map);

@@ -105,7 +105,7 @@ ```

Allows you to set an image's position on the map manually (somewhere other than center).
Allows you to set an image's position on the map manually (somewhere other than the center default).
They should be passed as an array of `L.latLng` objects in NW, NE, SW, SE order (in a "Z" shape).
Note that this can manipulate shape and dimensions of your image.
This will not have an effect on the map view, but it will determine the shape and dimensions of the rendered image.
The corners should be passed as an array of `L.latLng` objects in NW, NE, SW, SE order (in a "Z" shape).

@@ -181,10 +181,10 @@ They will be stored on the image. See the [Quick API Reference](#Quick-API-Reference) for their getter and setter methods.

* **scale**: Resize only.
* **rotateScale**: Free transform. Combines the rotate and scale modes into one.
* **lock**: Locks the image in place. Prevents moving it via user gestures, toolbar actions, and hotkeys until the toolbar action ToggleLock is explicitly triggered (or its hotkey <kbd>l</kbd>).
* **freeRotate**: Combines the rotate and scale modes into one.
* **lock**: Locks the image in place. Disables any user gestures, toolbar actions, or hotkeys that are not associated with mode. Exception: `L.ExportAction` will still be enabled.
In the below example, the image will be initialiazed with "rotateScale" handles:
In the below example, the image will be initialiazed with "freeRotate" handles:
```js
img = L.distortableImageOverlay('example.jpg', {
mode: 'rotateScale',
mode: 'freeRotate',
}).addTo(map);

@@ -213,3 +213,3 @@ ```

Our `DistortableCollection` class allows working with multiple images simultaneously. This interface builds on the single image interface.
Our `DistortableCollection` class builds on the single image interface to allow working with multiple images simultaneously.

@@ -251,3 +251,3 @@ The setup is relatively similar.

<blockquote><strong>Note</strong>: You must instantiate a blank collection, then dynamically add layers to it like above. This is because <code>DistortableCollection</code> uses the <code>layeradd</code> event to enable additional editing features on images as they are added, and it is only triggered when they are added dynamically.</blockquote>
<blockquote><strong>Note</strong>: You must instantiate a blank collection, then dynamically add layers to it like above. This is because <code>DistortableCollection</code> internally uses the <code>layeradd</code> event to enable additional editing features on images as they are added, and it is only triggered when they are added dynamically.</blockquote>

@@ -263,11 +263,11 @@

* `actions` (*optional*, default: [Exports, Deletes, Locks, Unlocks], value: *array*)
* `actions` (*optional*, default: [`L.ExportAction`, `L.DeleteAction`, `L.LockAction`, `L.UnlocksAction`], value: *array*)
Overrwrite the default toolbar actions for an image collection's `L.Control` toolbar. Reference the available values [here](#Multiple-Image-Interface).
For example, to overrwrite the toolbar to only include the `Deletes` action:
For example, to overrwrite the toolbar to only include the `L.DeleteAction`:
```JS
imgGroup = L.distortableCollection({
actions: [Deletes],
actions: [L.DeleteAction],
}).addTo(map);

@@ -319,3 +319,3 @@ ```

Currently it supports multiple image selection and translations, and WIP we are working on porting all editing tools to work for it, such as transparency, etc. Image distortions still use the single-image interface.
Currently it supports multiple image selection and translations, and WIP we are working on porting all editing tools to work for it, such as opacity, etc. Image distortions (via modes) still use the single-image interface.

@@ -325,3 +325,3 @@ **multi-select:** A single toolbar instance (using `L.control`) renders the set of tools available to use on collections of images.

1. Multi-selection works with <kbd>shift</kbd> + `click` to toggle an individual image's inclusion in this interface.
2. Or <kbd>shift</kbd> + `drag` to use our `BoxSelector` handler to select multiple at once.
2. Or <kbd>shift</kbd> + `drag` to use our `L.Map.BoxSelector` handler to select multiple at once.
3. Or for touch devices, `touch` + `hold` (aka `longpress`).

@@ -331,4 +331,4 @@

* In order to return to the single-image interface, where each `L.popup` toolbar only applies actions on the image it's attached to, you must toggle *all* images out of multi-select or...
* ...Click on the map or hit the <kbd>esc</kbd> key to quickly deselect all images.
* In order to return to the single-image interface, where each `L.popup` toolbar only applies actions on the image it's attached to, you must toggle *all* images out of multi-select with `shift` + click, or...
* ...Click on the map or hit the <kbd>esc</kbd> key to quickly deselect.
* For the aforementioned 3 mutli-select methods, the `BoxSelector` method is the only one that doesn't also toggle _out_ of multi-select mode.

@@ -348,26 +348,24 @@

* **ToggleLock (<kbd>l</kbd>)**
* **L.ScaleAction** (<kbd>s</kbd>):
* Sets `scale` mode.
* **L.RotateAction** (<kbd>r</kbd>):
* Sets `rotate` mode.
* **L.FreeRotateAction** (<kbd>f</kbd>)
* Sets `freeRotate` mode.
* **L.LockAction** (<kbd>l</kbd>, <kbd>u</kbd>)
* Toggles between `lock` mode and `distort` mode.
* **ToggleRotateScale (<kbd>r</kbd>, <kbd>d</kbd>)**
* Toggles between `rotateScale` and `distort` mode.
* **ToggleOrder (<kbd>j</kbd>, <kbd>k</kbd>)**
* If you have multiple images, use this to switch an individual image's overlap back and forth into view. Employs [`bringToFront()`](https://leafletjs.com/reference-1.5.0.html\#imageoverlay-bringtofront) and [`bringToBack()`](https://leafletjs.com/reference-1.5.0.html#imageoverlay-bringtoback) from the Leaflet API.
* **ToggleOutline (<kbd>o</kbd>)**
* **ToggleTransparency (<kbd>t</kbd>)**
* **Revert**
* Restores the image to its original proportions and scale, but keeps its current rotation angle and location on the map intact.
* **Export**
* **Delete (<kbd>delete</kbd>, <kbd>backscpace</kbd>)**
* Permanently deletes the image from the map.
* **L.BorderAction** (<kbd>b</kbd>)
* **L.OpacityAction** (<kbd>o</kbd>)
* **L.ExportAction** (<kbd>e</kbd>)
* **L.DeleteAction** (<kbd>backscpace</kbd>, <kbd>delete</kbd>)
* Permanently deletes the image from the map. Uses a `confirm()` modal dialog.
* windows `backspace` / mac `delete`
Addons:
* **L.StackAction** (<kbd>q</kbd>, <kbd>a</kbd>)
* Switch an image's overlap compared to neighboring images back and forth into view. Employs [`bringToFront()`](https://leafletjs.com/reference-1.5.0.html\#imageoverlay-bringtofront) and [`bringToBack()`](https://leafletjs.com/reference-1.5.0.html#imageoverlay-bringtoback) from the Leaflet API.
* **L.GeolocateAction (WIP)**
* **L.RevertAction (WIP)**
* Restores the image to its original proportions and scale, but keeps its current rotation angle and location on the map intact.
* **ToggleRotate** (<kbd>caps lock</kbd>):
* Toggles between `rotate` mode and `distort` mode.
* Replaced as a default toolbar action by `ToggleRotateScale`, but still accessible via its hotkey, `mode`, and (WIP) custom toolbar actions API.
* **ToggleScale** (<kbd>s</kbd>):
* Toggles between `scale` mode and `distort` mode.
* Replaced as a default toolbar action by `ToggleRotateScale`, but still accessible via its hotkey, `mode`, and (WIP) custom toolbar actions API.
* **EnableEXIF (WIP)**
---

@@ -381,7 +379,9 @@

* **Exports** (WIP)
* **Deletes (<kbd>delete</kbd>, <kbd>backspace</kbd>)**
* Permanently deletes groups of selected images from the map. Uses a `confirm()` modal dialog.
* **Locks** (<kbd>l</kbd>)
* **Unlocks** (<kbd>u</kbd>)
* **L.ExportAction** (<kbd>e</kbd>) (WIP)
* **L.DeleteAction** (<kbd>backscpace</kbd>, <kbd>delete</kbd>)
* Permanently deletes a group of images from the map.
* **L.LockAction** (<kbd>l</kbd>)
* Sets `lock` mode for a group of images.
* **L.UnlocksAction** (<kbd>u</kbd>)
* Unsets `lock` mode for a group of images.

@@ -553,2 +553,8 @@ ## Quick API Reference

<details><summary><code><b>getMode()</b>: String</code></summary>
<ul>
<li>Returns the current <code>mode</code> of the image.</li>
</ul>
</details>
---

@@ -555,0 +561,0 @@

@@ -83,11 +83,13 @@ L.DomUtil = L.DomUtil || {};

/* eslint-disable */
'<tr><td><div class="left"><span>Stack up / down</span></div><div class="right"><kbd>j</kbd>\xa0<kbd>k</kbd></div></td></tr>' +
'<tr><td><div class="left"><span>Lock Image</span></div><div class="right"><kbd>l</kbd></div></td></tr>' +
'<tr><td><div class="left"><span>Outline</span></div><div class="right"><kbd>o</kbd></div></td></tr>' +
'<tr><td><div class="left"><span>Scale</span></div><div class="right"><kbd>s</kbd></div></td></tr>' +
'<tr><td><div class="left"><span>Transparency</span></div><div class="right"><kbd>t</kbd></div></td></tr>' +
'<tr><td><div class="left"><span>RotateScale</span></div><div class="right"><kbd>d</kbd>\xa0<kbd>r</kbd></div></td></tr>' +
'<tr><td><div class="left"><span>Rotate Mode</span></div><div class="right"><kbd>R</kbd></div></td></tr>' +
'<tr><td><div class="left"><span>RotateScale Mode</span></div><div class="right"><kbd>r</kbd></div></td></tr>' +
'<tr><td><div class="left"><span>Scale Mode</span></div><div class="right"><kbd>s</kbd></div></td></tr>' +
'<tr><td><div class="left"><span>Distort Mode</span></div><div class="right"><kbd>d</kbd></div></td></tr>' +
'<tr><td><div class="left"><span>Lock (Mode) / Unlock Image</span></div><div class="right"><kbd>l</kbd>\xa0<kbd>u</kbd></div></td></tr>' +
'<tr><td><div class="left"><span>Stack up / down</span></div><div class="right"><kbd>q</kbd>\xa0<kbd>a</kbd></div></td></tr>' +
'<tr><td><div class="left"><span>Add / Remove Image Border</span></div><div class="right"><kbd>b</kbd></div></td></tr>' +
'<tr><td><div class="left"><span>Toggle Opacity</span></div><div class="right"><kbd>o</kbd></div></td></tr>' +
'<tr><td><div class="left"><span>Deselect All</span></div><div class="right"><kbd>esc</kbd></div></td></tr>' +
'<tr><td><div class="left"><span>Delete Image</span></div><div class="right"><kbd>delete</kbd>\xa0<kbd>backspace</kbd></div></td></tr>' +
'<tr><td><div class="left"><span>Rotate</span></div><div class="right"><kbd>caps</kbd></div></td></tr>' +
'<tr><td><div class="left"><span>Delete Image(s)</span></div><div class="right"><kbd>delete</kbd>\xa0<kbd>backspace</kbd></div></td></tr>' +
'<tr><td><div class="left"><span>Export Image(s)</span></div><div class="right"><kbd>e</kbd></div></td></tr>' +
'</tbody></table>'

@@ -94,0 +96,0 @@ );

@@ -114,3 +114,3 @@ L.DistortableCollection = L.FeatureGroup.extend({

L.DomEvent.stopPropagation(e);
if (e) { L.DomEvent.stopPropagation(e); }
},

@@ -133,3 +133,4 @@

for (i = 0; i < 4; i++) {
layer._dragStartPoints[i] = layer._map.latLngToLayerPoint(layer.getCorner(i));
var c = layer.getCorner(i);
layer._dragStartPoints[i] = layer._map.latLngToLayerPoint(c);
}

@@ -136,0 +137,0 @@ });

@@ -10,2 +10,3 @@ L.DistortableImageOverlay = L.ImageOverlay.extend({

editable: true,
mode: 'distort',
},

@@ -115,3 +116,7 @@

this._initialDimensions = {'height': imageHeight, 'width': imageWidth, 'offset': offset};
this._initialDimensions = {
'height': imageHeight,
'width': imageWidth,
'offset': offset,
};
},

@@ -263,3 +268,3 @@

_revert: function() {
var angle = this.rotation;
var a = this.rotation;
var map = this._map;

@@ -280,7 +285,7 @@ var edit = this.editing;

if (angle !== 0) { this.rotateBy(L.TrigUtil.degreesToRadians(360 - angle)); }
if (a !== 0) { this.rotateBy(L.TrigUtil.degreesToRadians(360 - a)); }
map.addLayer(edit._handles[edit._mode]);
this.rotation = angle;
this.rotation = a;
},

@@ -287,0 +292,0 @@

@@ -82,5 +82,3 @@ L.DistortableImage = L.DistortableImage || {};

if (!this[handlerName]) {
return;
}
if (!this[handlerName]) { return; }

@@ -133,4 +131,2 @@ if (this._group.anySelected()) {

_unlockGroup: function() {
var map = this._group._map;
this._group.eachLayer(function(layer) {

@@ -140,5 +136,5 @@ if (this._group.isSelected(layer)) {

if (edit._mode === 'lock') {
map.removeLayer(edit._handles[edit._mode]);
edit._unlock();
edit._refreshPopupIcons();
// unlock updates the layer's handles; deselect to ensure they're hidden
edit._deselect();
}

@@ -150,4 +146,2 @@ }

_lockGroup: function() {
var map = this._group._map;
this._group.eachLayer(function(layer) {

@@ -158,4 +152,2 @@ if (this._group.isSelected(layer) ) {

edit._lock();
map.addLayer(edit._handles[edit._mode]);
edit._refreshPopupIcons();
// map.addLayer also deselects the image, so we reselect here

@@ -174,6 +166,5 @@ L.DomUtil.addClass(layer.getElement(), 'selected');

var edit = layer.editing;
if (edit._selected) {
edit._deselect();
}
if (edit._selected) { edit._deselect(); }
var imgBounds = L.latLngBounds(layer.getCorner(2), layer.getCorner(1));

@@ -279,13 +270,8 @@ imgBounds = map._latLngBoundsToNewLayerBounds(imgBounds, map.getZoom(), map.getCenter());

if (group.options.suppressToolbar) { return; }
if (group.options.suppressToolbar || this.toolbar) { return; }
try {
if (!this.toolbar) {
this.toolbar = L.distortableImage.controlBar({
actions: this.editActions,
position: 'topleft',
}).addTo(map, group);
this.fire('toolbar:created');
}
} catch (e) { }
this.toolbar = L.distortableImage.controlBar({
actions: this.editActions,
position: 'topleft',
}).addTo(map, group);
},

@@ -295,3 +281,2 @@

var map = this._group._map;
if (this.toolbar) {

@@ -334,1 +319,5 @@ map.removeLayer(this.toolbar);

});
L.distortableCollection.edit = function(group, options) {
return new L.DistortableCollection.Edit(group, options);
};

@@ -10,2 +10,3 @@ /* eslint-disable valid-jsdoc */

keymap: L.distortableImage.action_map,
modes: ['scale', 'distort', 'rotate', 'freeRotate', 'lock'],
},

@@ -18,5 +19,4 @@

* limiting modes similar to toolbar actions API */
var modes = ['distort', 'lock', 'rotate', 'scale', 'rotateScale'];
this._mode = modes[modes.indexOf(overlay.options.mode)] || 'distort';
this._modes = this.options.modes;
this._mode = this._modes[this._modes.indexOf(overlay.options.mode)];
this._selected = this._overlay.options.selected || false;

@@ -142,7 +142,5 @@ this._transparent = false;

this._lockHandles = L.layerGroup();
this._scaleHandles = L.layerGroup();
for (i = 0; i < 4; i++) {
this._lockHandles.addLayer(
new L.LockHandle(overlay, i, {draggable: false})
);
this._scaleHandles.addLayer(new L.ScaleHandle(overlay, i));
}

@@ -160,19 +158,21 @@

this._scaleHandles = L.layerGroup();
// handle includes rotate AND scale
this._freeRotateHandles = L.layerGroup();
for (i = 0; i < 4; i++) {
this._scaleHandles.addLayer(new L.ScaleHandle(overlay, i));
this._freeRotateHandles.addLayer(new L.RotateScaleHandle(overlay, i));
}
// handle includes rotate AND scale
this._rotateScaleHandles = L.layerGroup();
this._lockHandles = L.layerGroup();
for (i = 0; i < 4; i++) {
this._rotateScaleHandles.addLayer(new L.RotateScaleHandle(overlay, i));
this._lockHandles.addLayer(
new L.LockHandle(overlay, i, {draggable: false})
);
}
this._handles = {
lock: this._lockHandles,
scale: this._scaleHandles,
distort: this._distortHandles,
rotateScale: this._rotateScaleHandles,
scale: this._scaleHandles,
rotate: this._rotateHandles,
freeRotate: this._freeRotateHandles,
lock: this._lockHandles,
};

@@ -203,3 +203,3 @@ },

var handlerName = keymap[e.key];
var overlay = this._overlay;
var ov = this._overlay;
var eP = this.parentGroup;

@@ -209,4 +209,4 @@

if (this[handlerName] !== undefined && !overlay.options.suppressToolbar) {
if (this._selected) {
if (this[handlerName] !== undefined && !ov.options.suppressToolbar) {
if (this._selected && this.toolbar) {
this[handlerName].call(this);

@@ -275,3 +275,4 @@ }

this.dragging._updatePosition = function() {
var delta = this._newPos.subtract(map.latLngToLayerPoint(overlay.getCorner(0)));
var topLeft = overlay.getCorner(0);
var delta = this._newPos.subtract(map.latLngToLayerPoint(topLeft));
var currentPoint;

@@ -295,46 +296,34 @@ var corners = {0: '', 1: '', 2: '', 3: ''};

_toggleRotateScale: function() {
var map = this._overlay._map;
_scaleMode: function() {
if (!this.hasTool(L.ScaleAction)) { return; }
this._setMode('scale');
},
if (this._mode === 'lock') { return; }
_distortMode: function() {
if (!this.hasTool(L.DistortAction)) { return; }
this._setMode('distort');
},
map.removeLayer(this._handles[this._mode]);
if (this._mode === 'rotateScale') { this._mode = 'distort'; }
else { this._mode = 'rotateScale'; }
map.addLayer(this._handles[this._mode]);
this._addToolbar();
_rotateMode: function() {
if (!this.hasTool(L.RotateAction)) { return; }
this._setMode('rotate');
},
_toggleScale: function() {
var map = this._overlay._map;
if (this._mode === 'lock') { return; }
map.removeLayer(this._handles[this._mode]);
if (this._mode === 'scale') { this._mode = 'distort'; }
else { this._mode = 'scale'; }
map.addLayer(this._handles[this._mode]);
_freeRotateMode: function() {
if (!this.hasTool(L.FreeRotateAction)) { return; }
this._setMode('freeRotate');
},
_toggleRotate: function() {
var map = this._overlay._map;
if (this._mode === 'lock') { return; }
map.removeLayer(this._handles[this._mode]);
if (this._mode === 'rotate') { this._mode = 'distort'; }
else { this._mode = 'rotate'; }
map.addLayer(this._handles[this._mode]);
_toggleLockMode: function() {
if (!this.hasTool(L.LockAction)) { return; }
if (this._mode === 'lock') { this._unlock(); }
else { this._lock(); }
},
_toggleTransparency: function() {
_toggleOpacity: function() {
var image = this._overlay.getElement();
var opacity;
if (!this.hasTool(L.OpacityAction)) { return; }
this._transparent = !this._transparent;

@@ -346,6 +335,6 @@ opacity = this._transparent ? this.options.opacity : 1;

this._addToolbar();
this._refresh();
},
_toggleOutline: function() {
_toggleBorder: function() {
var image = this._overlay.getElement();

@@ -355,2 +344,4 @@ var opacity;

if (!this.hasTool(L.BorderAction)) { return; }
this._outlined = !this._outlined;

@@ -364,37 +355,139 @@ outline = this._outlined ? this.options.outline : 'none';

this._addToolbar();
this._refresh();
},
_sendUp: function() {
// compare this to using overlay zIndex
_toggleOrder: function() {
if (!this.hasTool(L.StackAction)) { return; }
if (this._toggledImage) { this._stackUp(); }
else { this._stackDown(); }
},
_removeOverlay: function() {
var ov = this._overlay;
var eP = this.parentGroup;
var m = this._mode;
if (m === 'lock' || !this.hasTool(L.DeleteAction)) { return; }
var choice = L.DomUtil.confirmDelete();
if (!choice) { return; }
this._removeToolbar();
if (eP) { eP.removeLayer(ov); }
else { ov._map.removeLayer(ov); }
},
// Based on https://github.com/publiclab/mapknitter/blob/8d94132c81b3040ae0d0b4627e685ff75275b416/app/assets/javascripts/mapknitter/Map.js#L47-L82
_getExport: function() {
var overlay = this._overlay;
var map = overlay._map;
if (!this.hasTool(L.ExportAction)) { return; }
// 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,
// 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
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
);
}
};
downloadable.src = overlay.options.fullResolutionSrc || overlay._image.src;
},
_stackUp: function() {
var t = this._toggledImage;
if (!t || !this.hasTool(L.StackAction)) { return; }
this._toggledImage = false;
this._overlay.bringToFront();
this._refresh();
},
_sendDown: function() {
_stackDown: function() {
var t = this._toggledImage;
if (t || !this.hasTool(L.StackAction)) { return; }
this._toggledImage = true;
this._overlay.bringToBack();
this._refresh();
},
_unlock: function() {
this._mode = 'distort';
var ov = this._overlay;
var map = ov._map;
var m = this._mode;
if (m !== 'lock' || !this.hasTool(L.LockAction)) { return; }
map.removeLayer(this._handles[m]);
if (ov.options.mode === 'lock') {
this._mode = 'distort';
} else {
this._mode = ov.options.mode;
}
this._enableDragging();
map.addLayer(this._handles[this._mode]);
this._refresh();
},
_lock: function() {
var map = this._overlay._map;
var m = this._mode;
if (m === 'lock' || !this.hasTool(L.LockAction)) { return; }
map.removeLayer(this._handles[m]);
this._mode = 'lock';
if (this.dragging) {
this.dragging.disable();
delete this.dragging;
}
delete this.dragging;
},
_toggleLock: function() {
var map = this._overlay._map;
map.removeLayer(this._handles[this._mode]);
if (this._mode === 'lock') { this._unlock(); }
else { this._lock(); }
map.addLayer(this._handles[this._mode]);
this._addToolbar();
this._refresh();
},

@@ -409,3 +502,2 @@

var map = this._overlay._map;
L.DomEvent.off(map, 'click', this._deselect, this);

@@ -416,3 +508,2 @@ },

var map = this._overlay._map;
L.DomEvent.on(map, 'click', this._deselect, this);

@@ -439,6 +530,8 @@ },

var eP = this.parentGroup;
var m = this._mode;
// mutli-image interface doesn't have markers so check if its on & return early if true
if (this._mode === 'lock' || (eP && eP.anySelected())) { return; }
if (this._mode === 'lock' || eP && eP.anySelected()) { return; }
var currentHandle = this._handles[this._mode];
var currentHandle = this._handles[m];

@@ -459,4 +552,4 @@ currentHandle.eachLayer(function(layer) {

var mode = this._mode;
var currentHandle = this._handles[mode];
var m = this._mode;
var currentHandle = this._handles[m];

@@ -467,3 +560,3 @@ currentHandle.eachLayer(function(layer) {

if (mode !== 'lock') { layer.setOpacity(0); }
if (m !== 'lock') { layer.setOpacity(0); }
if (drag) { drag.disable(); }

@@ -475,7 +568,7 @@ if (opts.draggable) { opts.draggable = false; }

_addToolbar: function() {
var overlay = this._overlay;
var ov = this._overlay;
var eP = this.parentGroup;
var map = overlay._map;
var map = ov._map;
// Find the topmost point on the image.
var corners = overlay.getCorners();
var corners = ov.getCorners();
var maxLat = -Infinity;

@@ -488,3 +581,3 @@

if (overlay.options.suppressToolbar) { return; }
if (ov.options.suppressToolbar || this.toolbar) { return; }

@@ -498,3 +591,3 @@ for (var i = 0; i < corners.length; i++) {

// Longitude is based on the centroid of the image.
var raisedPoint = overlay.getCenter();
var raisedPoint = ov.getCenter();
raisedPoint.lat = maxLat;

@@ -505,10 +598,10 @@

actions: this.editActions,
}).addTo(map, overlay);
overlay.fire('toolbar:created');
}).addTo(map, ov);
ov.fire('toolbar:created');
} catch (e) { }
},
_refreshPopupIcons: function() {
_refresh: function() {
if (this.toolbar) { this._removeToolbar(); }
this._addToolbar();
this._removeToolbar();
},

@@ -540,84 +633,25 @@

_removeOverlay: function() {
var overlay = this._overlay;
var map = overlay._map;
getMode: function() {
return this._mode;
},
_setMode: function(newMode) {
var map = this._overlay._map;
var eP = this.parentGroup;
var m = this._mode;
if (this._mode === 'lock') { return; }
if ((eP && eP.anySelected()) || !this.enabled()) { return false; }
if (newMode === m || !this.toolbar) { return false; }
var choice = L.DomUtil.confirmDelete();
if (!choice) { return; }
this.toolbar.clickTool(newMode);
this._removeToolbar();
if (eP) { eP.removeLayer(overlay); }
else { map.removeLayer(overlay); }
},
// compare this to using overlay zIndex
_toggleOrder: function() {
if (this._toggledImage) {
this._toggledImage = false;
this._overlay.bringToFront();
} else {
this._toggledImage = true;
this._overlay.bringToBack();
if (this._modes.indexOf(newMode) !== -1) {
if (m === 'lock' && !this.dragging) { this._enableDragging(); }
map.removeLayer(this._handles[m]);
this._mode = newMode;
map.addLayer(this._handles[this._mode]);
}
this._addToolbar();
},
this._refresh();
// Based on https://github.com/publiclab/mapknitter/blob/8d94132c81b3040ae0d0b4627e685ff75275b416/app/assets/javascripts/mapknitter/Map.js#L47-L82
_getExport: function() {
var overlay = this._overlay;
var map = overlay._map;
// 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,
// 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
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
);
}
};
downloadable.src = overlay.options.fullResolutionSrc || overlay._image.src;
return this;
},

@@ -630,11 +664,17 @@

_nextMode: function(e) {
var eP = this.parentGroup;
var m = this._mode;
var idx = this._modes.indexOf(m);
var nextIdx = (idx + 1) % this._modes.length;
var newMode = this._modes[nextIdx];
this._enableDragging();
this.enable();
this._toggleRotateScale();
if (e) { L.DomEvent.stop(e); }
if (eP && eP.anySelected()) { this._deselect(); }
L.DomEvent.stop(e);
if (this._modes.indexOf(newMode) !== -1) {
return this._setMode(newMode);
} else { return false; }
},
});
L.distortableImage.edit = function(overlay, options) {
return new L.DistortableImage.Edit(overlay, options);
};

@@ -21,3 +21,3 @@ /* eslint-disable max-len */

'<symbol viewBox="0 0 18 18" id="transform"><path d="M16.5 13.5V12H6V3h1.5L5.25.75 3 3h1.5v1.5h-3V6h3v6c0 .825.675 1.5 1.5 1.5h6V15h-1.5l2.25 2.25L15 15h-1.5v-1.5h3zM7.5 6H12v4.5h1.5V6c0-.825-.675-1.5-1.5-1.5H7.5V6z"/></symbol>' +
'<symbol viewBox="0 0 18 18" id="unlock"><path d="M13.5 6h-.75V4.5C12.75 2.43 11.07.75 9 .75 6.93.75 5.25 2.43 5.25 4.5h1.5A2.247 2.247 0 0 1 9 2.25a2.247 2.247 0 0 1 2.25 2.25V6H4.5C3.675 6 3 6.675 3 7.5V15c0 .825.675 1.5 1.5 1.5h9c.825 0 1.5-.675 1.5-1.5V7.5c0-.825-.675-1.5-1.5-1.5zm0 9h-9V7.5h9V15zM9 12.75c.825 0 1.5-.675 1.5-1.5s-.675-1.5-1.5-1.5-1.5.675-1.5 1.5.675 1.5 1.5 1.5z"/></symbol>'
'<symbol viewBox="0 0 18 18" id="unlock"><path d="M13.5 6h-.75V4.5C12.75 2.43 11.07.75 9 .75 6.93.75 5.25 2.43 5.25 4.5h1.5A2.247 2.247 0 0 1 9 2.25a2.247 2.247 0 0 1 2.25 2.25V6H4.5C3.675 6 3 6.675 3 7.5V15c0 .825.675 1.5 1.5 1.5h9c.825 0 1.5-.675 1.5-1.5V7.5c0-.825-.675-1.5-1.5-1.5zm0 9h-9V7.5h9V15zM9 12.75c.825 0 1.5-.675 1.5-1.5s-.675-1.5-1.5-1.5-1.5.675-1.5 1.5.675 1.5 1.5 1.5z"/></symbol>',
});

@@ -6,5 +6,5 @@ L.Map.mergeOptions({

/**
* primarily Leaflet 1.5.1 source code. Overriden so that its a selection box with our `L.DistortableCollection` class
* instead of a zoom box.
/**
* primarily Leaflet 1.5.1 source code. Overriden so that it's a selection box used with
* our `L.DistortableCollection` class instead of a zoom box.
* */

@@ -109,11 +109,8 @@ L.Map.BoxSelector = L.Map.BoxZoom.extend({

_onMouseUp: function(e) {
if (e.which !== 1 && e.button !== 1) {
return;
}
if (e.which !== 1 && e.button !== 1) { return; }
this._finish();
if (!this._moved) {
return;
}
if (!this._moved) { return; }
// Postpone to next JS tick so internal click event handling

@@ -126,4 +123,4 @@ // still see it as "moved".

var bounds = L.latLngBounds(
this._map.containerPointToLatLng(this._bounds.getBottomLeft()),
this._map.containerPointToLatLng(this._bounds.getTopRight())
this._map.containerPointToLatLng(this._bounds.getBottomLeft()),
this._map.containerPointToLatLng(this._bounds.getTopRight())
);

@@ -130,0 +127,0 @@

@@ -12,7 +12,6 @@ // Karma configuration

require('karma-mocha'),
require('karma-sinon'),
require('karma-coverage'),
require('karma-mocha-reporter'),
require('karma-phantomjs-launcher'),
require('glfx'),
require('webgl-distort/dist/webgl-distort.js'),
],

@@ -22,3 +21,3 @@

// available frameworks: https://npmjs.org/browse/keyword/karma-adapter
frameworks: ['mocha'],
frameworks: ['mocha', 'sinon'],

@@ -38,21 +37,17 @@ // list of files / patterns to load in the browser

'src/util/*.js',
'src/DistortableImageOverlay.js',
'src/DistortableCollection.js',
'src/edit/getEXIFdata.js',
'src/mapmixins/*.js',
'src/edit/EditHandle.js',
'src/edit/LockHandle.js',
'src/edit/DistortHandle.js',
'src/edit/RotateScaleHandle.js',
'src/edit/RotateHandle.js',
'src/edit/ScaleHandle.js',
'src/DistortableCollection.js',
'src/DistortableImageOverlay.js',
'src/edit/handles/EditHandle.js',
'src/edit/handles/*.js',
'src/iconsets/IconSet.js',
'src/iconsets/KeymapperIconSet.js',
'src/iconsets/ToolbarIconSet.js',
'src/edit/tools/EditAction.js',
'src/components/DistortableImage.Keymapper.js',
'src/edit/tools/DistortableImage.PopupBar.js',
'src/edit/tools/DistortableImage.ControlBar.js',
'src/edit/actions/EditAction.js',
'src/edit/actions/*.js',
'src/edit/toolbars/*',
'src/edit/DistortableImage.Edit.js',
'src/edit/DistortableCollection.Edit.js',
'src/components/DistortableImage.Keymapper.js',
'test/SpecHelper.js',

@@ -59,0 +54,0 @@ 'test/src/*Spec.js',

@@ -11,12 +11,16 @@ beforeEach(function() {

type: 'mousedown',
isShift: true
isShift: true,
},
MouseDown: {
type: 'mousedown',
isShift: false
isShift: false,
},
Click: {
type: 'click',
isShift: false
isShift: false,
},
Dblclick: {
type: 'dblclick',
isShift: false,
}
}

@@ -23,0 +27,0 @@

@@ -5,6 +5,3 @@ describe('L.DistortableCollection', function() {

beforeEach(function(done) {
map = L.map(L.DomUtil.create('div', '', document.body)).setView(
[41.7896, -87.5996],
15
);
map = L.map(L.DomUtil.create('div', '', document.body)).setView([41.7896, -87.5996], 15);

@@ -64,4 +61,4 @@ overlay = L.distortableImageOverlay('/examples/example.png', {

it('Should only return true if the image was selected using shift + mousedown', function() {
var img = overlay.getElement(),
img2 = overlay2.getElement();
var img = overlay.getElement();
var img2 = overlay2.getElement();

@@ -78,4 +75,4 @@ chai.simulateEvent(img, chai.mouseEvents.ShiftMouseDown);

it('Should return false if no selections were made with shift + mousedown', function() {
var img = overlay.getElement(),
img2 = overlay2.getElement();
var img = overlay.getElement();
var img2 = overlay2.getElement();

@@ -92,4 +89,4 @@ chai.simulateEvent(img, chai.mouseEvents.MouseDown);

it('Should allow multiple image selection on shift + click', function() {
var img = overlay.getElement(),
img2 = overlay2.getElement();
var img = overlay.getElement();
var img2 = overlay2.getElement();

@@ -106,3 +103,3 @@ chai.simulateEvent(img, chai.mouseEvents.ShiftMouseDown);

overlay.editing._toggleLock();
overlay.editing._toggleLockMode();
chai.simulateEvent(img, chai.mouseEvents.ShiftMouseDown);

@@ -109,0 +106,0 @@

@@ -1,266 +0,261 @@

describe('L.DistortableCollection.Edit', function () {
var map,
overlay,
overlay2,
imgGroup;
describe('L.DistortableCollection.Edit', function() {
var map;
var overlay;
var overlay2;
var imgGroup;
beforeEach(function (done) {
map = L.map(L.DomUtil.create('div', '', document.body)).setView([41.7896, -87.5996], 15);
beforeEach(function(done) {
map = L.map(L.DomUtil.create('div', '', document.body)).setView([41.7896, -87.5996], 15);
overlay = L.distortableImageOverlay('/examples/example.png', {
corners: [
L.latLng(41.7934, -87.6052),
L.latLng(41.7934, -87.5852),
L.latLng(41.7834, -87.6052),
L.latLng(41.7834, -87.5852)
]
});
overlay = L.distortableImageOverlay('/examples/example.png', {
corners: [
L.latLng(41.7934, -87.6052),
L.latLng(41.7934, -87.5852),
L.latLng(41.7834, -87.6052),
L.latLng(41.7834, -87.5852),
],
});
overlay2 = L.distortableImageOverlay('/examples/example.png', {
corners: [
L.latLng(41.7934, -87.6050),
L.latLng(41.7934, -87.5850),
L.latLng(41.7834, -87.6050),
L.latLng(41.7834, -87.5850)
]
});
overlay2 = L.distortableImageOverlay('/examples/example.png', {
corners: [
L.latLng(41.7934, -87.6050),
L.latLng(41.7934, -87.5850),
L.latLng(41.7834, -87.6050),
L.latLng(41.7834, -87.5850),
],
});
overlay3 = L.distortableImageOverlay('/examples/example.png', {
corners: [
L.latLng(41.7934, -87.6054),
L.latLng(41.7934, -87.5854),
L.latLng(41.7834, -87.6054),
L.latLng(41.7834, -87.5854)
]
});
overlay3 = L.distortableImageOverlay('/examples/example.png', {
corners: [
L.latLng(41.7934, -87.6054),
L.latLng(41.7934, -87.5854),
L.latLng(41.7834, -87.6054),
L.latLng(41.7834, -87.5854),
],
});
imgGroup = L.distortableCollection().addTo(map);
imgGroup.addLayer(overlay);
imgGroup.addLayer(overlay2);
imgGroup.addLayer(overlay3);
imgGroup = L.distortableCollection().addTo(map);
/* Forces the images to load before any tests are run. */
L.DomEvent.on(overlay3, 'load', function () { done(); });
});
imgGroup.addLayer(overlay);
imgGroup.addLayer(overlay2);
imgGroup.addLayer(overlay3);
afterEach(function () {
imgGroup.removeLayer(overlay);
imgGroup.removeLayer(overlay2);
imgGroup.removeLayer(overlay3);
});
/* Forces the images to load before any tests are run. */
L.DomEvent.on(overlay3, 'load', function() { done(); });
});
describe('#_deselectAll', function() {
it('Should remove the \'selected\' class from all images', function() {
var img = overlay.getElement(),
img2 = overlay2.getElement();
afterEach(function() {
imgGroup.removeLayer(overlay);
imgGroup.removeLayer(overlay2);
imgGroup.removeLayer(overlay3);
});
L.DomUtil.addClass(img, 'selected');
L.DomUtil.addClass(img2, 'selected');
describe('#_deselectAll', function() {
it('Should remove the \'selected\' class from all images', function() {
var img = overlay.getElement();
var img2 = overlay2.getElement();
map.fire('click');
L.DomUtil.addClass(img, 'selected');
L.DomUtil.addClass(img2, 'selected');
// we deselect after 3ms to confirm the click wasn't a dblclick
setTimeout(function () {
expect(L.DomUtil.getClass(img)).to.not.include('selected');
expect(L.DomUtil.getClass(img2)).to.not.include('selected');
}, 3000);
});
map.fire('click');
it('Should hide all images\' handles unless they\'re lock handles', function() {
var edit = overlay.editing,
edit2 = overlay2.editing;
// we deselect after 3ms to confirm the click wasn't a dblclick
setTimeout(function() {
expect(L.DomUtil.getClass(img)).to.not.include('selected');
expect(L.DomUtil.getClass(img2)).to.not.include('selected');
}, 3000);
});
// turn on lock handles for one of the DistortableImages
edit2._toggleLock();
it('Should hide all images\' handles unless they\'re lock handles', function() {
var edit = overlay.editing;
var edit2 = overlay2.editing;
var distortHandleState = [];
var lockHandleState = [];
// then trigger _deselectAll
map.fire('click');
// turn on lock handles for one of the DistortableImageOverlay instances.
edit2._toggleLockMode();
setTimeout(function () {
var distortHandleState = [];
edit._handles['distort'].eachLayer(function (handle) {
distortHandleState.push(handle._icon.style.opacity);
});
var lockHandleState = [];
edit2._handles['lock'].eachLayer(function (handle) {
lockHandleState.push(handle._icon.style.opacity);
});
expect(distortHandleState).to.deep.equal(['0', '0', '0', '0']);
// opacity for lockHandles is unset because we never altered it to hide it as part of deselection
expect(lockHandleState).to.deep.equal(['', '', '', '']);
}, 3000);
});
// then trigger _deselectAll
map.fire('click');
it("Should remove all images' individual toolbar instances regardless of lock handles", function() {
var edit = overlay.editing,
edit2 = overlay2.editing;
setTimeout(function() {
edit._handles['distort'].eachLayer(function(handle) {
distortHandleState.push(handle._icon.style.opacity);
});
// turn on lock handles for one of the DistortableImages
edit2._toggleLock();
edit2._handles['lock'].eachLayer(function(handle) {
lockHandleState.push(handle._icon.style.opacity);
});
// select both images to initially create individual toolbar instances (single selection interface)
chai.simulateEvent(overlay.getElement(), chai.mouseEvents.Click);
chai.simulateEvent(overlay2.getElement(), chai.mouseEvents.Click);
expect(distortHandleState).to.deep.equal(['0', '0', '0', '0']);
// opacity for lockHandles is unset because we never altered it to hide it as part of deselection
expect(lockHandleState).to.deep.equal(['', '', '', '']);
}, 3000);
});
expect(edit.toolbar).to.not.be.false;
expect(edit2.toolbar).to.not.be.false;
it('Should remove all images\' individual toolbar instances regardless of lock handles', function() {
var edit = overlay.editing;
var edit2 = overlay2.editing;
// then trigger _deselectAll
map.fire('click');
edit2._toggleLockMode();
setTimeout(function () {
expect(edit.toolbar).to.be.false;
expect(edit2.toolbar).to.be.false;
}, 3000);
});
// select both images to initially create individual toolbar instances (single selection interface)
chai.simulateEvent(overlay.getElement(), chai.mouseEvents.Click);
chai.simulateEvent(overlay2.getElement(), chai.mouseEvents.Click);
expect(edit.toolbar).to.not.be.false;
expect(edit2.toolbar).to.not.be.false;
// then trigger _deselectAll
map.fire('click');
setTimeout(function() {
expect(edit.toolbar).to.be.false;
expect(edit2.toolbar).to.be.false;
}, 3000);
});
});
describe('#_addToolbar', function () {
it('is invoked on the click event that follows mousedown multi-select', function () {
expect(map._toolbars).to.be.empty;
describe('#_addToolbar', function() {
it('is invoked on the click event that follows mousedown multi-select', function() {
expect(map._toolbars).to.be.empty;
// need both bc simulated `mousedown`s don't fire `click` events afterwards like regular user generated `mousedown`s.
chai.simulateEvent(overlay.getElement(), chai.mouseEvents.ShiftMouseDown);
chai.simulateEvent(overlay.getElement(), chai.mouseEvents.Click);
// need both bc simulated `mousedown`s don't fire `click` events afterwards like regular user generated `mousedown`s.
chai.simulateEvent(overlay.getElement(), chai.mouseEvents.ShiftMouseDown);
chai.simulateEvent(overlay.getElement(), chai.mouseEvents.Click);
expect(Object.keys(map._toolbars)).to.have.lengthOf(1);
});
expect(Object.keys(map._toolbars)).to.have.lengthOf(1);
});
it('it adds a control toolbar to the map', function () {
expect(map._toolbars).to.be.empty;
it('it adds a control toolbar to the map', function() {
expect(map._toolbars).to.be.empty;
imgGroup.editing._addToolbar();
imgGroup.editing._addToolbar();
expect(Object.keys(map._toolbars)).to.have.lengthOf(1);
expect(Object.keys(map._toolbars)[0]._container).className = "leaflet-control";
});
expect(Object.keys(map._toolbars)).to.have.lengthOf(1);
expect(Object.keys(map._toolbars)[0]._container).className = 'leaflet-control';
});
it('does not add multiple instances of a control toolbar', function () {
expect(map._toolbars).to.be.empty;
it('does not add multiple instances of a control toolbar', function() {
expect(map._toolbars).to.be.empty;
imgGroup.editing._addToolbar();
imgGroup.editing._addToolbar();
imgGroup.editing._addToolbar();
imgGroup.editing._addToolbar();
expect(Object.keys(map._toolbars)).to.have.lengthOf(1);
});
expect(Object.keys(map._toolbars)).to.have.lengthOf(1);
});
});
describe('#_removeToolbar', function () {
describe('#_removeToolbar', function() {
beforeEach(function() { // multi-select the image and add the toolbar
chai.simulateEvent(overlay.getElement(), chai.mouseEvents.ShiftMouseDown);
imgGroup.editing._addToolbar();
beforeEach(function () { // multi-select the image and add the toolbar
chai.simulateEvent(overlay.getElement(), chai.mouseEvents.ShiftMouseDown);
imgGroup.editing._addToolbar();
expect(Object.keys(map._toolbars)).to.have.lengthOf(1);
});
expect(Object.keys(map._toolbars)).to.have.lengthOf(1);
});
it('is invoked on map click', function () {
map.fire("click");
setTimeout(function () {
expect(map._toolbars).to.be.empty;
}, 3000);
});
it('is invoked on map click', function() {
map.fire('click');
setTimeout(function() {
expect(map._toolbars).to.be.empty;
}, 3000);
});
it('is invoked on command + mousedown when it toggles the image *out* of multi-select', function () {
// deselecting the image removes the control toolbar
chai.simulateEvent(overlay.getElement(), chai.mouseEvents.ShiftMouseDown);
expect(map._toolbars).to.be.empty;
});
it('is invoked on shift + mousedown when it toggles the image *out* of multi-select', function() {
// deselecting the image removes the control toolbar
chai.simulateEvent(overlay.getElement(), chai.mouseEvents.ShiftMouseDown);
expect(map._toolbars).to.be.empty;
});
it('it removes a control toolbar from the map', function () {
imgGroup.editing._removeToolbar();
expect(map._toolbars).to.be.empty;
});
it('it removes a control toolbar from the map', function() {
imgGroup.editing._removeToolbar();
expect(map._toolbars).to.be.empty;
});
it('it returns false if there was no control toolbar to remove', function () {
expect(imgGroup.editing._removeToolbar()).to.not.be.false;
expect(imgGroup.editing._removeToolbar()).to.be.false;
});
it('it returns false if there was no control toolbar to remove', function() {
expect(imgGroup.editing._removeToolbar()).to.not.be.false;
expect(imgGroup.editing._removeToolbar()).to.be.false;
});
});
describe('#_lockGroup', function() {
describe('#_lockGroup', function() {
beforeEach(function() {
chai.simulateEvent(overlay.getElement(), chai.mouseEvents.ShiftMouseDown);
chai.simulateEvent(overlay3.getElement(), chai.mouseEvents.ShiftMouseDown);
beforeEach(function () {
chai.simulateEvent(overlay.getElement(), chai.mouseEvents.ShiftMouseDown);
chai.simulateEvent(overlay3.getElement(), chai.mouseEvents.ShiftMouseDown);
imgGroup.editing._lockGroup();
});
imgGroup.editing._lockGroup();
});
it('it only puts the multi-selected images in lock mode', function () {
expect(overlay.editing._mode).to.equal('lock');
expect(overlay3.editing._mode).to.equal('lock');
it('it only puts the multi-selected images in lock mode', function() {
expect(overlay.editing._mode).to.equal('lock');
expect(overlay3.editing._mode).to.equal('lock');
expect(overlay2.editing._mode).to.not.equal('lock');
});
expect(overlay2.editing._mode).to.not.equal('lock');
});
it('does not toggle lock mode', function () {
imgGroup.editing._lockGroup();
expect(overlay.editing._mode).to.equal('lock');
});
it('does not toggle lock mode', function() {
imgGroup.editing._lockGroup();
expect(overlay.editing._mode).to.equal('lock');
});
it('prevents images in that group from being dragged', function () {
expect(overlay.editing.dragging).to.be.undefined;
expect(overlay3.editing.dragging).to.be.undefined;
it('prevents images in that group from being dragged', function() {
expect(overlay.editing.dragging).to.be.undefined;
expect(overlay3.editing.dragging).to.be.undefined;
expect(overlay2.editing.dragging).to.be.an.instanceOf(L.Draggable);
});
expect(overlay2.editing.dragging).to.be.an.instanceOf(L.Draggable);
});
});
describe('#_unlockGroup', function() {
describe('#_unlockGroup', function() {
beforeEach(function() {
chai.simulateEvent(overlay.getElement(), chai.mouseEvents.ShiftMouseDown);
chai.simulateEvent(overlay2.getElement(), chai.mouseEvents.ShiftMouseDown);
chai.simulateEvent(overlay3.getElement(), chai.mouseEvents.ShiftMouseDown);
beforeEach(function () {
chai.simulateEvent(overlay.getElement(), chai.mouseEvents.ShiftMouseDown);
chai.simulateEvent(overlay2.getElement(), chai.mouseEvents.ShiftMouseDown);
chai.simulateEvent(overlay3.getElement(), chai.mouseEvents.ShiftMouseDown);
imgGroup.editing._lockGroup();
expect(overlay.editing._mode).to.equal('lock');
});
imgGroup.editing._lockGroup();
expect(overlay.editing._mode).to.equal('lock');
});
it('it removes the multi-selected images from lock mode', function() {
imgGroup.editing._unlockGroup();
expect(overlay.editing._mode).to.not.equal('lock');
});
it('it removes the multi-selected images from lock mode', function () {
imgGroup.editing._unlockGroup();
expect(overlay.editing._mode).to.not.equal('lock');
});
it('does not toggle lock mode', function() {
imgGroup.editing._unlockGroup();
imgGroup.editing._unlockGroup();
expect(overlay.editing._mode).to.not.equal('lock');
});
});
it('does not toggle lock mode', function () {
imgGroup.editing._unlockGroup();
imgGroup.editing._unlockGroup();
expect(overlay.editing._mode).to.not.equal('lock');
});
describe('#_removeGroup', function() {
beforeEach(function() { // multi-selects the images to add them to the feature group
chai.simulateEvent(overlay.getElement(), chai.mouseEvents.ShiftMouseDown);
chai.simulateEvent(overlay3.getElement(), chai.mouseEvents.ShiftMouseDown);
});
describe('#_removeGroup', function () {
beforeEach(function() { // multi-selects the images to add them to the feature group
chai.simulateEvent(overlay.getElement(), chai.mouseEvents.ShiftMouseDown);
chai.simulateEvent(overlay3.getElement(), chai.mouseEvents.ShiftMouseDown);
});
it('removes a collection of layers that are multi-selected', function() {
var layers = imgGroup.getLayers();
expect(layers).to.include.members([overlay, overlay2, overlay3]);
it('removes a collection of layers that are multi-selected', function () {
var layers = imgGroup.getLayers();
expect(layers).to.include.members([overlay, overlay2, overlay3]);
imgGroup.editing._removeGroup();
imgGroup.editing._removeGroup();
expect(layers).to.not.have.members([overlay, overlay3]);
expect(layers).to.include.members([overlay2]);
});
expect(layers).to.not.have.members([overlay, overlay3]);
expect(layers).to.include.members([overlay2]);
});
it('removes the layers from the map on removal from group', function () {
var id = imgGroup.getLayerId(overlay),
id2 = imgGroup.getLayerId(overlay2),
id3 = imgGroup.getLayerId(overlay3);
it('removes the layers from the map on removal from group', function() {
var id = imgGroup.getLayerId(overlay);
var id2 = imgGroup.getLayerId(overlay2);
var id3 = imgGroup.getLayerId(overlay3);
expect(map._layers).to.include.all.keys(id, id2, id3);
expect(map._layers).to.include.all.keys(id, id2, id3);
imgGroup.editing._removeGroup();
imgGroup.editing._removeGroup();
expect(map._layers).to.not.have.all.keys(id, id3);
expect(map._layers).to.include.all.keys(id2);
});
expect(map._layers).to.not.have.all.keys(id, id3);
expect(map._layers).to.include.all.keys(id2);
});
});
});
describe('L.DistortableImage.Edit', function() {
var map, overlay;
var map;
var overlay;
beforeEach(function(done) {
map = L.map(L.DomUtil.create('div', '', document.body)).setView(
[41.7896, -87.5996],
15
);
map = L.map(L.DomUtil.create('div', '', document.body)).setView([41.7896, -87.5996], 15);

@@ -15,4 +13,4 @@ overlay = L.distortableImageOverlay('/examples/example.png', {

L.latLng(41.7834, -87.5852),
L.latLng(41.7834, -87.6052)
]
L.latLng(41.7834, -87.6052),
],
}).addTo(map);

@@ -33,5 +31,5 @@

it('Should keep handles on the map in sync with the corners of the image.', function() {
var corners = overlay.getCorners(),
edit = overlay.editing,
img = overlay.getElement();
var corners = overlay.getCorners();
var edit = overlay.editing;
var img = overlay.getElement();

@@ -49,6 +47,6 @@ edit.enable();

edit._toggleRotateScale();
edit._freeRotateMode();
/* After we toggle modes, the rotateScaleHandles are on the map and should be synced. */
edit._rotateScaleHandles.eachLayer(function(handle) {
/* After we toggle modes, the freeRotateHandles are on the map and should be synced. */
edit._freeRotateHandles.eachLayer(function(handle) {
expect(handle.getLatLng()).to.be.closeToLatLng(corners[handle._corner]);

@@ -58,57 +56,118 @@ });

describe('#_deselect', function () {
it('It should hide an unlocked image\'s handles by updating their opacity', function () {
var edit = overlay.editing;
describe('#_deselect', function() {
it('It should hide an unlocked image\'s handles by updating their opacity', function() {
var edit = overlay.editing;
edit.enable();
// then trigger _deselect
map.fire('click');
edit.enable();
// then trigger _deselect
map.fire('click');
var handleState = [];
edit._handles['distort'].eachLayer(function (handle) {
handleState.push(handle._icon.style.opacity)
});
var handleState = [];
edit._handles['distort'].eachLayer(function(handle) {
handleState.push(handle._icon.style.opacity);
});
expect(handleState).to.deep.equal(['0', '0', '0', '0']);
});
expect(handleState).to.deep.equal(['0', '0', '0', '0']);
});
it('But it should not hide a locked image\'s handles', function () {
var edit = overlay.editing;
it('But it should not hide a locked image\'s handles', function() {
var edit = overlay.editing;
edit.enable();
// switch to lock handles
edit._toggleLock();
// then trigger _deselect
map.fire('click');
edit.enable();
// switch to lock handles
edit._toggleLockMode();
// then trigger _deselect
map.fire('click');
var lockHandleState = [];
edit._handles['lock'].eachLayer(function (handle) {
lockHandleState.push(handle._icon.style.opacity)
});
var lockHandleState = [];
edit._handles['lock'].eachLayer(function(handle) {
lockHandleState.push(handle._icon.style.opacity);
});
// opacity for lockHandles is unset because we never altered it to hide it as part of deselection
expect(lockHandleState).to.deep.equal(['', '', '', '']);
});
// opacity for lockHandles is unset because we never altered it to hide it as part of deselection
expect(lockHandleState).to.deep.equal(['', '', '', '']);
});
it('Should remove an image\'s individual toolbar instance regardless of lock handles', function () {
var edit = overlay.editing,
img = overlay.getElement();
it('Should remove an image\'s individual toolbar instance regardless of lock handles', function() {
var edit = overlay.editing;
var img = overlay.getElement();
edit.enable();
// switch to lock handles
edit._toggleLock();
// select the image to initially create its individual toolbar instance
chai.simulateEvent(img, chai.mouseEvents.Click);
edit.enable();
// switch to lock handles
edit._toggleLockMode();
// select the image to initially create its individual toolbar instance
chai.simulateEvent(img, chai.mouseEvents.Click);
expect(edit.toolbar).to.not.be.false
expect(edit.toolbar).to.not.be.false;
// then trigger _deselect
map.fire('click');
// then trigger _deselect
map.fire('click');
// we deselect after 3ms to confirm the click wasn't a dblclick
setTimeout(function() {
expect(edit.toolbar).to.be.false;
}, 3000);
});
});
// we deselect after 3ms to confirm the click wasn't a dblclick
setTimeout(function() {
expect(edit.toolbar).to.be.false;
}, 3000);
});
});
describe('#_nextMode', function () {
beforeEach(function () {
overlay.editing.enable();
});
it('Should update images mode to the "next" (depending on developer) mode on dblclick', function() {
var edit = overlay.editing;
var modes = edit._modes;
edit._mode = 'distort'
var idx = modes.indexOf('distort');
var newIdx = modes.indexOf(edit._nextMode()._mode)
setTimeout(function () {
expect(newIdx).to.equal((idx + 1) % modes.length)
}, 3000);
});
it('Will update to next mode even when current mode is \'lock\'', function() {
var edit = overlay.editing;
var img = overlay.getElement();
edit._lock();
expect(edit._mode).to.equal('lock');
chai.simulateEvent(img, chai.mouseEvents.Dblclick);
expect(edit._mode).to.not.equal('lock');
});
it('It prevents dblclick events from propagating to the map', function() {
var overlaySpy = sinon.spy();
var mapSpy = sinon.spy();
overlay.on('dblclick', overlaySpy);
map.on('dblclick', mapSpy);
overlay.fire('dblclick');
expect(overlay.editing._nextMode).to.have.been.called;
expect(L.DomEvent.stop).to.have.been.called;
expect(overlaySpy.called).to.be.true;
expect(mapSpy.notCalled).to.be.true;
});
it('Will return false when the image is disabled or is multi-selected', function() {
var edit = overlay.editing;
var img = overlay.getElement();
edit.disable();
expect(edit._nextMode()).to.be.false
edit.enable();
chai.simulateEvent(img, chai.mouseEvents.ShiftMouseDown);
setTimeout(function () {
expect(L.DomUtil.getClass(img)).to.include('selected');
expect(edit._nextMode()).to.be.false
}, 3000);
});
});
});

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc