leaflet-distortableimage
Advanced tools
Comparing version 0.7.8 to 0.8.0
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
851521
114
6727
660
6
+ Addedjquery@~> 3.4.0
+ Addedjquery@3.4.1(transitive)