diff --git a/umap/static/umap/base.css b/umap/static/umap/base.css index ac3edea2..748128da 100644 --- a/umap/static/umap/base.css +++ b/umap/static/umap/base.css @@ -163,7 +163,9 @@ select { select[multiple="multiple"] { height: auto; } -.button, input[type="submit"] { +.button, +[type="button"], +input[type="submit"] { display: block; margin-bottom: 14px; text-align: center; @@ -176,18 +178,31 @@ select[multiple="multiple"] { line-height: 32px; border: none; text-decoration: none; + background-color: white; } -.dark .button { +.dark .button, +.dark [type="button"] { background-color: #2a2e30; color: #eeeeec; border: 1px solid #1b1f20; } -.dark .button:hover, .dark input[type="submit"]:hover { +.dark .button:hover, +.dark [type="button"]:hover, +.dark input[type="submit"]:hover { background-color: #2e3436; } .dark a { color: #eeeeec; } +[type="button"].flat, +.dark [type="button"].flat { + border: none; + background-color: inherit; + padding: 0; + text-align: left; + min-height: inherit; + text-decoration: underline; +} .help-text, .helptext { display: block; padding: 7px 7px; @@ -361,7 +376,8 @@ input.switch:checked ~ label:after { .umap-multiplechoice.by4 { grid-template-columns: 1fr 1fr 1fr 1fr; } -.button-bar .button { +.button-bar .button, +.button-bar [type="button"] { display: inline-block; } .umap-multiplechoice input[type='radio'] { @@ -558,10 +574,12 @@ input.blur { border-top-right-radius: 0; border-bottom-right-radius: 0; } -.blur + .button:before { +.blur + .button:before, +.blur + [type="button"]:before { content: '✔'; } -.blur + .button { +.blur + .button, +.blur + [type="button"] { width: 40px; height: 18px; display: inline-block; @@ -571,7 +589,8 @@ input.blur { border-bottom-left-radius: 0; box-sizing: border-box; } -input[type=hidden].blur + .button { +input[type=hidden].blur + .button, +input[type=hidden].blur + [type="button"] { display: none; } @@ -726,6 +745,7 @@ input:invalid { .umap-alert input { padding: 5px; border-radius: 4px; + width: 100%; } /* *********** */ @@ -762,6 +782,19 @@ input:invalid { border-width: 11px; margin-left: calc(-50% + 21px); } +#umap-tooltip-container.tooltip-bottom:before { + top: -22px; + left: calc(50% - 11px); + border: solid transparent; + content: " "; + height: 0; + width: 0; + position: absolute; + pointer-events: none; + border-top-color: rgba(30, 30, 30, 0.7); + border-width: 11px; + transform: rotate(180deg); +} #umap-tooltip-container.tooltip.tooltip-left:after { left: 100%; top: 50%; @@ -807,10 +840,22 @@ input:invalid { color: #fff; float: right; padding-right: 10px; + width: 100px; + line-height: 1; + margin: .5rem; + background-color: #666; + font-size: .7rem; } #umap-alert-container .umap-close-icon { background-position: -74px -55px; } +#umap-alert-container .umap-alert-actions { + display: flex; + margin: 1rem; +} +#umap-alert-container .umap-alert-actions .umap-action { + margin-bottom: 0; +} /* *********** */ diff --git a/umap/static/umap/js/umap.controls.js b/umap/static/umap/js/umap.controls.js index ba459f48..4a81cd93 100644 --- a/umap/static/umap/js/umap.controls.js +++ b/umap/static/umap/js/umap.controls.js @@ -367,18 +367,29 @@ L.U.EditControl = L.Control.extend({ }, onAdd: function (map) { - const container = L.DomUtil.create('div', 'leaflet-control-edit-enable'), - edit = L.DomUtil.create('a', '', container) - edit.href = '#' - edit.title = `${L._('Enable editing')} (Ctrl+E)` - edit.textContent = L._('Edit') - - L.DomEvent.addListener(edit, 'click', L.DomEvent.stop).addListener( - edit, - 'click', + const container = L.DomUtil.create('div', 'leaflet-control-edit-enable') + const enableEditing = L.DomUtil.createButton( + '', + container, + L._('Edit'), map.enableEdit, map ) + L.DomEvent.on( + enableEditing, + 'mouseover', + function () { + map.ui.tooltip({ + content: `${L._('Switch to edit mode')} (Ctrl+E)`, + anchor: enableEditing, + position: 'bottom', + delay: 750, + duration: 5000, + }) + }, + this + ) + return container }, }) @@ -391,15 +402,14 @@ L.Control.Embed = L.Control.extend({ onAdd: function (map) { const container = L.DomUtil.create('div', 'leaflet-control-embed umap-control') - - const link = L.DomUtil.create('a', '', container) - link.href = '#' - link.title = L._('Embed and share this map') - - L.DomEvent.on(link, 'click', L.DomEvent.stop) - .on(link, 'click', map.renderShareBox, map) - .on(link, 'dblclick', L.DomEvent.stopPropagation) - + const shareButton = L.DomUtil.createButton( + '', + container, + L._('Embed and share this map'), + map.renderShareBox, + map + ) + L.DomEvent.on(shareButton, 'dblclick', L.DomEvent.stopPropagation) return container }, }) @@ -410,19 +420,21 @@ L.U.MoreControls = L.Control.extend({ }, onAdd: function () { - const container = L.DomUtil.create('div', 'umap-control-text'), - more = L.DomUtil.create('a', 'umap-control-more', container), - less = L.DomUtil.create('a', 'umap-control-less', container) - more.href = '#' - more.title = L._('More controls') - - L.DomEvent.on(more, 'click', L.DomEvent.stop).on(more, 'click', this.toggle, this) - - less.href = '#' - less.title = L._('Hide controls') - - L.DomEvent.on(less, 'click', L.DomEvent.stop).on(less, 'click', this.toggle, this) - + const container = L.DomUtil.create('div', 'umap-control-text') + const moreButton = L.DomUtil.createButton( + 'umap-control-more', + container, + L._('More controls'), + this.toggle, + this + ) + const lessButton = L.DomUtil.createButton( + 'umap-control-less', + container, + L._('Hide controls'), + this.toggle, + this + ) return container }, @@ -500,23 +512,21 @@ L.U.DataLayersControl = L.Control.extend({ actions ) - const link = L.DomUtil.create('a', 'umap-browse-link', actions) - link.href = '#' - link.title = link.textContent = L._('Browse data') - - const toggle = L.DomUtil.create('a', 'umap-browse-toggle', container) - toggle.href = '#' - toggle.title = L._('See data layers') - - L.DomEvent.on(toggle, 'click', L.DomEvent.stop) - - L.DomEvent.on(link, 'click', L.DomEvent.stop).on( - link, - 'click', + L.DomUtil.createButton( + 'umap-browse-link', + actions, + L._('Browse data'), map.openBrowser, map ) + const toggleButton = L.DomUtil.createButton( + 'umap-browse-toggle', + container, + L._('See data layers') + ) + L.DomEvent.on(toggleButton, 'click', L.DomEvent.stop) + map.whenReady(function () { this.update() }, this) @@ -537,8 +547,8 @@ L.U.DataLayersControl = L.Control.extend({ ) } else { L.DomEvent.on(container, 'click', L.DomEvent.stopPropagation) - L.DomEvent.on(toggle, 'click', L.DomEvent.stop).on( - toggle, + L.DomEvent.on(toggleButton, 'click', L.DomEvent.stop).on( + toggleButton, 'click', this.expand, this @@ -628,14 +638,11 @@ L.U.DataLayersControl = L.Control.extend({ this ) - const bar = L.DomUtil.create('div', 'button-bar', container), - add = L.DomUtil.create('a', 'show-on-edit block add-datalayer button', bar) - add.href = '#' - add.textContent = add.title = L._('Add a layer') - - L.DomEvent.on(add, 'click', L.DomEvent.stop).on( - add, - 'click', + const bar = L.DomUtil.create('div', 'button-bar', container) + L.DomUtil.createButton( + 'show-on-edit block add-datalayer button', + bar, + L._('Add a layer'), this.newDataLayer, this ) @@ -725,7 +732,6 @@ L.U.DataLayer.addInitHook(function () { }) L.U.Map.include({ - _openFacet: function () { const container = L.DomUtil.create('div', 'umap-facet-search'), title = L.DomUtil.add('h3', 'umap-filter-title', container, L._('Facet search')), @@ -825,13 +831,17 @@ L.U.Map.include({ } if (this.options.licence) { const licence = L.DomUtil.add( - 'p', - '', - credits, - `${L._('Map user content has been published under licence')} ` - ), - link = L.DomUtil.add('a', '', licence, this.options.licence.name) - link.href = this.options.licence.url + 'p', + '', + credits, + `${L._('Map user content has been published under licence')} ` + ) + L.DomUtil.createLink( + '', + licence, + this.options.licence.name, + this.options.licence.url + ) } else { L.DomUtil.add('p', '', credits, L._('No licence has been set')) } @@ -929,76 +939,148 @@ L.U.Map.include({ renderEditToolbar: function () { const container = L.DomUtil.create( - 'div', - 'umap-main-edit-toolbox with-transition dark', - this._controlContainer - ), - logo = L.DomUtil.add('a', 'logo', container), - name = L.DomUtil.create('a', 'map-name', container), - share_status = L.DomUtil.create('a', 'share-status', container), - update = () => { - const status = this.permissions.getShareStatusDisplay() - name.textContent = this.getDisplayName() - // status is not set until map is saved once - if (status) - share_status.textContent = L._('Visibility: {status}', { - status: status, - }) + 'div', + 'umap-main-edit-toolbox with-transition dark', + this._controlContainer + ) + const leftContainer = L.DomUtil.create('div', 'umap-left-edit-toolbox', container) + const rightContainer = L.DomUtil.create('div', 'umap-right-edit-toolbox', container) + const logo = L.DomUtil.create('div', 'logo', leftContainer) + L.DomUtil.createLink('', logo, 'uMap', '/', null, L._('Go to the homepage')) + const nameButton = L.DomUtil.createButton( + 'map-name', + leftContainer, + '', + this.edit, + this + ) + L.DomEvent.on( + nameButton, + 'mouseover', + function () { + this.ui.tooltip({ + content: L._('Edit the title of the map'), + anchor: nameButton, + position: 'bottom', + delay: 500, + duration: 5000, + }) + }, + this + ) + const shareStatusButton = L.DomUtil.createButton( + 'share-status', + leftContainer, + '', + this.permissions.edit, + this.permissions + ) + L.DomEvent.on( + shareStatusButton, + 'mouseover', + function () { + this.ui.tooltip({ + content: L._('Update who can see and edit the map'), + anchor: shareStatusButton, + position: 'bottom', + delay: 500, + duration: 5000, + }) + }, + this + ) + const update = () => { + const status = this.permissions.getShareStatusDisplay() + nameButton.textContent = this.getDisplayName() + // status is not set until map is saved once + if (status) { + shareStatusButton.textContent = L._('Visibility: {status}', { + status: status, + }) } + } update() this.once('saved', L.bind(update, this)) - logo.href = '/' if (this.options.editMode === 'advanced') { - name.href = '#' - share_status.href = '#' - L.DomEvent.on(name, 'click', this.edit, this) - L.DomEvent.on(share_status, 'click', this.permissions.edit, this.permissions) + L.DomEvent.on(nameButton, 'click', this.edit, this) + L.DomEvent.on(shareStatusButton, 'click', this.permissions.edit, this.permissions) } this.on('postsync', L.bind(update, this)) - const save = L.DomUtil.create('a', 'leaflet-control-edit-save button', container) - save.href = '#' - save.title = `${L._('Save current edits')} (Ctrl+S)` - save.textContent = L._('Save') - const cancel = L.DomUtil.create('a', 'leaflet-control-edit-cancel', container) - cancel.href = '#' - cancel.title = `${L._('Cancel edits')} (Ctrl+Z)` - cancel.textContent = L._('Cancel all') - const disable = L.DomUtil.create('a', 'leaflet-control-edit-disable', container) - disable.href = '#' - disable.textContent = L._('Disable editing') - disable.title = `${disable.textContent} (Ctrl+E)` - this.help.link(container, 'edit') if (this.options.user) { - const userLabel = L.DomUtil.add( - 'a', + L.DomUtil.createLink( 'umap-user', - container, - L._(`My Dashboard ({username})`, { username: this.options.user.name }) + rightContainer, + L._(`My Dashboard ({username})`, { + username: this.options.user.name, + }), + this.options.user.url ) - userLabel.href = this.options.user.url } - - L.DomEvent.addListener(disable, 'click', L.DomEvent.stop).addListener( - disable, - 'click', + this.help.link(rightContainer, 'edit') + const controlEditCancel = L.DomUtil.createButton( + 'leaflet-control-edit-cancel', + rightContainer, + L.DomUtil.add('span', '', null, L._('Cancel edits')), + this.askForReset, + this + ) + L.DomEvent.on( + controlEditCancel, + 'mouseover', + function () { + this.ui.tooltip({ + content: `${L._('Cancel')} (Ctrl+Z)`, + anchor: controlEditCancel, + position: 'bottom', + delay: 500, + duration: 5000, + }) + }, + this + ) + const controlEditDisable = L.DomUtil.createButton( + 'leaflet-control-edit-disable', + rightContainer, + L.DomUtil.add('span', '', null, L._('View')), function (e) { this.disableEdit(e) this.ui.closePanel() }, this ) - - L.DomEvent.addListener(save, 'click', L.DomEvent.stop).addListener( - save, - 'click', + L.DomEvent.on( + controlEditDisable, + 'mouseover', + function () { + this.ui.tooltip({ + content: `${L._('Back to preview')} (Ctrl+E)`, + anchor: controlEditDisable, + position: 'bottom', + delay: 500, + duration: 5000, + }) + }, + this + ) + const controlEditSave = L.DomUtil.createButton( + 'leaflet-control-edit-save button', + rightContainer, + L.DomUtil.add('span', '', null, L._('Save')), this.save, this ) - - L.DomEvent.addListener(cancel, 'click', L.DomEvent.stop).addListener( - cancel, - 'click', - this.askForReset, + L.DomEvent.on( + controlEditSave, + 'mouseover', + function () { + this.ui.tooltip({ + content: `${L._('Save current edits')} (Ctrl+S)`, + anchor: controlEditSave, + position: 'bottom', + delay: 500, + duration: 5000, + }) + }, this ) }, @@ -1084,12 +1166,19 @@ L.U.Map.include({ } } toggleCaveat() - const download = L.DomUtil.create('a', 'button', container) - download.textContent = L._('Download data') - L.DomEvent.on(download, 'click', () => { - if (typeInput.value === 'umap') this.fullDownload() - else this.download(typeInput.value) - }) + L.DomUtil.createButton( + 'button', + container, + L._('Download data'), + () => { + if (typeInput.value === 'umap') { + this.fullDownload() + } else { + this.download(typeInput.value) + } + }, + this + ) this.ui.openPanel({ data: { html: container } }) }, @@ -1235,15 +1324,14 @@ L.U.TileLayerControl = L.Control.extend({ onAdd: function () { const container = L.DomUtil.create('div', 'leaflet-control-tilelayers umap-control') - - const link = L.DomUtil.create('a', '', container) - link.href = '#' - link.title = L._('Change map background') - - L.DomEvent.on(link, 'click', L.DomEvent.stop) - .on(link, 'click', this.openSwitcher, this) - .on(link, 'dblclick', L.DomEvent.stopPropagation) - + const changeMapBackgroundButton = L.DomUtil.createButton( + '', + container, + L._('Change map background'), + this.openSwitcher, + this + ) + L.DomEvent.on(changeMapBackgroundButton, 'dblclick', L.DomEvent.stopPropagation) return container }, @@ -1300,7 +1388,12 @@ L.U.AttributionControl = L.Control.Attribution.extend({ // Use our how container, so we can hide/show on small screens const credits = this._container.innerHTML this._container.innerHTML = '' - const container = L.DomUtil.add('div', 'attribution-container', this._container, credits) + const container = L.DomUtil.add( + 'div', + 'attribution-container', + this._container, + credits + ) if (this._map.options.shortCredit) { L.DomUtil.add( 'span', @@ -1317,19 +1410,17 @@ L.U.AttributionControl = L.Control.Attribution.extend({ } if (window.top === window.self && this._map.options.captionMenus) { // We are not in iframe mode - const home = L.DomUtil.add('a', '', container, ` — ${L._('Home')}`) - home.href = '/' + L.DomUtil.createLink('', container, ` — ${L._('Home')}`, '/') } if (this._map.options.captionMenus) { - const poweredBy = L.DomUtil.add( - 'a', + L.DomUtil.createLink( '', container, - ` — ${L._('Powered by uMap')}` + ` — ${L._('Powered by uMap')}`, + 'https://github.com/umap-project/umap/' ) - poweredBy.href = 'https://github.com/umap-project/umap/' } - L.DomUtil.create('a', 'attribution-toggle', this._container) + L.DomUtil.createLink('attribution-toggle', this._container, '') }, }) @@ -1341,16 +1432,17 @@ L.U.StarControl = L.Control.extend({ onAdd: function (map) { const status = map.options.starred ? ' starred' : '' const container = L.DomUtil.create( - 'div', - `leaflet-control-star umap-control${status}` - ), - link = L.DomUtil.create('a', '', container) - link.href = '#' - link.title = L._('Star this map') - L.DomEvent.on(link, 'click', L.DomEvent.stop) - .on(link, 'click', map.star, map) - .on(link, 'dblclick', L.DomEvent.stopPropagation) - + 'div', + `leaflet-control-star umap-control${status}` + ) + const starMapButton = L.DomUtil.createButton( + '', + container, + L._('Star this map'), + map.star, + map + ) + L.DomEvent.on(starMapButton, 'dblclick', L.DomEvent.stopPropagation) return container }, }) @@ -1410,17 +1502,18 @@ L.U.SearchControl = L.Control.extend({ }, onAdd: function (map) { - const container = L.DomUtil.create('div', 'leaflet-control-search umap-control'), - self = this - + const container = L.DomUtil.create('div', 'leaflet-control-search umap-control') L.DomEvent.disableClickPropagation(container) - const link = L.DomUtil.create('a', '', container) - link.href = '#' - link.title = L._('Search a place name') - L.DomEvent.on(link, 'click', (e) => { - L.DomEvent.stop(e) - self.openPanel(map) - }) + L.DomUtil.createButton( + '', + container, + L._('Search a place name'), + (e) => { + L.DomEvent.stop(e) + this.openPanel(map) + }, + this + ) return container }, @@ -1626,7 +1719,7 @@ L.U.Editable = L.Editable.extend({ return new L.U.Marker(this.map, latlng, this._getDefaultProperties()) }, - _getDefaultProperties: function() { + _getDefaultProperties: function () { const result = {} if (this.map.options.featuresHaveOwner && this.map.options.hasOwnProperty('user')) { result.geojson = { properties: { owner: this.map.options.user.id } } diff --git a/umap/static/umap/js/umap.core.js b/umap/static/umap/js/umap.core.js index a9398945..5958598b 100644 --- a/umap/static/umap/js/umap.core.js +++ b/umap/static/umap/js/umap.core.js @@ -129,7 +129,10 @@ L.Util.toHTML = (r, options) => { // images r = r.replace(/{{([^\]|]*?)}}/g, '') - r = r.replace(/{{([^|]*?)\|(\d*?)(px)?}}/g, '') + r = r.replace( + /{{([^|]*?)\|(\d*?)(px)?}}/g, + '' + ) //Unescape http r = r.replace(/(h_t_t_p)/g, 'http') @@ -258,32 +261,31 @@ L.Util.hasVar = (value) => { } L.Util.copyToClipboard = function (textToCopy) { - // https://stackoverflow.com/a/65996386 - // Navigator clipboard api needs a secure context (https) - if (navigator.clipboard && window.isSecureContext) { - navigator.clipboard.writeText(textToCopy) - } else { - // Use the 'out of viewport hidden text area' trick - const textArea = document.createElement('textarea') - textArea.value = textToCopy + // https://stackoverflow.com/a/65996386 + // Navigator clipboard api needs a secure context (https) + if (navigator.clipboard && window.isSecureContext) { + navigator.clipboard.writeText(textToCopy) + } else { + // Use the 'out of viewport hidden text area' trick + const textArea = document.createElement('textarea') + textArea.value = textToCopy - // Move textarea out of the viewport so it's not visible - textArea.style.position = 'absolute' - textArea.style.left = '-999999px' + // Move textarea out of the viewport so it's not visible + textArea.style.position = 'absolute' + textArea.style.left = '-999999px' - document.body.prepend(textArea) - textArea.select() + document.body.prepend(textArea) + textArea.select() - try { - document.execCommand('copy') - } catch (error) { - console.error(error) - } finally { - textArea.remove() - } - } + try { + document.execCommand('copy') + } catch (error) { + console.error(error) + } finally { + textArea.remove() } - + } +} L.DomUtil.add = (tagName, className, container, content) => { const el = L.DomUtil.create(tagName, className, container) @@ -314,14 +316,26 @@ L.DomUtil.createFieldset = (container, legend, options) => { } L.DomUtil.createButton = (className, container, content, callback, context) => { - const el = L.DomUtil.add('a', className, container, content) - el.href = '#' + const el = L.DomUtil.add('button', className, container, content) + el.type = 'button' if (callback) { L.DomEvent.on(el, 'click', L.DomEvent.stop).on(el, 'click', callback, context) } return el } +L.DomUtil.createLink = (className, container, content, url, target, title) => { + const el = L.DomUtil.add('a', className, container, content) + el.href = url + if (target) { + el.target = target + } + if (title) { + el.title = title + } + return el +} + L.DomUtil.classIf = (el, className, bool) => { if (bool) L.DomUtil.addClass(el, className) else L.DomUtil.removeClass(el, className) @@ -418,13 +432,17 @@ L.U.Help = L.Class.extend({ 'umap-help-box with-transition dark', document.body ) - const closeLink = L.DomUtil.create('a', 'umap-close-link', this.box) - closeLink.href = '#' - L.DomUtil.add('i', 'umap-close-icon', closeLink) - const label = L.DomUtil.create('span', '', closeLink) + const closeButton = L.DomUtil.createButton( + 'umap-close-link', + this.box, + '', + this.hide, + this + ) + L.DomUtil.add('i', 'umap-close-icon', closeButton) + const label = L.DomUtil.create('span', '', closeButton) label.title = label.textContent = L._('Close') this.content = L.DomUtil.create('div', 'umap-help-content', this.box) - L.DomEvent.on(closeLink, 'click', this.hide, this) }, onKeyDown: function (e) { @@ -457,8 +475,11 @@ L.U.Help = L.Class.extend({ }, button: function (container, entries, classname) { - const helpButton = L.DomUtil.create('a', classname || 'umap-help-button', container) - helpButton.href = '#' + const helpButton = L.DomUtil.createButton( + classname || 'umap-help-button', + container, + L._('Help') + ) if (entries) { L.DomEvent.on(helpButton, 'click', L.DomEvent.stop).on( helpButton, @@ -475,7 +496,7 @@ L.U.Help = L.Class.extend({ link: function (container, entries) { const helpButton = this.button(container, entries, 'umap-help-link') - helpButton.textContent = L._("Help") + helpButton.textContent = L._('Help') return helpButton }, diff --git a/umap/static/umap/js/umap.features.js b/umap/static/umap/js/umap.features.js index aa7eda67..2cbee193 100644 --- a/umap/static/umap/js/umap.features.js +++ b/umap/static/umap/js/umap.features.js @@ -130,12 +130,10 @@ L.U.FeatureMixin = { }, getAdvancedEditActions: function (container) { - const deleteLink = L.DomUtil.create('a', 'button umap-delete', container) - deleteLink.href = '#' - deleteLink.textContent = L._('Delete') - L.DomEvent.on( - deleteLink, - 'click', + const deleteButton = L.DomUtil.createButton( + 'button umap-delete', + container, + L._('Delete'), function (e) { L.DomEvent.stop(e) if (this.confirmDelete()) this.map.ui.closePanel() @@ -1018,10 +1016,13 @@ L.U.Polyline = L.Polyline.extend({ getAdvancedEditActions: function (container) { L.U.FeatureMixin.getAdvancedEditActions.call(this, container) - const toPolygon = L.DomUtil.create('a', 'button umap-to-polygon', container) - toPolygon.href = '#' - toPolygon.textContent = L._('Transform to polygon') - L.DomEvent.on(toPolygon, 'click', this.toPolygon, this) + const toPolygon = L.DomUtil.createButton( + 'button umap-to-polygon', + container, + L._('Transform to polygon'), + this.toPolygon, + this + ) }, _mergeShapes: function (from, to) { @@ -1165,10 +1166,13 @@ L.U.Polygon = L.Polygon.extend({ getAdvancedEditActions: function (container) { L.U.FeatureMixin.getAdvancedEditActions.call(this, container) - const toPolyline = L.DomUtil.create('a', 'button umap-to-polyline', container) - toPolyline.href = '#' - toPolyline.textContent = L._('Transform to lines') - L.DomEvent.on(toPolyline, 'click', this.toPolyline, this) + const toPolyline = L.DomUtil.createButton( + 'button umap-to-polyline', + container, + L._('Transform to lines'), + this.toPolyline, + this + ) }, isMulti: function () { diff --git a/umap/static/umap/js/umap.forms.js b/umap/static/umap/js/umap.forms.js index fe3892f2..d5411ef5 100644 --- a/umap/static/umap/js/umap.forms.js +++ b/umap/static/umap/js/umap.forms.js @@ -397,7 +397,11 @@ L.FormBuilder.DataLayerSwitcher = L.FormBuilder.Select.extend({ getOptions: function () { const options = [] this.builder.map.eachDataLayerReverse((datalayer) => { - if (datalayer.isLoaded() && !datalayer.isDataReadOnly() && datalayer.canBrowse()) { + if ( + datalayer.isLoaded() && + !datalayer.isDataReadOnly() && + datalayer.canBrowse() + ) { options.push([L.stamp(datalayer), datalayer.getName()]) } }) @@ -557,12 +561,10 @@ L.FormBuilder.IconUrl = L.FormBuilder.BlurInput.extend({ L.DomEvent.on(el, 'click', this.fetchIconList, this) } } - this.button = L.DomUtil.create('a', 'button action-button', this.buttonsContainer) - this.button.textContent = this.value() ? L._('Change') : L._('Add') - this.button.href = '#' - L.DomEvent.on(this.button, 'click', L.DomEvent.stop).on( - this.button, - 'click', + this.button = L.DomUtil.createButton( + 'button action-button', + this.buttonsContainer, + this.value() ? L._('Change') : L._('Add'), this.fetchIconList, this ) @@ -616,34 +618,29 @@ L.FormBuilder.IconUrl = L.FormBuilder.BlurInput.extend({ for (const idx in data.pictogram_list) { this.addIconPreview(data.pictogram_list[idx]) } - const closeButton = L.DomUtil.create('a', 'button action-button', this.pictogramsContainer) - closeButton.textContent = L._('Close') - closeButton.href = '#' - closeButton.style.display = 'block' - closeButton.style.clear = 'both' - L.DomEvent.on(closeButton, 'click', L.DomEvent.stop).on( - closeButton, - 'click', + const closeButton = L.DomUtil.createButton( + 'button action-button', + this.pictogramsContainer, + L._('Close'), function (e) { this.pictogramsContainer.innerHTML = '' this.udpatePreview() }, this ) - const customButton = L.DomUtil.create('a', '', this.pictogramsContainer) - customButton.textContent = L._('Toggle direct input (advanced)') - customButton.href = '#' - customButton.style.display = 'block' - customButton.style.clear = 'both' - this.builder.map.help.button(customButton, 'formatIconSymbol') - L.DomEvent.on(customButton, 'click', L.DomEvent.stop).on( - customButton, - 'click', + closeButton.style.display = 'block' + closeButton.style.clear = 'both' + + const customButton = L.DomUtil.createButton( + 'flat', + this.pictogramsContainer, + L._('Toggle direct input (advanced)'), function (e) { this.input.type = this.input.type === 'text' ? 'hidden' : 'text' }, this ) + this.builder.map.help.button(customButton, 'formatIconSymbol') }, fetchIconList: function (e) { @@ -733,7 +730,10 @@ L.FormBuilder.MultiChoice = L.FormBuilder.Element.extend({ fetch: function () { let value = (this.backup = this.toHTML()) if (!this.container.querySelector(`input[type="radio"][value="${value}"]`)) - value = typeof(this.options.default) !== 'undefined' ? this.options.default : this.default + value = + typeof this.options.default !== 'undefined' + ? this.options.default + : this.default this.container.querySelector(`input[type="radio"][value="${value}"]`).checked = true }, @@ -843,7 +843,9 @@ L.FormBuilder.Range = L.FormBuilder.FloatInput.extend({ }, value: function () { - return L.DomUtil.hasClass(this.wrapper, 'undefined') ? undefined : L.FormBuilder.FloatInput.prototype.value.call(this) + return L.DomUtil.hasClass(this.wrapper, 'undefined') + ? undefined + : L.FormBuilder.FloatInput.prototype.value.call(this) }, buildHelpText: function () { @@ -858,7 +860,9 @@ L.FormBuilder.Range = L.FormBuilder.FloatInput.extend({ const step = this.options.step || 1, digits = step < 1 ? 1 : 0 for (let i = this.options.min; i <= this.options.max; i += this.options.step) { - options += `` + options += `` } datalist.innerHTML = options L.FormBuilder.Input.prototype.buildHelpText.call(this) diff --git a/umap/static/umap/js/umap.js b/umap/static/umap/js/umap.js index 1ab612bd..3e1a9fe3 100644 --- a/umap/static/umap/js/umap.js +++ b/umap/static/umap/js/umap.js @@ -1558,16 +1558,10 @@ L.U.Map.include({ }) limitBounds.appendChild(boundsBuilder.build()) const boundsButtons = L.DomUtil.create('div', 'button-bar half', limitBounds) - const setCurrentButton = L.DomUtil.add( - 'a', + L.DomUtil.createButton( 'button', boundsButtons, - L._('Use current bounds') - ) - setCurrentButton.href = '#' - L.DomEvent.on( - setCurrentButton, - 'click', + L._('Use current bounds'), function () { const bounds = this.getBounds() this.options.limitBounds.south = L.Util.formatNum(bounds.getSouth()) @@ -1580,11 +1574,10 @@ L.U.Map.include({ }, this ) - const emptyBounds = L.DomUtil.add('a', 'button', boundsButtons, L._('Empty')) - emptyBounds.href = '#' - L.DomEvent.on( - emptyBounds, - 'click', + L.DomUtil.createButton( + 'button', + boundsButtons, + L._('Empty'), function () { this.options.limitBounds.south = null this.options.limitBounds.west = null @@ -1676,34 +1669,39 @@ L.U.Map.include({ const advancedActions = L.DomUtil.createFieldset(container, L._('Advanced actions')) const advancedButtons = L.DomUtil.create('div', 'button-bar half', advancedActions) if (this.permissions.isOwner()) { - const del = L.DomUtil.create('a', 'button umap-delete', advancedButtons) - del.href = '#' - del.title = L._('Delete map') - del.textContent = L._('Delete') - L.DomEvent.on(del, 'click', L.DomEvent.stop).on(del, 'click', this.del, this) - const empty = L.DomUtil.create('a', 'button umap-empty', advancedButtons) - empty.href = '#' - empty.textContent = L._('Empty') - empty.title = L._('Delete all layers') - L.DomEvent.on(empty, 'click', L.DomEvent.stop).on( - empty, - 'click', + L.DomUtil.createButton( + 'button umap-delete', + advancedButtons, + L._('Delete'), + this.del, + this + ) + L.DomUtil.createButton( + 'button umap-empty', + advancedButtons, + L._('Empty'), this.empty, this ) } - const clone = L.DomUtil.create('a', 'button umap-clone', advancedButtons) - clone.href = '#' - clone.textContent = L._('Clone') - clone.title = L._('Clone this map') - L.DomEvent.on(clone, 'click', L.DomEvent.stop).on(clone, 'click', this.clone, this) - const download = L.DomUtil.create('a', 'button umap-download', advancedButtons) - download.href = '#' - download.textContent = L._('Download') - download.title = L._('Open download panel') - L.DomEvent.on(download, 'click', L.DomEvent.stop).on( - download, - 'click', + L.DomUtil.createButton( + 'button umap-clone', + advancedButtons, + L._('Clone this map'), + this.clone, + this + ) + L.DomUtil.createButton( + 'button umap-empty', + advancedButtons, + L._('Delete all layers'), + this.empty, + this + ) + L.DomUtil.createButton( + 'button umap-download', + advancedButtons, + L._('Open download panel'), this.renderShareBox, this ) @@ -1767,38 +1765,25 @@ L.U.Map.include({ L.DomEvent.disableClickPropagation(container) this.permissions.addOwnerLink('span', container) if (this.options.captionMenus) { - const about = L.DomUtil.add( - 'a', + L.DomUtil.createButton( 'umap-about-link', container, - ` — ${L._('About')}` + ` — ${L._('About')}`, + this.displayCaption, + this ) - about.href = '#' - L.DomEvent.on(about, 'click', this.displayCaption, this) - const browser = L.DomUtil.add( - 'a', + L.DomUtil.createButton( 'umap-open-browser-link', container, - ` | ${L._('Browse data')}` - ) - browser.href = '#' - L.DomEvent.on(browser, 'click', L.DomEvent.stop).on( - browser, - 'click', + ` | ${L._('Browse data')}`, this.openBrowser, this ) if (this.options.facetKey) { - const filter = L.DomUtil.add( - 'a', + L.DomUtil.createButton( 'umap-open-filter-link', container, - ` | ${L._('Select data')}` - ) - filter.href = '#' - L.DomEvent.on(filter, 'click', L.DomEvent.stop).on( - filter, - 'click', + ` | ${L._('Select data')}`, this.openFacet, this ) diff --git a/umap/static/umap/js/umap.layer.js b/umap/static/umap/js/umap.layer.js index d2661d24..7b751a47 100644 --- a/umap/static/umap/js/umap.layer.js +++ b/umap/static/umap/js/umap.layer.js @@ -1273,16 +1273,10 @@ L.U.DataLayer = L.Evented.extend({ const advancedActions = L.DomUtil.createFieldset(container, L._('Advanced actions')) const advancedButtons = L.DomUtil.create('div', 'button-bar half', advancedActions) - const deleteLink = L.DomUtil.create( - 'a', + const deleteLink = L.DomUtil.createButton( 'button delete_datalayer_button umap-delete', - advancedButtons - ) - deleteLink.textContent = L._('Delete') - deleteLink.href = '#' - L.DomEvent.on(deleteLink, 'click', L.DomEvent.stop).on( - deleteLink, - 'click', + advancedButtons, + L._('Delete'), function () { this._delete() this.map.ui.closePanel() @@ -1290,22 +1284,18 @@ L.U.DataLayer = L.Evented.extend({ this ) if (!this.isRemoteLayer()) { - const emptyLink = L.DomUtil.create('a', 'button umap-empty', advancedButtons) - emptyLink.textContent = L._('Empty') - emptyLink.href = '#' - L.DomEvent.on(emptyLink, 'click', L.DomEvent.stop).on( - emptyLink, - 'click', + const emptyLink = L.DomUtil.createButton( + 'button umap-empty', + advancedButtons, + L._('Empty'), this.empty, this ) } - const cloneLink = L.DomUtil.create('a', 'button umap-clone', advancedButtons) - cloneLink.textContent = L._('Clone') - cloneLink.href = '#' - L.DomEvent.on(cloneLink, 'click', L.DomEvent.stop).on( - cloneLink, - 'click', + const cloneLink = L.DomUtil.createButton( + 'button umap-clone', + advancedButtons, + L._('Clone'), function () { const datalayer = this.clone() datalayer.edit() @@ -1313,10 +1303,13 @@ L.U.DataLayer = L.Evented.extend({ this ) if (this.umap_id) { - const download = L.DomUtil.create('a', 'button umap-download', advancedButtons) - download.textContent = L._('Download') - download.href = this._dataUrl() - download.target = '_blank' + const download = L.DomUtil.createLink( + 'button umap-download', + advancedButtons, + L._('Download'), + this._dataUrl(), + '_blank' + ) } this.map.ui.openPanel({ data: { html: container }, className: 'dark' }) }, @@ -1344,16 +1337,14 @@ L.U.DataLayer = L.Evented.extend({ const date = new Date(parseInt(data.at, 10)) const content = `${date.toLocaleString(L.lang)} (${parseInt(data.size) / 1000}Kb)` const el = L.DomUtil.create('div', 'umap-datalayer-version', versionsContainer) - const a = L.DomUtil.create('a', '', el) - L.DomUtil.add('span', '', el, content) - a.href = '#' - a.title = L._('Restore this version') - L.DomEvent.on(a, 'click', L.DomEvent.stop).on( - a, - 'click', + const a = L.DomUtil.createButton( + '', + el, + L._('Restore this version'), () => this.restore(data.name), this ) + L.DomUtil.add('span', '', el, content) } const versionsContainer = L.DomUtil.createFieldset(container, L._('Versions'), { diff --git a/umap/static/umap/js/umap.permissions.js b/umap/static/umap/js/umap.permissions.js index 7e277503..1687e142 100644 --- a/umap/static/umap/js/umap.permissions.js +++ b/umap/static/umap/js/umap.permissions.js @@ -116,12 +116,10 @@ L.U.MapPermissions = L.Class.extend({ L._('Advanced actions') ) const advancedButtons = L.DomUtil.create('div', 'button-bar', advancedActions) - const download = L.DomUtil.create('a', 'button', advancedButtons) - download.href = '#' - download.textContent = L._('Attach the map to my account') - L.DomEvent.on(download, 'click', L.DomEvent.stop).on( - download, - 'click', + const download = L.DomUtil.createButton( + 'button', + advancedButtons, + L._('Attach the map to my account'), this.attach, this ) @@ -188,15 +186,17 @@ L.U.MapPermissions = L.Class.extend({ addOwnerLink: function (element, container) { if (this.options.owner && this.options.owner.name && this.options.owner.url) { const ownerContainer = L.DomUtil.add( - element, - 'umap-map-owner', - container, - ` ${L._('by')} ` - ), - owner = L.DomUtil.create('a') - owner.href = this.options.owner.url - owner.textContent = this.options.owner.name - ownerContainer.appendChild(owner) + element, + 'umap-map-owner', + container, + ` ${L._('by')} ` + ) + L.DomUtil.createLink( + '', + ownerContainer, + this.options.owner.name, + this.options.owner.url + ) } }, diff --git a/umap/static/umap/js/umap.popup.js b/umap/static/umap/js/umap.popup.js index 9fd96b3c..9487890c 100644 --- a/umap/static/umap/js/umap.popup.js +++ b/umap/static/umap/js/umap.popup.js @@ -107,7 +107,7 @@ L.U.PopupTemplate.Default = L.Class.extend({ properties ) content = L.Util.greedyTemplate(template, properties) - content = L.Util.toHTML(content, {target: target}) + content = L.Util.toHTML(content, { target: target }) container.innerHTML = content return container }, diff --git a/umap/static/umap/js/umap.ui.js b/umap/static/umap/js/umap.ui.js index 28bb6403..30386915 100644 --- a/umap/static/umap/js/umap.ui.js +++ b/umap/static/umap/js/umap.ui.js @@ -93,41 +93,36 @@ L.U.UI = L.Evented.extend({ if (timeoutID) window.clearTimeout(timeoutID) this.popAlert() } - const closeLink = L.DomUtil.create('a', 'umap-close-link', this._alert) - closeLink.href = '#' - L.DomUtil.add('i', 'umap-close-icon', closeLink) - const label = L.DomUtil.create('span', '', closeLink) - label.title = label.textContent = L._('Close') - L.DomEvent.on(closeLink, 'click', L.DomEvent.stop).on( - closeLink, - 'click', + const closeButton = L.DomUtil.createButton( + 'umap-close-link', + this._alert, + '', close, this ) + L.DomUtil.add('i', 'umap-close-icon', closeButton) + const label = L.DomUtil.create('span', '', closeButton) + label.title = label.textContent = L._('Close') L.DomUtil.add('div', '', this._alert, e.content) if (e.actions) { let action, el, input + const form = L.DomUtil.add('div', 'umap-alert-actions', this._alert) for (let i = 0; i < e.actions.length; i++) { action = e.actions[i] if (action.input) { input = L.DomUtil.element( 'input', { className: 'umap-alert-input', placeholder: action.input }, - this._alert - ) - } - el = L.DomUtil.element('a', { className: 'umap-action' }, this._alert) - el.href = '#' - el.textContent = action.label - L.DomEvent.on(el, 'click', L.DomEvent.stop) - if (action.callback) { - L.DomEvent.on( - el, - 'click', - action.callback, - action.callbackContext || this.map + form ) } + el = L.DomUtil.createButton( + 'umap-action', + form, + action.label, + action.callback, + action.callbackContext || this.map + ) L.DomEvent.on(el, 'click', close, this) } } @@ -139,20 +134,32 @@ L.U.UI = L.Evented.extend({ } }, - tooltip: function (e) { + tooltip: function (opts) { this.TOOLTIP_ID = Math.random() const id = this.TOOLTIP_ID - L.DomUtil.addClass(this.parent, 'umap-tooltip') - if (e.anchor && e.position === 'top') this.anchorTooltipTop(e.anchor) - else if (e.anchor && e.position === 'left') this.anchorTooltipLeft(e.anchor) - else this.anchorTooltipAbsolute() - this._tooltip.innerHTML = e.content + function showIt() { + if (opts.anchor && opts.position === 'top') { + this.anchorTooltipTop(opts.anchor) + } else if (opts.anchor && opts.position === 'left') { + this.anchorTooltipLeft(opts.anchor) + } else if (opts.anchor && opts.position === 'bottom') { + this.anchorTooltipBottom(opts.anchor) + } else { + this.anchorTooltipAbsolute() + } + L.DomUtil.addClass(this.parent, 'umap-tooltip') + this._tooltip.innerHTML = opts.content + } function closeIt() { this.closeTooltip(id) } - if (e.anchor) L.DomEvent.once(e.anchor, 'mouseout', closeIt, this) - if (e.duration !== Infinity) - window.setTimeout(L.bind(closeIt, this), e.duration || 3000) + window.setTimeout(L.bind(showIt, this), opts.delay || 0) + if (opts.anchor) { + L.DomEvent.once(opts.anchor, 'mouseout', closeIt, this) + } + if (opts.duration !== Infinity) { + window.setTimeout(L.bind(closeIt, this), opts.duration || 3000) + } }, anchorTooltipAbsolute: function () { @@ -174,6 +181,15 @@ L.U.UI = L.Evented.extend({ }) }, + anchorTooltipBottom: function (el) { + this._tooltip.className = 'tooltip-bottom' + const coords = this.getPosition(el) + this.setTooltipPosition({ + left: coords.left, + top: coords.bottom + 11, + }) + }, + anchorTooltipLeft: function (el) { this._tooltip.className = 'tooltip-left' const coords = this.getPosition(el) @@ -185,7 +201,9 @@ L.U.UI = L.Evented.extend({ closeTooltip: function (id) { if (id && id !== this.TOOLTIP_ID) return + this._tooltip.className = '' this._tooltip.innerHTML = '' + this.setTooltipPosition({}) L.DomUtil.removeClass(this.parent, 'umap-tooltip') }, diff --git a/umap/static/umap/map.css b/umap/static/umap/map.css index 41e7977c..8661922a 100644 --- a/umap/static/umap/map.css +++ b/umap/static/umap/map.css @@ -42,7 +42,8 @@ } .leaflet-measure-control a, .leaflet-control-locate a, -.umap-control a { +.umap-control a, +.umap-control [type="button"] { background-position: 50% 50%; background-repeat: no-repeat; display: block; @@ -50,15 +51,19 @@ width: 36px; line-height: 36px; background-image: url('./img/24.svg'); + text-indent: -9999px; + margin-bottom: 0; } .leaflet-control.display-on-more, -a.umap-control-less { +.umap-control-less { display: none; } .umap-control-more, .umap-control-less { background-image: url('./img/24-white.svg'); background-position: -72px -474px; + text-indent: -9999px; + margin-bottom: 0; } .umap-control-less { background-position: -108px -476px; @@ -70,13 +75,13 @@ a.umap-control-less { .umap-more-controls .umap-control-more { display: none; } -.leaflet-control-embed a { +.leaflet-control-embed [type="button"] { background-position: -72px -108px; } -.leaflet-control-tilelayers a { +.leaflet-control-tilelayers [type="button"] { background-position: -72px 0; } -.leaflet-control-home a { +.leaflet-control-home [type="button"] { background-position: -122px -82px; } .leaflet-control-locate a { @@ -88,17 +93,17 @@ a.umap-control-less { background-position: -72px -144px; box-shadow: 0 0 4px 0 black inset; } -.leaflet-control-star a { +.leaflet-control-star [type="button"] { background-position: -108px -144px; } -.leaflet-control-star.starred a { +.leaflet-control-star.starred [type="button"] { background-position: -144px -144px; } -.leaflet-control-search a { +.leaflet-control-search [type="button"] { background-position: -36px -108px; display: block; } -.leaflet-control-search a.loading { +.leaflet-control-search [type="button"].loading { background-image: url('./img/search.gif'); } .umap-control-text { @@ -109,14 +114,15 @@ a.umap-control-less { text-align: center; font-size: 0.8em; } -.umap-control-text a { +.umap-control-text [type="button"] { float: right; + background-color: #666; margin: 0; width: 36px; + min-height: 23px; height: 23px; - line-height: 23px; } -.leaflet-control-edit-enable a:before { +.leaflet-control-edit-enable [type="button"]:before { content: ' '; width: 24px; height: 24px; @@ -126,7 +132,7 @@ a.umap-control-less { background-position: -52px -49px; } -.leaflet-control-edit-enable a { +.leaflet-control-edit-enable [type="button"] { width: initial; padding: 0 20px; background-color: #353c3e; @@ -138,7 +144,7 @@ a.umap-control-less { display: block; } .leaflet-control-toolbar .leaflet-toolbar-icon.dark:hover, -.leaflet-control-edit-enable a:hover { +.leaflet-control-edit-enable [type="button"]:hover { background-color: #4d5759; } .umap-permanent-credits-container { @@ -320,6 +326,7 @@ ul.photon-autocomplete { border: 1px solid #bbb; border-radius: 4px; box-shadow: none; + background-color: white; } .leaflet-measure-control a { background-position: 0 -72px; @@ -353,6 +360,7 @@ ul.photon-autocomplete { } .umap-help-box .umap-close-link { float: right; + width: 100px; } .umap-help-button { display: inline-block; @@ -362,15 +370,16 @@ ul.photon-autocomplete { background-position: -4px -4px; background-repeat: no-repeat; background-image: url('./img/16.svg'); + background-color: #323737 !important; vertical-align: middle; + text-indent: -9999px; + min-height: inherit; + padding-top: 5px; + border: none !important; } .dark .umap-help-button { background-image: url('./img/16-white.svg'); } -.umap-help-link { - float: right; - margin-right: 20px; -} .umap-help-on .umap-help-box { visibility: visible; top: 100px; @@ -411,27 +420,37 @@ ul.photon-autocomplete { /* ********************************* */ /* Edit main toolbox */ /* ********************************* */ +.umap-main-edit-toolbox [type="button"] { + color: #fff; + font-size: 1.2em; + border: none; + background-color: #323737; + width: auto; + margin-bottom: 0; +} +.umap-main-edit-toolbox [type="button"]:hover { + text-decoration: underline; +} -.leaflet-container a.leaflet-control-edit-save, -.leaflet-container a.leaflet-control-edit-cancel, -.leaflet-container a.leaflet-control-edit-disable { +.leaflet-container .umap-help-link { + font-size: 12px; +} +.leaflet-container .leaflet-control-edit-save, +.leaflet-container .leaflet-control-edit-cancel, +.leaflet-container .leaflet-control-edit-disable { display: block; border: none; - font-size: 11px; - margin-left: 10px; - float: right; + font-size: 12px; border-radius: 20px; color: #f8f8f8; - width: auto; height: 36px; line-height: 36px; min-height: 36px; padding: 0 20px; - min-width: 100px; } -.leaflet-container a.leaflet-control-edit-disable:before, -.leaflet-container a.leaflet-control-edit-save:before, -.leaflet-container a.leaflet-control-edit-cancel:before { +.leaflet-container .leaflet-control-edit-disable:before, +.leaflet-container .leaflet-control-edit-save:before, +.leaflet-container .leaflet-control-edit-cancel:before { display: inline-block; width: 24px; height: 24px; @@ -441,37 +460,40 @@ ul.photon-autocomplete { vertical-align: middle; content: ' '; } -.leaflet-container a.leaflet-control-edit-save:before { +.leaflet-container .leaflet-control-edit-save:before { background-position: -2px -25px; } -.leaflet-container a.leaflet-control-edit-disable:before { - background-position: -26px -1px; +.leaflet-container .leaflet-control-edit-disable:before { + background-position: -52px -25px; } -.leaflet-container a.leaflet-control-edit-cancel, -.leaflet-container a.leaflet-control-edit-disable { +.leaflet-container .leaflet-control-edit-cancel, +.leaflet-container .leaflet-control-edit-disable { border: 1px solid #555; } -.leaflet-container a.leaflet-control-edit-save { +.leaflet-container .leaflet-control-edit-save { opacity: 0.5; cursor: not-allowed; background-color: #215d9c; } -.umap-is-dirty a.leaflet-control-edit-save { +.umap-is-dirty .leaflet-control-edit-save { opacity: 1; cursor: pointer; } -.leaflet-container a.leaflet-control-edit-save, -.leaflet-container a.leaflet-control-edit-cancel, -.leaflet-container a.leaflet-control-edit-disable, +.umap-is-dirty .leaflet-control-edit-save:hover { + background-color: #215d9c; +} +.leaflet-container .leaflet-control-edit-save, +.leaflet-container .leaflet-control-edit-cancel, +.leaflet-container .leaflet-control-edit-disable, .umap-edit-enabled .leaflet-control-edit-enable { display: none; } -.umap-edit-enabled a.leaflet-control-edit-save, -.umap-edit-enabled a.leaflet-control-edit-disable, -.umap-edit-enabled .umap-is-dirty a.leaflet-control-edit-cancel { +.umap-edit-enabled .leaflet-control-edit-save, +.umap-edit-enabled .leaflet-control-edit-disable, +.umap-edit-enabled .umap-is-dirty .leaflet-control-edit-cancel { display: inline-block; } -.umap-is-dirty a.leaflet-control-edit-disable { +.umap-is-dirty .leaflet-control-edit-disable { display: none; } .umap-caption-bar { @@ -485,7 +507,7 @@ ul.photon-autocomplete { right: 0; height: 46px; background-color: #323737; - padding: 5px 10px; + padding: 0 10px; text-align: left; line-height: 36px; cursor: auto; @@ -493,45 +515,56 @@ ul.photon-autocomplete { z-index: 1000; opacity: 0.98; color: #fff; + display: flex; + justify-content: space-between; } +.umap-left-edit-toolbox, +.umap-right-edit-toolbox { + display: flex; + column-gap: 10px; +} +.umap-right-edit-toolbox { + align-items: baseline; +} + .umap-main-edit-toolbox .logo { + width: 39px; + height: 100%; +} +.umap-main-edit-toolbox .logo a { background-image: url('./img/logo_small.svg'); background-position: 0 center; background-repeat: no-repeat; - width: 60px; display: inline-block; + width: 39px; height: 100%; vertical-align: middle; -} -.umap-main-edit-toolbox a { - color: #fff; - font-size: 1.2em; - vertical-align: middle; -} -.umap-main-edit-toolbox a:hover { - text-decoration: underline; + text-indent: -9999px; } .umap-main-edit-toolbox .map-name { display: inline-block; - max-width: 200px; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; - margin-right: 5px; font-weight: bold; + text-align: left; } -a.map-name:after { +.umap-main-edit-toolbox .share-status { + font-size: 1em; + font-style: italic; + overflow: hidden; + text-overflow: ellipsis; +} + +.map-name:after { content: '\00a0'; padding-left: 3px; width: 1ch; display: inline-block; } -.umap-is-dirty a.map-name:after { +.umap-is-dirty .map-name:after { content: '*'; } -.umap-main-edit-toolbox .share-status { - margin: 0 20px; -} .umap-edit-enabled .umap-main-edit-toolbox { top: 0; } @@ -543,12 +576,15 @@ a.map-name:after { display: inline; } .umap-main-edit-toolbox .umap-user { - margin-right: 20px; - float: right; + color: #fff; +} +.umap-main-edit-toolbox .umap-user:hover { + text-decoration: underline; } .umap-main-edit-toolbox .umap-user:after { content: '|'; padding-left: 20px; + display: inline-block; /* Prevents underline on hover. */ } .umap-edit-enabled .leaflet-top { top: 48px; @@ -813,13 +849,14 @@ a.map-name:after { .leaflet-control-browse .umap-browse-actions .off .layer-title { color: rgb(179, 179, 179); } -.leaflet-control-browse.expanded > a { +.leaflet-control-browse.expanded > a, +.leaflet-control-browse.expanded > button { display: none; } .leaflet-control-browse.expanded .umap-browse-actions { display: block; } -.leaflet-control-browse a.umap-browse-link { +.leaflet-control-browse .umap-browse-link { background-image: none; background-color: rgb(68, 68, 68); color: white; @@ -834,7 +871,7 @@ a.map-name:after { border-radius: 2px; } a.add-datalayer:before, -.leaflet-control-browse a.umap-browse-link:before { +.leaflet-control-browse .umap-browse-link:before { background-image: url('./img/16.svg'); background-repeat: no-repeat; background-position: -45px -96px; @@ -848,7 +885,7 @@ a.add-datalayer:before { background-position: -20px -20px; } a.add-datalayer:hover, -.leaflet-control-browse a.umap-browse-link:hover { +.leaflet-control-browse .umap-browse-link:hover { background-color: rgb(99, 99, 99); } .umap-browse-data .off .feature { @@ -1513,14 +1550,12 @@ a.add-datalayer:hover, @media all and (max-width: 980px) { - .leaflet-container a.leaflet-control-edit-save, - .leaflet-container a.leaflet-control-edit-disable, - .leaflet-container a.leaflet-control-edit-cancel { - text-indent: calc(100% - 10px); - width: 35px; - min-width: initial; + .umap-main-edit-toolbox .umap-user span, + .leaflet-container .leaflet-control-edit-save span, + .leaflet-container .leaflet-control-edit-disable span, + .leaflet-container .leaflet-control-edit-cancel span { + display: none; } - .umap-main-edit-toolbox .umap-help-button { display: none; } @@ -1530,7 +1565,15 @@ a.add-datalayer:hover, .umap-main-edit-toolbox .umap-user:after { display: none; } +} +@media all and (max-width: 640px) { + .umap-main-edit-toolbox .umap-user { + display: none; + } + .umap-main-edit-toolbox .map-name { + max-width: 150px; + } } @media all and (max-width: 480px) { diff --git a/umap/static/umap/test/Choropleth.js b/umap/static/umap/test/Choropleth.js index f87e7cce..1cd8c2ec 100644 --- a/umap/static/umap/test/Choropleth.js +++ b/umap/static/umap/test/Choropleth.js @@ -205,7 +205,7 @@ describe('L.U.Choropleth', function () { }) after(function () { this.server.restore() - //resetMap() + resetMap() }) describe('#init()', function () { diff --git a/umap/static/umap/test/Controls.js b/umap/static/umap/test/Controls.js index 5541376b..00616316 100644 --- a/umap/static/umap/test/Controls.js +++ b/umap/static/umap/test/Controls.js @@ -78,7 +78,7 @@ describe('L.U.Controls', function () { describe('#exportPanel()', function () { it('should be opened at datalayer button click', function () { - let button = qs('.leaflet-control-embed a') + let button = qs('.leaflet-control-embed button') assert.ok(button) happen.click(button) assert.ok(qs('#umap-ui-container .umap-share')) diff --git a/umap/static/umap/test/DataLayer.js b/umap/static/umap/test/DataLayer.js index c2094f90..3c545ff8 100644 --- a/umap/static/umap/test/DataLayer.js +++ b/umap/static/umap/test/DataLayer.js @@ -341,7 +341,7 @@ describe('L.U.DataLayer', function () { happen.click( qs('#browse_data_toggle_' + L.stamp(this.datalayer) + ' .layer-edit') ) - deleteLink = qs('a.delete_datalayer_button') + deleteLink = qs('button.delete_datalayer_button') assert.ok(deleteLink) }) diff --git a/umap/static/umap/test/Map.js b/umap/static/umap/test/Map.js index 9bcc7cfb..12b64d73 100644 --- a/umap/static/umap/test/Map.js +++ b/umap/static/umap/test/Map.js @@ -50,7 +50,7 @@ describe('L.U.Map', function () { }) it('enable edit on click on toggle button', function () { - var el = qs('div.leaflet-control-edit-enable a') + var el = qs('div.leaflet-control-edit-enable button') happen.click(el) assert.isTrue(L.DomUtil.hasClass(document.body, 'umap-edit-enabled')) }) @@ -109,7 +109,7 @@ describe('L.U.Map', function () { var button = qs('a.update-map-settings') assert.ok(button, 'update map info button exists') happen.click(button) - var deleteLink = qs('a.umap-delete') + var deleteLink = qs('button.umap-delete') assert.ok(deleteLink, 'delete map button exists') sinon.spy(window, 'confirm') this.server.respondWith('POST', path, JSON.stringify({ redirect: '#' })) @@ -301,7 +301,7 @@ describe('L.U.Map', function () { }) it('should update title bar (umap format import)', function () { - var title = qs('#map div.umap-main-edit-toolbox a.map-name') + var title = qs('#map div.umap-main-edit-toolbox button.map-name') assert.equal(title.innerHTML, 'Imported map') }) diff --git a/umap/static/umap/test/_pre.js b/umap/static/umap/test/_pre.js index dda0c79e..5df2e152 100644 --- a/umap/static/umap/test/_pre.js +++ b/umap/static/umap/test/_pre.js @@ -44,20 +44,20 @@ var resetMap = function () { document.body.className = '' } var enableEdit = function () { - happen.click(qs('div.leaflet-control-edit-enable a')) + happen.click(qs('div.leaflet-control-edit-enable button')) } var disableEdit = function () { - happen.click(qs('a.leaflet-control-edit-disable')) + happen.click(qs('.leaflet-control-edit-disable')) } var clickSave = function () { - happen.click(qs('a.leaflet-control-edit-save')) + happen.click(qs('.leaflet-control-edit-save')) } var clickCancel = function () { var _confirm = window.confirm window.confirm = function (text) { return true } - happen.click(qs('a.leaflet-control-edit-cancel')) + happen.click(qs('button.leaflet-control-edit-cancel')) happen.once(document.body, { type: 'keypress', keyCode: 13 }) window.confirm = _confirm }