From 79c0e6c2d61345451fc0a51b145ddf902fa7c85a Mon Sep 17 00:00:00 2001 From: Lena Daxenbichler Date: Mon, 14 Oct 2024 12:27:32 +0200 Subject: [PATCH] Style location widget for bootstrap5. Inlcude dark mode variant --- js/rollup.conf.js | 39 ++- js/src/bootstrap5/bundle.js | 17 ++ js/src/bootstrap5/widget.js | 66 +++++ js/src/widget.js | 12 +- package.json | 3 +- scripts/styles.sh | 7 + scss/bootstrap5.scss | 178 ++++++++++++ src/yafowil/widget/location/__init__.py | 92 +++++++ .../location/resources/bootstrap5/styles.css | 10 + .../location/resources/bootstrap5/widget.css | 148 ++++++++++ .../location/resources/bootstrap5/widget.js | 257 ++++++++++++++++++ .../resources/bootstrap5/widget.min.js | 1 + .../widget/location/resources/widget.js | 11 +- .../widget/location/resources/widget.min.js | 2 +- 14 files changed, 832 insertions(+), 11 deletions(-) create mode 100644 js/src/bootstrap5/bundle.js create mode 100644 js/src/bootstrap5/widget.js create mode 100755 scripts/styles.sh create mode 100644 scss/bootstrap5.scss create mode 100644 src/yafowil/widget/location/resources/bootstrap5/styles.css create mode 100644 src/yafowil/widget/location/resources/bootstrap5/widget.css create mode 100644 src/yafowil/widget/location/resources/bootstrap5/widget.js create mode 100644 src/yafowil/widget/location/resources/bootstrap5/widget.min.js diff --git a/js/rollup.conf.js b/js/rollup.conf.js index 15dec6e..5a0c329 100644 --- a/js/rollup.conf.js +++ b/js/rollup.conf.js @@ -2,6 +2,7 @@ import cleanup from 'rollup-plugin-cleanup'; import {terser} from 'rollup-plugin-terser'; const out_dir = 'src/yafowil/widget/location/resources'; +const out_dir_bs5 = 'src/yafowil/widget/location/resources/bootstrap5'; const outro = ` window.yafowil = window.yafowil || {}; @@ -43,5 +44,41 @@ export default args => { interop: 'default' }); } - return conf; + + // Bootstrap 5 + let conf_2 = { + input: 'js/src/bootstrap5/bundle.js', + plugins: [ + cleanup() + ], + output: [{ + name: 'yafowil_location', + file: `${out_dir_bs5}/widget.js`, + format: 'iife', + outro: outro, + globals: { + jquery: 'jQuery' + }, + interop: 'default' + }], + external: [ + 'jquery' + ] + }; + if (args.configDebug !== true) { + conf_2.output.push({ + name: 'yafowil_location', + file: `${out_dir_bs5}/widget.min.js`, + format: 'iife', + plugins: [ + terser() + ], + outro: outro, + globals: { + jquery: 'jQuery' + }, + interop: 'default' + }); + } + return [conf, conf_2]; }; diff --git a/js/src/bootstrap5/bundle.js b/js/src/bootstrap5/bundle.js new file mode 100644 index 0000000..c9ab197 --- /dev/null +++ b/js/src/bootstrap5/bundle.js @@ -0,0 +1,17 @@ +import $ from 'jquery'; + +import {BS5LocationWidget} from './widget.js'; +import {register_array_subscribers} from './widget.js'; + +export * from './widget.js'; + +$(function() { + if (window.ts !== undefined) { + ts.ajax.register(BS5LocationWidget.initialize, true); + } else if (window.bdajax !== undefined) { + bdajax.register(BS5LocationWidget.initialize, true); + } else { + BS5LocationWidget.initialize(); + } + register_array_subscribers(); +}); diff --git a/js/src/bootstrap5/widget.js b/js/src/bootstrap5/widget.js new file mode 100644 index 0000000..8eaece0 --- /dev/null +++ b/js/src/bootstrap5/widget.js @@ -0,0 +1,66 @@ +import {LocationWidgetMarkerPopup} from '../widget.js'; +import {LocationWidget} from '../widget.js'; + +const locationIcon = L.divIcon({ + html: '', + className: 'leaflet-div-icon', + iconSize: [32, 32], + iconAnchor: [16, 32], + popupAnchor: [0, -32] +}); + +export class BS5LocationWidgetMarker { + + constructor(widget, lat, lon) { + this.widget = widget; + let marker = new L.Marker([lat, lon], {icon: locationIcon}, {draggable: true}); + marker.addTo(widget.markers); + new LocationWidgetMarkerPopup(widget, marker); + marker.on('dragend', this.dragend_handle.bind(this)); + } + + dragend_handle(evt) { + let latlng = evt.target._latlng, + widget = this.widget; + widget.lat = latlng.lat; + widget.lon = latlng.lng; + widget.zoom = widget.map.getZoom(); + } +} + +export class BS5LocationWidget extends LocationWidget { + + static initialize(context) { + $('div.location-map', context).each(function() { + if (window.yafowil_array !== undefined && + window.yafowil_array.inside_template($(this))) { + return; + } + new BS5LocationWidget($(this)); + }); + } + + constructor(elem) { + super(elem); + } + + create_marker(lat, lon) { + console.log('XXXX') + return new BS5LocationWidgetMarker(this, lat, lon); + } +} + +////////////////////////////////////////////////////////////////////////////// +// yafowil.widget.array integration +////////////////////////////////////////////////////////////////////////////// + +function location_on_array_add(inst, context) { + BS5LocationWidget.initialize(context); +} + +export function register_array_subscribers() { + if (window.yafowil_array === undefined) { + return; + } + window.yafowil_array.on_array_event('on_add', location_on_array_add); +} diff --git a/js/src/widget.js b/js/src/widget.js index 25212e5..b3d9658 100644 --- a/js/src/widget.js +++ b/js/src/widget.js @@ -69,7 +69,7 @@ export class LocationWidgetSearch { lon = location.x, widget = this.widget; widget.markers.clearLayers(); - new LocationWidgetMarker(widget, lat, lon); + this.widget.create_marker(lat, lon); widget.lat = lat; widget.lon = lon; } @@ -159,6 +159,10 @@ export class LocationWidget { this._input_zoom.val(val); } + create_marker(lat, lon) { + return new LocationWidgetMarker(this, lat, lon); + } + create_map() { // create map let map = this.map = new L.Map(this.id); @@ -174,7 +178,7 @@ export class LocationWidget { map.addLayer(markers); // add marker if value given if (this.value) { - new LocationWidgetMarker(this, this.lat, this.lon); + this.create_marker(this.lat, this.lon); } // add or move marker on map click map.on('click', this.click_handle.bind(this)); @@ -184,7 +188,7 @@ export class LocationWidget { // XXX: confirmation dialog this.markers.clearLayers(); let latlng = evt.latlng; - new LocationWidgetMarker(this, latlng.lat, latlng.lng); + this.create_marker(latlng.lat, latlng.lng); this.lat = latlng.lat; this.lon = latlng.lng; this.zoom = this.map.getZoom(); @@ -198,7 +202,7 @@ export class LocationWidget { } this[name] = val; this.markers.clearLayers(); - new LocationWidgetMarker(this, this.lat, this.lon); + this.create_marker(this.lat, this.lon); this.map.setView([this.lat, this.lon], this.zoom); } diff --git a/package.json b/package.json index 54d2b04..2e0c13b 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,7 @@ "qunit": "^2.19.3", "rollup": "^2.79.1", "rollup-plugin-cleanup": "^3.2.1", - "rollup-plugin-terser": "^7.0.2" + "rollup-plugin-terser": "^7.0.2", + "sass": "^1.58.3" } } diff --git a/scripts/styles.sh b/scripts/styles.sh new file mode 100755 index 0000000..8c2a311 --- /dev/null +++ b/scripts/styles.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +SASS_BIN="./node_modules/sass/sass.js" +SASS_DIR="./scss" +TARGET_DIR="./src/yafowil/widget/location/resources" + +$SASS_BIN $SASS_DIR/bootstrap5.scss --no-source-map $TARGET_DIR/bootstrap5/widget.css \ No newline at end of file diff --git a/scss/bootstrap5.scss b/scss/bootstrap5.scss new file mode 100644 index 0000000..7a68251 --- /dev/null +++ b/scss/bootstrap5.scss @@ -0,0 +1,178 @@ +.location-wrapper { + // bootstrap 5 input-group styles + + .leaflet-control-geosearch { + .results { + border-top-left-radius: 0; + border-top-right-radius: 0; + border-bottom-left-radius: 0.25rem; + border-bottom-right-radius: 0.25rem; + border: 1px solid var(--bs-border-color); + color: var(--bs-body-color); + background-color: var(--bs-body-bg); + + &:not(.active) { + border: 0; + } + + > * { + padding: 0.375rem 0.75rem; + font-size: 1rem; + font-weight: 400; + line-height: 1.5; + border: none; + + &:hover, &.active { + background-color: var(--bs-secondary-bg); + border: none; + } + } + } + + > form { + border: 0; + background: none; + + &.open input { + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; + } + + input { + display: block; + width: 100%; + height: 36px; + padding: 0.375rem 0.75rem; + font-size: var(--bs-body-font-size); + font-weight: var(--bs-body-font-weight); + line-height: var(--bs-body-line-height); + color: var(--bs-body-color); + background-clip: padding-box; + border: 1px solid var(--bs-border-color); + appearance: none; + border-radius: var(--bs-border-radius); + transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; + background-color: var(--bs-body-bg); + + &:focus { + color: var(--bs-body-color); + background-color: var(--bs-body-bg); + border-color: var(--bs-border-color); + outline: 0; + box-shadow: 0 0 0 0.25rem rgba(13,110,253,.25); + } + + &::placeholder { + color: var(--bs-placeholder-color); + opacity: 1; + } + } + } + a.reset { + background: none; + line-height: 36px; + height: 36px; + font-size: 0; + + > * { + display: none; + } + + &::before { + content: "\F659"; + font-family: 'bootstrap-icons'; + font-size: 1rem; + color: var(--bs-body-color); + } + } + } + .leaflet-geosearch-bar form { + padding: 0; + } + + .leaflet-control-zoom { + font-size: var(--bs-body-font-size); + font-weight: var(--bs-body-font-weight); + line-height: var(--bs-body-line-height); + color: var(--bs-body-color); + border: 1px solid var(--bs-border-color); + background-color: var(--bs-body-bg); + + .leaflet-control-zoom-in { + font-size: 0; + border-top-left-radius: var(--bs-border-radius)!important; + border-top-right-radius: var(--bs-border-radius)!important; + + &::before { + content: "\F64D"; + font-family: 'bootstrap-icons'; + font-size: 1rem; + color: currentColor; + } + } + .leaflet-control-zoom-out { + font-size: 0; + border-bottom-left-radius: var(--bs-border-radius)!important; + border-bottom-right-radius: var(--bs-border-radius)!important; + + &::before { + content: "\F63B"; + font-family: 'bootstrap-icons'; + font-size: 1rem; + color: currentColor; + } + } + } + + .leaflet-div-icon { + background: transparent; + border: none; + } + .custom-marker { + font-size: 2rem; + color: var(--bs-primary); + } + + div.location-map { + height: 360px; + width: 100%; + } + + .leaflet-popup-content-wrapper, .leaflet-popup-tip { + background: var(--bs-secondary-bg); + box-shadow: 0 3px 14px rgba(0, 0, 0, 0.4); + + a { + color: var(--bs-body-color); + font-size: var(--bs-body-font-size); + } + } + + .leaflet-popup-close-button { + font-size: 0!important; + + &::before { + content: "\F659"; + font-family: 'bootstrap-icons'; + font-size: .7rem; + color: var(--bs-body-color); + } + } +} + +[data-bs-theme="dark"] { + .leaflet-container { + background: #000; + } + + .leaflet-popup-content-wrapper, .leaflet-popup-tip { + box-shadow: 0 3px 14px rgba(0, 0, 0, 1); + } + + .leaflet-layer, + .leaflet-control-zoom-in, + .leaflet-control-zoom-out, + .leaflet-control-attribution { + filter: invert(100%) hue-rotate(355deg) brightness(95%) contrast(90%); + } +} diff --git a/src/yafowil/widget/location/__init__.py b/src/yafowil/widget/location/__init__.py index 0c1b46f..6d98a1f 100644 --- a/src/yafowil/widget/location/__init__.py +++ b/src/yafowil/widget/location/__init__.py @@ -87,6 +87,83 @@ }] +############################################################################## +# Bootstrap 5 +############################################################################## + +# webresource ################################################################ + +bootstrap5_resources = wr.ResourceGroup( + name='yafowil.widget.location', + directory=resources_dir, + path='yafowil-location' +) +bootstrap5_resources.add(wr.ScriptResource( + name='leaflet-js', + directory=os.path.join(resources_dir, 'leaflet'), + path='yafowil-location/leaflet', + resource='leaflet-src.js', + compressed='leaflet.js' +)) +bootstrap5_resources.add(wr.ScriptResource( + name='leaflet-geosearch-js', + depends='leaflet-js', + directory=os.path.join(resources_dir, 'leaflet-geosearch'), + path='yafowil-location/leaflet-geosearch', + resource='geosearch.umd.js' +)) +bootstrap5_resources.add(wr.ScriptResource( + name='yafowil-location-js', + depends=['jquery-js', 'leaflet-geosearch-js'], + resource='bootstrap5/widget.js', + compressed='bootstrap5/widget.min.js' +)) +bootstrap5_resources.add(wr.StyleResource( + name='leaflet-css', + directory=os.path.join(resources_dir, 'leaflet'), + path='yafowil-location/leaflet', + resource='leaflet.css' +)) +bootstrap5_resources.add(wr.StyleResource( + name='leaflet-geosearch-css', + depends='leaflet-css', + directory=os.path.join(resources_dir, 'leaflet-geosearch'), + path='yafowil-location/leaflet-geosearch', + resource='geosearch.css' +)) +bootstrap5_resources.add(wr.StyleResource( + name='yafowil-location-css', + depends='leaflet-geosearch-css', + resource='bootstrap5/widget.css' +)) +# B/C resources ############################################################## +bootstrap5_js = [{ + 'group': 'yafowil.widget.location.dependencies', + 'resource': 'leaflet/leaflet.js', + 'order': 20, +}, { + 'group': 'yafowil.widget.location.dependencies', + 'resource': 'leaflet-geosearch/geosearch.umd.js', + 'order': 21, +}, { + 'group': 'yafowil.widget.location.common', + 'resource': 'bootstrap5/widget.js', + 'order': 23, +}] +bootstrap5_css = [{ + 'group': 'yafowil.widget.location.dependencies', + 'resource': 'leaflet/leaflet.css', + 'order': 20, +}, { + 'group': 'yafowil.widget.location.dependencies', + 'resource': 'leaflet-geosearch/geosearch.css', + 'order': 21, +}, { + 'group': 'yafowil.widget.location.common', + 'resource': 'bootstrap5/widget.css', + 'order': 22, +}] + ############################################################################## # Registration ############################################################################## @@ -106,3 +183,18 @@ def register(): css=css ) factory.register_resources('default', widget_name, resources) + + # Bootstrap 5 + factory.register_theme( + ['bootstrap5'], + widget_name, + resources_dir, + js=bootstrap5_js, + css=bootstrap5_css + ) + + factory.register_resources( + ['bootstrap5'], + widget_name, + bootstrap5_resources + ) diff --git a/src/yafowil/widget/location/resources/bootstrap5/styles.css b/src/yafowil/widget/location/resources/bootstrap5/styles.css new file mode 100644 index 0000000..01438b7 --- /dev/null +++ b/src/yafowil/widget/location/resources/bootstrap5/styles.css @@ -0,0 +1,10 @@ +.location-wrapper .leaflet-control-geosearch > div { + border: var(--bs-border-width) solid var(--bs-border-color); +} +.location-wrapper .leaflet-geosearch-bar form { + padding: 0; +} +.location-wrapper div.location-map { + height: 300px; + width: 100%; +} diff --git a/src/yafowil/widget/location/resources/bootstrap5/widget.css b/src/yafowil/widget/location/resources/bootstrap5/widget.css new file mode 100644 index 0000000..99300f6 --- /dev/null +++ b/src/yafowil/widget/location/resources/bootstrap5/widget.css @@ -0,0 +1,148 @@ +.location-wrapper .leaflet-control-geosearch .results { + border-top-left-radius: 0; + border-top-right-radius: 0; + border-bottom-left-radius: 0.25rem; + border-bottom-right-radius: 0.25rem; + border: 1px solid var(--bs-border-color); + color: var(--bs-body-color); + background-color: var(--bs-body-bg); +} +.location-wrapper .leaflet-control-geosearch .results:not(.active) { + border: 0; +} +.location-wrapper .leaflet-control-geosearch .results > * { + padding: 0.375rem 0.75rem; + font-size: 1rem; + font-weight: 400; + line-height: 1.5; + border: none; +} +.location-wrapper .leaflet-control-geosearch .results > *:hover, .location-wrapper .leaflet-control-geosearch .results > *.active { + background-color: var(--bs-secondary-bg); + border: none; +} +.location-wrapper .leaflet-control-geosearch > form { + border: 0; + background: none; +} +.location-wrapper .leaflet-control-geosearch > form.open input { + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; +} +.location-wrapper .leaflet-control-geosearch > form input { + display: block; + width: 100%; + height: 36px; + padding: 0.375rem 0.75rem; + font-size: var(--bs-body-font-size); + font-weight: var(--bs-body-font-weight); + line-height: var(--bs-body-line-height); + color: var(--bs-body-color); + background-clip: padding-box; + border: 1px solid var(--bs-border-color); + appearance: none; + border-radius: var(--bs-border-radius); + transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; + background-color: var(--bs-body-bg); +} +.location-wrapper .leaflet-control-geosearch > form input:focus { + color: var(--bs-body-color); + background-color: var(--bs-body-bg); + border-color: var(--bs-border-color); + outline: 0; + box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25); +} +.location-wrapper .leaflet-control-geosearch > form input::placeholder { + color: var(--bs-placeholder-color); + opacity: 1; +} +.location-wrapper .leaflet-control-geosearch a.reset { + background: none; + line-height: 36px; + height: 36px; + font-size: 0; +} +.location-wrapper .leaflet-control-geosearch a.reset > * { + display: none; +} +.location-wrapper .leaflet-control-geosearch a.reset::before { + content: "\f659"; + font-family: "bootstrap-icons"; + font-size: 1rem; + color: var(--bs-body-color); +} +.location-wrapper .leaflet-geosearch-bar form { + padding: 0; +} +.location-wrapper .leaflet-control-zoom { + font-size: var(--bs-body-font-size); + font-weight: var(--bs-body-font-weight); + line-height: var(--bs-body-line-height); + color: var(--bs-body-color); + border: 1px solid var(--bs-border-color); + background-color: var(--bs-body-bg); +} +.location-wrapper .leaflet-control-zoom .leaflet-control-zoom-in { + font-size: 0; + border-top-left-radius: var(--bs-border-radius) !important; + border-top-right-radius: var(--bs-border-radius) !important; +} +.location-wrapper .leaflet-control-zoom .leaflet-control-zoom-in::before { + content: "\f64d"; + font-family: "bootstrap-icons"; + font-size: 1rem; + color: currentColor; +} +.location-wrapper .leaflet-control-zoom .leaflet-control-zoom-out { + font-size: 0; + border-bottom-left-radius: var(--bs-border-radius) !important; + border-bottom-right-radius: var(--bs-border-radius) !important; +} +.location-wrapper .leaflet-control-zoom .leaflet-control-zoom-out::before { + content: "\f63b"; + font-family: "bootstrap-icons"; + font-size: 1rem; + color: currentColor; +} +.location-wrapper .leaflet-div-icon { + background: transparent; + border: none; +} +.location-wrapper .custom-marker { + font-size: 2rem; + color: var(--bs-primary); +} +.location-wrapper div.location-map { + height: 360px; + width: 100%; +} +.location-wrapper .leaflet-popup-content-wrapper, .location-wrapper .leaflet-popup-tip { + background: var(--bs-secondary-bg); + box-shadow: 0 3px 14px rgba(0, 0, 0, 0.4); +} +.location-wrapper .leaflet-popup-content-wrapper a, .location-wrapper .leaflet-popup-tip a { + color: var(--bs-body-color); + font-size: var(--bs-body-font-size); +} +.location-wrapper .leaflet-popup-close-button { + font-size: 0 !important; +} +.location-wrapper .leaflet-popup-close-button::before { + content: "\f659"; + font-family: "bootstrap-icons"; + font-size: 0.7rem; + color: var(--bs-body-color); +} + +[data-bs-theme=dark] .leaflet-container { + background: #000; +} +[data-bs-theme=dark] .leaflet-popup-content-wrapper, [data-bs-theme=dark] .leaflet-popup-tip { + box-shadow: 0 3px 14px rgb(0, 0, 0); +} +[data-bs-theme=dark] .leaflet-layer, +[data-bs-theme=dark] .leaflet-control-zoom-in, +[data-bs-theme=dark] .leaflet-control-zoom-out, +[data-bs-theme=dark] .leaflet-control-attribution { + filter: invert(100%) hue-rotate(355deg) brightness(95%) contrast(90%); +} diff --git a/src/yafowil/widget/location/resources/bootstrap5/widget.js b/src/yafowil/widget/location/resources/bootstrap5/widget.js new file mode 100644 index 0000000..029a6f7 --- /dev/null +++ b/src/yafowil/widget/location/resources/bootstrap5/widget.js @@ -0,0 +1,257 @@ +var yafowil_location = (function (exports, $$1) { + 'use strict'; + + class LocationWidgetMarkerPopup { + constructor(widget, marker) { + this.widget = widget; + this.marker = marker; + this.create_popup(); + } + create_popup() { + let popup = document.createElement('a'); + popup.href = "#"; + popup.innerHTML = "Remove"; + popup.onclick = this.remove_handle.bind(this); + this.marker.bindPopup(popup); + } + remove_handle() { + let widget = this.widget; + widget.markers.removeLayer(this.marker); + widget.lat = ''; + widget.lon = ''; + widget.zoom = ''; + return false; + } + } + class LocationWidgetMarker { + constructor(widget, lat, lon) { + this.widget = widget; + let marker = new L.Marker([lat, lon], {draggable: true}); + marker.addTo(widget.markers); + new LocationWidgetMarkerPopup(widget, marker); + marker.on('dragend', this.dragend_handle.bind(this)); + } + dragend_handle(evt) { + let latlng = evt.target._latlng, + widget = this.widget; + widget.lat = latlng.lat; + widget.lon = latlng.lng; + widget.zoom = widget.map.getZoom(); + } + } + class LocationWidgetSearch { + constructor(widget) { + this.widget = widget; + let geosearch = this.geosearch = new GeoSearch.GeoSearchControl({ + provider: new GeoSearch.OpenStreetMapProvider(), + style: 'bar', + autoClose: true + }); + widget.map.addControl(geosearch); + widget.map.on( + 'geosearch/showlocation', + this.showloaction_handle.bind(this) + ); + } + showloaction_handle(result) { + let location = result.location, + lat = location.y, + lon = location.x, + widget = this.widget; + widget.markers.clearLayers(); + this.widget.create_marker(lat, lon); + widget.lat = lat; + widget.lon = lon; + } + } + class LocationWidget { + static initialize(context) { + $$1('div.location-map', context).each(function() { + if (window.yafowil_array !== undefined && + window.yafowil_array.inside_template($$1(this))) { + return; + } + new LocationWidget($$1(this)); + }); + } + constructor(elem) { + elem.data('yafowil-location', this); + this.elem = elem; + this.id = elem.attr('id'); + let wrapper = elem.parent(); + this._input_lat = $$1('input.location-lat', wrapper); + this._input_lon = $$1('input.location-lon', wrapper); + this._input_zoom = $$1('input.location-zoom', wrapper); + this.change_lat_handle = this.change_lat_handle.bind(this); + this._input_lat.on('change', this.change_lat_handle); + this.change_lon_handle = this.change_lon_handle.bind(this); + this._input_lon.on('change', this.change_lon_handle); + this.min_zoom = elem.data('min_zoom'); + this.max_zoom = elem.data('max_zoom'); + this.tile_layers = elem.data('tile_layers'); + this._lat = elem.data('lat'); + this._lon = elem.data('lon'); + this._zoom = elem.data('zoom'); + this.value = this.elem.data('value'); + this.create_map(); + new LocationWidgetSearch(this); + } + get value() { + return this._value; + } + set value(val) { + this._value = val; + if (val) { + if (val.lat !== undefined && val.lon !== undefined) { + this._lat = val.lat; + this._lon = val.lon; + } + if (val.zoom !== undefined) { + this._zoom = val.zoom; + } + } + } + get lat() { + return this._lat; + } + set lat(val) { + this._lat = val; + this._input_lat.val(val); + } + get lon() { + return this._lon; + } + set lon(val) { + this._lon = val; + this._input_lon.val(val); + } + get zoom() { + return this._zoom; + } + set zoom(val) { + this._zoom = val; + this._input_zoom.val(val); + } + create_marker(lat, lon) { + return new LocationWidgetMarker(this, lat, lon); + } + create_map() { + let map = this.map = new L.Map(this.id); + this.map.setView([this.lat, this.lon], this.zoom); + for (let layer of this.tile_layers) { + layer.options.minZoom = this.min_zoom; + layer.options.maxZoom = this.max_zoom; + new L.TileLayer(layer.urlTemplate, layer.options).addTo(map); + } + let markers = this.markers = new L.FeatureGroup(); + map.addLayer(markers); + if (this.value) { + this.create_marker(this.lat, this.lon); + } + map.on('click', this.click_handle.bind(this)); + } + click_handle(evt) { + this.markers.clearLayers(); + let latlng = evt.latlng; + this.create_marker(latlng.lat, latlng.lng); + this.lat = latlng.lat; + this.lon = latlng.lng; + this.zoom = this.map.getZoom(); + } + change_val(elem, name) { + let val = parseFloat(elem.val()); + if (isNaN(val)) { + elem.val(this[name]); + return; + } + this[name] = val; + this.markers.clearLayers(); + this.create_marker(this.lat, this.lon); + this.map.setView([this.lat, this.lon], this.zoom); + } + change_lat_handle(evt) { + evt.preventDefault(); + this.change_val($$1(evt.currentTarget), '_lat'); + } + change_lon_handle(evt) { + evt.preventDefault(); + this.change_val($$1(evt.currentTarget), '_lon'); + } + } + + const locationIcon = L.divIcon({ + html: '', + className: 'leaflet-div-icon', + iconSize: [32, 32], + iconAnchor: [16, 32], + popupAnchor: [0, -32] + }); + class BS5LocationWidgetMarker { + constructor(widget, lat, lon) { + this.widget = widget; + let marker = new L.Marker([lat, lon], {icon: locationIcon}, {draggable: true}); + marker.addTo(widget.markers); + new LocationWidgetMarkerPopup(widget, marker); + marker.on('dragend', this.dragend_handle.bind(this)); + } + dragend_handle(evt) { + let latlng = evt.target._latlng, + widget = this.widget; + widget.lat = latlng.lat; + widget.lon = latlng.lng; + widget.zoom = widget.map.getZoom(); + } + } + class BS5LocationWidget extends LocationWidget { + static initialize(context) { + $('div.location-map', context).each(function() { + if (window.yafowil_array !== undefined && + window.yafowil_array.inside_template($(this))) { + return; + } + new BS5LocationWidget($(this)); + }); + } + constructor(elem) { + super(elem); + } + create_marker(lat, lon) { + console.log('XXXX'); + return new BS5LocationWidgetMarker(this, lat, lon); + } + } + function location_on_array_add(inst, context) { + BS5LocationWidget.initialize(context); + } + function register_array_subscribers() { + if (window.yafowil_array === undefined) { + return; + } + window.yafowil_array.on_array_event('on_add', location_on_array_add); + } + + $$1(function() { + if (window.ts !== undefined) { + ts.ajax.register(BS5LocationWidget.initialize, true); + } else if (window.bdajax !== undefined) { + bdajax.register(BS5LocationWidget.initialize, true); + } else { + BS5LocationWidget.initialize(); + } + register_array_subscribers(); + }); + + exports.BS5LocationWidget = BS5LocationWidget; + exports.BS5LocationWidgetMarker = BS5LocationWidgetMarker; + exports.register_array_subscribers = register_array_subscribers; + + Object.defineProperty(exports, '__esModule', { value: true }); + + + window.yafowil = window.yafowil || {}; + window.yafowil.location = exports; + + + return exports; + +})({}, jQuery); diff --git a/src/yafowil/widget/location/resources/bootstrap5/widget.min.js b/src/yafowil/widget/location/resources/bootstrap5/widget.min.js new file mode 100644 index 0000000..0661ff3 --- /dev/null +++ b/src/yafowil/widget/location/resources/bootstrap5/widget.min.js @@ -0,0 +1 @@ +var yafowil_location=function(t,a){"use strict";class e{constructor(t,a){this.widget=t,this.marker=a,this.create_popup()}create_popup(){let t=document.createElement("a");t.href="#",t.innerHTML="Remove",t.onclick=this.remove_handle.bind(this),this.marker.bindPopup(t)}remove_handle(){let t=this.widget;return t.markers.removeLayer(this.marker),t.lat="",t.lon="",t.zoom="",!1}}class i{constructor(t,a,i){this.widget=t;let o=new L.Marker([a,i],{draggable:!0});o.addTo(t.markers),new e(t,o),o.on("dragend",this.dragend_handle.bind(this))}dragend_handle(t){let a=t.target._latlng,e=this.widget;e.lat=a.lat,e.lon=a.lng,e.zoom=e.map.getZoom()}}class o{constructor(t){this.widget=t;let a=this.geosearch=new GeoSearch.GeoSearchControl({provider:new GeoSearch.OpenStreetMapProvider,style:"bar",autoClose:!0});t.map.addControl(a),t.map.on("geosearch/showlocation",this.showloaction_handle.bind(this))}showloaction_handle(t){let a=t.location,e=a.y,i=a.x,o=this.widget;o.markers.clearLayers(),this.widget.create_marker(e,i),o.lat=e,o.lon=i}}class n{static initialize(t){a("div.location-map",t).each((function(){void 0!==window.yafowil_array&&window.yafowil_array.inside_template(a(this))||new n(a(this))}))}constructor(t){t.data("yafowil-location",this),this.elem=t,this.id=t.attr("id");let e=t.parent();this._input_lat=a("input.location-lat",e),this._input_lon=a("input.location-lon",e),this._input_zoom=a("input.location-zoom",e),this.change_lat_handle=this.change_lat_handle.bind(this),this._input_lat.on("change",this.change_lat_handle),this.change_lon_handle=this.change_lon_handle.bind(this),this._input_lon.on("change",this.change_lon_handle),this.min_zoom=t.data("min_zoom"),this.max_zoom=t.data("max_zoom"),this.tile_layers=t.data("tile_layers"),this._lat=t.data("lat"),this._lon=t.data("lon"),this._zoom=t.data("zoom"),this.value=this.elem.data("value"),this.create_map(),new o(this)}get value(){return this._value}set value(t){this._value=t,t&&(void 0!==t.lat&&void 0!==t.lon&&(this._lat=t.lat,this._lon=t.lon),void 0!==t.zoom&&(this._zoom=t.zoom))}get lat(){return this._lat}set lat(t){this._lat=t,this._input_lat.val(t)}get lon(){return this._lon}set lon(t){this._lon=t,this._input_lon.val(t)}get zoom(){return this._zoom}set zoom(t){this._zoom=t,this._input_zoom.val(t)}create_marker(t,a){return new i(this,t,a)}create_map(){let t=this.map=new L.Map(this.id);this.map.setView([this.lat,this.lon],this.zoom);for(let a of this.tile_layers)a.options.minZoom=this.min_zoom,a.options.maxZoom=this.max_zoom,new L.TileLayer(a.urlTemplate,a.options).addTo(t);let a=this.markers=new L.FeatureGroup;t.addLayer(a),this.value&&this.create_marker(this.lat,this.lon),t.on("click",this.click_handle.bind(this))}click_handle(t){this.markers.clearLayers();let a=t.latlng;this.create_marker(a.lat,a.lng),this.lat=a.lat,this.lon=a.lng,this.zoom=this.map.getZoom()}change_val(t,a){let e=parseFloat(t.val());isNaN(e)?t.val(this[a]):(this[a]=e,this.markers.clearLayers(),this.create_marker(this.lat,this.lon),this.map.setView([this.lat,this.lon],this.zoom))}change_lat_handle(t){t.preventDefault(),this.change_val(a(t.currentTarget),"_lat")}change_lon_handle(t){t.preventDefault(),this.change_val(a(t.currentTarget),"_lon")}}const l=L.divIcon({html:'',className:"leaflet-div-icon",iconSize:[32,32],iconAnchor:[16,32],popupAnchor:[0,-32]});class s{constructor(t,a,i){this.widget=t;let o=new L.Marker([a,i],{icon:l},{draggable:!0});o.addTo(t.markers),new e(t,o),o.on("dragend",this.dragend_handle.bind(this))}dragend_handle(t){let a=t.target._latlng,e=this.widget;e.lat=a.lat,e.lon=a.lng,e.zoom=e.map.getZoom()}}class r extends n{static initialize(t){$("div.location-map",t).each((function(){void 0!==window.yafowil_array&&window.yafowil_array.inside_template($(this))||new r($(this))}))}constructor(t){super(t)}create_marker(t,a){return console.log("XXXX"),new s(this,t,a)}}function h(t,a){r.initialize(a)}function d(){void 0!==window.yafowil_array&&window.yafowil_array.on_array_event("on_add",h)}return a((function(){void 0!==window.ts?ts.ajax.register(r.initialize,!0):void 0!==window.bdajax?bdajax.register(r.initialize,!0):r.initialize(),d()})),t.BS5LocationWidget=r,t.BS5LocationWidgetMarker=s,t.register_array_subscribers=d,Object.defineProperty(t,"__esModule",{value:!0}),window.yafowil=window.yafowil||{},window.yafowil.location=t,t}({},jQuery); diff --git a/src/yafowil/widget/location/resources/widget.js b/src/yafowil/widget/location/resources/widget.js index cab7e39..31f61bf 100644 --- a/src/yafowil/widget/location/resources/widget.js +++ b/src/yafowil/widget/location/resources/widget.js @@ -59,7 +59,7 @@ var yafowil_location = (function (exports, $) { lon = location.x, widget = this.widget; widget.markers.clearLayers(); - new LocationWidgetMarker(widget, lat, lon); + this.widget.create_marker(lat, lon); widget.lat = lat; widget.lon = lon; } @@ -132,6 +132,9 @@ var yafowil_location = (function (exports, $) { this._zoom = val; this._input_zoom.val(val); } + create_marker(lat, lon) { + return new LocationWidgetMarker(this, lat, lon); + } create_map() { let map = this.map = new L.Map(this.id); this.map.setView([this.lat, this.lon], this.zoom); @@ -143,14 +146,14 @@ var yafowil_location = (function (exports, $) { let markers = this.markers = new L.FeatureGroup(); map.addLayer(markers); if (this.value) { - new LocationWidgetMarker(this, this.lat, this.lon); + this.create_marker(this.lat, this.lon); } map.on('click', this.click_handle.bind(this)); } click_handle(evt) { this.markers.clearLayers(); let latlng = evt.latlng; - new LocationWidgetMarker(this, latlng.lat, latlng.lng); + this.create_marker(latlng.lat, latlng.lng); this.lat = latlng.lat; this.lon = latlng.lng; this.zoom = this.map.getZoom(); @@ -163,7 +166,7 @@ var yafowil_location = (function (exports, $) { } this[name] = val; this.markers.clearLayers(); - new LocationWidgetMarker(this, this.lat, this.lon); + this.create_marker(this.lat, this.lon); this.map.setView([this.lat, this.lon], this.zoom); } change_lat_handle(evt) { diff --git a/src/yafowil/widget/location/resources/widget.min.js b/src/yafowil/widget/location/resources/widget.min.js index a316fce..7a2cac5 100644 --- a/src/yafowil/widget/location/resources/widget.min.js +++ b/src/yafowil/widget/location/resources/widget.min.js @@ -1 +1 @@ -var yafowil_location=function(t,a){"use strict";class i{constructor(t,a){this.widget=t,this.marker=a,this.create_popup()}create_popup(){let t=document.createElement("a");t.href="#",t.innerHTML="Remove",t.onclick=this.remove_handle.bind(this),this.marker.bindPopup(t)}remove_handle(){let t=this.widget;return t.markers.removeLayer(this.marker),t.lat="",t.lon="",t.zoom="",!1}}class e{constructor(t,a,e){this.widget=t;let o=new L.Marker([a,e],{draggable:!0});o.addTo(t.markers),new i(t,o),o.on("dragend",this.dragend_handle.bind(this))}dragend_handle(t){let a=t.target._latlng,i=this.widget;i.lat=a.lat,i.lon=a.lng,i.zoom=i.map.getZoom()}}class o{constructor(t){this.widget=t;let a=this.geosearch=new GeoSearch.GeoSearchControl({provider:new GeoSearch.OpenStreetMapProvider,style:"bar",autoClose:!0});t.map.addControl(a),t.map.on("geosearch/showlocation",this.showloaction_handle.bind(this))}showloaction_handle(t){let a=t.location,i=a.y,o=a.x,n=this.widget;n.markers.clearLayers(),new e(n,i,o),n.lat=i,n.lon=o}}class n{static initialize(t){a("div.location-map",t).each((function(){void 0!==window.yafowil_array&&window.yafowil_array.inside_template(a(this))||new n(a(this))}))}constructor(t){t.data("yafowil-location",this),this.elem=t,this.id=t.attr("id");let i=t.parent();this._input_lat=a("input.location-lat",i),this._input_lon=a("input.location-lon",i),this._input_zoom=a("input.location-zoom",i),this.change_lat_handle=this.change_lat_handle.bind(this),this._input_lat.on("change",this.change_lat_handle),this.change_lon_handle=this.change_lon_handle.bind(this),this._input_lon.on("change",this.change_lon_handle),this.min_zoom=t.data("min_zoom"),this.max_zoom=t.data("max_zoom"),this.tile_layers=t.data("tile_layers"),this._lat=t.data("lat"),this._lon=t.data("lon"),this._zoom=t.data("zoom"),this.value=this.elem.data("value"),this.create_map(),new o(this)}get value(){return this._value}set value(t){this._value=t,t&&(void 0!==t.lat&&void 0!==t.lon&&(this._lat=t.lat,this._lon=t.lon),void 0!==t.zoom&&(this._zoom=t.zoom))}get lat(){return this._lat}set lat(t){this._lat=t,this._input_lat.val(t)}get lon(){return this._lon}set lon(t){this._lon=t,this._input_lon.val(t)}get zoom(){return this._zoom}set zoom(t){this._zoom=t,this._input_zoom.val(t)}create_map(){let t=this.map=new L.Map(this.id);this.map.setView([this.lat,this.lon],this.zoom);for(let a of this.tile_layers)a.options.minZoom=this.min_zoom,a.options.maxZoom=this.max_zoom,new L.TileLayer(a.urlTemplate,a.options).addTo(t);let a=this.markers=new L.FeatureGroup;t.addLayer(a),this.value&&new e(this,this.lat,this.lon),t.on("click",this.click_handle.bind(this))}click_handle(t){this.markers.clearLayers();let a=t.latlng;new e(this,a.lat,a.lng),this.lat=a.lat,this.lon=a.lng,this.zoom=this.map.getZoom()}change_val(t,a){let i=parseFloat(t.val());isNaN(i)?t.val(this[a]):(this[a]=i,this.markers.clearLayers(),new e(this,this.lat,this.lon),this.map.setView([this.lat,this.lon],this.zoom))}change_lat_handle(t){t.preventDefault(),this.change_val(a(t.currentTarget),"_lat")}change_lon_handle(t){t.preventDefault(),this.change_val(a(t.currentTarget),"_lon")}}function l(t,a){n.initialize(a)}function s(){void 0!==window.yafowil_array&&window.yafowil_array.on_array_event("on_add",l)}return a((function(){void 0!==window.ts?ts.ajax.register(n.initialize,!0):void 0!==window.bdajax?bdajax.register(n.initialize,!0):n.initialize(),s()})),t.LocationWidget=n,t.LocationWidgetMarker=e,t.LocationWidgetMarkerPopup=i,t.LocationWidgetSearch=o,t.register_array_subscribers=s,Object.defineProperty(t,"__esModule",{value:!0}),window.yafowil=window.yafowil||{},window.yafowil.location=t,t}({},jQuery); +var yafowil_location=function(t,a){"use strict";class e{constructor(t,a){this.widget=t,this.marker=a,this.create_popup()}create_popup(){let t=document.createElement("a");t.href="#",t.innerHTML="Remove",t.onclick=this.remove_handle.bind(this),this.marker.bindPopup(t)}remove_handle(){let t=this.widget;return t.markers.removeLayer(this.marker),t.lat="",t.lon="",t.zoom="",!1}}class i{constructor(t,a,i){this.widget=t;let o=new L.Marker([a,i],{draggable:!0});o.addTo(t.markers),new e(t,o),o.on("dragend",this.dragend_handle.bind(this))}dragend_handle(t){let a=t.target._latlng,e=this.widget;e.lat=a.lat,e.lon=a.lng,e.zoom=e.map.getZoom()}}class o{constructor(t){this.widget=t;let a=this.geosearch=new GeoSearch.GeoSearchControl({provider:new GeoSearch.OpenStreetMapProvider,style:"bar",autoClose:!0});t.map.addControl(a),t.map.on("geosearch/showlocation",this.showloaction_handle.bind(this))}showloaction_handle(t){let a=t.location,e=a.y,i=a.x,o=this.widget;o.markers.clearLayers(),this.widget.create_marker(e,i),o.lat=e,o.lon=i}}class n{static initialize(t){a("div.location-map",t).each((function(){void 0!==window.yafowil_array&&window.yafowil_array.inside_template(a(this))||new n(a(this))}))}constructor(t){t.data("yafowil-location",this),this.elem=t,this.id=t.attr("id");let e=t.parent();this._input_lat=a("input.location-lat",e),this._input_lon=a("input.location-lon",e),this._input_zoom=a("input.location-zoom",e),this.change_lat_handle=this.change_lat_handle.bind(this),this._input_lat.on("change",this.change_lat_handle),this.change_lon_handle=this.change_lon_handle.bind(this),this._input_lon.on("change",this.change_lon_handle),this.min_zoom=t.data("min_zoom"),this.max_zoom=t.data("max_zoom"),this.tile_layers=t.data("tile_layers"),this._lat=t.data("lat"),this._lon=t.data("lon"),this._zoom=t.data("zoom"),this.value=this.elem.data("value"),this.create_map(),new o(this)}get value(){return this._value}set value(t){this._value=t,t&&(void 0!==t.lat&&void 0!==t.lon&&(this._lat=t.lat,this._lon=t.lon),void 0!==t.zoom&&(this._zoom=t.zoom))}get lat(){return this._lat}set lat(t){this._lat=t,this._input_lat.val(t)}get lon(){return this._lon}set lon(t){this._lon=t,this._input_lon.val(t)}get zoom(){return this._zoom}set zoom(t){this._zoom=t,this._input_zoom.val(t)}create_marker(t,a){return new i(this,t,a)}create_map(){let t=this.map=new L.Map(this.id);this.map.setView([this.lat,this.lon],this.zoom);for(let a of this.tile_layers)a.options.minZoom=this.min_zoom,a.options.maxZoom=this.max_zoom,new L.TileLayer(a.urlTemplate,a.options).addTo(t);let a=this.markers=new L.FeatureGroup;t.addLayer(a),this.value&&this.create_marker(this.lat,this.lon),t.on("click",this.click_handle.bind(this))}click_handle(t){this.markers.clearLayers();let a=t.latlng;this.create_marker(a.lat,a.lng),this.lat=a.lat,this.lon=a.lng,this.zoom=this.map.getZoom()}change_val(t,a){let e=parseFloat(t.val());isNaN(e)?t.val(this[a]):(this[a]=e,this.markers.clearLayers(),this.create_marker(this.lat,this.lon),this.map.setView([this.lat,this.lon],this.zoom))}change_lat_handle(t){t.preventDefault(),this.change_val(a(t.currentTarget),"_lat")}change_lon_handle(t){t.preventDefault(),this.change_val(a(t.currentTarget),"_lon")}}function l(t,a){n.initialize(a)}function s(){void 0!==window.yafowil_array&&window.yafowil_array.on_array_event("on_add",l)}return a((function(){void 0!==window.ts?ts.ajax.register(n.initialize,!0):void 0!==window.bdajax?bdajax.register(n.initialize,!0):n.initialize(),s()})),t.LocationWidget=n,t.LocationWidgetMarker=i,t.LocationWidgetMarkerPopup=e,t.LocationWidgetSearch=o,t.register_array_subscribers=s,Object.defineProperty(t,"__esModule",{value:!0}),window.yafowil=window.yafowil||{},window.yafowil.location=t,t}({},jQuery);