diff --git a/umap/static/umap/base.css b/umap/static/umap/base.css index 79a25de0..827fa350 100644 --- a/umap/static/umap/base.css +++ b/umap/static/umap/base.css @@ -194,6 +194,7 @@ input[type="submit"] { .dark a { color: #eeeeec; } +button.flat, [type="button"].flat, .dark [type="button"].flat { border: none; @@ -535,9 +536,27 @@ i.info { margin-top: -8px; padding: 0 5px; } -.umap-pictogram-grid { +.pictogram-tabs { display: flex; - flex-wrap: wrap; + justify-content: space-around; + font-size: 1.2em; + padding-bottom: 20px; +} +.pictogram-tabs button { + padding: 10px; + color: #fff; + text-decoration: none; + cursor: pointer; +} +.pictogram-tabs .on { + font-weight: bold; + border-bottom: 1px solid #fff; +} +.umap-pictogram-grid { + display: grid; + grid-template-columns: repeat(auto-fill, 30px); + justify-content: space-between; + grid-gap: 5px; } .umap-pictogram-choice { width: 30px; @@ -547,7 +566,6 @@ i.info { background-color: #999; text-align: center; margin-bottom: 5px; - margin-right: 5px; } .umap-pictogram-choice img { vertical-align: middle; @@ -556,7 +574,8 @@ i.info { .umap-pictogram-choice:hover, .umap-pictogram-choice.selected, .umap-color-picker span:hover { - box-shadow: 0 0 4px 0 black; + box-shadow: 0 0 4px 0 rgb(66, 236, 230); + background-color: #aaa; } .umap-pictogram-choice .leaflet-marker-icon { bottom: 0; diff --git a/umap/static/umap/js/umap.forms.js b/umap/static/umap/js/umap.forms.js index 20cd99b3..53510ca4 100644 --- a/umap/static/umap/js/umap.forms.js +++ b/umap/static/umap/js/umap.forms.js @@ -1,4 +1,10 @@ L.FormBuilder.Element.include({ + undefine: function () { + L.DomUtil.addClass(this.wrapper, 'undefined') + this.clear() + this.sync() + }, + getParentNode: function () { if (this.options.wrapper) { return L.DomUtil.create( @@ -29,15 +35,10 @@ L.FormBuilder.Element.include({ }, this ) - L.DomEvent.on( + L.DomEvent.on(undefine, 'click', L.DomEvent.stop).on( undefine, 'click', - function (e) { - L.DomEvent.stop(e) - L.DomUtil.addClass(this.wrapper, 'undefined') - this.clear() - this.sync() - }, + this.undefine, this ) } @@ -524,16 +525,50 @@ L.FormBuilder.IconUrl = L.FormBuilder.BlurInput.extend({ build: function () { L.FormBuilder.BlurInput.prototype.build.call(this) - // Try to guess if the icon content has been customized, and if yes - // directly display the field - this.input.type = this.value() && !this.value().startsWith('/') ? 'text' : 'hidden' - this.input.placeholder = L._('Symbol or url') this.buttonsContainer = L.DomUtil.create('div', '') this.pictogramsContainer = L.DomUtil.create('div', 'umap-pictogram-list') + this.tabsContainer = L.DomUtil.create('div', 'pictogram-tabs') L.DomUtil.before(this.input, this.buttonsContainer) + L.DomUtil.before(this.input, this.tabsContainer) L.DomUtil.before(this.input, this.pictogramsContainer) this.udpatePreview() - this.on('define', this.fetchIconList) + this.on('define', this.onDefine) + }, + + onDefine: function () { + this.buildTabs() + this.showSymbols() + }, + + buildTabs: function () { + const symbol = L.DomUtil.add( + 'button', + 'flat on', + this.tabsContainer, + L._('Symbol') + ), + char = L.DomUtil.add( + 'button', + 'flat', + this.tabsContainer, + L._('Emoji & Character') + ) + url = L.DomUtil.add('button', 'flat', this.tabsContainer, L._('URL')) + toggle = (e) => { + L.DomUtil.removeClass(symbol, 'on') + L.DomUtil.removeClass(char, 'on') + L.DomUtil.removeClass(url, 'on') + L.DomUtil.addClass(e.target, 'on') + } + L.DomEvent.on(symbol, 'click', L.DomEvent.stop) + .on(symbol, 'click', this.showSymbols, this) + .on(symbol, 'click', toggle) + L.DomEvent.on(char, 'click', L.DomEvent.stop) + .on(char, 'click', this.showChars, this) + .on(char, 'click', toggle) + L.DomEvent.on(url, 'click', L.DomEvent.stop) + .on(url, 'click', this.showURL, this) + .on(url, 'click', toggle) }, isUrl: function () { @@ -541,6 +576,10 @@ L.FormBuilder.IconUrl = L.FormBuilder.BlurInput.extend({ }, udpatePreview: function () { + if (this.isDefault()) { + this.buttonsContainer.innerHTML = '' + return + } if (!L.Util.hasVar(this.value())) { // Do not try to render URL with variables if (this.isUrl()) { @@ -550,7 +589,7 @@ L.FormBuilder.IconUrl = L.FormBuilder.BlurInput.extend({ L.DomUtil.create('div', 'umap-pictogram-choice', this.buttonsContainer) ) img.src = this.value() - L.DomEvent.on(img, 'click', this.fetchIconList, this) + L.DomEvent.on(img, 'click', this.showSymbols, this) } else { const el = L.DomUtil.create( 'span', @@ -558,14 +597,14 @@ L.FormBuilder.IconUrl = L.FormBuilder.BlurInput.extend({ L.DomUtil.create('div', 'umap-pictogram-choice', this.buttonsContainer) ) el.textContent = this.value() - L.DomEvent.on(el, 'click', this.fetchIconList, this) + L.DomEvent.on(el, 'click', this.showSymbols, this) } } this.button = L.DomUtil.createButton( 'button action-button', this.buttonsContainer, this.value() ? L._('Change') : L._('Add'), - this.fetchIconList, + this.showSymbols, this ) }, @@ -623,7 +662,7 @@ L.FormBuilder.IconUrl = L.FormBuilder.BlurInput.extend({ } }, - buildIconList: function (data) { + buildSymbolsList: function (data) { this.searchInput = L.DomUtil.create('input', '', this.pictogramsContainer) this.searchInput.type = 'search' this.searchInput.placeholder = L._('Search') @@ -647,35 +686,44 @@ L.FormBuilder.IconUrl = L.FormBuilder.BlurInput.extend({ L._('Close'), function (e) { this.pictogramsContainer.innerHTML = '' - this.udpatePreview() + this.tabsContainer.innerHTML = '' + if (this.isDefault()) this.undefine(e) + else this.udpatePreview() }, this ) - 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) { + isDefault: function () { + return !this.value() || this.value() === this.obj.getMap().options.default_iconUrl + }, + + showChars: function () { + // Do not show default value here, as it's not a character + // and it has not been explicitely chosen by the user. + if (this.isDefault()) this.input.value = '' + this.input.type = 'text' + this.input.placeholder = L._('Type char or paste emoji') + this.pictogramsContainer.innerHTML = '' + }, + + showSymbols: function () { + this.input.type = 'hidden' // Clean parent element before calling ajax, to prevent blinking this.pictogramsContainer.innerHTML = '' this.buttonsContainer.innerHTML = '' this.builder.map.get(this.builder.map.options.urls.pictogram_list_json, { - callback: this.buildIconList, + callback: this.buildSymbolsList, context: this, }) }, + showURL: function () { + this.input.type = 'url' + this.input.placeholder = L._('Add URL') + this.pictogramsContainer.innerHTML = '' + }, + unselectAll: function (container) { const els = container.querySelectorAll('div.selected') for (const el in els) {