aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuilhem Moulin <guilhem@fripost.org>2024-01-22 01:58:37 +0100
committerGuilhem Moulin <guilhem@fripost.org>2024-01-22 02:53:40 +0100
commit0c0488cc79f363a2aaebac14d9edca76faf492fc (patch)
treec7ec4638da3591b5554dbeb19957d69d7c218c12
parentd35a43f0e99d523e373c2810eaf31932cfb679d0 (diff)
Add ability to grab and move popovers.
-rw-r--r--main.js67
-rw-r--r--style.css18
2 files changed, 74 insertions, 11 deletions
diff --git a/main.js b/main.js
index 4ed491f..051ef5f 100644
--- a/main.js
+++ b/main.js
@@ -807,9 +807,54 @@ map.addLayer(new VectorTileLayer({
const header = document.createElement('div');
header.classList.add('d-flex');
- const pageNode = document.createElement('div');
- pageNode.classList.add('flex-grow-1', 'pe-4');
- header.appendChild(pageNode);
+ const headerGrabbingArea = document.createElement('div');
+ headerGrabbingArea.classList.add('flex-grow-1', 'grabbing-area', 'pe-2', 'me-2');
+ header.appendChild(headerGrabbingArea);
+
+ headerGrabbingArea.onmousedown = function(event) {
+ if (event.button != 0) {
+ return;
+ }
+ const popoverTip = Popover.getInstance(popup).tip;
+ pageNode.classList.add('grabbing-area-grabbed');
+
+ if (!popoverTip.classList.contains('popover-detached')) {
+ /* detach popover tip */
+ popoverTip.classList.add('popover-detached');
+ const rect = popoverTip.getBoundingClientRect();
+ const maxHeight = document.getElementById('map').getBoundingClientRect().height - 1 - rect.top -
+ popoverTip.getElementsByClassName('popover-header')[0].getBoundingClientRect().height;
+
+ const style = popoverTip.style;
+ style.display = 'none'; /* avoid reflows between the following assignments */
+ style.position = 'absolute';
+ style.transform = '';
+ style.inset = `${rect.top}px auto auto ${rect.left}px`;
+ style.display = '';
+ }
+
+ let clientX = event.clientX, clientY = event.clientY;
+ document.onmousemove = function(event) {
+ const offsetX = clientX - event.clientX;
+ const offsetY = clientY - event.clientY;
+ clientX = event.clientX;
+ clientY = event.clientY;
+ popoverTip.style.top = (popoverTip.offsetTop - offsetY).toString() + 'px';
+ popoverTip.style.left = (popoverTip.offsetLeft - offsetX).toString() + 'px';
+ };
+
+ document.onmouseup = function(event) {
+ if (event.button != 0) {
+ return;
+ }
+ pageNode.classList.remove('grabbing-area-grabbed');
+ document.onmousemove = null;
+ document.onmouseup = null;
+ };
+ };
+
+ const pageNode = document.createElement('h6');
+ headerGrabbingArea.appendChild(pageNode);
const pageNum = document.createElement('span');
const pageCount = document.createElement('span');
@@ -891,10 +936,10 @@ map.addLayer(new VectorTileLayer({
return;
}
- /* unclear how many feature we'll find, render prev/next buttons invisible for now */
- pageNode.classList.add('invisible');
- btnPrev.classList.add('invisible', 'disabled');
- btnNext.classList.add('invisible', 'disabled');
+ /* unclear how many feature we'll find, don't render prev/next buttons for now */
+ pageNode.classList.add('d-none');
+ btnPrev.classList.add('d-none', 'disabled');
+ btnNext.classList.add('d-none', 'disabled');
map.forEachFeatureAtPixel(event.pixel, function(feature, layer) {
const properties = feature.getProperties();
@@ -955,10 +1000,10 @@ map.addLayer(new VectorTileLayer({
pageCount.innerHTML = features.length.toString();
if (features.length == 2) {
- /* there are ≥2 features, make prev/pre buttons visible */
- btnNext.classList.remove('invisible', 'disabled');
- btnPrev.classList.remove('invisible');
- pageNode.classList.remove('invisible');
+ /* there are ≥2 features, render prev/pre buttons */
+ btnNext.classList.remove('d-none', 'disabled');
+ btnPrev.classList.remove('d-none');
+ pageNode.classList.remove('d-none');
}
if (popover === null || popover.tip === null) {
diff --git a/style.css b/style.css
index 3377f44..4b78cee 100644
--- a/style.css
+++ b/style.css
@@ -348,6 +348,9 @@ html, body {
padding: 0.1rem 0.3rem;
}
+.popover-header h6 {
+ margin: 0;
+}
/* inspired from bootstrap's .btn-close */
.popover-header .popover-button {
box-sizing: content-box;
@@ -384,3 +387,18 @@ html, body {
.popover-header .popover-button-close {
--popover-button-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23000'%3e%3cpath transform='scale(1.3332) translate(-2 -2)' d='M2.146 2.854a.5.5 0 1 1 .708-.708L8 7.293l5.146-5.147a.5.5 0 0 1 .708.708L8.707 8l5.147 5.146a.5.5 0 0 1-.708.708L8 8.707l-5.146 5.147a.5.5 0 0 1-.708-.708L7.293 8z'/%3e%3c/svg%3e");
}
+
+.popover .grabbing-area {
+ cursor: move; /* fallback if grab cursor is unsupported */
+ cursor: grab;
+ cursor: -moz-grab;
+ cursor: -webkit-grab;
+}
+.popover .grabbing-area.grabbing-area-grabbed {
+ cursor: grabbing;
+ cursor: -moz-grabbing;
+ cursor: -webkit-grabbing;
+}
+.popover.popover-detached > .popover-arrow {
+ display: none;
+}