Hello everyone, I would like to know if it is possible and, most importantly, how to create a Java script that allows you to select an entity with just a click, without using the star-shaped selection tool. I want to be able to select my entity with a single click, just like QGIS does. Thank you for your feedback!
But in QGIS, you still need to activate the “selection tool”, which would be the same the “star-shaped” icon. So i guess you still mean to use the “star shaped” icon, but then having a single click to select a feature ?
If I remember correctly, this has already been discussed, but there was a technical limitation, I might get wrong, I also like the way it is done in QGIS.
Bonjour à Tous. Comment rajouter un script java à son projet lizmap?
I guess you mean JavaScript, not Java, which is totally different.
Did you read the documentation ? (I suggest the as video as well)
Show us what you have tried, what is the error, what you have looked.
lizmap.events.on({
‘ready’: function(e) {
const layerId = ‘zich@Zones inondables’; // format: ‘layername@projectname.qgs’
const container = $(‘#smart-filter’);
function createCheckbox(name, value, checked = false) {
const id = `${name}-${value}`;
return `
<div>
<input type="checkbox" id="${id}" name="${name}" value="${value}" ${checked ? 'checked' : ''}>
<label for="${id}">${value}</label>
</div>
`;
}
function loadUniqueValues(layerId, attribute, filter = null, callback) {
let data = {
'project': LizmapProject.project,
'layer': layerId,
'attribute': attribute
};
if (filter) {
data['filter'] = filter;
}
$.ajax({
url: Lizmap.baseUrl + 'server/api/uniqueValues',
data: data,
success: function(response) {
if (response && response.values) {
callback(response.values);
}
}
});
}
function updateFilters() {
const selectedSecteurs = [];
container.find('input[name="secteur"]:checked').each(function() {
selectedSecteurs.push($(this).val());
});
const filterSecteur = selectedSecteurs.length > 0
? `"secteur" IN (${selectedSecteurs.map(v => `'${v}'`).join(',')})`
: null;
loadUniqueValues(layerId, 'categorie', filterSecteur, function(categories) {
const catContainer = container.find('#categorie');
catContainer.html('<strong>Catégories :</strong>');
categories.forEach(cat => {
catContainer.append(createCheckbox('categorie', cat));
});
});
loadUniqueValues(layerId, 'hauteur_zich', filterSecteur, function(hauteurs) {
const hContainer = container.find('#hauteur_zich');
hContainer.html('<strong>Hauteurs :</strong>');
hauteurs.forEach(h => {
hContainer.append(createCheckbox('hauteur_zich', h));
});
});
}
function applyFilter() {
const secteur = [];
const categorie = [];
const hauteur = [];
container.find('input[name="secteur"]:checked').each(function() {
secteur.push(`"secteur" = '${$(this).val()}'`);
});
container.find('input[name="categorie"]:checked').each(function() {
categorie.push(`"categorie" = '${$(this).val()}'`);
});
container.find('input[name="hauteur_zich"]:checked').each(function() {
hauteur.push(`"hauteur_zich" = '${$(this).val()}'`);
});
const clauses = [...secteur, ...categorie, ...hauteur];
const filterExpression = clauses.join(' AND ');
lizmap.setFilter(layerId, filterExpression);
}
// Initial UI
container.html(`
<div id="secteur"><strong>Secteurs :</strong></div>
<div id="categorie"><strong>Catégories :</strong></div>
<div id="hauteur_zich"><strong>Hauteurs :</strong></div>
<button id="applyFilter">Appliquer le filtre</button>
`);
loadUniqueValues(layerId, 'secteur', null, function(secteurs) {
const sContainer = container.find('#secteur');
secteurs.forEach(s => {
sContainer.append(createCheckbox('secteur', s));
});
// Mise à jour en cascade
container.on('change', 'input[name="secteur"]', updateFilters);
});
// Bouton appliquer
container.on('click', '#applyFilter', applyFilter);
}
});
I watched the tutorial, I even tried to do the same javascript as the tutorial but nothing happens, should I do some server-side manipulations?
In the administration panel, in your repositories page, you need to enable “JavaScript”.
Great, it works. One last question: is it possible to only show the layers and filter step in the guided tour? If so, how can I do this? Which part should I change?:
function htmlPopup(tour) {
var html = ‘’;
var title = ‘A Lire’;
var content = ‘Bienvenue’;
// Header ( l'entête)
html += '<div class="modal-header" style="background-color:rgba(0, 0, 0, 0.7);">';
html += '<h3 style="color:white;">' + title + '</h3></div>';
// Main content : body
html += '<div class="modal-body">';
html += '<p>' + content + '</p>';
// Project Metadata
html += $('#metadata').html();
// End of main content body
html += '</div>';
// Footer
html += '<div class="modal-footer" style="background-color:rgba(0, 0, 0, 0.7);"></div>';
// Return shepherd
return {
id: 'Popup Startup',
text: html,
attachTo: {
element: 'body',
},
buttons: [{ text: 'Voir le tutoriel', action: tour.next }],
};
}
// Check the browser’s localstorage
function dismissTour() {
if (!localStorage.getItem(‘shepherd-tour’)) {
localStorage.setItem(‘shepherd-tour’, ‘yes’);
}
}
// Start the tutorial
function startTutorial() {
// Create a tour
const tour = new Shepherd.Tour({
useModalOverlay: true,
defaultStepOptions: {
classes: ‘shepherd-theme-custom’,
scrollTo: true,
cancelIcon: { enabled: true },
keyboardNavigation: true,
exitOnEsc: true,
when: {
show() {
// Don’t show the progress bar on first and final step
if (tour.steps.indexOf(tour.currentStep) != 0 && tour.steps.indexOf(tour.currentStep) != tour.steps.length - 1) {
const currentStepElement = tour.currentStep.el;
const header = currentStepElement.querySelector(‘.shepherd-footer’);
const progress = document.createElement(‘div’);
const innerBar = document.createElement(‘span’);
const progressPercentage = ((tour.steps.indexOf(tour.currentStep) + 1) / tour.steps.length) * 100 + ‘%’;
progress.className = 'shepherd-progress-bar';
innerBar.style.width = progressPercentage;
progress.style.minWidth = '10px';
progress.appendChild(innerBar);
header.insertBefore(progress, currentStepElement.querySelector('.shepherd-button'));
}
}
}
},
});
// Add the first step (the popup)
tour.addStep(htmlPopup(tour));
// Add automatic tour steps
const tourSteps = $('.nav.nav-list li').filter(function () {
return this.style.display !== 'none' && !this.classList.contains('hide');
}).map(function (index, element) {
const aElement = $(element).find('a')[0];
return {
id: `Étape ${index + 1}`,
title: `Étape ${index + 1}`,
text: $(aElement).attr('data-original-title'),
attachTo: {
element: aElement,
on: 'right',
},
buttons: [{ text: 'Précédent', action: tour.back }, { text: 'Suivant', action: tour.next }],
};
}).get();
// Add 3 more personal tour steps
const stepHappyCoding = [
{
id: 'move-map',
title: 'Déplacer la carte',
text: 'Déplacez la carte pour explorer d\'autres zones.',
attachTo: {
element: 'span#navbar',
on: 'left',
},
buttons: [{ text: 'Précédent', action: tour.back }, { text: 'Suivant', action: tour.next }],
},
{
id: 'overview',
title: 'Etape 2',
text: 'La boîte de prévisualisation vous permet de voir une vue d\'ensemble de la carte.',
attachTo: {
element: '#overview-box',
on: 'top',
},
buttons: [{ text: 'Précédent', action: tour.back }, { text: 'Suivant', action: tour.next }],
},
{
id: 'happy-coding',
title: 'Merci pour votre lecture',
text: 'C\'est tout pour ce tutoriel, allez-y et commencez à explorer cette carte interactive 😉.',
attachTo: {
element: 'body',
},
buttons: [
{ text: 'Précédent', action: tour.back },
{
text: 'Terminer',
action() {
// Dismiss the tour when the finish button is clicked
dismissTour();
return this.hide();
}
}],
}
];
// Spread the steps into the tour array
tourSteps.push(...stepHappyCoding);
// Modification de l'étape 1
if (tourSteps.length > 0) {
tourSteps[0].text += '<br><br>cliquez ici pour retourner sur la page d\'accueil';
tourSteps[0].title = 'Page d\'acceuil';
}
// Modification de l'étape 2
if (tourSteps.length > 1) {
tourSteps[1].text += 'Cliquez ici si vous ne voulez pas retourner sur la page d\'accueil, vous avez la possibilité d\'accéder aux répertoires des applications directement.';
tourSteps[1].title = 'Page des répertoires';
}
// Modification de l'étape 3
if (tourSteps.length > 2) {
tourSteps[2].text = 'Par cet onglet vous accédez à l\'ensemble des couches qui composent ce projet. Cliquez dessus pour les voir s\'afficher.';
tourSteps[2].title = 'Les couches';
}
// Modification de l'étape 4
if (tourSteps.length > 3) {
tourSteps[3].text = 'Vous trouverez ici les informations sur l\'ensemble du projet.';
tourSteps[3].title = 'Informations';
}
// Modification de l'étape 5
if (tourSteps.length > 4) {
tourSteps[4].text = 'Nous avons intégré à notre application des statistiques permettant de visualiser graphiquement le nombre de bâtiments potentiellement impactés par les ZICH.';
tourSteps[4].title = 'Fenêtre contextuelle';
}
// Modification de l'étape 6
if (tourSteps.length > 5) {
tourSteps[5].text = 'Nous avons intégré à notre applications des statistiques afin de voir graphiquement le nombre de bâtiments qui pourraient être impactés par les ZICH.';
tourSteps[5].title = 'Statistiques';
}
// Modification de l'étape 7
if (tourSteps.length > 6) {
tourSteps[6].text = 'pour filtrer, il vous faut cliquez sur un critère.';
tourSteps[6].title = 'Filtres';
}
// Ajouter les étapes au tour
tour.addSteps(tourSteps);
// Démarrer le tutoriel automatiquement chaque fois que l'application s\'ouvre
tour.start();
// Retourner le tour
return tour;
}
lizMap.events.on({
uicreated: function () {
// Inclure le CSS CDN de shepherd
var link = document.createElement(‘link’);
link.href = ‘https://cdn.jsdelivr.net/npm/shepherd.js@10.0.1/dist/css/shepherd.css’;
link.rel = ‘stylesheet’;
document.head.appendChild(link);
// Inclure le JS CDN de shepherd
var script = document.createElement('script');
script.src = 'https://cdn.jsdelivr.net/npm/shepherd.js@10.0.1/dist/js/shepherd.min.js';
script.type = 'text/javascript';
script.onload = function () {
console.log('Shepherd.js a été chargé avec succès!');
const tour = startTutorial();
// Dismiss the tour when the cancel icon is clicked
tour.on('cancel', dismissTour);
};
script.onerror = function () {
console.error('Erreur lors du chargement de shepherd.js');
};
document.head.appendChild(script);
}
});