diff --git a/Gruntfile.js b/Gruntfile.js index 9db5aefc0..4a6556d2b 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -78,9 +78,9 @@ module.exports = function(grunt) { { removeViewBox: false }, { removeEmptyAttrs: false }, { removeTitle: true }, // "leaflet-toolbar" lets us specify the title attribute later - { removeAttrs: - { - attrs: ['xmlns', 'fill'] + { + removeAttrs: { + attrs: ['xmlns', 'fill'] } } ] @@ -131,12 +131,14 @@ module.exports = function(grunt) { 'src/edit/RotateScaleHandle.js', 'src/edit/RotateHandle.js', 'src/edit/ScaleHandle.js', - 'src/edit/tools/IconSet.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/DistortableImage.Edit.js', - 'src/edit/DistortableImage.Keymapper.js', + 'src/components/DistortableImage.Keymapper.js', 'src/edit/BoxSelector.js' ], dest: 'dist/leaflet.distortableimage.js' diff --git a/README.md b/README.md index f06c7326e..018a5e4e7 100644 --- a/README.md +++ b/README.md @@ -58,17 +58,16 @@ L.tileLayer('https://{s}.tiles.mapbox.com/v3/anishshah101.ipm9j6em/{z}/{x}/{y}.p }).addTo(map); // create an image -img = L.distortableImageOverlay( - 'example.png', { - // 'corners' is the only required option for this class - // and is in NW, NE, SW, SE order - corners: [ - L.latLng(51.52,-0.14), - L.latLng(51.52,-0.10), - L.latLng(51.50,-0.14), - L.latLng(51.50,-0.10) - ], - }).addTo(map); +img = L.distortableImageOverlay('example.png', { + // 'corners' is the only required option for this class + // and is in NW, NE, SW, SE order + corners: [ + L.latLng(51.52,-0.14), + L.latLng(51.52,-0.10), + L.latLng(51.50,-0.14), + L.latLng(51.50,-0.10) + ], +}).addTo(map); // enable editing L.DomEvent.on(img._image, 'load', img.editing.enable, img.editing); @@ -93,18 +92,15 @@ If you would like to overrwrite the default toolbar actions available for an ind For example, to overrwrite the toolbar to only include the `ToggleTransparency` and `Delete` actions: ``` JS -img = L.distortableImageOverlay( -* 'example.png', { - // 'corners' is the only required option for this class - // and is in NW, NE, SW, SE order - corners: [ - L.latLng(51.52,-0.14), - L.latLng(51.52,-0.10), - L.latLng(51.50,-0.14), - L.latLng(51.50,-0.10) - ], - actions: [ToggleTransparency, Delete] - }).addTo(map); +img = L.distortableImageOverlay('example.png', { + corners: [ + L.latLng(51.52,-0.14), + L.latLng(51.52,-0.10), + L.latLng(51.50,-0.14), + L.latLng(51.50,-0.10) + ], + actions: [ToggleTransparency, Delete] +}).addTo(map); ``` ### Corners @@ -180,13 +176,10 @@ In the below example, the image will be initialiazed with "rotateScale" handles: L.DomEvent.on(img._image, 'load', img.editing.enable, img.editing); ``` -### Keymapper - -`keymapper` (*optional*, default: true, value: *boolean*) +### Full-resolution download -By default, an image loads with a keymapper legend showing the available key bindings for different editing / interaction options. To suppress the keymapper, pass `keymapper: false` as an additional option to the image. +`fullResolutionSrc` (*optional*) -### Full-resolution download We've added a GPU-accelerated means to generate a full resolution version of the distorted image; it requires two additional dependencies to enable; see how we've included them in the demo: @@ -198,20 +191,15 @@ We've added a GPU-accelerated means to generate a full resolution version of the When instantiating a Distortable Image, pass in a `fullResolutionSrc` option set to the url of the higher resolution image. This image will be used in full-res exporting. ```JS -// create basic map setup from above - -// create an image - note the optional -// fullResolutionSrc option is now passed in -img = L.distortableImageOverlay( - 'example.png', { - corners: [ - L.latLng(51.52,-0.14), - L.latLng(51.52,-0.10), - L.latLng(51.50,-0.14), - L.latLng(51.50,-0.10) - ], - fullResolutionSrc: 'large.jpg' - }).addTo(map); +img = L.distortableImageOverlay('example.png', { + corners: [ + L.latLng(51.52,-0.14), + L.latLng(51.52,-0.10), + L.latLng(51.50,-0.14), + L.latLng(51.50,-0.10) + ], + fullResolutionSrc: 'large.jpg' +}).addTo(map); L.DomEvent.on(img._image, 'load', img.editing.enable, img.editing); ``` @@ -239,26 +227,22 @@ The setup is relatively similar - here is an example with two images: ```JS // 1. Instantiate map // 2. Instantiate images but this time *dont* add them directly to the map -img = L.distortableImageOverlay( - 'example.png', { - keymapper: false, - corners: [ - L.latLng(51.52, -0.14), - L.latLng(51.52,-0.10), - L.latLng(51.50, -0.14), - L.latLng(51.50,-0.10) - ], - }); +img = L.distortableImageOverlay('example.png', { + corners: [ + L.latLng(51.52, -0.14), + L.latLng(51.52,-0.10), + L.latLng(51.50, -0.14), + L.latLng(51.50,-0.10) + ], +}); -img2 = L.distortableImageOverlay( - 'example.png', { - keymapper: false, - corners: [ - L.latLng(51.51, -0.20), - L.latLng(51.51,-0.16), - L.latLng(51.49, -0.21), - L.latLng(51.49,-0.17) - ], +img2 = L.distortableImageOverlay('example.png', { + corners: [ + L.latLng(51.51, -0.20), + L.latLng(51.51,-0.16), + L.latLng(51.49, -0.21), + L.latLng(51.49,-0.17) + ], }); // 3. Instantiate an empty `DistortableCollection` group @@ -294,13 +278,15 @@ To add / remove a tool from the toolbar at runtime, we have also added the metho ### UI and functionalities 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. -**How to multi-select:** +**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 cmd + `click` to toggle an individual image's inclusion in this interface. 2. Or shift + `drag` to use our `BoxSelector` handler to select multiple at once. 3. Or for touch devices, `touch` and `hold` (aka `longpress`). **How to un-multi-select:** - - A single toolbar instance (using `L.control`) renders the set of tools available to use on collections of 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 or... - ...Click on the map or hit the esc key to quickly deselect all images. - For the aforementioned 3 mutli-select methods, the `BoxSelector` method is the only one that doesn't also toggle _out_ of multi-select mode. @@ -403,6 +389,26 @@ Defaults: - `hasTool(action)` - Checks if the tool is already present in the currently rendered control toolbar. +## Additional Components + +### Keymapper + + +```JS +// add a position option with combinations of 'top', 'bottom', 'left' or 'right' +L.distortableImage.keymapper(map, { + position: 'topleft' +}); +``` + +Options: + - `position` (*optional*, default: 'topright', value: *string*) + + +Adds a control onto the map which opens a keymapper legend showing the available key bindings for different editing / interaction options. + +(WIP) Currently includes keybindings for all available actions and does not update yet if you use the `actions` API to limit available actions. + ## Contributing This plugin has basic functionality, and is in production as part of MapKnitter, but there are [plenty of outstanding issues to resolve](https://github.com/publiclab/Leaflet.DistortableImage/issues). Please consider helping out! diff --git a/assets/icons/svg-min/crop_rotate.svg b/assets/icons/svg-min/crop_rotate.svg index e0e445f78..d4fd73158 100644 --- a/assets/icons/svg-min/crop_rotate.svg +++ b/assets/icons/svg-min/crop_rotate.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/assets/icons/svg-min/explore.svg b/assets/icons/svg-min/explore.svg index bf8563e8f..d472ffc61 100644 --- a/assets/icons/svg-min/explore.svg +++ b/assets/icons/svg-min/explore.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/assets/icons/svg-min/flip_to_back.svg b/assets/icons/svg-min/flip_to_back.svg index 515b289a9..cea43270e 100644 --- a/assets/icons/svg-min/flip_to_back.svg +++ b/assets/icons/svg-min/flip_to_back.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/assets/icons/svg-min/flip_to_front.svg b/assets/icons/svg-min/flip_to_front.svg index 31ee51b2b..9fba3be5a 100644 --- a/assets/icons/svg-min/flip_to_front.svg +++ b/assets/icons/svg-min/flip_to_front.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/assets/icons/svg-min/keyboard_open.svg b/assets/icons/svg-min/keyboard_open.svg new file mode 100644 index 000000000..829e9d0c2 --- /dev/null +++ b/assets/icons/svg-min/keyboard_open.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/icons/svg-min/lock.svg b/assets/icons/svg-min/lock.svg index ccc151079..4b4fc834b 100644 --- a/assets/icons/svg-min/lock.svg +++ b/assets/icons/svg-min/lock.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/assets/icons/svg-min/opacity.svg b/assets/icons/svg-min/opacity.svg index 0bde93a18..04a6fb124 100644 --- a/assets/icons/svg-min/opacity.svg +++ b/assets/icons/svg-min/opacity.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/assets/icons/svg-min/opacity_empty.svg b/assets/icons/svg-min/opacity_empty.svg index 3369c1235..ea567b6ae 100644 --- a/assets/icons/svg-min/opacity_empty.svg +++ b/assets/icons/svg-min/opacity_empty.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/assets/icons/svg-min/restore.svg b/assets/icons/svg-min/restore.svg index a4a37eebc..3ce2ff8f2 100644 --- a/assets/icons/svg-min/restore.svg +++ b/assets/icons/svg-min/restore.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/assets/icons/svg-min/unlock.svg b/assets/icons/svg-min/unlock.svg index 50e7afa2e..2d65dade9 100644 --- a/assets/icons/svg-min/unlock.svg +++ b/assets/icons/svg-min/unlock.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/assets/icons/svg/keyboard_open.svg b/assets/icons/svg/keyboard_open.svg new file mode 100644 index 000000000..39cb4d047 --- /dev/null +++ b/assets/icons/svg/keyboard_open.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/icons/symbol/sprite.symbol.html b/assets/icons/symbol/sprite.symbol.html deleted file mode 100644 index d34851273..000000000 --- a/assets/icons/symbol/sprite.symbol.html +++ /dev/null @@ -1,441 +0,0 @@ - - - - - - - - SVG <symbol> sprite preview | svg-sprite - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-

SVG <symbol> sprite preview

-

This preview features two methods of using the generated sprite in conjunction with inline SVG. Please have a look at the HTML source for further details and be aware of the following constraints:

- -
-
- - - -

A) Inline SVG with embedded sprite

