Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/1252 control hajk programatically #1272

Merged
merged 32 commits into from
Jan 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
1424646
Initial commit for #1252:
jacobwod Dec 1, 2022
967ca0c
Merge branch 'develop' into feature/1252-control-hajk-programatically
jacobwod Dec 6, 2022
b47dfee
Added a generic text field that can be used to try out any hash params
jacobwod Dec 6, 2022
27b76f9
Major addition to index.js that we'll need to investigate:
jacobwod Dec 6, 2022
8837b28
Quite a lot in here, but I'm basically done with 1 & 2 of the Methodo…
jacobwod Dec 9, 2022
d1de2f0
Added 'env: browser' to eslintrc in order to get rid of 'Unknown vari…
jacobwod Dec 13, 2022
e99bc20
Experimental: Added the OL Map object to the public Hajk API.
jacobwod Dec 13, 2022
de4a7a7
Merge branch 'develop' into feature/1252-control-hajk-programatically
jacobwod Dec 19, 2022
3e54443
Implemented search functionality in the hash API:
jacobwod Dec 20, 2022
4ca0017
Merge remote-tracking branch 'origin/develop' into feature/1252-contr…
jacobwod Jan 4, 2023
7bade8d
Merge branch 'develop' into feature/1252-control-hajk-programatically
jacobwod Jan 10, 2023
fbdef4f
Very much WIP, but I'll commit it for the record:
jacobwod Jan 13, 2023
bc73248
Merge branch 'develop' into feature/1252-control-hajk-programatically
jacobwod Jan 16, 2023
609ef13
Cleaned up the AnchorModel API by making private properties private.
jacobwod Jan 16, 2023
fa6b980
The 'clean' param is only added to the AnchorView's URL, never to the…
jacobwod Jan 16, 2023
ddeb594
URLs generated by anchor now only include the hash portion:
jacobwod Jan 16, 2023
352cc98
A little longer default delay on debounce
jacobwod Jan 16, 2023
f6001f1
Added support for x & y, plus new param: p:
jacobwod Jan 16, 2023
44cf1e1
Minor fix: separator must by specified when calling .split()
jacobwod Jan 16, 2023
f849088
Some comments and cleanups
jacobwod Jan 17, 2023
6d977bc
Merge branch 'develop' into feature/1252-control-hajk-programatically
jacobwod Jan 18, 2023
dcfcdb7
Layer history and toggling almost done:
jacobwod Jan 24, 2023
77b7a0d
Fixed functionality for Hajk's group layers:
jacobwod Jan 24, 2023
f45f9d1
I had a nice long comment explaining the mess. Forgot to put the code…
jacobwod Jan 24, 2023
8fec397
Removed a log message
jacobwod Jan 24, 2023
f855f8a
Got rid of a (probably) unneeded timeout.
jacobwod Jan 24, 2023
b20c887
Extended the embedded example page.
jacobwod Jan 24, 2023
a3b740e
Merge branch 'develop' into feature/1252-control-hajk-programatically
jacobwod Jan 24, 2023
5195e59
Added `enableAppStateInHash` option to dotnet backend
Hallbergs Jan 25, 2023
be22910
Fixed scroll-zoom "jump"-issue.
Hallbergs Jan 25, 2023
5d580f4
Fixed another zoom-parsing issue
Hallbergs Jan 25, 2023
f4ba12f
Fixed missing delay in debounce
Hallbergs Jan 25, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions backend/mapservice/Models/MapSetting.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ public class MapSetting

public bool enableDownloadLink { get; set; }

public bool enableAppStateInHash { get; set; }

public string logo { get; set; }

