leaflet-distortableimage
Advanced tools
Comparing version 0.10.0 to 0.11.0
@@ -38,4 +38,5 @@ module.exports = { | ||
'prefer-const': 1, | ||
'require-jsdoc': 0, | ||
'valid-jsdoc': 0, | ||
} | ||
}; |
{ | ||
"name": "leaflet-distortableimage", | ||
"version": "0.10.0", | ||
"version": "0.11.0", | ||
"description": "Leaflet plugin enabling image overlays to be distorted, stretched, and warped (built for Public Lab's MapKnitter: http://publiclab.org).", | ||
@@ -5,0 +5,0 @@ "scripts": { |
L.DistortableCollection = L.FeatureGroup.extend({ | ||
options: { | ||
editable: true, | ||
exportOpts: { | ||
exportStartUrl: '//export.mapknitter.org/export', | ||
statusUrl: '//export.mapknitter.org', | ||
exportUrl: 'http://export.mapknitter.org/', | ||
}, | ||
}, | ||
@@ -5,0 +10,0 @@ |
L.ExportAction = L.EditAction.extend({ | ||
// This function is executed every time we select an image | ||
initialize: function(map, overlay, options) { | ||
@@ -6,2 +7,6 @@ var edit = overlay.editing; | ||
this.isExporting = false; | ||
this.mouseLeaveSkip = true; | ||
this.isHooksExecuted = false; | ||
if (edit instanceof L.DistortableImage.Edit) { | ||
@@ -11,3 +16,3 @@ L.DistortableImage.action_map.e = '_getExport'; | ||
} else { | ||
L.DistortableImage.group_action_map.e = 'startExport'; | ||
L.DistortableImage.group_action_map.e = 'runExporter'; | ||
tooltip = overlay.options.translation.exportImages; | ||
@@ -29,14 +34,89 @@ } | ||
if (edit instanceof L.DistortableImage.Edit) { edit._getExport(); } | ||
else { | ||
L.IconUtil.toggleXlink(this._link, 'get_app', 'spinner'); | ||
L.IconUtil.toggleTitle(this._link, 'Export Images', 'Loading...'); | ||
L.IconUtil.addClassToSvg(this._link, 'loader'); | ||
edit.startExport().then(function() { | ||
L.IconUtil.toggleXlink(this._link, 'get_app', 'spinner'); | ||
L.IconUtil.toggleTitle(this._link, 'Export Images', 'Loading...'); | ||
L.DomUtil.removeClass(this._link.firstChild, 'loader'); | ||
}.bind(this)); | ||
if (edit instanceof L.DistortableImage.Edit) { | ||
edit._getExport(); | ||
return; | ||
} | ||
// Make sure that addHooks is executed only once, event listeners will handle the rest | ||
if (this.isHooksExecuted) { | ||
return; | ||
} else { | ||
this.isHooksExecuted = true; | ||
} | ||
var toolbarExportElement = this._link.parentElement; | ||
this.mouseEnterHandler = this.handleMouseEnter.bind(this); | ||
this.mouseLeaveHandler = this.handleMouseLeave.bind(this); | ||
L.DomEvent.on(toolbarExportElement, 'click', function() { | ||
if (!this.isExporting) { | ||
this.isExporting = true; | ||
this.renderExportIcon(); | ||
setTimeout(this.attachMouseEventListeners.bind(this, toolbarExportElement), 100); | ||
edit.runExporter().then( | ||
function() { | ||
this.resetState(); | ||
this.detachMouseEventListeners(toolbarExportElement); | ||
}.bind(this) | ||
); | ||
} else { | ||
// Clicking on the export icon after export has started will be ignored | ||
if (this.mouseLeaveSkip) { | ||
return; | ||
} | ||
this.resetState(); | ||
this.detachMouseEventListeners(toolbarExportElement); | ||
edit.cancelExport(); | ||
} | ||
}, this); | ||
}, | ||
resetState: function() { | ||
this.renderDownloadIcon(); | ||
this.isExporting = false; | ||
this.mouseLeaveSkip = true; | ||
}, | ||
attachMouseEventListeners: function(element) { | ||
element.addEventListener('mouseenter', this.mouseEnterHandler); | ||
element.addEventListener('mouseleave', this.mouseLeaveHandler); | ||
}, | ||
detachMouseEventListeners: function(element) { | ||
element.removeEventListener('mouseenter', this.mouseEnterHandler); | ||
element.removeEventListener('mouseleave', this.mouseLeaveHandler); | ||
}, | ||
handleMouseEnter: function() { | ||
this.renderCancelIcon(); | ||
}, | ||
handleMouseLeave: function() { | ||
if (!this.mouseLeaveSkip) { | ||
this.renderExportIcon(); | ||
} else { | ||
this.mouseLeaveSkip = false; | ||
} | ||
}, | ||
renderDownloadIcon: function() { | ||
L.IconUtil.toggleXlink(this._link, 'get_app', 'spinner'); | ||
L.IconUtil.toggleTitle(this._link, 'Export Images', 'Loading...'); | ||
L.DomUtil.removeClass(this._link.firstChild, 'loader'); | ||
}, | ||
renderExportIcon: function() { | ||
L.IconUtil.toggleXlink(this._link, 'spinner'); | ||
L.IconUtil.toggleTitle(this._link, 'Export Images', 'Loading...'); | ||
L.IconUtil.addClassToSvg(this._link, 'loader'); | ||
}, | ||
renderCancelIcon: function() { | ||
L.IconUtil.toggleXlink(this._link, 'cancel'); | ||
L.IconUtil.toggleTitle(this._link, 'Cancel Export', 'Loading...'); | ||
L.DomUtil.removeClass(this._link.firstChild, 'loader'); | ||
}, | ||
}); |
@@ -11,82 +11,7 @@ L.DistortableImage = L.DistortableImage || {}; | ||
this._group = group; | ||
this._exportOpts = group.options.exportOpts; | ||
this.startExport = options.startExport || function startExport() { | ||
return new Promise(function(resolve) { | ||
var opts = group.options || {}; | ||
// this may be overridden to update the UI to show export progress or completion | ||
// eslint-disable-next-line require-jsdoc | ||
function _defaultUpdater(data, _opts) { | ||
data = JSON.parse(data); | ||
// optimization: fetch status directly from google storage: | ||
if (_opts.statusUrl !== data.status_url && data.status_url.match('.json')) { | ||
if (data.status_url && data.status_url.substr(0,1) === "/") { | ||
_opts.statusUrl = _opts.exportUrl + data.status_url; | ||
} else { | ||
_opts.statusUrl = data.status_url; | ||
} | ||
} | ||
if (data.status === 'complete') { | ||
clearInterval(_opts.updateInterval); | ||
resolve(); | ||
} | ||
if (data.status === 'complete' && data.jpg !== null) { | ||
alert('Export succeeded. ' + _opts.exportUrl + data.jpg); | ||
} | ||
// TODO: update to clearInterval when status == "failed" if we update that in this file: | ||
// https://github.com/publiclab/mapknitter-exporter/blob/main/lib/mapknitterExporter.rb | ||
console.log(data); | ||
} | ||
// receives the URL of status.json, and starts running the updater to repeatedly fetch from status.json; | ||
// this may be overridden to integrate with any UI | ||
// eslint-disable-next-line require-jsdoc | ||
function _defaultHandleStatusResponse(data, _opts) { | ||
// repeatedly fetch the status.json | ||
_opts.updateInterval = setInterval(function intervalUpdater() { | ||
$.ajax(_opts.statusUrl + '?' + Date.now(), {// bust cache with timestamp | ||
type: 'GET', | ||
crossDomain: true, | ||
}).done(function(data) { | ||
_opts.updater(data, _opts); | ||
}); | ||
}, _opts.frequency); | ||
} | ||
// initiate the export | ||
// eslint-disable-next-line require-jsdoc | ||
function _defaultFetchStatusUrl(_opts) { | ||
$.ajax({ | ||
url: _opts.exportStartUrl, | ||
crossDomain: true, | ||
type: 'POST', | ||
data: { | ||
collection: JSON.stringify(_opts.collection), | ||
scale: _opts.scale, | ||
upload: true | ||
}, | ||
success: function(data) { _opts.handleStatusResponse(data, _opts); }, // this handles the initial response | ||
}); | ||
} | ||
opts.resolve = resolve; // allow user-specified functions to resolve the promise | ||
opts.collection = opts.collection || this._group.generateExportJson(); | ||
opts.frequency = opts.frequency || 3000; | ||
opts.scale = opts.scale || 100; // switch it to _getAvgCmPerPixel ! | ||
opts.updater = opts.updater || _defaultUpdater; | ||
opts.handleStatusResponse = opts.handleStatusResponse || _defaultHandleStatusResponse; | ||
opts.fetchStatusUrl = opts.fetchStatusUrl || _defaultFetchStatusUrl; | ||
opts.exportStartUrl = opts.exportStartUrl || '//export.mapknitter.org/export'; | ||
opts.exportUrl = opts.exportUrl || 'http//export.mapknitter.org/'; | ||
opts.fetchStatusUrl(opts); | ||
}.bind(this)); | ||
}; | ||
L.setOptions(this, options); | ||
L.distortableImage.group_action_map.Escape = '_decollectAll'; | ||
}, | ||
@@ -99,2 +24,5 @@ | ||
this.editActions = this.options.actions; | ||
this.runExporter = | ||
L.bind(L.Utils.getNestedVal(this, '_exportOpts', 'exporter') || | ||
this.startExport, this); | ||
@@ -275,2 +203,6 @@ L.DomEvent.on(document, 'keydown', this._onKeyDown, this); | ||
cancelExport: function() { | ||
clearInterval(this.updateInterval); | ||
}, | ||
_addToolbar: function() { | ||
@@ -326,2 +258,77 @@ var group = this._group; | ||
}, | ||
startExport: function() { | ||
return new Promise(function(resolve) { | ||
var opts = this._exportOpts; | ||
var statusUrl; | ||
var self = this; | ||
this.updateInterval = null; | ||
// this may be overridden to update the UI to show export progress or completion | ||
function _defaultUpdater(data) { | ||
data = JSON.parse(data); | ||
// optimization: fetch status directly from google storage: | ||
if (data.status_url) { | ||
if (statusUrl !== data.status_url && data.status_url.match('.json')) { | ||
// if (data.status_url && data.status_url.substr(0,1) === "/") { | ||
// opts.statusUrl = opts.statusUrl + data.status_url; | ||
// } else { | ||
statusUrl = data.status_url; | ||
// } | ||
} | ||
if (data.status === 'complete') { | ||
clearInterval(this.updateInterval); | ||
resolve(); | ||
if (data.jpg !== null) { | ||
alert('Export succeeded. ' + opts.exportUrl + data.jpg); | ||
} | ||
} | ||
// TODO: update to clearInterval when status == "failed" if we update that in this file: | ||
// https://github.com/publiclab/mapknitter-exporter/blob/main/lib/mapknitterExporter.rb | ||
console.log(data); | ||
} | ||
} | ||
// receives the URL of status.json, and starts running the updater to repeatedly fetch from status.json; | ||
// this may be overridden to integrate with any UI | ||
function _defaultHandleStatusRes(data) { | ||
statusUrl = opts.statusUrl + data; | ||
// repeatedly fetch the status.json | ||
self.updateInterval = setInterval(function intervalUpdater() { | ||
$.ajax(statusUrl + '?' + Date.now(), {// bust cache with timestamp | ||
type: 'GET', | ||
crossDomain: true, | ||
}).done(function(data) { | ||
opts.updater(data); | ||
}); | ||
}, opts.frequency); | ||
} | ||
// initiate the export | ||
function _defaultFetchStatusUrl(opts) { | ||
$.ajax({ | ||
url: opts.exportStartUrl, | ||
crossDomain: true, | ||
type: 'POST', | ||
data: { | ||
collection: JSON.stringify(opts.collection.images), | ||
scale: opts.scale, | ||
upload: true, | ||
}, | ||
success: function(data) { opts.handleStatusRes(data); }, // this handles the initial response | ||
}); | ||
} | ||
opts.collection = opts.collection || this._group.generateExportJson(); | ||
opts.frequency = opts.frequency || 3000; | ||
opts.scale = opts.scale || 100; // switch it to _getAvgCmPerPixel ! | ||
opts.updater = opts.updater || _defaultUpdater; | ||
opts.handleStatusRes = opts.handleStatusRes || _defaultHandleStatusRes; | ||
opts.fetchStatusUrl = opts.fetchStatusUrl || _defaultFetchStatusUrl; | ||
opts.fetchStatusUrl(opts); | ||
}.bind(this)); | ||
}, | ||
}); | ||
@@ -328,0 +335,0 @@ |
@@ -6,2 +6,3 @@ /* eslint-disable max-len */ | ||
'<symbol viewBox="0 0 18 18" id="border_outer"><path d="M9.75 5.25h-1.5v1.5h1.5v-1.5zm0 3h-1.5v1.5h1.5v-1.5zm3 0h-1.5v1.5h1.5v-1.5zm-10.5-6v13.5h13.5V2.25H2.25zm12 12H3.75V3.75h10.5v10.5zm-4.5-3h-1.5v1.5h1.5v-1.5zm-3-3h-1.5v1.5h1.5v-1.5z"/></symbol>' + | ||
'<symbol viewBox="0 0 18 18" id="cancel"><path d="M13.279 5.779l-1.058-1.058L9 7.942 5.779 4.721 4.721 5.779 7.942 9l-3.221 3.221 1.058 1.058L9 10.057l3.221 3.222 1.058-1.058L10.057 9z"/></symbol>' + | ||
'<symbol viewBox="0 0 18 18" id="crop_rotate"><path d="M5.603 16.117C3.15 14.947 1.394 12.57 1.125 9.75H0C.383 14.37 4.245 18 8.963 18c.172 0 .33-.015.495-.023L6.6 15.113l-.997 1.005zM9.037 0c-.172 0-.33.015-.495.03L11.4 2.888l.998-.998a7.876 7.876 0 0 1 4.477 6.36H18C17.617 3.63 13.755 0 9.037 0zM12 10.5h1.5V6A1.5 1.5 0 0 0 12 4.5H7.5V6H12v4.5zM6 12V3H4.5v1.5H3V6h1.5v6A1.5 1.5 0 0 0 6 13.5h6V15h1.5v-1.5H15V12H6z"/></symbol>' + | ||
@@ -8,0 +9,0 @@ '<symbol viewBox="0 0 18 18" id="delete_forever"><path d="M4.5 14.25c0 .825.675 1.5 1.5 1.5h6c.825 0 1.5-.675 1.5-1.5v-9h-9v9zm1.845-5.34l1.058-1.058L9 9.443l1.59-1.59 1.058 1.058-1.59 1.59 1.59 1.59-1.058 1.058L9 11.558l-1.59 1.59-1.058-1.058 1.59-1.59-1.597-1.59zM11.625 3l-.75-.75h-3.75l-.75.75H3.75v1.5h10.5V3h-2.625z"/></symbol>' + |
@@ -43,2 +43,9 @@ L.Utils = { | ||
}, | ||
getNestedVal: function(obj, key, nestedKey) { | ||
var dig = [key, nestedKey]; | ||
return dig.reduce(function(obj, k) { | ||
return obj && obj[k]; | ||
}, obj); | ||
}, | ||
}; |
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 not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
898869
121
7501