- - - - -
-
- - - -

B) Inline SVG with external sprite (IE 9-11 with polyfill only)

- - - - -
- - - diff --git a/assets/icons/symbol/sprite.symbol.svg b/assets/icons/symbol/sprite.symbol.svg index 7d7d00353..e0495dc62 100644 --- a/assets/icons/symbol/sprite.symbol.svg +++ b/assets/icons/symbol/sprite.symbol.svg @@ -1 +1 @@ - \ No newline at end of file + diff --git a/dist/leaflet.distortableimage.css b/dist/leaflet.distortableimage.css index 70f46b342..25ca1b0f7 100644 --- a/dist/leaflet.distortableimage.css +++ b/dist/leaflet.distortableimage.css @@ -1,3 +1,11 @@ +.ldi .leaflet-pane .leaflet-overlay-pane img { + pointer-events: all !important; +} + +.ldi img.leaflet-image-layer.selected { + box-shadow: 0px 0px 0px 12px #ffea00; +} + .ldi-icon { width: 18px; height: 18px; @@ -13,15 +21,15 @@ fill: #058dc4; } +.ldi-icon.ldi-keyboard_open { + fill: black; +} + input.ldi { position:absolute; top:-100px; } -.ldi .leaflet-pane .leaflet-overlay-pane img { - pointer-events: all !important; -} - .ldi .leaflet-toolbar-icon { box-sizing: initial; } @@ -30,42 +38,65 @@ input.ldi { box-sizing: border-box; } -.ldi img.leaflet-image-layer.selected { - box-shadow: 0px 0px 0px 12px #ffea00; -} - .ldi-keymapper { - background-color: rgb(255, 255, 255, 0.75); + background-color: rgb(255, 255, 255, 1); color: black; - padding: 0px 10px 6px 10px; - font-size: 14px; - font-weight: 400; - letter-spacing: 0.5px; - line-height: 1.2; + padding: 8px; + font-size: 13px; + letter-spacing: 0.2px; + line-height: 1.3; + height: auto; + width: 235px; + border-radius: 21px; + overflow: hidden; +} + +.ldi #keymapper-wrapper { + position: relative; + width: 100%; + overflow-x: hidden; + overflow-y: auto; + max-height: 186px; + min-height: 186px; +} + +.ldi .left { + width: 46%; +} + +.ldi .left span { + overflow-wrap: break-word; +} + +.ldi .right { + display: flex; + max-width: 40%; + flex-wrap: wrap; + margin-left: 20px; + align-items: flex-start; } -.ldi-keymapper table th { - font-size: 16px; - padding-top: 8px; +.ldi #keymapper-hr { + transform: rotate(90deg); + position: relative; + transform-origin: 0px; + left: 50%; + margin: -2px; + width: 200%; } -.ldi-keymapper th { - vertical-align: bottom; - border-bottom: 2px solid rgba(0, 0, 0, 0.06); - padding: 0.75rem; - vertical-align: top; - border-top: 1px solid rgba(0, 0, 0, 0.06); +.ldi-keymapper tr { + display: block; } .ldi-keymapper td { - padding: 0.3rem; - vertical-align: top; + padding: 0.2rem; + display: flex; + width: 100%; } .ldi-keymapper kbd { - font-weight: 500; padding: 0.2rem 0.4rem; - font-size: 95%; color: black; background-color: rgb(247, 247, 247); border-radius: 3px; @@ -76,3 +107,47 @@ input.ldi { box-shadow: 0 1px 1px rgba(0, 0, 0, .2), 0 2px 0 0 rgba(255, 255, 255, .7) inset; text-shadow: 0 0.5px 0 #fff; } + +#toggle-keymapper { + background-color: #fff; + padding: 0px; + width: 30px; + height: 30px; + border-radius: 4px; + right: 16px; + cursor: pointer; + background-position: 50% 50%; + background-repeat: no-repeat; + display: block; + text-align: center; + text-decoration: none; + border: 2px solid rgba(184, 178, 173, 0.9); + line-height: 30px; +} + +#toggle-keymapper:hover { + background-color: #f4f4f4; +} + +.close-icon#toggle-keymapper { + text-transform: uppercase; + width: 254px; + font-size: 11px; + border: 1px solid lightgray; + margin: 0; + padding: 0; + background-color: whitesmoke; + border-radius: 0; + border-bottom-left-radius: 21px; + border-bottom-right-radius: 21px; + position: relative; + height: 21px; + line-height: 22px; + color: gray; + top: 10px; + left: -10px +} + +.close-icon#toggle-keymapper:hover { + background-color: #efefef; +} diff --git a/dist/leaflet.distortableimage.js b/dist/leaflet.distortableimage.js index b9f23d61d..101acb6e5 100644 --- a/dist/leaflet.distortableimage.js +++ b/dist/leaflet.distortableimage.js @@ -51,6 +51,43 @@ L.DomUtil = L.extend(L.DomUtil, { }); +L.IconUtil = { + /** creates an svg elemenet with built in accessibility properties and standardized + * classes for styling, takes in the fragment identifier (id) of the symbol to reference. + * note for symplicity we allow providing the icon target with or without the '#' prefix */ + create: function(ref) { + if (/^#/.test(ref)) { + ref = ref.replace(/^#/, ''); + } + + return ( + '' + + '' + + '' + ); + }, + + /** finds the use element and toggles its icon reference */ + toggleXlink: function(container, ref1, ref2) { + if (!/^#/.test(ref1)) { ref1 = '#' + ref1; } + if (!/^#/.test(ref2)) { ref2 = '#' + ref2; } + + var use = container.querySelector('use'); + if (use) { + var toggled = use.getAttribute('xlink:href') === ref1 ? ref2 : ref1; + use.setAttribute('xlink:href', toggled); + return toggled; + } + return false; + }, + + toggleTooltip: function(container, title1, title2) { + var toggled = container.getAttribute('title') === title1 ? title2 : title1; + container.setAttribute('title', toggled); + return toggled; + } +}; + L.ImageUtil = { getCmPerPixel: function(overlay) { @@ -175,6 +212,113 @@ L.TrigUtil = { } }; +/** this is the baseclass other IconSets inherit from, we don't use it directly */ +L.IconSet = L.Class.extend({ + + _svg: '', + + _symbols: '', + + render: function() { + this.addSymbols(this._symbols); + return this._svg; + }, + + addSymbols: function(symbols) { + this._svg += symbols; + } + +}); + +L.ToolbarIconSet = L.IconSet.extend({ + + _symbols: + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + +}); + +L.KeymapperIconSet = L.IconSet.extend({ + + _symbols: + '', + +}); + +L.EditAction = L.Toolbar2.Action.extend({ + + options: { + toolbarIcon: { + svg: false, + html: '', + className: '', + tooltip: '' + }, + }, + + initialize: function(map, overlay, options) { + this._overlay = overlay; + this._map = map; + + L.setOptions(this, options); + L.Toolbar2.Action.prototype.initialize.call(this, options); + + this._injectIconSet(); + }, + + _createIcon: function(toolbar, container, args) { + var iconOptions = this.options.toolbarIcon; + + this.toolbar = toolbar; + this._icon = L.DomUtil.create('li', '', container); + this._link = L.DomUtil.create('a', '', this._icon); + + if (iconOptions.svg) { + this._link.innerHTML = L.IconUtil.create(iconOptions.html); + } else { + this._link.innerHTML = iconOptions.html; + } + + this._link.setAttribute('href', '#'); + this._link.setAttribute('title', iconOptions.tooltip); + this._link.setAttribute('role', 'button'); + + L.DomUtil.addClass(this._link, this.constructor.baseClass); + if (iconOptions.className) { + L.DomUtil.addClass(this._link, iconOptions.className); + } + + L.DomEvent.on(this._link, 'click', this.enable, this); + + /* Add secondary toolbar */ + this._addSubToolbar(toolbar, this._icon, args); + }, + + _injectIconSet: function() { + if (document.querySelector('#iconset')) { return; } + + var el = document.createElement('div'); + el.id = 'iconset'; + el.setAttribute('hidden', 'hidden'); + el.innerHTML = new L.ToolbarIconSet().render(); + + document.querySelector('.leaflet-marker-pane').appendChild(el); + } +}); + + L.DistortableImageOverlay = L.ImageOverlay.extend({ options: { @@ -1029,7 +1173,7 @@ L.EditHandle = L.Marker.extend({ zIndexOffset: 10 }; - if (options && options.hasOwnProperty("draggable")) { + if (options && options.hasOwnProperty('draggable')) { markerOptions.draggable = options.draggable; } @@ -1049,7 +1193,7 @@ L.EditHandle = L.Marker.extend({ }, _onHandleDragStart: function() { - this._handled.fire("editstart"); + this._handled.fire('editstart'); }, _onHandleDragEnd: function() { @@ -1058,7 +1202,7 @@ L.EditHandle = L.Marker.extend({ _fireEdit: function() { this._handled.edited = true; - this._handled.fire("edit"); + this._handled.fire('edit'); }, _bindListeners: function() { @@ -1071,9 +1215,9 @@ L.EditHandle = L.Marker.extend({ this ); - this._handled._map.on("zoomend", this.updateHandle, this); + this._handled._map.on('zoomend', this.updateHandle, this); - this._handled.on("update", this.updateHandle, this); + this._handled.on('update', this.updateHandle, this); }, _unbindListeners: function() { @@ -1086,8 +1230,8 @@ L.EditHandle = L.Marker.extend({ this ); - this._handled._map.off("zoomend", this.updateHandle, this); - this._handled.off("update", this.updateHandle, this); + this._handled._map.off('zoomend', this.updateHandle, this); + this._handled.off('update', this.updateHandle, this); }, /* Takes two latlngs and calculates the scaling difference. */ @@ -1276,122 +1420,6 @@ L.ScaleHandle = L.EditHandle.extend({ }, }); -L.IconSet = L.Class.extend({ - - _svg: '', - - render: function() { - this.addSymbols(); - return this._svg; - }, - - addSymbols: function() { - this._svg += - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' - ; - } -}); - -L.EditAction = L.Toolbar2.Action.extend({ - - options: { - toolbarIcon: { - svg: false, - html: '', - className: '', - tooltip: '' - }, - }, - - initialize: function(map, overlay, options) { - this._overlay = overlay; - this._map = map; - - L.setOptions(this, options); - L.Toolbar2.Action.prototype.initialize.call(this, options); - - this._injectIconSet(); - }, - - toggleXlink: function(ref1, ref2) { - var href1 = "#" + ref1, - href2 = "#" + ref2; - - if (this._link.querySelector('use')) { - var xlink = this._link.querySelector('use:nth-child(1)'); - var newXlink = xlink.getAttribute('xlink:href') === href1 ? href2 : href1; - xlink.setAttribute('xlink:href', newXlink); - return newXlink; - } - return false; - }, - - toggleTooltip: function(title1, title2) { - var newTt = this._link.getAttribute('title') === title1 ? title2 : title1; - this._link.setAttribute('title', newTt); - return newTt; - }, - - _createIcon: function(toolbar, container, args) { - var iconOptions = this.options.toolbarIcon; - - this.toolbar = toolbar; - this._icon = L.DomUtil.create('li', '', container); - this._link = L.DomUtil.create('a', '', this._icon); - - if (iconOptions.svg) { - this._link.innerHTML = this._svgIconHelper(iconOptions.html); - } else { - this._link.innerHTML = iconOptions.html; - } - - this._link.setAttribute('href', '#'); - this._link.setAttribute('title', iconOptions.tooltip); - - L.DomUtil.addClass(this._link, this.constructor.baseClass); - if (iconOptions.className) { - L.DomUtil.addClass(this._link, iconOptions.className); - } - - L.DomEvent.on(this._link, 'click', this.enable, this); - - /* Add secondary toolbar */ - this._addSubToolbar(toolbar, this._icon, args); - }, - - _svgIconHelper: function(ref) { - return ( - '' + - '' + - '' - ); - }, - - _injectIconSet: function() { - if (document.querySelector('#iconset')) { return; } - - var el = document.createElement('div'); - el.id = 'iconset'; - el.setAttribute('hidden', 'hidden'); - el.innerHTML = new L.IconSet().render(); - - document.querySelector('.leaflet-marker-pane').appendChild(el); - } -}); - L.DistortableImage = L.DistortableImage || {}; L.distortableImage = L.DistortableImage; @@ -1421,8 +1449,8 @@ var ToggleTransparency = L.EditAction.extend({ addHooks: function() { var editing = this._overlay.editing; - this.toggleXlink('opacity_empty', 'opacity'); - this.toggleTooltip('Make Image Opaque', 'Make Image Transparent'); + L.IconUtil.toggleXlink(this._link, 'opacity_empty', 'opacity'); + L.IconUtil.toggleTooltip(this._link, 'Make Image Opaque', 'Make Image Transparent'); editing._toggleTransparency(); } }); @@ -1453,8 +1481,8 @@ var ToggleOutline = L.EditAction.extend({ addHooks: function() { var editing = this._overlay.editing; - this.toggleXlink('border_clear', 'border_outer'); - this.toggleTooltip('Remove Border', 'Add Border'); + L.IconUtil.toggleXlink(this._link, 'border_clear', 'border_outer'); + L.IconUtil.toggleTooltip(this._link, 'Remove Border', 'Add Border'); editing._toggleOutline(); } }); @@ -1506,8 +1534,8 @@ var ToggleLock = L.EditAction.extend({ addHooks: function() { var editing = this._overlay.editing; - this.toggleXlink('unlock', 'lock'); - this.toggleTooltip('Unlock', 'Lock'); + L.IconUtil.toggleXlink(this._link, 'unlock', 'lock'); + L.IconUtil.toggleTooltip(this._link, 'Unlock', 'Lock'); editing._toggleLock(); } }); @@ -1538,8 +1566,8 @@ var ToggleRotateScale = L.EditAction.extend({ addHooks: function() { var editing = this._overlay.editing; - this.toggleXlink('transform', 'crop_rotate'); - this.toggleTooltip('Distort', 'Rotate+Scale'); + L.IconUtil.toggleXlink(this._link, 'transform', 'crop_rotate'); + L.IconUtil.toggleTooltip(this._link, 'Distort', 'Rotate+Scale'); editing._toggleRotateScale(); } }); @@ -1591,8 +1619,8 @@ var ToggleOrder = L.EditAction.extend({ addHooks: function() { var editing = this._overlay.editing; - this.toggleXlink('flip_to_front', 'flip_to_back'); - this.toggleTooltip('Stack to Front', 'Stack to Back'); + L.IconUtil.toggleXlink(this._link, 'flip_to_front', 'flip_to_back'); + L.IconUtil.toggleTooltip(this._link, 'Stack to Front', 'Stack to Back'); editing._toggleOrder(); } }); @@ -1855,24 +1883,13 @@ L.DistortableImage.Edit = L.Handler.extend({ this._transparent = false; this._outlined = false; - /* generate instance counts. TODO - add the keymapper to collection instead of individ. imgs perhaps? */ - this.instance_count = L.DistortableImage.Edit.prototype.instances = - L.DistortableImage.Edit.prototype.instances ? L.DistortableImage.Edit.prototype.instances + 1 : 1; - L.setOptions(this, options); }, /* Run on image selection. */ addHooks: function() { var overlay = this._overlay, - map = overlay._map, - keymapper_position; - - /* instantiate and render keymapper for one instance only */ - if (this.instance_count === 1 && overlay.options.keymapper !== false) { - keymapper_position = overlay.options.keymapper_position || 'topright'; - map.addControl(new L.DistortableImage.Keymapper({ position: keymapper_position })); - } + map = overlay._map; /* bring the selected image into view */ overlay.bringToFront(); @@ -2474,38 +2491,162 @@ L.DistortableImage.Edit = L.Handler.extend({ L.DomUtil = L.DomUtil || {}; L.DistortableImage = L.DistortableImage || {}; +L.distortableImage = L.DistortableImage; + +L.DistortableImage.Keymapper = L.Handler.extend({ + + options: { + position: 'topright' + }, + + initialize: function (map, options) { + this._map = map; + L.setOptions(this, options); + }, -L.DistortableImage.Keymapper = L.Control.extend({ - initialize: function(options) { - L.Control.prototype.initialize.call(this, options); - }, - - onAdd: function() { - var el_wrapper = L.DomUtil.create("div", "ldi-keymapper"); - el_wrapper.innerHTML = - "" + - "" + - "" + - "" + - "" + - "" + - "" + - "" + - "" + - "" + - "" + - "" + - "
Keymappings
t: Transparency
o: Outline
l: Lock
caps: Rotate
s: Scale
d: Distort
r: Rotate+Scale
j, k: Stack up / down
esc: Deselect All
delete , backspace: Delete
"; - return el_wrapper; + addHooks: function () { + if (!this._keymapper) { + this._toggler = this._toggleButton(); + this._scrollWrapper = this._wrap(); + this._setMapper(this._toggler, this._scrollWrapper); + + L.DomEvent.on(this._toggler, 'click', this._toggleKeymapper, this); + + L.DomEvent.on(this._scrollWrapper, { + click: L.DomEvent.stop, + mouseenter: this._disableMap, + mouseleave: this._enableMap, + }, this); } -}); + }, + + removeHooks: function () { + if (this._keymapper) { + L.DomEvent.off(this._toggler, 'click', this._toggleKeymapper, this); + + L.DomEvent.off(this._scrollWrapper, { + click: L.DomEvent.stop, + mouseenter: this._disableMap, + mouseleave: this._enableMap, + }, this); + + L.DomUtil.remove(this._toggler); + L.DomUtil.remove(this._scrollWrapper); + L.DomUtil.remove(this._keymapper._container); + this._keymapper = false; + } + }, + + _toggleButton: function () { + var toggler = L.DomUtil.create('a', ''); + toggler.setAttribute('id', 'toggle-keymapper'); + toggler.setAttribute('href', '#'); + toggler.setAttribute('role', 'button'); + toggler.setAttribute('title', 'Show Keybindings'); + toggler.innerHTML = L.IconUtil.create("keyboard_open"); + + return toggler; + }, + + _wrap: function () { + var wrap = L.DomUtil.create('div', ''); + wrap.setAttribute('id', 'keymapper-wrapper'); + wrap.style.display = 'none'; + + return wrap; + }, + + _setMapper: function (button, wrap) { + this._keymapper = L.control({ position: this.options.position }); + + this._container = this._keymapper.onAdd = function () { + var el_wrapper = L.DomUtil.create('div', 'ldi-keymapper-hide'); + el_wrapper.setAttribute('id', 'ldi-keymapper'); + var divider = L.DomUtil.create('br', 'divider'); + el_wrapper.appendChild(divider); + el_wrapper.appendChild(wrap); + wrap.insertAdjacentHTML( + 'beforeend', + '' + + '
' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '
Stack up / down
j\xa0k
Lock Image
l
Outline
o
Scale
s
Transparency
t
RotateScale
d\xa0r
Deselect All
esc
Delete Image
delete\xa0backspace
Rotate
caps
' + ); + el_wrapper.appendChild(button); + return el_wrapper; + }; + + this._keymapper.addTo(this._map); + }, + + _toggleKeymapper: function (e) { + L.DomEvent.stop(e); + var container = document.getElementById('ldi-keymapper'); + var keymapWrap = document.getElementById('keymapper-wrapper'); + + var newClass = container.className === 'ldi-keymapper leaflet-control' ? 'ldi-keymapper-hide leaflet-control' : 'ldi-keymapper leaflet-control'; + var newStyle = keymapWrap.style.display === 'none' ? 'block' : 'none'; + + container.className = newClass; + keymapWrap.style.display = newStyle; + + L.IconUtil.toggleTooltip(this._toggler, 'Show Keybindings', 'Hide Keybindings'); + this._toggler.innerHTML = this._toggler.innerHTML === 'close' ? L.IconUtil.create('keyboard_open') : 'close'; + L.DomUtil.toggleClass(this._toggler, 'close-icon'); + }, + + _disableMap: function() { + this._map.scrollWheelZoom.disable(); + this._map.dragging.disable(); + }, + + _enableMap: function() { + this._map.scrollWheelZoom.enable(); + this._map.dragging.enable(); + }, + + _injectIconSet: function() { + if (document.querySelector('#keymapper-iconset')) { return; } + + var el = document.createElement('div'); + el.id = 'keymapper-iconset'; + el.setAttribute('hidden', 'hidden'); + + this._iconset = new L.KeymapperIconSet().render(); + el.innerHTML = this._iconset; + + document.querySelector('.leaflet-control-container').appendChild(el); + } +}); + +L.DistortableImage.Keymapper.addInitHook(function() { + L.DistortableImage.Keymapper.prototype._n = + L.DistortableImage.Keymapper.prototype._n ? L.DistortableImage.Keymapper.prototype._n + 1 : 1; + + if (L.DistortableImage.Keymapper.prototype._n === 1) { + this.enable(); + this._injectIconSet(); + } +}); + +L.distortableImage.keymapper = function (map, options) { + return new L.DistortableImage.Keymapper(map, options); +}; + L.Map.mergeOptions({ boxSelector: true, boxZoom: false }); /** * primarily Leaflet 1.5.1 source code. Overriden so that its a selection box with our `L.DistortableCollection` class * instead of a zoom box. * */ - L.Map.BoxSelector = L.Map.BoxZoom.extend({ initialize: function(map) { this._map = map; diff --git a/examples/index.html b/examples/index.html index 1a450f958..a623b0016 100644 --- a/examples/index.html +++ b/examples/index.html @@ -33,7 +33,7 @@ var map; (function() { - // basic Leaflet map setup + map = L.map("map").setView([51.505, -0.09], 13); L.tileLayer( "https://{s}.tiles.mapbox.com/v3/anishshah101.ipm9j6em/{z}/{x}/{y}.png", @@ -47,10 +47,10 @@ }).addTo(map); // create an image - img = L.distortableImageOverlay("example.jpg", { - // add a keymapper_position field with combinations of 'top', 'bottom', 'left' or 'right' + img = L.distortableImageOverlay("example.png", { + // (WIP) add a toolbarType field with values 'popup' (default) or 'control' + // add a suppressToolbar: 'true' here to disable toolbars // mode: "distort", => default handle - keymapper: false, selected: true, corners: [ L.latLng(51.52, -0.14), @@ -61,6 +61,9 @@ fullResolutionSrc: "large.jpg" }).addTo(map); + // add a position option with combinations of 'top', 'bottom', 'left' or 'right' + kmpr1 = L.distortableImage.keymapper(map, { position: 'topleft' }); + L.DomEvent.on(img._image, "load", img.editing.enable, img.editing); })(); diff --git a/examples/listeners.html b/examples/listeners.html index f2f74b022..152688855 100644 --- a/examples/listeners.html +++ b/examples/listeners.html @@ -46,7 +46,6 @@ // create an image img = L.distortableImageOverlay( 'example.png', { - keymapper: false, corners: [ L.latLng(51.52,-0.10), L.latLng(51.52,-0.14), diff --git a/examples/select.html b/examples/select.html index 0b5cb44a1..40ae3a76d 100644 --- a/examples/select.html +++ b/examples/select.html @@ -49,7 +49,6 @@ map.whenReady(function() { img = L.distortableImageOverlay( 'example.jpg', { - keymapper: false, corners: [ L.latLng(51.52, -0.14), L.latLng(51.52,-0.10), @@ -62,7 +61,6 @@ // create a second image img2 = L.distortableImageOverlay( 'example.jpg', { - keymapper: false, corners: [ L.latLng(51.51, -0.20), L.latLng(51.51,-0.16), @@ -74,7 +72,6 @@ img3 = L.distortableImageOverlay( 'example.jpg', { - keymapper: false, corners: [ L.latLng(51.50, -0.13), L.latLng(51.50,-0.09), @@ -86,7 +83,6 @@ img4 = L.distortableImageOverlay( 'example.jpg', { actions: [Export, Delete, ToggleTransparency], - keymapper: false, corners: [ L.latLng(51.51, -0.07), L.latLng(51.51,-0.03), diff --git a/package-lock.json b/package-lock.json index a1f0c273d..0b89bd05f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "leaflet-distortableimage", - "version": "0.6.6", + "version": "0.6.7", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -68,9 +68,9 @@ "dev": true }, "ajv": { - "version": "6.10.1", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.1.tgz", - "integrity": "sha512-w1YQaVGNC6t2UCPjEawK/vo/dG8OOrVtUmhBT1uJJYxbl5kU2Tj3v6LGqBcsysN1yhuCStJCCA3GqdvKY8sqXQ==", + "version": "6.10.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz", + "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==", "dev": true, "requires": { "fast-deep-equal": "^2.0.1", @@ -108,24 +108,13 @@ } }, "anymatch": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", - "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.0.3.tgz", + "integrity": "sha512-c6IvoeBECQlMVuYUjSwimnhmztImpErfxJzWZhIQinIvQWoGOnB0dLIgifbPHQt5heS6mNlaZG16f06H3C8t1g==", "dev": true, "requires": { - "micromatch": "^3.1.4", - "normalize-path": "^2.1.1" - }, - "dependencies": { - "normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true, - "requires": { - "remove-trailing-separator": "^1.0.1" - } - } + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" } }, "argparse": { @@ -225,12 +214,6 @@ "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", "dev": true }, - "async-each": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", - "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==", - "dev": true - }, "async-limiter": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", @@ -353,9 +336,9 @@ } }, "binary-extensions": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", - "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.0.0.tgz", + "integrity": "sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow==", "dev": true }, "blob": { @@ -579,25 +562,39 @@ "dev": true }, "chokidar": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.6.tgz", - "integrity": "sha512-V2jUo67OKkc6ySiRpJrjlpJKl9kDuG+Xb8VgsGzb+aEouhgS1D0weyPU4lEzdAcsCAvrih2J2BqyXqHWvVLw5g==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.0.2.tgz", + "integrity": "sha512-c4PR2egjNjI1um6bamCQ6bUNPDiyofNQruHvKgHQ4gDUP/ITSVSzNsiI5OWtHOsX323i5ha/kk4YmOZ1Ktg7KA==", "dev": true, "requires": { - "anymatch": "^2.0.0", - "async-each": "^1.0.1", - "braces": "^2.3.2", - "fsevents": "^1.2.7", - "glob-parent": "^3.1.0", - "inherits": "^2.0.3", - "is-binary-path": "^1.0.0", - "is-glob": "^4.0.0", + "anymatch": "^3.0.1", + "braces": "^3.0.2", + "fsevents": "^2.0.6", + "glob-parent": "^5.0.0", + "is-binary-path": "^2.1.0", + "is-glob": "^4.0.1", "normalize-path": "^3.0.0", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.2.1", - "upath": "^1.1.1" + "readdirp": "^3.1.1" }, "dependencies": { + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, "is-glob": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", @@ -606,6 +603,21 @@ "requires": { "is-extglob": "^2.1.1" } + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } } } }, @@ -961,9 +973,9 @@ "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=" }, "core-js": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.9.tgz", - "integrity": "sha512-HOpZf6eXmnl7la+cUdMnLvUxKNqLUzJvgIziQ0DiF3JwSImNphIqdGqzj6hIKyX04MmV0poclQ7+wjWvxQyR2A==", + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.1.4.tgz", + "integrity": "sha512-YNZN8lt82XIMLnLirj9MhKDFZHalwzzrL9YLt6eb0T5D0EDl4IQ90IGkua8mHbnxNrkj1d8hbdizMc0Qmg1WnQ==", "dev": true }, "core-util-is": { @@ -1022,21 +1034,15 @@ "dev": true }, "css-tree": { - "version": "1.0.0-alpha.28", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.28.tgz", - "integrity": "sha512-joNNW1gCp3qFFzj4St6zk+Wh/NBv0vM5YbEreZk0SD4S23S+1xBKb6cLDg2uj4P4k/GUMlIm6cKIDqIG+vdt0w==", + "version": "1.0.0-alpha.33", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.33.tgz", + "integrity": "sha512-SPt57bh5nQnpsTBsx/IXbO14sRc9xXu5MtMAVuo0BaQQmyf0NupNPPSoMaqiAF5tDFafYsTkfeH4Q/HCKXkg4w==", "dev": true, "requires": { - "mdn-data": "~1.1.0", + "mdn-data": "2.0.4", "source-map": "^0.5.3" } }, - "css-url-regex": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/css-url-regex/-/css-url-regex-1.1.0.tgz", - "integrity": "sha1-g4NCMMyfdMRX3lnuvRVD/uuDt+w=", - "dev": true - }, "css-what": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.3.tgz", @@ -1067,6 +1073,12 @@ "mdn-data": "~1.1.0", "source-map": "^0.5.3" } + }, + "mdn-data": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-1.1.4.tgz", + "integrity": "sha512-FSYbp3lyKjyj3E7fMl6rYvUdX0FBXaluGqlFoYESWQlyUTq8R+wp0rkFxoYFqZlHCvsUXGjyJmLQSnXToYhOSA==", + "dev": true } } }, @@ -1101,9 +1113,9 @@ } }, "date-format": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/date-format/-/date-format-2.0.0.tgz", - "integrity": "sha512-M6UqVvZVgFYqZL1SfHsRGIQSz3ZL+qgbsV5Lp1Vj61LZVYuEwcMXYay7DRDtYs2HQQBK5hQtQ0fD9aEJ89V0LA==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-2.1.0.tgz", + "integrity": "sha512-bYQuGLeFxhkxNOF3rcMtiZxvCBAquGzZm6oWA1oZ0g2THUzivaRhv8uOhdr19LmoobSOLoIAxeUK2RdbM8IFTA==", "dev": true }, "date-now": { @@ -1953,552 +1965,11 @@ "dev": true }, "fsevents": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.9.tgz", - "integrity": "sha512-oeyj2H3EjjonWcFjD5NvZNE9Rqe4UW+nQBU2HNeKw0koVLEFIhtyETyAakeAM3de7Z/SW5kcA+fZUait9EApnw==", + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.0.7.tgz", + "integrity": "sha512-a7YT0SV3RB+DjYcppwVDLtn13UQnmg0SWZS7ezZD0UjnLwXmy8Zm21GMVGLaFGimIqcvyMQaOJBrop8MyOp1kQ==", "dev": true, - "optional": true, - "requires": { - "nan": "^2.12.1", - "node-pre-gyp": "^0.12.0" - }, - "dependencies": { - "abbrev": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "ansi-regex": { - "version": "2.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "aproba": { - "version": "1.2.0", - "bundled": true, - "dev": true, - "optional": true - }, - "are-we-there-yet": { - "version": "1.1.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.6" - } - }, - "balanced-match": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "brace-expansion": { - "version": "1.1.11", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "chownr": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "code-point-at": { - "version": "1.1.0", - "bundled": true, - "dev": true, - "optional": true - }, - "concat-map": { - "version": "0.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "console-control-strings": { - "version": "1.1.0", - "bundled": true, - "dev": true, - "optional": true - }, - "core-util-is": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "debug": { - "version": "4.1.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ms": "^2.1.1" - } - }, - "deep-extend": { - "version": "0.6.0", - "bundled": true, - "dev": true, - "optional": true - }, - "delegates": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "detect-libc": { - "version": "1.0.3", - "bundled": true, - "dev": true, - "optional": true - }, - "fs-minipass": { - "version": "1.2.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minipass": "^2.2.1" - } - }, - "fs.realpath": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "gauge": { - "version": "2.7.4", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "aproba": "^1.0.3", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", - "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" - } - }, - "glob": { - "version": "7.1.3", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "has-unicode": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "iconv-lite": { - "version": "0.4.24", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "ignore-walk": { - "version": "3.0.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minimatch": "^3.0.4" - } - }, - "inflight": { - "version": "1.0.6", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.3", - "bundled": true, - "dev": true, - "optional": true - }, - "ini": { - "version": "1.3.5", - "bundled": true, - "dev": true, - "optional": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "isarray": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "minimatch": { - "version": "3.0.4", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "0.0.8", - "bundled": true, - "dev": true, - "optional": true - }, - "minipass": { - "version": "2.3.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safe-buffer": "^5.1.2", - "yallist": "^3.0.0" - } - }, - "minizlib": { - "version": "1.2.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minipass": "^2.2.1" - } - }, - "mkdirp": { - "version": "0.5.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minimist": "0.0.8" - } - }, - "ms": { - "version": "2.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "needle": { - "version": "2.3.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "debug": "^4.1.0", - "iconv-lite": "^0.4.4", - "sax": "^1.2.4" - } - }, - "node-pre-gyp": { - "version": "0.12.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "detect-libc": "^1.0.2", - "mkdirp": "^0.5.1", - "needle": "^2.2.1", - "nopt": "^4.0.1", - "npm-packlist": "^1.1.6", - "npmlog": "^4.0.2", - "rc": "^1.2.7", - "rimraf": "^2.6.1", - "semver": "^5.3.0", - "tar": "^4" - } - }, - "nopt": { - "version": "4.0.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "abbrev": "1", - "osenv": "^0.1.4" - } - }, - "npm-bundled": { - "version": "1.0.6", - "bundled": true, - "dev": true, - "optional": true - }, - "npm-packlist": { - "version": "1.4.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ignore-walk": "^3.0.1", - "npm-bundled": "^1.0.1" - } - }, - "npmlog": { - "version": "4.1.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" - } - }, - "number-is-nan": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "object-assign": { - "version": "4.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "once": { - "version": "1.4.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "wrappy": "1" - } - }, - "os-homedir": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "os-tmpdir": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "osenv": { - "version": "0.1.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" - } - }, - "path-is-absolute": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "process-nextick-args": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "rc": { - "version": "1.2.8", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "bundled": true, - "dev": true, - "optional": true - } - } - }, - "readable-stream": { - "version": "2.3.6", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "rimraf": { - "version": "2.6.3", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "glob": "^7.1.3" - } - }, - "safe-buffer": { - "version": "5.1.2", - "bundled": true, - "dev": true, - "optional": true - }, - "safer-buffer": { - "version": "2.1.2", - "bundled": true, - "dev": true, - "optional": true - }, - "sax": { - "version": "1.2.4", - "bundled": true, - "dev": true, - "optional": true - }, - "semver": { - "version": "5.7.0", - "bundled": true, - "dev": true, - "optional": true - }, - "set-blocking": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "signal-exit": { - "version": "3.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "string-width": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "string_decoder": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safe-buffer": "~5.1.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "strip-json-comments": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "tar": { - "version": "4.4.8", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "chownr": "^1.1.1", - "fs-minipass": "^1.2.5", - "minipass": "^2.3.4", - "minizlib": "^1.1.1", - "mkdirp": "^0.5.0", - "safe-buffer": "^5.1.2", - "yallist": "^3.0.2" - } - }, - "util-deprecate": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "wide-align": { - "version": "1.1.3", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "string-width": "^1.0.2 || 2" - } - }, - "wrappy": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "yallist": { - "version": "3.0.3", - "bundled": true, - "dev": true, - "optional": true - } - } + "optional": true }, "function-bind": { "version": "1.1.1", @@ -2583,13 +2054,23 @@ } }, "glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.0.0.tgz", + "integrity": "sha512-Z2RwiujPRGluePM6j699ktJYxmPpJKCfpGA13jz2hmFZC7gKetzrWvg5KN3+OsIFmydGyZ1AVwERCq1w/ZZwRg==", "dev": true, "requires": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" + "is-glob": "^4.0.1" + }, + "dependencies": { + "is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + } } }, "global-modules": { @@ -2804,12 +2285,12 @@ }, "dependencies": { "async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.2.tgz", - "integrity": "sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg==", + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", + "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", "dev": true, "requires": { - "lodash": "^4.17.11" + "lodash": "^4.17.14" } } } @@ -3194,12 +2675,12 @@ "dev": true }, "is-binary-path": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", - "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", "dev": true, "requires": { - "binary-extensions": "^1.0.0" + "binary-extensions": "^2.0.0" } }, "is-buffer": { @@ -3569,18 +3050,18 @@ "dev": true }, "karma": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/karma/-/karma-4.1.0.tgz", - "integrity": "sha512-xckiDqyNi512U4dXGOOSyLKPwek6X/vUizSy2f3geYevbLj+UIdvNwbn7IwfUIL2g1GXEPWt/87qFD1fBbl/Uw==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/karma/-/karma-4.2.0.tgz", + "integrity": "sha512-fmCuxN1rwJxTdZfOXK5LjlmS4Ana/OvzNMpkyLL/TLE8hmgSkpVpMYQ7RTVa8TNKRVQDZNl5W1oF5cfKfgIMlA==", "dev": true, "requires": { "bluebird": "^3.3.0", "body-parser": "^1.16.1", - "braces": "^2.3.2", - "chokidar": "^2.0.3", + "braces": "^3.0.2", + "chokidar": "^3.0.0", "colors": "^1.1.0", "connect": "^3.6.0", - "core-js": "^2.2.0", + "core-js": "^3.1.3", "di": "^0.0.1", "dom-serialize": "^2.2.0", "flatted": "^2.0.0", @@ -3603,6 +3084,24 @@ "useragent": "2.3.0" }, "dependencies": { + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, "glob": { "version": "7.1.4", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", @@ -3617,11 +3116,26 @@ "path-is-absolute": "^1.0.0" } }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } } } }, @@ -3940,16 +3454,16 @@ } }, "log4js": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/log4js/-/log4js-4.4.0.tgz", - "integrity": "sha512-xwRvmxFsq8Hb7YeS+XKfvCrsH114bXex6mIwJ2+KmYVi23pB3+hlzyGq1JPycSFTJWNLhD/7PCtM0RfPy6/2yg==", + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-4.5.1.tgz", + "integrity": "sha512-EEEgFcE9bLgaYUKuozyFfytQM2wDHtXn4tAN41pkaxpNjAykv11GVdeI4tHtmPWW4Xrgh9R/2d7XYghDVjbKKw==", "dev": true, "requires": { "date-format": "^2.0.0", "debug": "^4.1.1", "flatted": "^2.0.0", "rfdc": "^1.1.4", - "streamroller": "^1.0.5" + "streamroller": "^1.0.6" }, "dependencies": { "debug": { @@ -4071,9 +3585,9 @@ } }, "mdn-data": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-1.1.4.tgz", - "integrity": "sha512-FSYbp3lyKjyj3E7fMl6rYvUdX0FBXaluGqlFoYESWQlyUTq8R+wp0rkFxoYFqZlHCvsUXGjyJmLQSnXToYhOSA==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.4.tgz", + "integrity": "sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA==", "dev": true }, "media-typer": { @@ -4385,13 +3899,6 @@ "integrity": "sha512-jFI/4UVRsRYdUbuDTKT7KzfOp7FiD5WzYmmwNwXyUVypC0xjoTL78Fqc0jHUPIvvGD+6DQSPHIt1NE7D1ArsqA==", "dev": true }, - "nan": { - "version": "2.14.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz", - "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==", - "dev": true, - "optional": true - }, "nanomatch": { "version": "1.2.13", "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", @@ -4813,12 +4320,6 @@ "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=" }, - "path-dirname": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", - "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", - "dev": true - }, "path-exists": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", @@ -4921,6 +4422,12 @@ "which": "^1.2.10" } }, + "picomatch": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.0.7.tgz", + "integrity": "sha512-oLHIdio3tZ0qH76NybpeneBhYVj0QFTfXEFTc/B3zKQspYfYYkWYgFsmzo+4kvId/bQRcNkVeguI3y+CD22BtA==", + "dev": true + }, "pify": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", @@ -4954,9 +4461,9 @@ "dev": true }, "pretty-bytes": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.2.0.tgz", - "integrity": "sha512-ujANBhiUsl9AhREUDUEY1GPOharMGm8x8juS7qOHybcLi7XsKfrYQ88hSly1l2i0klXHTDYrlL8ihMCG55Dc3w==", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.3.0.tgz", + "integrity": "sha512-hjGrh+P926p4R4WbaB6OckyRtO0F0/lQBiT+0gnxjV+5kjPBrfVBFCsCLbMqVQeydvIoouYTCmmEURiH3R1Bdg==", "dev": true }, "prettysize": { @@ -5081,46 +4588,12 @@ } }, "readdirp": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", - "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.1.1.tgz", + "integrity": "sha512-XXdSXZrQuvqoETj50+JAitxz1UPdt5dupjT6T5nVB+WvjMv2XKYj+s7hPeAVCXvmJrL36O4YYyWlIC3an2ePiQ==", "dev": true, "requires": { - "graceful-fs": "^4.1.11", - "micromatch": "^3.1.10", - "readable-stream": "^2.0.2" - }, - "dependencies": { - "readable-stream": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } + "picomatch": "^2.0.4" } }, "rechoir": { @@ -5736,9 +5209,9 @@ } }, "spdx-license-ids": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.4.tgz", - "integrity": "sha512-7j8LYJLeY/Yb6ACbQ7F76qy5jHkp0U6jgBfJsk97bwWlVUnUWsAgpyaCvo17h0/RQGnQ036tVDomiwoI4pDkQA==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz", + "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==", "dev": true }, "split-string": { @@ -5810,25 +5283,25 @@ "dev": true }, "streamroller": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-1.0.5.tgz", - "integrity": "sha512-iGVaMcyF5PcUY0cPbW3xFQUXnr9O4RZXNBBjhuLZgrjLO4XCLLGfx4T2sGqygSeylUjwgWRsnNbT9aV0Zb8AYw==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-1.0.6.tgz", + "integrity": "sha512-3QC47Mhv3/aZNFpDDVO44qQb9gwB9QggMEE0sQmkTAwBVYdBRWISdsywlkfm5II1Q5y/pmrHflti/IgmIzdDBg==", "dev": true, "requires": { "async": "^2.6.2", "date-format": "^2.0.0", "debug": "^3.2.6", "fs-extra": "^7.0.1", - "lodash": "^4.17.11" + "lodash": "^4.17.14" }, "dependencies": { "async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.2.tgz", - "integrity": "sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg==", + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", + "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", "dev": true, "requires": { - "lodash": "^4.17.11" + "lodash": "^4.17.14" } }, "debug": { @@ -5985,12 +5458,12 @@ }, "dependencies": { "async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.2.tgz", - "integrity": "sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg==", + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", + "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", "dev": true, "requires": { - "lodash": "^4.17.11" + "lodash": "^4.17.14" } }, "dateformat": { @@ -6069,17 +5542,16 @@ } }, "svgo": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/svgo/-/svgo-1.2.2.tgz", - "integrity": "sha512-rAfulcwp2D9jjdGu+0CuqlrAUin6bBWrpoqXWwKDZZZJfXcUXQSxLJOFJCQCSA0x0pP2U0TxSlJu2ROq5Bq6qA==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-1.3.0.tgz", + "integrity": "sha512-MLfUA6O+qauLDbym+mMZgtXCGRfIxyQoeH6IKVcFslyODEe/ElJNwr0FohQ3xG4C6HK6bk3KYPPXwHVJk3V5NQ==", "dev": true, "requires": { "chalk": "^2.4.1", "coa": "^2.0.2", "css-select": "^2.0.0", "css-select-base-adapter": "^0.1.1", - "css-tree": "1.0.0-alpha.28", - "css-url-regex": "^1.1.0", + "css-tree": "1.0.0-alpha.33", "csso": "^3.5.1", "js-yaml": "^3.13.1", "mkdirp": "~0.5.1", @@ -6381,12 +5853,6 @@ } } }, - "upath": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/upath/-/upath-1.1.2.tgz", - "integrity": "sha512-kXpym8nmDmlCBr7nKdIx8P2jNBa+pBpIUFRnKJ4dr8htyYGJFokkr2ZvERRtUN+9SY+JqXouNgUPtv6JQva/2Q==", - "dev": true - }, "uri-js": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", @@ -6557,12 +6023,12 @@ }, "dependencies": { "async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.2.tgz", - "integrity": "sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg==", + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", + "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", "dev": true, "requires": { - "lodash": "^4.17.11" + "lodash": "^4.17.14" } }, "readable-stream": { diff --git a/package.json b/package.json index 5cc53d5da..5481707fb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "leaflet-distortableimage", - "version": "0.6.6", + "version": "0.6.7", "description": "Leaflet plugin enabling image overlays to be distorted, stretched, and warped (built for Public Lab's MapKnitter: http://publiclab.org).", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" diff --git a/src/components/DistortableImage.Keymapper.js b/src/components/DistortableImage.Keymapper.js new file mode 100644 index 000000000..cec5d34d7 --- /dev/null +++ b/src/components/DistortableImage.Keymapper.js @@ -0,0 +1,151 @@ +L.DomUtil = L.DomUtil || {}; +L.DistortableImage = L.DistortableImage || {}; +L.distortableImage = L.DistortableImage; + +L.DistortableImage.Keymapper = L.Handler.extend({ + + options: { + position: 'topright' + }, + + initialize: function (map, options) { + this._map = map; + L.setOptions(this, options); + }, + + addHooks: function () { + if (!this._keymapper) { + this._toggler = this._toggleButton(); + this._scrollWrapper = this._wrap(); + this._setMapper(this._toggler, this._scrollWrapper); + + L.DomEvent.on(this._toggler, 'click', this._toggleKeymapper, this); + + L.DomEvent.on(this._scrollWrapper, { + click: L.DomEvent.stop, + mouseenter: this._disableMap, + mouseleave: this._enableMap, + }, this); + } + }, + + removeHooks: function () { + if (this._keymapper) { + L.DomEvent.off(this._toggler, 'click', this._toggleKeymapper, this); + + L.DomEvent.off(this._scrollWrapper, { + click: L.DomEvent.stop, + mouseenter: this._disableMap, + mouseleave: this._enableMap, + }, this); + + L.DomUtil.remove(this._toggler); + L.DomUtil.remove(this._scrollWrapper); + L.DomUtil.remove(this._keymapper._container); + this._keymapper = false; + } + }, + + _toggleButton: function () { + var toggler = L.DomUtil.create('a', ''); + toggler.setAttribute('id', 'toggle-keymapper'); + toggler.setAttribute('href', '#'); + toggler.setAttribute('role', 'button'); + toggler.setAttribute('title', 'Show Keybindings'); + toggler.innerHTML = L.IconUtil.create("keyboard_open"); + + return toggler; + }, + + _wrap: function () { + var wrap = L.DomUtil.create('div', ''); + wrap.setAttribute('id', 'keymapper-wrapper'); + wrap.style.display = 'none'; + + return wrap; + }, + + _setMapper: function (button, wrap) { + this._keymapper = L.control({ position: this.options.position }); + + this._container = this._keymapper.onAdd = function () { + var el_wrapper = L.DomUtil.create('div', 'ldi-keymapper-hide'); + el_wrapper.setAttribute('id', 'ldi-keymapper'); + var divider = L.DomUtil.create('br', 'divider'); + el_wrapper.appendChild(divider); + el_wrapper.appendChild(wrap); + wrap.insertAdjacentHTML( + 'beforeend', + '' + + '
' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '
Stack up / down
j\xa0k
Lock Image
l
Outline
o
Scale
s
Transparency
t
RotateScale
d\xa0r
Deselect All
esc
Delete Image
delete\xa0backspace
Rotate
caps
' + ); + el_wrapper.appendChild(button); + return el_wrapper; + }; + + this._keymapper.addTo(this._map); + }, + + _toggleKeymapper: function (e) { + L.DomEvent.stop(e); + var container = document.getElementById('ldi-keymapper'); + var keymapWrap = document.getElementById('keymapper-wrapper'); + + var newClass = container.className === 'ldi-keymapper leaflet-control' ? 'ldi-keymapper-hide leaflet-control' : 'ldi-keymapper leaflet-control'; + var newStyle = keymapWrap.style.display === 'none' ? 'block' : 'none'; + + container.className = newClass; + keymapWrap.style.display = newStyle; + + L.IconUtil.toggleTooltip(this._toggler, 'Show Keybindings', 'Hide Keybindings'); + this._toggler.innerHTML = this._toggler.innerHTML === 'close' ? L.IconUtil.create('keyboard_open') : 'close'; + L.DomUtil.toggleClass(this._toggler, 'close-icon'); + }, + + _disableMap: function() { + this._map.scrollWheelZoom.disable(); + this._map.dragging.disable(); + }, + + _enableMap: function() { + this._map.scrollWheelZoom.enable(); + this._map.dragging.enable(); + }, + + _injectIconSet: function() { + if (document.querySelector('#keymapper-iconset')) { return; } + + var el = document.createElement('div'); + el.id = 'keymapper-iconset'; + el.setAttribute('hidden', 'hidden'); + + this._iconset = new L.KeymapperIconSet().render(); + el.innerHTML = this._iconset; + + document.querySelector('.leaflet-control-container').appendChild(el); + } +}); + +L.DistortableImage.Keymapper.addInitHook(function() { + L.DistortableImage.Keymapper.prototype._n = + L.DistortableImage.Keymapper.prototype._n ? L.DistortableImage.Keymapper.prototype._n + 1 : 1; + + if (L.DistortableImage.Keymapper.prototype._n === 1) { + this.enable(); + this._injectIconSet(); + } +}); + +L.distortableImage.keymapper = function (map, options) { + return new L.DistortableImage.Keymapper(map, options); +}; diff --git a/src/edit/BoxSelector.js b/src/edit/BoxSelector.js index cb9b22d8c..435ab0437 100644 --- a/src/edit/BoxSelector.js +++ b/src/edit/BoxSelector.js @@ -4,7 +4,6 @@ L.Map.mergeOptions({ boxSelector: true, boxZoom: false }); * primarily Leaflet 1.5.1 source code. Overriden so that its a selection box with our `L.DistortableCollection` class * instead of a zoom box. * */ - L.Map.BoxSelector = L.Map.BoxZoom.extend({ initialize: function(map) { this._map = map; diff --git a/src/edit/DistortableImage.Edit.js b/src/edit/DistortableImage.Edit.js index f484a949f..5e132e689 100644 --- a/src/edit/DistortableImage.Edit.js +++ b/src/edit/DistortableImage.Edit.js @@ -30,24 +30,13 @@ L.DistortableImage.Edit = L.Handler.extend({ this._transparent = false; this._outlined = false; - /* generate instance counts. TODO - add the keymapper to collection instead of individ. imgs perhaps? */ - this.instance_count = L.DistortableImage.Edit.prototype.instances = - L.DistortableImage.Edit.prototype.instances ? L.DistortableImage.Edit.prototype.instances + 1 : 1; - L.setOptions(this, options); }, /* Run on image selection. */ addHooks: function() { var overlay = this._overlay, - map = overlay._map, - keymapper_position; - - /* instantiate and render keymapper for one instance only */ - if (this.instance_count === 1 && overlay.options.keymapper !== false) { - keymapper_position = overlay.options.keymapper_position || 'topright'; - map.addControl(new L.DistortableImage.Keymapper({ position: keymapper_position })); - } + map = overlay._map; /* bring the selected image into view */ overlay.bringToFront(); diff --git a/src/edit/DistortableImage.Keymapper.js b/src/edit/DistortableImage.Keymapper.js deleted file mode 100644 index cbdb04747..000000000 --- a/src/edit/DistortableImage.Keymapper.js +++ /dev/null @@ -1,27 +0,0 @@ -L.DomUtil = L.DomUtil || {}; -L.DistortableImage = L.DistortableImage || {}; - -L.DistortableImage.Keymapper = L.Control.extend({ - initialize: function(options) { - L.Control.prototype.initialize.call(this, options); - }, - - onAdd: function() { - var el_wrapper = L.DomUtil.create("div", "ldi-keymapper"); - el_wrapper.innerHTML = - "" + - "" + - "" + - "" + - "" + - "" + - "" + - "" + - "" + - "" + - "" + - "" + - "
Keymappings
t: Transparency
o: Outline
l: Lock
caps: Rotate
s: Scale
d: Distort
r: Rotate+Scale
j, k: Stack up / down
esc: Deselect All
delete , backspace: Delete
"; - return el_wrapper; - } -}); \ No newline at end of file diff --git a/src/edit/EditHandle.js b/src/edit/EditHandle.js index f043bb24c..fdc9227d7 100644 --- a/src/edit/EditHandle.js +++ b/src/edit/EditHandle.js @@ -13,7 +13,7 @@ L.EditHandle = L.Marker.extend({ zIndexOffset: 10 }; - if (options && options.hasOwnProperty("draggable")) { + if (options && options.hasOwnProperty('draggable')) { markerOptions.draggable = options.draggable; } @@ -33,7 +33,7 @@ L.EditHandle = L.Marker.extend({ }, _onHandleDragStart: function() { - this._handled.fire("editstart"); + this._handled.fire('editstart'); }, _onHandleDragEnd: function() { @@ -42,7 +42,7 @@ L.EditHandle = L.Marker.extend({ _fireEdit: function() { this._handled.edited = true; - this._handled.fire("edit"); + this._handled.fire('edit'); }, _bindListeners: function() { @@ -55,9 +55,9 @@ L.EditHandle = L.Marker.extend({ this ); - this._handled._map.on("zoomend", this.updateHandle, this); + this._handled._map.on('zoomend', this.updateHandle, this); - this._handled.on("update", this.updateHandle, this); + this._handled.on('update', this.updateHandle, this); }, _unbindListeners: function() { @@ -70,8 +70,8 @@ L.EditHandle = L.Marker.extend({ this ); - this._handled._map.off("zoomend", this.updateHandle, this); - this._handled.off("update", this.updateHandle, this); + this._handled._map.off('zoomend', this.updateHandle, this); + this._handled.off('update', this.updateHandle, this); }, /* Takes two latlngs and calculates the scaling difference. */ diff --git a/src/edit/tools/DistortableImage.PopupBar.js b/src/edit/tools/DistortableImage.PopupBar.js index daa05561d..69207a875 100644 --- a/src/edit/tools/DistortableImage.PopupBar.js +++ b/src/edit/tools/DistortableImage.PopupBar.js @@ -27,8 +27,8 @@ var ToggleTransparency = L.EditAction.extend({ addHooks: function() { var editing = this._overlay.editing; - this.toggleXlink('opacity_empty', 'opacity'); - this.toggleTooltip('Make Image Opaque', 'Make Image Transparent'); + L.IconUtil.toggleXlink(this._link, 'opacity_empty', 'opacity'); + L.IconUtil.toggleTooltip(this._link, 'Make Image Opaque', 'Make Image Transparent'); editing._toggleTransparency(); } }); @@ -59,8 +59,8 @@ var ToggleOutline = L.EditAction.extend({ addHooks: function() { var editing = this._overlay.editing; - this.toggleXlink('border_clear', 'border_outer'); - this.toggleTooltip('Remove Border', 'Add Border'); + L.IconUtil.toggleXlink(this._link, 'border_clear', 'border_outer'); + L.IconUtil.toggleTooltip(this._link, 'Remove Border', 'Add Border'); editing._toggleOutline(); } }); @@ -112,8 +112,8 @@ var ToggleLock = L.EditAction.extend({ addHooks: function() { var editing = this._overlay.editing; - this.toggleXlink('unlock', 'lock'); - this.toggleTooltip('Unlock', 'Lock'); + L.IconUtil.toggleXlink(this._link, 'unlock', 'lock'); + L.IconUtil.toggleTooltip(this._link, 'Unlock', 'Lock'); editing._toggleLock(); } }); @@ -144,8 +144,8 @@ var ToggleRotateScale = L.EditAction.extend({ addHooks: function() { var editing = this._overlay.editing; - this.toggleXlink('transform', 'crop_rotate'); - this.toggleTooltip('Distort', 'Rotate+Scale'); + L.IconUtil.toggleXlink(this._link, 'transform', 'crop_rotate'); + L.IconUtil.toggleTooltip(this._link, 'Distort', 'Rotate+Scale'); editing._toggleRotateScale(); } }); @@ -197,8 +197,8 @@ var ToggleOrder = L.EditAction.extend({ addHooks: function() { var editing = this._overlay.editing; - this.toggleXlink('flip_to_front', 'flip_to_back'); - this.toggleTooltip('Stack to Front', 'Stack to Back'); + L.IconUtil.toggleXlink(this._link, 'flip_to_front', 'flip_to_back'); + L.IconUtil.toggleTooltip(this._link, 'Stack to Front', 'Stack to Back'); editing._toggleOrder(); } }); diff --git a/src/edit/tools/EditAction.js b/src/edit/tools/EditAction.js index 58b716cae..3a37e729f 100644 --- a/src/edit/tools/EditAction.js +++ b/src/edit/tools/EditAction.js @@ -19,25 +19,6 @@ L.EditAction = L.Toolbar2.Action.extend({ this._injectIconSet(); }, - toggleXlink: function(ref1, ref2) { - var href1 = "#" + ref1, - href2 = "#" + ref2; - - if (this._link.querySelector('use')) { - var xlink = this._link.querySelector('use:nth-child(1)'); - var newXlink = xlink.getAttribute('xlink:href') === href1 ? href2 : href1; - xlink.setAttribute('xlink:href', newXlink); - return newXlink; - } - return false; - }, - - toggleTooltip: function(title1, title2) { - var newTt = this._link.getAttribute('title') === title1 ? title2 : title1; - this._link.setAttribute('title', newTt); - return newTt; - }, - _createIcon: function(toolbar, container, args) { var iconOptions = this.options.toolbarIcon; @@ -46,13 +27,14 @@ L.EditAction = L.Toolbar2.Action.extend({ this._link = L.DomUtil.create('a', '', this._icon); if (iconOptions.svg) { - this._link.innerHTML = this._svgIconHelper(iconOptions.html); + this._link.innerHTML = L.IconUtil.create(iconOptions.html); } else { this._link.innerHTML = iconOptions.html; } this._link.setAttribute('href', '#'); this._link.setAttribute('title', iconOptions.tooltip); + this._link.setAttribute('role', 'button'); L.DomUtil.addClass(this._link, this.constructor.baseClass); if (iconOptions.className) { @@ -65,22 +47,15 @@ L.EditAction = L.Toolbar2.Action.extend({ this._addSubToolbar(toolbar, this._icon, args); }, - _svgIconHelper: function(ref) { - return ( - '' + - '' + - '' - ); - }, - _injectIconSet: function() { if (document.querySelector('#iconset')) { return; } var el = document.createElement('div'); el.id = 'iconset'; el.setAttribute('hidden', 'hidden'); - el.innerHTML = new L.IconSet().render(); + el.innerHTML = new L.ToolbarIconSet().render(); document.querySelector('.leaflet-marker-pane').appendChild(el); } }); + diff --git a/src/iconsets/IconSet.js b/src/iconsets/IconSet.js new file mode 100644 index 000000000..0fd4fff67 --- /dev/null +++ b/src/iconsets/IconSet.js @@ -0,0 +1,17 @@ +/** this is the baseclass other IconSets inherit from, we don't use it directly */ +L.IconSet = L.Class.extend({ + + _svg: '', + + _symbols: '', + + render: function() { + this.addSymbols(this._symbols); + return this._svg; + }, + + addSymbols: function(symbols) { + this._svg += symbols; + } + +}); diff --git a/src/iconsets/KeymapperIconSet.js b/src/iconsets/KeymapperIconSet.js new file mode 100644 index 000000000..59c0c39be --- /dev/null +++ b/src/iconsets/KeymapperIconSet.js @@ -0,0 +1,6 @@ +L.KeymapperIconSet = L.IconSet.extend({ + + _symbols: + '', + +}); diff --git a/src/edit/tools/IconSet.js b/src/iconsets/ToolbarIconSet.js similarity index 96% rename from src/edit/tools/IconSet.js rename to src/iconsets/ToolbarIconSet.js index a5c4688a1..96b375879 100644 --- a/src/edit/tools/IconSet.js +++ b/src/iconsets/ToolbarIconSet.js @@ -1,14 +1,6 @@ -L.IconSet = L.Class.extend({ +L.ToolbarIconSet = L.IconSet.extend({ - _svg: '', - - render: function() { - this.addSymbols(); - return this._svg; - }, - - addSymbols: function() { - this._svg += + _symbols: '' + '' + '' + @@ -23,6 +15,5 @@ L.IconSet = L.Class.extend({ '' + '' + '' - ; - } + }); diff --git a/src/util/IconUtil.js b/src/util/IconUtil.js new file mode 100644 index 000000000..6f322b222 --- /dev/null +++ b/src/util/IconUtil.js @@ -0,0 +1,36 @@ +L.IconUtil = { + /** creates an svg elemenet with built in accessibility properties and standardized + * classes for styling, takes in the fragment identifier (id) of the symbol to reference. + * note for symplicity we allow providing the icon target with or without the '#' prefix */ + create: function(ref) { + if (/^#/.test(ref)) { + ref = ref.replace(/^#/, ''); + } + + return ( + '' + + '' + + '' + ); + }, + + /** finds the use element and toggles its icon reference */ + toggleXlink: function(container, ref1, ref2) { + if (!/^#/.test(ref1)) { ref1 = '#' + ref1; } + if (!/^#/.test(ref2)) { ref2 = '#' + ref2; } + + var use = container.querySelector('use'); + if (use) { + var toggled = use.getAttribute('xlink:href') === ref1 ? ref2 : ref1; + use.setAttribute('xlink:href', toggled); + return toggled; + } + return false; + }, + + toggleTooltip: function(container, title1, title2) { + var toggled = container.getAttribute('title') === title1 ? title2 : title1; + container.setAttribute('title', toggled); + return toggled; + } +}; diff --git a/test/karma.conf.js b/test/karma.conf.js index c22d128c1..61a6c0a80 100644 --- a/test/karma.conf.js +++ b/test/karma.conf.js @@ -4,68 +4,70 @@ module.exports = function(config) { config.set({ // base path that will be used to resolve all patterns (eg. files, exclude) - basePath: "../", + basePath: '../', plugins: [ - require("mocha"), - require("karma-mocha"), - require("karma-coverage"), - require("karma-mocha-reporter"), - require("karma-phantomjs-launcher"), - require("glfx"), - require("webgl-distort/dist/webgl-distort.js") + require('mocha'), + require('karma-mocha'), + require('karma-coverage'), + require('karma-mocha-reporter'), + require('karma-phantomjs-launcher'), + require('glfx'), + require('webgl-distort/dist/webgl-distort.js') ], // frameworks to use // available frameworks: https://npmjs.org/browse/keyword/karma-adapter - frameworks: ["mocha"], + frameworks: ['mocha'], // list of files / patterns to load in the browser files: [ - { pattern: "examples/*.jpg", included: false, served: true }, - { pattern: "examples/*.png", included: false, served: true }, - "node_modules/leaflet/dist/leaflet-src.js", - "node_modules/leaflet/dist/leaflet.css", - "node_modules/leaflet-toolbar/dist/leaflet.toolbar.js", - "node_modules/leaflet-toolbar/dist/leaflet.toolbar.css", - "node_modules/webgl-distort/dist/webgl-distort.js", - "node_modules/glfx/glfx.js", - "node_modules/chai/chai.js", - "node_modules/sinon/pkg/sinon.js", - "src/util/*.js", - "src/edit/getEXIFdata.js", - "src/edit/BoxSelector.js", - "src/edit/tools/IconSet.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/DistortableImage.Keymapper.js", - "src/edit/tools/EditAction.js", - "src/edit/tools/DistortableImage.PopupBar.js", - "src/edit/tools/DistortableImage.ControlBar.js", - "src/edit/DistortableImage.Edit.js", - "test/SpecHelper.js", - "test/src/*Spec.js", - "test/src/**/*Spec.js" + { pattern: 'examples/*.jpg', included: false, served: true }, + { pattern: 'examples/*.png', included: false, served: true }, + 'node_modules/leaflet/dist/leaflet-src.js', + 'node_modules/leaflet/dist/leaflet.css', + 'node_modules/leaflet-toolbar/dist/leaflet.toolbar.js', + 'node_modules/leaflet-toolbar/dist/leaflet.toolbar.css', + 'node_modules/webgl-distort/dist/webgl-distort.js', + 'node_modules/glfx/glfx.js', + 'node_modules/chai/chai.js', + 'node_modules/sinon/pkg/sinon.js', + 'src/util/*.js', + 'src/edit/getEXIFdata.js', + 'src/edit/BoxSelector.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/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/DistortableImage.Edit.js', + 'test/SpecHelper.js', + 'test/src/*Spec.js', + 'test/src/**/*Spec.js' ], // so that karma can serve examples/example.png proxies: { - "/examples/": "/base/examples/" + '/examples/': '/base/examples/' }, // test results reporter to use // possible values: 'dots', 'progress' // available reporters: https://npmjs.org/browse/keyword/karma-reporter - reporters: ["mocha", "coverage"], + reporters: ['mocha', 'coverage'], preprocessors: { - "../src/**/*.js": "coverage" + '../src/**/*.js': 'coverage' }, // web server port @@ -80,7 +82,7 @@ module.exports = function(config) { // start these browsers // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher - browsers: ["PhantomJS"], + browsers: ['PhantomJS'], // Continuous Integration mode // if true, Karma captures browsers, runs the tests and exits @@ -90,9 +92,9 @@ module.exports = function(config) { coverageReporter: { reporters: [ - { type: "text", dir: "../coverage/", file: "coverage.txt" }, - { type: "lcovonly", dir: "../coverage/" }, - { type: "html", dir: "../coverage/" } + { type: 'text', dir: '../coverage/', file: 'coverage.txt' }, + { type: 'lcovonly', dir: '../coverage/' }, + { type: 'html', dir: '../coverage/' } ] } }); diff --git a/test/src/edit/DistortableImageEditSpec.js b/test/src/edit/DistortableImageEditSpec.js index 7066343b9..d2b58f3c3 100644 --- a/test/src/edit/DistortableImageEditSpec.js +++ b/test/src/edit/DistortableImageEditSpec.js @@ -20,7 +20,6 @@ describe("L.DistortableImage.Edit", function() { afterEach(function () { L.DomUtil.remove(overlay); }); - }); it("Should be initialized along with each instance of L.DistortableImageOverlay.", function() {