From 6ad9df80441f02397ed3124515990f1820e3ada2 Mon Sep 17 00:00:00 2001 From: Yohan Boniface Date: Wed, 15 Aug 2018 17:07:21 +0200 Subject: [PATCH] Split popupTemplate in popupShape + popupTemplate cf #600 --- docs/changelog.md | 4 + umap/static/umap/base.css | 6 +- umap/static/umap/js/umap.features.js | 4 +- umap/static/umap/js/umap.forms.js | 28 +-- umap/static/umap/js/umap.js | 4 +- umap/static/umap/js/umap.layer.js | 1 + umap/static/umap/js/umap.popup.js | 244 +++++++++++++-------------- umap/static/umap/js/umap.xhr.js | 2 +- 8 files changed, 153 insertions(+), 140 deletions(-) diff --git a/docs/changelog.md b/docs/changelog.md index ee20f38a..cdcbe2f3 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -55,6 +55,10 @@ COMMIT; - fixed popup template parsing of url with url as query string (#607) - naive support for nested variables in templates (#600) - Removed Map.tilelayer foreignkey +- split popupTemplate in popupShape and popupTemplate: popupShape is for + choosing between proper popup and panel, while popupTemplate now will allow + to choose between default "name + description" mode, or table, or geoRss ones. + Allows to add more of those in the future also. ## 1.0.0.rc-1 - BREAKING: support of python 2 is removed per upgrading to Django 2.0 diff --git a/umap/static/umap/base.css b/umap/static/umap/base.css index 9de276ce..4569f1cb 100644 --- a/umap/static/umap/base.css +++ b/umap/static/umap/base.css @@ -585,7 +585,7 @@ input[type=hidden].blur + .button { } #umap-ui-container { width: 400px; - position: fixed; + position: absolute; top: 0; bottom: 0; right: -400px; @@ -597,6 +597,10 @@ input[type=hidden].blur + .button { opacity: 0.98; cursor: initial; } +#umap-ui-container.login-panel { + position: fixed; /* Should not scroll when used in content pages (like home page) */ + z-index: 1011; /* Above a map panel if any */ +} #umap-ui-container.dark { border-left: 1px solid #222; background-color: #323737; diff --git a/umap/static/umap/js/umap.features.js b/umap/static/umap/js/umap.features.js index bed57df0..dc8acb49 100644 --- a/umap/static/umap/js/umap.features.js +++ b/umap/static/umap/js/umap.features.js @@ -143,6 +143,7 @@ L.U.FeatureMixin = { getInteractionOptions: function () { return [ + 'properties._umap_options.popupShape', 'properties._umap_options.popupTemplate', 'properties._umap_options.showLabel', 'properties._umap_options.labelDirection', @@ -165,7 +166,8 @@ L.U.FeatureMixin = { }, getPopupClass: function () { - return L.U.Popup[this.getOption('popupTemplate')] || L.U.Popup; + var old = this.getOption('popupTemplate'); // Retrocompat. + return L.U.Popup[this.getOption('popupShape') || old] || L.U.Popup; }, attachPopup: function () { diff --git a/umap/static/umap/js/umap.forms.js b/umap/static/umap/js/umap.forms.js index dde70bce..019520ba 100644 --- a/umap/static/umap/js/umap.forms.js +++ b/umap/static/umap/js/umap.forms.js @@ -212,23 +212,24 @@ L.FormBuilder.ProxyTTLSelect = L.FormBuilder.Select.extend({ }); -L.FormBuilder.PopupTemplate = L.FormBuilder.Select.extend({ +L.FormBuilder.PopupShape = L.FormBuilder.Select.extend({ selectOptions: [ - ['Default', L._('Name and description')], - ['Large', L._('Name and description (large)')], + ['Default', L._('Popup')], + ['Large', L._('Popup (large)')], + ['Panel', L._('Side panel')], + ] + +}); + +L.FormBuilder.PopupContent = L.FormBuilder.Select.extend({ + + selectOptions: [ + ['Default', L._('Default')], ['Table', L._('Table')], ['GeoRSSImage', L._('GeoRSS (title + image)')], ['GeoRSSLink', L._('GeoRSS (only link)')], - ['SimplePanel', L._('Side panel')], - ['TablePanel', L._('Side panel')] - ], - - toJS: function () { - var value = L.FormBuilder.Select.prototype.toJS.apply(this); - if (value === 'table') { value = 'Table'; } - return value; - } + ] }); @@ -735,7 +736,8 @@ L.U.FormBuilder = L.FormBuilder.extend({ dashArray: {label: L._('dash array'), helpEntries: 'dashArray', inheritable: true}, iconClass: {handler: 'IconClassSwitcher', label: L._('Icon shape'), inheritable: true}, iconUrl: {handler: 'IconUrl', label: L._('Icon symbol'), inheritable: true, helpText: L.U.Help.formatIconSymbol}, - popupTemplate: {handler: 'PopupTemplate', label: L._('Popup style'), inheritable: true}, + popupShape: {handler: 'PopupShape', label: L._('Popup shape'), inheritable: true}, + popupTemplate: {handler: 'PopupContent', label: L._('Popup content style'), inheritable: true}, popupContentTemplate: {label: L._('Popup content template'), handler: 'Textarea', helpEntries: ['dynamicProperties', 'textFormatting'], placeholder: '# {name}', inheritable: true}, datalayer: {handler: 'DataLayerSwitcher', label: L._('Choose the layer of the feature')}, moreControl: {handler: 'Switch', label: L._('Do you want to display the «more» control?')}, diff --git a/umap/static/umap/js/umap.js b/umap/static/umap/js/umap.js index 5880afd6..abb43c41 100644 --- a/umap/static/umap/js/umap.js +++ b/umap/static/umap/js/umap.js @@ -1003,6 +1003,7 @@ L.U.Map.include({ 'fillColor', 'fillOpacity', 'dashArray', + 'popupShape', 'popupTemplate', 'popupContentTemplate', 'zoomTo', @@ -1213,6 +1214,7 @@ L.U.Map.include({ defaultProperties.appendChild(builder.build()); var popupFields = [ + 'options.popupShape', 'options.popupTemplate', 'options.popupContentTemplate', 'options.showLabel', @@ -1221,7 +1223,7 @@ L.U.Map.include({ ]; builder = new L.U.FormBuilder(this, popupFields, { callback: function (e) { - if (e.helper.field === 'options.popupTemplate' || e.helper.field === 'options.popupContentTemplate') return; + if (e.helper.field === 'options.popupTemplate' || e.helper.field === 'options.popupContentTemplate' || e.helper.field === 'options.popupShape') return; this.eachDataLayer(function (datalayer) { datalayer.redraw(); }) diff --git a/umap/static/umap/js/umap.layer.js b/umap/static/umap/js/umap.layer.js index 1bc67bd0..0b82233c 100644 --- a/umap/static/umap/js/umap.layer.js +++ b/umap/static/umap/js/umap.layer.js @@ -781,6 +781,7 @@ L.U.DataLayer = L.Class.extend({ advancedProperties.appendChild(builder.build()); var popupFields = [ + 'options.popupShape', 'options.popupTemplate', 'options.popupContentTemplate', 'options.showLabel', diff --git a/umap/static/umap/js/umap.popup.js b/umap/static/umap/js/umap.popup.js index cd8994cb..95316037 100644 --- a/umap/static/umap/js/umap.popup.js +++ b/umap/static/umap/js/umap.popup.js @@ -1,3 +1,5 @@ +/* Shapes */ + L.U.Popup = L.Popup.extend({ options: { @@ -12,68 +14,19 @@ L.U.Popup = L.Popup.extend({ this.setContent(this.container); }, - hasFooter: function () { - return this.feature.hasPopupFooter(); - }, - - renderTitle: function () {}, - - renderBody: function () { - var template = this.feature.getOption('popupContentTemplate'), - container = L.DomUtil.create('div', ''), - content = '', properties, center; - if (this.options.parseTemplate) { - properties = this.feature.extendedProperties(); - // Resolve properties inside description - properties.description = L.Util.greedyTemplate(this.feature.properties.description || '', properties); - content = L.Util.greedyTemplate(template, properties); - } - content = L.Util.toHTML(content); - container.innerHTML = content; - var els = container.querySelectorAll('img,iframe'); + format: function () { + var mode = this.feature.getOption('popupTemplate') || 'Default', + klass = L.U.PopupTemplate[mode] || L.U.PopupTemplate.Default; + this.content = new klass(this.feature, this.container); + this.content.render(); + var els = this.container.querySelectorAll('img,iframe'); for (var i = 0; i < els.length; i++) { this.onElementLoaded(els[i]); } - if (!els.length && container.textContent.replace('\n', '') === '') { - container.innerHTML = ''; - L.DomUtil.add('h3', '', container, this.feature.getDisplayName()); + if (!els.length && this.container.textContent.replace('\n', '') === '') { + this.container.innerHTML = ''; + L.DomUtil.add('h3', '', this.container, this.feature.getDisplayName()); } - return container; - }, - - renderFooter: function () { - if (this.hasFooter()) { - var footer = L.DomUtil.create('ul', 'umap-popup-footer', this.container), - previousLi = L.DomUtil.create('li', 'previous', footer), - zoomLi = L.DomUtil.create('li', 'zoom', footer), - nextLi = L.DomUtil.create('li', 'next', footer), - next = this.feature.getNext(), - prev = this.feature.getPrevious(); - if (next) { - nextLi.title = L._('Go to «{feature}»', {feature: next.properties.name || L._('next')}); - } - if (prev) { - previousLi.title = L._('Go to «{feature}»', {feature: prev.properties.name || L._('previous')}); - } - zoomLi.title = L._('Zoom to this feature'); - L.DomEvent.on(nextLi, 'click', function () { - if (next) next.bringToCenter({zoomTo: next.getOption('zoomTo'), callback: next.view}); - }); - L.DomEvent.on(previousLi, 'click', function () { - if (prev) prev.bringToCenter({zoomTo: prev.getOption('zoomTo'), callback: prev.view}); - }); - L.DomEvent.on(zoomLi, 'click', function () { - this.bringToCenter({zoomTo: this.getOption('zoomTo')}); - }, this.feature); - } - }, - - format: function () { - var title = this.renderTitle(); - if (title) this.container.appendChild(title); - var body = this.renderBody(); - if (body) L.DomUtil.add('div', 'umap-popup-content', this.container, body); - this.renderFooter(); }, onElementLoaded: function (el) { @@ -93,63 +46,13 @@ L.U.Popup.Large = L.U.Popup.extend({ } }); -L.U.Popup.BaseWithTitle = L.U.Popup.extend({ - renderTitle: function () { - var title; - if (this.feature.getDisplayName()) { - title = L.DomUtil.create('h3', 'popup-title'); - title.innerHTML = L.Util.escapeHTML(this.feature.getDisplayName()); - } - return title; - } - -}); - -L.U.Popup.GeoRSSImage = L.U.Popup.BaseWithTitle.extend({ +L.U.Popup.Panel = L.U.Popup.extend({ options: { - minWidth: 300, - maxWidth: 500, - className: 'umap-popup-large umap-georss-image' + zoomAnimation: false }, - renderBody: function () { - var container = L.DomUtil.create('a'); - container.href = this.feature.properties.link; - container.target = '_blank'; - if (this.feature.properties.img) { - var img = L.DomUtil.create('img', '', container); - img.src = this.feature.properties.img; - // Sadly, we are unable to override this from JS the clean way - // See https://github.com/Leaflet/Leaflet/commit/61d746818b99d362108545c151a27f09d60960ee#commitcomment-6061847 - img.style.maxWidth = this.options.maxWidth + 'px'; - img.style.maxHeight = this.options.maxWidth + 'px'; - this.onElementLoaded(img); - } - return container; - } - -}); - -L.U.Popup.GeoRSSLink = L.U.Popup.extend({ - - options: { - className: 'umap-georss-link' - }, - - renderBody: function () { - var title = this.renderTitle(this), - a = L.DomUtil.add('a'); - a.href = this.feature.properties.link; - a.target = '_blank'; - a.appendChild(title); - return a; - } -}); - -L.U.Popup.PanelMixin = { - allButton: function () { var button = L.DomUtil.create('li', ''); L.DomUtil.create('i', 'umap-icon-16 umap-list', button); @@ -173,20 +76,70 @@ L.U.Popup.PanelMixin = { _updatePosition: function () {}, _adjustPan: function () {} -} +}); +L.U.Popup.SimplePanel = L.U.Popup.Panel; // Retrocompat. -L.U.Popup.SimplePanel = L.U.Popup.extend({ +/* Content templates */ - includes: L.U.Popup.PanelMixin, +L.U.PopupTemplate = {}; - options: { - zoomAnimation: false +L.U.PopupTemplate.Default = L.Class.extend({ + + initialize: function (feature, container) { + this.feature = feature; + this.container = container; + }, + + renderTitle: function () {}, + + renderBody: function () { + var template = this.feature.getOption('popupContentTemplate'), + container = L.DomUtil.create('div', ''), + content = '', properties, center; + properties = this.feature.extendedProperties(); + // Resolve properties inside description + properties.description = L.Util.greedyTemplate(this.feature.properties.description || '', properties); + content = L.Util.greedyTemplate(template, properties); + content = L.Util.toHTML(content); + container.innerHTML = content; + return container; + }, + + renderFooter: function () { + if (this.feature.hasPopupFooter()) { + var footer = L.DomUtil.create('ul', 'umap-popup-footer', this.container), + previousLi = L.DomUtil.create('li', 'previous', footer), + zoomLi = L.DomUtil.create('li', 'zoom', footer), + nextLi = L.DomUtil.create('li', 'next', footer), + next = this.feature.getNext(), + prev = this.feature.getPrevious(); + if (next) nextLi.title = L._('Go to «{feature}»', {feature: next.properties.name || L._('next')}); + if (prev) previousLi.title = L._('Go to «{feature}»', {feature: prev.properties.name || L._('previous')}); + zoomLi.title = L._('Zoom to this feature'); + L.DomEvent.on(nextLi, 'click', function () { + if (next) next.bringToCenter({zoomTo: next.getOption('zoomTo'), callback: next.view}); + }); + L.DomEvent.on(previousLi, 'click', function () { + if (prev) prev.bringToCenter({zoomTo: prev.getOption('zoomTo'), callback: prev.view}); + }); + L.DomEvent.on(zoomLi, 'click', function () { + this.bringToCenter({zoomTo: this.getOption('zoomTo')}); + }, this.feature); + } + }, + + render: function () { + var title = this.renderTitle(); + if (title) this.container.appendChild(title); + var body = this.renderBody(); + if (body) L.DomUtil.add('div', 'umap-popup-content', this.container, body); + this.renderFooter(); } }); -L.U.Popup.TableMixin = { +L.U.PopupTemplate.Table = L.U.PopupTemplate.Default.extend({ formatRow: function (key, value) { if (value.indexOf('http') === 0) { @@ -212,14 +165,59 @@ L.U.Popup.TableMixin = { return table; } -}; - -L.U.Popup.Table = L.U.Popup.BaseWithTitle.extend({ - includes: L.U.Popup.TableMixin }); -L.U.Popup.table = L.U.Popup.Table; // backward compatibility +L.U.PopupTemplate.BaseWithTitle = L.U.PopupTemplate.Default.extend({ + + renderTitle: function () { + var title; + if (this.feature.getDisplayName()) { + title = L.DomUtil.create('h3', 'popup-title'); + title.innerHTML = L.Util.escapeHTML(this.feature.getDisplayName()); + } + return title; + } -L.U.Popup.TablePanel = L.U.Popup.extend({ - includes: [L.U.Popup.PanelMixin, L.U.Popup.TableMixin] +}); + +L.U.PopupTemplate.GeoRSSImage = L.U.PopupTemplate.BaseWithTitle.extend({ + + options: { + minWidth: 300, + maxWidth: 500, + className: 'umap-popup-large umap-georss-image' + }, + + renderBody: function () { + var container = L.DomUtil.create('a'); + container.href = this.feature.properties.link; + container.target = '_blank'; + if (this.feature.properties.img) { + var img = L.DomUtil.create('img', '', container); + img.src = this.feature.properties.img; + // Sadly, we are unable to override this from JS the clean way + // See https://github.com/Leaflet/Leaflet/commit/61d746818b99d362108545c151a27f09d60960ee#commitcomment-6061847 + img.style.maxWidth = this.options.maxWidth + 'px'; + img.style.maxHeight = this.options.maxWidth + 'px'; + this.onElementLoaded(img); + } + return container; + } + +}); + +L.U.PopupTemplate.GeoRSSLink = L.U.PopupTemplate.Default.extend({ + + options: { + className: 'umap-georss-link' + }, + + renderBody: function () { + var title = this.renderTitle(this), + a = L.DomUtil.add('a'); + a.href = this.feature.properties.link; + a.target = '_blank'; + a.appendChild(title); + return a; + } }); diff --git a/umap/static/umap/js/umap.xhr.js b/umap/static/umap/js/umap.xhr.js index d1b011f9..ce994ad8 100644 --- a/umap/static/umap/js/umap.xhr.js +++ b/umap/static/umap/js/umap.xhr.js @@ -242,7 +242,7 @@ L.U.Xhr = L.Evented.extend({ else self.default_callback(data, {}); }; var ask_for_login = function (data) { - self.ui.openPanel({'data': data}); + self.ui.openPanel({'data': data, className: 'login-panel'}); self.listen_form('login_form', { 'callback': function (data) { if (data.html) ask_for_login(data); // Problem in the login - ask again