public string logoLight { get; set; }
Expand Down
29 changes: 28 additions & 1 deletion new-admin/src/views/mapoptions.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,8 @@ class MapOptions extends Component {
constrainOnlyCenter: config.constrainOnlyCenter,
constrainResolution: config.constrainResolution,
constrainResolutionMobile: config.constrainResolutionMobile || false,
enableDownloadLink: config.enableDownloadLink,
enableDownloadLink: config.enableDownloadLink || false,
enableAppStateInHash: config.enableAppStateInHash,
altShiftDragRotate: config.altShiftDragRotate || true,
onFocusOnly: config.onFocusOnly || false,
doubleClickZoom: config.doubleClickZoom || true,
Expand Down Expand Up @@ -150,6 +151,7 @@ class MapOptions extends Component {
constrainResolution: mapConfig.constrainResolution,
constrainResolutionMobile: mapConfig.constrainResolutionMobile || false,
enableDownloadLink: mapConfig.enableDownloadLink,
enableAppStateInHash: mapConfig.enableAppStateInHash,
altShiftDragRotate: mapConfig.altShiftDragRotate,
onFocusOnly: mapConfig.onFocusOnly,
doubleClickZoom: mapConfig.doubleClickZoom,
Expand Down Expand Up @@ -347,6 +349,7 @@ class MapOptions extends Component {
case "constrainResolution":
case "constrainResolutionMobile":
case "enableDownloadLink":
case "enableAppStateInHash":
case "altShiftDragRotate":
case "onFocusOnly":
case "doubleClickZoom":
Expand Down Expand Up @@ -414,6 +417,7 @@ class MapOptions extends Component {
"constrainResolutionMobile"
);
config.enableDownloadLink = this.getValue("enableDownloadLink");
config.enableAppStateInHash = this.getValue("enableAppStateInHash");
config.altShiftDragRotate = this.getValue("altShiftDragRotate");
config.onFocusOnly = this.getValue("onFocusOnly");
config.doubleClickZoom = this.getValue("doubleClickZoom");
Expand Down Expand Up @@ -822,6 +826,29 @@ class MapOptions extends Component {
/>
</label>
</div>
<div>
<input
id="input_enableAppStateInHash"
type="checkbox"
ref="input_enableAppStateInHash"
onChange={(e) => {
this.setState({ enableAppStateInHash: e.target.checked });
}}
checked={this.state.enableAppStateInHash}
/>
&nbsp;
<label
className="long-label"
htmlFor="input_enableAppStateInHash"
>
Beta: aktivera liveuppdatering av hashparametar i URL-fältet{" "}
<i
className="fa fa-question-circle"
data-toggle="tooltip"
title="Kartans status hålls ständigt uppdaterad, som en del av URL:ens #-parametrar. Se även #1252."
/>
</label>
</div>
<div className="separator">Kartinteraktioner</div>
<div>
Se{" "}
Expand Down
3 changes: 3 additions & 0 deletions new-client/.eslintrc
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
{
"extends": ["react-app", "react-app/jest", "prettier"],
"plugins": ["prettier"],
"env": {
"browser": true
},
"rules": {
"prettier/prettier": "error",
"arrow-body-style": "off",
Expand Down
184 changes: 184 additions & 0 deletions new-client/public/examples/embedded.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Example: Hajk Embedded</title>
<style>
p {
max-width: 660px;
}
</style>
</head>

<body style="max-width: 1280px">
<h1>How to embed and control Hajk</h1>

<form>
<fieldset>
<legend>Full control:</legend>
<input id="hashField" type="text" size="140" />
<button id="updateButton">Update IFRAME</button>
</fieldset>
<fieldset>
<legend>Quick buttons:</legend>
<button id="increaseButton">Increase zoom</button>
<button id="decreaseButton">Decrease zoom</button>
</fieldset>
</form>
<iframe id="iframe" src="/" width="1280" height="768"></iframe>

<p>
This example shows how an embedded Hajk instance can be controlled from
the embedding website.
</p>
<p>
<b
>It highlights the two-way interaction between the <i>embedded</i> Hajk
application and the <i>embedding</i> (parent) page.
</b>
</p>
<p>
You can use the <i>Quick buttons</i> to modify the <code>z</code> (zoom)
parameter, or use the <i>Full control</i> input field to freely set any
parameter.
</p>
<p>Currently the following parameters are supported by the API:
<ul>
<li><code>x</code> and <code>y</code> - map's center coordinates</li>
<li><code>z</code> - map's zoom level</li>
<li><code>p</code> - visible plugins</li>
<li><code>l</code> - visible layers</li>
<li><code>gl</code> - visible sublayers of group layers</li>
<li><code>q</code> - search query string</li>
</ul>
</p>
<p>
Hajk listens to changes to the hash parameters and acts accordingly, e.g.
by changing the map's zoom level. The input field's value (above) is being kept
up-to-date with Hajk's current value, so that <b>you can easily see how the
hash parameters change as you do things in the application</b>.
</p>

<p>
<i>
This example is accessible from
http://localhost:3000/examples/embedded.html when running Hajk in
development mode.</i
>
</p>

<p>
<i>
For more info on background and development, see issue <a href="https://github.com/hajkmap/Hajk/issues/1252" target="_blank">#1252</a>.</i
>
</p>
<script type="module">
// We start off with an empty hash
// const currentHash = new URLSearchParams("/");

// Grab some elements we want to access
const iframe = document.getElementById("iframe");
const hashField = document.getElementById("hashField");
const updateButton = document.getElementById("updateButton");
const increaseButton = document.getElementById("increaseButton");
const decreaseButton = document.getElementById("decreaseButton");

let hajkPublicApi = {
minZoom: 2,
maxZoom: 20,
};

const changeZoom = (increaseBy = 1) => {
const url = new URL(iframe.src);

// Extract hash params
const hash = new URLSearchParams(url.hash.replaceAll("#", ""));

// Try to grab current zoom level from hash params, default to "2"
const currentZ = parseInt(hash.get("z")) || 2;

let newZ = currentZ + increaseBy;
if (newZ < hajkPublicApi.minZoom) {
alert(`Can't zoom below level ${hajkPublicApi.minZoom}`);
newZ = hajkPublicApi.minZoom;
}

if (newZ > hajkPublicApi.maxZoom) {
alert(`Can't zoom above level ${hajkPublicApi.maxZoom}`);
newZ = hajkPublicApi.maxZoom;
}

// Set the property of the URLSearchParams object. This will either
// add "z", or update if already exists
hash.set("z", newZ);

// Transform the URLSearchParams object to a valid hash string…
const newHash = "#" + hash.toString();

// …and add to our URL.
url.hash = newHash;

// Finally, let's update the IFRAME's SRC attribute
iframe.src = url.toString();

// For the purpose of this test, let's update hash text field
hashField.value = hash.toString();
};

// Bind the listeners

iframe.contentWindow.addEventListener("hashchange", (e) => {
hashField.value = iframe.contentDocument.location.hash.replaceAll(
"#",
""
);
});

iframe.addEventListener("load", (e) => {
// Wait a second to ensure that JS is processed after Hajk is loaded in
// the IFRAME.
setTimeout(() => {
// Retrieve some data from public API
hajkPublicApi = {
...hajkPublicApi,
...iframe.contentWindow.hajkPublicApi,
};

// Ensure that the hash text field here corresponds to the actual from
// the embedded document (Hajk will change its hash string on init)
hashField.value = iframe.contentDocument.location.hash.replaceAll(
"#",
""
);
}, 700);
});

updateButton.addEventListener("click", (e) => {
e.preventDefault();
// Create the new hash value by taking the current hash field value
// and parse it into an params object
const newHash = new URLSearchParams(hashField.value).toString();

// Grab the URL (will be used to replace the SRC param of the IFRAME soon)
const url = new URL(iframe.src);
url.hash = "#" + newHash;

// Update IFRAME's SRC attribute
iframe.src = url.toString();

// Finally, let's ensure our hash field has correctly formatted
// params string too, with encoded values, e.g. ","->"%2C"
hashField.value = newHash;
});

increaseButton.addEventListener("click", (e) => {
e.preventDefault();
changeZoom(1);
});

decreaseButton.addEventListener("click", (e) => {
e.preventDefault();
changeZoom(-1);
});
</script>
</body>
</html>
Loading