/**
* @module modules/Permalink.js
* @name Permalink
* @copyright 2023 3Liz
* @license MPL-2.0
*/
import { mainLizmap } from '../modules/Globals.js';
import {transformExtent} from 'ol/proj.js';
import { html, render } from 'lit-html';
import { Config } from './Config.js';
import { Utils } from './Utils.js';
/**
* @class
* @name Permalink
*/
export default class Permalink {
/**
* Permalink is managed via short link
* @type {boolean}
*/
_shortLinkPermalink;
/**
* Creates a Permalink instance
* @param {Config} initialConfig - The lizmap initial config instance
* @param {null|object} initialPermalink - Initial permalink startup object
*/
constructor(initialConfig, initialPermalink) {
// Used to behave differently when hash is changed
// programmatically or by users in URL
this._ignoreHashChange = false;
// Store the build or received hash
this._hash = '';
this._extent4326 = [0, 0, 0, 0, 0];
// Don't refresh hash when map is initialized
this._ignoreStartupMapEvents = true;
this._shortLinkPermalink = initialConfig.options.short_link_permalink;
this._currentPermalinkId = null;
this._symbologyMap = new Map();
// initialize current permalink, if any
this.currentPermalinkProperties = initialPermalink;
// Change `checked`, `style` states based on URL fragment
if (window.location.hash) {
this._runPermalink(false, true);
}
this._historyTableTemplate = (links = [], newEntry) => html`
${links && links.length ? html`
<div class="permalink-history-title">${lizDict['permalink.history.title']}
<span
id="permalink-clear-history"
@click=${()=> this._clearPermalinkHistory()}>${lizDict['permalink.history.delete.all.title']}</span>
</div>
<table class='table table-sm table-condensed'>
<tbody>
${links.map((l,k) => {
return html`<tr data-url="${l.url}" data-share="${l.link}" class="${newEntry && k== 0 ? 'new-entry' : ''}">
<td>${l.link}</td>
<td><a href="${l.url}" target="_blank"><i title="${lizDict['permalink.history.visit']}" class='icon-eye-open'></i></a></td>
${navigator.clipboard ? html`
<td class="permalink-copy-to-clipboard" @click=${
(e) => {
const link = e.currentTarget.parentElement.getAttribute("data-url");
this._copyToClipboard(link);
}
}>
<i title="${lizDict['permalink.history.clipboard']}" class='icon-tags'></i>
</td>
` : ''}
<td @click=${(e) => {
const plink = e.currentTarget.parentElement.getAttribute("data-share");
this.currentPermalinkId = plink;
return this._sharePermalink();
}}><i title="${lizDict['permalink.history.share']}" class='icon-share'></i></td>
<td @click=${(e) => {
const plink = e.currentTarget.parentElement.getAttribute("data-share");
if(confirm(lizDict['permalink.history.delete.single']))
return this._updatePermalinkHistory(plink,'d');
}}><i title="${lizDict['permalink.history.delete.single.title']}" class='icon-trash'></i></td>
</tr>`
})}
</tbody>
</table>
` : ''}
`
// initialize UI
document.getElementById('permalink-box').style.display = this._shortLinkPermalink ? 'none' : 'block';
document.getElementById('permalink-generator').style.display = this._shortLinkPermalink ? 'flex' : 'none';
document.getElementById('permalink-back').style.display = this._shortLinkPermalink ? 'initial' : 'none';
this._renderHistoryTemplate();
window.addEventListener(
"hashchange", () => {
// The hash has been changed by the module
if (this._ignoreHashChange) {
this._ignoreHashChange = false;
return;
}
// Received the event but the hash does not change
if (this._hash == window.location.hash) {
return;
}
if (window.location.hash) {
this._runPermalink(true);
}
}
);
this._updatePermalinkParameters = () => {
this._enableNewPermalinkButton();
this._writeURLFragment();
}
this._refreshURLsInPermalinkComponent();
// define events on UI component
this._attachComponentEvents();
// Refresh hash parameters when map state changes
mainLizmap.state.map.addListener(
() => {
if (this._ignoreStartupMapEvents) {
this._ignoreStartupMapEvents = false;
return;
}
this._updatePermalinkParameters();
}, ['map.state.changed']
);
mainLizmap.state.rootMapGroup.addListener(
(ev) => {
const evtStyleChange = ev.type.indexOf("style.changed") >= 0;
if (this._shortLinkPermalink && evtStyleChange) {
mainLizmap.state.rootMapGroup.getMapLayerByName(ev.name).removeListener(
this._updatePermalinkParameters,
'layer.symbol.checked.changed'
);
if (this._symbologyMap.get(ev.name))
this._resetPermalinkSymbology(ev.name);
}
this._updatePermalinkParameters();
},
[
'layer.visibility.changed',
'group.visibility.changed',
'layer.style.changed',
'group.style.changed',
'layer.opacity.changed',
'group.opacity.changed',
]
);
if (this._shortLinkPermalink) {
mainLizmap.state.rootMapGroup.addListener(
(ev) => {
mainLizmap.state.rootMapGroup.getMapLayerByName(ev.name).addListener(
this._updatePermalinkParameters,
[
'layer.symbol.checked.changed'
]
)
const item = mainLizmap.state.layersAndGroupsCollection.getLayerOrGroupByName(ev.name);
this._symbologyMap.set(ev.name, true);
item.symbologyInitParameters = {};
this._updatePermalinkParameters();
}, ['layer.symbology.changed']
)
}
}
/**
* Setting the current permalink hash
* @param {string} permalinkId - the permalink hash
*/
set currentPermalinkId(permalinkId){
this._currentPermalinkId = permalinkId;
}
/**
* Getting the current permalink hash
* @type {string}
*/
get currentPermalinkId(){
return this._currentPermalinkId;
}
/**
* Stores the current permalink properties in local storage when short link permalink is enabled
* @param {object} plink - the permalink object
*/
set currentPermalinkProperties(plink){
if(!this._shortLinkPermalink) return;
const {repository, project} = globalThis['lizUrls'].params;
const storedPermalink = localStorage.getItem('lizmap_p_link');
let updatedPermalink;
if(typeof plink === 'object' && !Array.isArray(plink) && plink !== null) {
if (plink.repository && plink.repository == repository && plink.project && plink.project == project) {
updatedPermalink = [plink];
if (storedPermalink) {
let currentPermalinkList = JSON.parse(storedPermalink);
if(Array.isArray(currentPermalinkList)) {
updatedPermalink = [
...currentPermalinkList.filter(f => f.repository !== repository || f.project !== project),
...updatedPermalink,
];
}
}
}
} else {
// remove current permalink instance from local storage, if any
if (storedPermalink) {
let currentPermalinkList = JSON.parse(storedPermalink);
if(Array.isArray(currentPermalinkList)) {
updatedPermalink = currentPermalinkList.filter((f)=> f.repository != repository || f.project != project);
}
}
}
if (updatedPermalink) localStorage.setItem('lizmap_p_link', JSON.stringify(updatedPermalink));
}
/**
* Retrieves the current permalink properties from local storage
* @type {object}
*/
get currentPermalinkProperties(){
let currentPermalink = null;
const {repository, project} = globalThis['lizUrls'].params;
try {
const storedPermalink = localStorage.getItem('lizmap_p_link');
if (storedPermalink) {
let currentPermalinkList = JSON.parse(storedPermalink);
if(Array.isArray(currentPermalinkList)) {
let currentPermalinkObj = currentPermalinkList.filter((f)=> f.repository == repository && f.project == project);
if(currentPermalinkObj.length == 1) {
currentPermalink = currentPermalinkObj[0].plink;
}
}
}
} catch(e) {
console.log(e);
currentPermalink = null;
}
return currentPermalink;
}
/**
* Stores the permalink history in the local storage
* @param {Array} history - the permalink records on history
*/
set permalinksHistory(history){
localStorage.setItem('lizmap_permalink_history', JSON.stringify(history));
}
/**
* Get history records
* @type {Array}
*/
get permalinksHistory(){
let storedPermalink = [];
const {repository, project} = globalThis['lizUrls'].params;
try {
const permalinkParameters = localStorage.getItem('lizmap_permalink_history');
if (permalinkParameters) {
let historyPermalink = JSON.parse(permalinkParameters);
if (historyPermalink && Array.isArray(historyPermalink)) {
storedPermalink = historyPermalink.filter(f => f.repository == repository && f.project == project)
}
}
} catch (e) {
console.warn(e);
storedPermalink = [];
}
return storedPermalink;
}
/**
* Get permalink from server
* @param {string} permalinkId - the permalink hash
* @returns {Promise<object>} The permalink object or the error object
*/
static async getPermalink(permalinkId){
const permalinkParams = new URLSearchParams({
o:'g',
id: permalinkId,
...globalThis['lizUrls'].params
})
let permalinkData;
try {
permalinkData = await Utils.fetchJSON(globalThis['lizUrls'].short_link_permalink + '?' + permalinkParams);
} catch(e) {
permalinkData = { error: [e.message]};
}
return permalinkData;
}
/**
* Copy the permalink link to clipboard
* @param {string} link - the permalink url
* @returns {void}
*/
_copyToClipboard(link){
navigator.clipboard.writeText(link).then(() => {
});
}
/**
* Renders the history template on client
* @param {string} mode - update mode, 'a' = permalink added, 'd' = permalink deletes, '' = refresh only
* @returns {void}
*/
_renderHistoryTemplate(mode = '') {
if (this._shortLinkPermalink) {
render(this._historyTableTemplate(this.permalinksHistory, mode == 'a'), document.getElementById('permalink-history'));
}
}
/**
* Enables the add paermalink button.
* @returns {void}
*/
_enableNewPermalinkButton(){
if (!this._shortLinkPermalink) return;
document.getElementById('lizmap-new-permalink').disabled = false;
document.getElementById('lizmap-new-permalink').innerText = lizDict['permalink.new'];
}
/**
* Defines events on UI components
* @returns {void}
*/
_attachComponentEvents(){
// Handle events on permalink component
// close minidock
const btnPermalinkClear = document.querySelector('.btn-permalink-clear');
if (btnPermalinkClear) {
btnPermalinkClear.addEventListener('click', () => document.getElementById('button-permaLink').click());
}
// change embed iframe size
const selectEmbedPermalink = document.getElementById('select-embed-permalink');
if (selectEmbedPermalink) {
selectEmbedPermalink.addEventListener('change', event => {
document.getElementById('span-embed-personalized-permalink').classList.toggle('hide', event.target.value !== 'p')
this._refreshURLsInPermalinkComponent();
});
}
// custom iframe size
document.querySelectorAll('#input-embed-width-permalink, #input-embed-height-permalink').forEach(input =>
input.addEventListener('input', () => this._refreshURLsInPermalinkComponent())
);
// Geobookmarks (only for logged in users)
const geobookmarkForm = document.getElementById('geobookmark-form');
if (geobookmarkForm) {
this._bindGeobookmarkEvents();
geobookmarkForm.addEventListener('submit', async event => {
event.preventDefault();
const bname = document.querySelector('#geobookmark-form input[name="bname"]').value;
if (bname == '') {
lizMap.addMessage(lizDict['geobookmark.name.required'], 'danger', true);
return false;
}
let permalink = null;
if (this._shortLinkPermalink) {
permalink = await this._addShortLinkPermalink();
if(!permalink) return;
}
const gbparams = {};
gbparams['project'] = globalThis['lizUrls'].params.project;
gbparams['repository'] = globalThis['lizUrls'].params.repository;
gbparams['hash'] = this._shortLinkPermalink ? `#permalink=${permalink}` : this._hash;
gbparams['name'] = bname;
gbparams['q'] = 'add';
fetch(globalThis['lizUrls'].geobookmark, {
method: "POST",
body: new URLSearchParams(gbparams)
}).then(response => {
return response.text();
}).then( data => {
this._setGeobookmarkContent(data);
});
});
}
// If geobookmark is the same than the hash there is
// no `hashchange` event. In this case we run permalink
document.querySelectorAll('.btn-geobookmark-run').forEach(button => {
button.addEventListener('click', event => {
if (decodeURIComponent(window.location.hash) === event.currentTarget.getAttribute('href')) {
this._runPermalink(true);
}
});
});
// short link permalink
if (this._shortLinkPermalink) {
const backToLinkGenerator = document.getElementById('permalink-back');
backToLinkGenerator.addEventListener('click', () => {
document.getElementById('permalink-box').style.display = 'none';
document.getElementById('permalink-generator').style.display = 'flex';
})
const newPermalinkButton = document.getElementById('lizmap-new-permalink');
if(newPermalinkButton) {
newPermalinkButton.addEventListener('click', e => {
this._createNewPermalink(e);
})
}
}
}
/**
* Updates the local permalink history
* @param {string} plink - the permalink hash
* @param {string} mode - update mode, 'a' = add, 'd' = delete, '' = refresh only
* @returns {void}
*/
_updatePermalinkHistory(plink, mode){
const {repository, project} = globalThis['lizUrls'].params;
let permalinkList = this.permalinksHistory;
const isOnHistory = permalinkList.filter((e)=> e.link == plink);
if(!isOnHistory.length) {
if (mode == 'a') {
permalinkList.unshift({
link: plink,
repository: repository,
project:project,
url: this._getShortLinkPermalinkUrl(plink),
})
}
// keep only 20 items per tuple (repository, project)
permalinkList = permalinkList.slice(0,20);
} else {
// order history
permalinkList = [ ...(mode == 'd' ? [] : isOnHistory), ...permalinkList.filter((e)=> e.link != plink)]
}
this.permalinksHistory = permalinkList;
this._renderHistoryTemplate(mode);
}
/**
* Returns the permalink url
* @returns {string} The permalink url
*/
_getShortLinkPermalinkUrl(plink){
return window.location.origin
+ window.location.pathname
+ '?'
+ new URLSearchParams(globalThis['lizUrls'].params)
+ "#permalink="+plink;
}
/**
* Removes permalink history from local storage
* @returns {void}
*/
_clearPermalinkHistory(){
if(confirm(lizDict['permalink.history.delete.all'])) {
localStorage.removeItem('lizmap_permalink_history');
this._renderHistoryTemplate();
}
}
/**
* Reset current permalink symbology information
* @param {string} layerName the layer name
* @returns {void}
*/
_resetPermalinkSymbology(layerName){
let currentPermalink = this.currentPermalinkProperties;
const {repository, project} = globalThis['lizUrls'].params;
this._symbologyMap.set(layerName, false);
const nameEncoded = encodeURIComponent(layerName);
if(currentPermalink && currentPermalink.layers && currentPermalink.symbology) {
const layerIndex = currentPermalink.layers.indexOf(nameEncoded);
if(layerIndex > -1) {
currentPermalink.symbology[layerIndex] = '';
const item = mainLizmap.state.layersAndGroupsCollection.getLayerOrGroupByName(layerName);
item.symbologyInitParameters = {};
}
}
this.currentPermalinkProperties = {repository:repository, project:project, plink:{...currentPermalink}};
}
/**
* Creates a new permalink short link and updates UI.
* @param {Event} e - click event
* @returns {void}
*/
async _createNewPermalink(e){
e.preventDefault();
document.getElementById('lizmap-new-permalink').disabled = true;
const permalink = await this._addShortLinkPermalink();
if(permalink) {
this.currentPermalinkId = permalink;
this._updatePermalinkHistory(permalink, 'a');
if(navigator.clipboard) {
this._copyToClipboard(this._getShortLinkPermalinkUrl(permalink));
document.getElementById('lizmap-new-permalink').innerText = lizDict['permalink.clipboard'];
} else {
this._sharePermalink();
}
} else {
document.getElementById('lizmap-new-permalink').disabled = false;
}
}
/**
* Adds a new short link permalink for the given repository and project
* @returns {Promise<null|string>} The permalink hash or null in case of errors
*/
async _addShortLinkPermalink(){
let permalinkParams = new URLSearchParams({
o: 'add',
repository: globalThis['lizUrls'].params.repository,
project: globalThis['lizUrls'].params.project
});
// capture the current permalink properties
this._writeURLFragment();
let permalinkData;
// send request to the server
try {
permalinkData = await Utils.fetchJSON(globalThis['lizUrls'].short_link_permalink + '?' + permalinkParams,{
method:'POST',
headers: {
'Content-Type': 'application/json;charset=utf-8'
},
body: JSON.stringify({
permalink:{...this.currentPermalinkProperties}
})
})
if(permalinkData && permalinkData.permalink){
return permalinkData.permalink;
} else {
mainLizmap.displayMessage(permalinkData.error.reduce((p,c)=> p + '\n' + c,''), 'danger', true);
return null;
}
} catch (e) {
mainLizmap.displayMessage(e.message, 'danger', true);
return null;
}
}
/**
* Updates component UI for share functionality
* @returns {void}
*/
_sharePermalink(){
document.getElementById('permalink-box').style.display = 'block';
document.getElementById('permalink-generator').style.display = 'none';
this._refreshURLsInPermalinkComponent()
}
_setGeobookmarkContent(gbData) {
// set content
$('div#geobookmark-container').html(gbData);
// unbind previous click events
$('div#geobookmark-container button').unbind('click');
// Bind events
this._bindGeobookmarkEvents();
// Remove bname val
$('#geobookmark-form input[name="bname"]').val('').blur();
}
_bindGeobookmarkEvents() {
document.querySelectorAll('.btn-geobookmark-del').forEach(button => {
button.addEventListener('click', () => {
if (confirm(lizDict['geobookmark.confirm.delete'])) {
var gbid = button.value;
this._removeGeoBookmark(gbid);
}
});
});
}
_removeGeoBookmark(id) {
var gbparams = {
id: id,
q: 'del',
repository: globalThis['lizUrls'].params.repository,
project: globalThis['lizUrls'].params.project
};
fetch(globalThis['lizUrls'].geobookmark + '?' + new URLSearchParams(gbparams)).then(response => {
return response.text();
}).then( data => {
this._setGeobookmarkContent(data);
});
}
/**
* Runs the permalink to update the map
* @param {boolean} setExtent - whether set the map extent or not
* @param {boolean} useInitialPermalink - whether ignore permalink hash and use initial permalink
* @returns {Promise<void>}
*/
async _runPermalink(setExtent, useInitialPermalink = false) {
if (this._hash === ''+window.location.hash) {
return;
}
if (window.location.hash === "") {
this._hash = '';
return;
}
this._hash = ''+window.location.hash;
if (this._shortLinkPermalink && this._hash.indexOf('#permalink=') == 0){
if(!useInitialPermalink) {
const shortLink = window.location.hash.substring(1).split('=')[1];
if (shortLink) {
const permalink = await this.constructor.getPermalink(shortLink);
if (!permalink) return;
if(permalink.hasOwnProperty('error')) {
mainLizmap.displayMessage(permalink.error.reduce((p,c) => p + '\n' + c,''),'danger',true);
// remove permalink from local storage
this._updatePermalinkHistory(shortLink,'d');
} else {
this.currentPermalinkProperties = permalink;
}
}
}
if (mainLizmap.config.options.automatic_permalink) {
history.replaceState(null, '', window.location.pathname + window.location.search +'#map_status');
} else history.replaceState(null, '', window.location.pathname + window.location.search)
}
// items are layers then groups from leaf to root
const items = mainLizmap.state.layersAndGroupsCollection.layers.concat(
mainLizmap.state.layersAndGroupsCollection.groups.reverse() // reverse groups array to get from leaf to root
);
const [extent4326, itemsInURL, stylesInURL, opacitiesInURL, symbologyInUrl] = this._getPermalinkValues();
if (setExtent
&& extent4326
&& extent4326.length === 4
&& this._extent4326.filter((v, i) => {return parseFloat(extent4326[i]).toPrecision(6) != v}).length != 0) {
const mapExtent = transformExtent(
extent4326.map(coord => parseFloat(coord)),
'EPSG:4326',
lizMap.map.projection.projCode
);
this._extent4326 = extent4326.map(coord => parseFloat(coord).toPrecision(6));
mainLizmap.extent = mapExtent;
}
if (itemsInURL && itemsInURL.length != 0) {
for (const item of items){
if(itemsInURL && itemsInURL.includes(encodeURIComponent(item.name))){
const itemIndex = itemsInURL.indexOf(encodeURIComponent(item.name));
item.checked = true;
if (item.type === 'layer' && stylesInURL[itemIndex] !== undefined) {
item.wmsSelectedStyleName = decodeURIComponent(stylesInURL[itemIndex]);
}
if (opacitiesInURL[itemIndex]) {
item.opacity = parseFloat(opacitiesInURL[itemIndex]);
}
if (symbologyInUrl && symbologyInUrl[itemIndex]) {
// if symbology is already loaded, update its checked state
if (this._symbologyMap.get(item.name)) {
item.setSymbologyCheckedStateFromParameters(symbologyInUrl[itemIndex]);
} else {
// store info
item.symbologyInitParameters = symbologyInUrl[itemIndex];
}
}
} else {
item.checked = false;
}
}
}
}
/**
* Parse permalink hash
* @returns {Array} The array of permalink parameters
*/
_getPermalinkValues(){
if (this._shortLinkPermalink) {
let permalinkValues = Array(4);
try {
let currentPermalink = this.currentPermalinkProperties;
if (currentPermalink) {
permalinkValues = [
currentPermalink.bbox,
currentPermalink.layers ?? null,
currentPermalink.styles ?? null,
currentPermalink.opacities ?? null,
currentPermalink.symbology ?? null,
]
}
} catch(e){
console.warn(e)
}
return permalinkValues;
} else {
return window.location.hash.substring(1).split('|').map(part => part.split(','));
}
}
// Set URL in permalink component's input
_refreshURLsInPermalinkComponent() {
const inputSharePermalink = document.getElementById('input-share-permalink');
const permalink = document.getElementById('permalink');
const selectEmbedPermalink = document.getElementById('select-embed-permalink');
const inputEmbedPermalink = document.getElementById('input-embed-permalink');
var searchParams = {
repository: globalThis['lizUrls'].params.repository,
project: globalThis['lizUrls'].params.project
};
if (this._hash === '') {
const urlParameters = (new URL(window.location)).searchParams;
if (urlParameters.has('bbox')) {
searchParams['bbox'] = urlParameters.get('bbox');
}
if (urlParameters.has('crs')) {
searchParams['crs'] = urlParameters.get('crs');
}
}
const permalinkValue = window.location.origin
+ window.location.pathname
+ '?'
+ new URLSearchParams(searchParams)
+ (this._shortLinkPermalink ? "#permalink="+this.currentPermalinkId : this._hash);
if (inputSharePermalink) {
inputSharePermalink.value = permalinkValue;
}
if (permalink) {
permalink.href = permalinkValue;
}
if (selectEmbedPermalink) {
const iframeSize = selectEmbedPermalink.value;
let width = 0;
let height = 0;
if ( iframeSize === 's' ) {
width = 400;
height = 300;
} else if ( iframeSize === 'm' ) {
width = 600;
height = 450;
} else if (iframeSize === 'l') {
width = 800;
height = 600;
} else if (iframeSize === 'p') {
width = document.getElementById('input-embed-width-permalink').value;
height = document.getElementById('input-embed-height-permalink').value;
}
let embedURL = window.location.href.replace('/map?','/embed?');
if (this._shortLinkPermalink) {
embedURL = embedURL.split('#')[0] + "#permalink="+this.currentPermalinkId;
}
inputEmbedPermalink.value = `<iframe width="${width}" height="${height}" frameborder="0" style="border:0" src="${embedURL}" allowfullscreen></iframe>`;
}
}
/**
* Writes the hash.
* If the short link permalink functionality is enabled, stores the permalink information in the local storage
* @returns {void}
*/
_writeURLFragment() {
// Don't write initial permalink if waiting for first theme to be applied
if (this._suspendInitialWrite) {
return;
}
let hash;
// BBOX
let bbox = mainLizmap.extent;
if (lizMap.map.projection.projCode !== 'EPSG:4326') {
bbox = transformExtent(
bbox,
lizMap.map.projection.projCode,
'EPSG:4326'
);
}
this._extent4326 = bbox.map(x => x.toFixed(6));
hash = this._extent4326.join();
// Item's visibility, style and opacity
// Only write layer's properties when visible
let itemsVisibility = [];
let itemsStyle = [];
let itemsOpacity = [];
let itemsSymbology = [];
for (const item of mainLizmap.state.rootMapGroup.findMapLayersAndGroups()) {
if (item.checked){
itemsVisibility.push(encodeURIComponent(item.name));
itemsStyle.push(item.wmsSelectedStyleName ? encodeURIComponent(item.wmsSelectedStyleName) : item.wmsSelectedStyleName);
itemsOpacity.push(item.opacity);
if (this._shortLinkPermalink) {
if (item.symbology && item.symbology.wmsParameters) {
const symbologyParameters = item.symbology.wmsParameters(item.name);
if(symbologyParameters && Object.keys(symbologyParameters).length) {
itemsSymbology.push(symbologyParameters);
} else itemsSymbology.push('');
} else itemsSymbology.push('')
}
}
}
if (itemsVisibility.length) {
hash += '|' + itemsVisibility.join();
}
if (itemsStyle.length) {
hash += '|' + itemsStyle.join();
}
if (itemsOpacity.length) {
hash += '|' + itemsOpacity.join();
}
// Saved new hash
this._hash = '#'+hash;
// Finally override URL fragment
if(this._shortLinkPermalink) {
const {repository, project} = globalThis['lizUrls'].params;
const hashParams = {}
hashParams.bbox = this._extent4326;
if (itemsVisibility.length) hashParams.layers = itemsVisibility;
if (itemsStyle.length) hashParams.styles = itemsStyle;
if (itemsOpacity.length) hashParams.opacities = itemsOpacity;
if (itemsSymbology.length) hashParams.symbology = itemsSymbology;
this.currentPermalinkProperties = {repository: repository, project: project, plink: hashParams};
}
if (mainLizmap.initialConfig.options.automatic_permalink) {
if (this._shortLinkPermalink) {
history.replaceState(null, '', window.location.pathname + window.location.search +'#map_status');
} else {
this._ignoreHashChange = true;
window.location.hash = hash;
}
}
this._refreshURLsInPermalinkComponent();
}
}