Skip to content

8 - Validating a selection

This example validates a selection using checkIsolatedNodes, checking that the current selection doesn't leave any seat isolated.

On real time, it marks isolated seats with orange color as a warning.

Once the validation button is pressed, if there is none isolated seat, a last check is made, checking that the selected seats are not separated between them, using the neighbors plugin method validateNeighbors.

If the current selection is still invalid, the checkout shouldn't be allowed.

Warning

This example is using the flag styles_by_groups. If you don't use it, then you have to use tags instead of groups, replacing addNodesToGroups and removeNodesFromGroups with setNodesTag.

Map Viewer

Code

import { loadModule } from "@3ddv/dvm";

loadModule("map_viewer", {
    container: "viewer-container",
    styles_by_groups: true,
    instanced_nodes: true,
    plugins: ["neighbors"],
})
    .then((viewer) =>{
        start(viewer);
    })
    .catch((err) =>{
        console.error(err);
    });

function start(viewer) {
    const btn_validate = document.getElementById("btn-validate");
    btn_validate.addEventListener("click", () => void validate())

    // Just for the example purpose
    viewer.flags.scroll_with_mod_key = true;

    const venue_id = "eu-es-00059-valenciabasket";
    const map_id = "S_320";

    viewer.subscribe("load_success", (_obj) => {
        customizeStyles();
        setRandomAvailability();
    });

    viewer.subscribe("select", () => checkWarnings());
    viewer.subscribe("unselect", () => checkWarnings());

    // Load the map
    viewer.loadMap({ venue_id, map_id })
        .then(() => {
            // Successfully loaded
            console.log("LOADED!");
        })
        .catch((err) => {
            // Error while loading
            console.error(err);
        });

    function customizeStyles() {
        const styles = viewer.getStyles();
        styles[0].seat.available.normal.warning = {
            fillStyle: "orange"
        };
        viewer.setStyles(styles);
    }

    function checkWarnings() {
        resetWarnings();
        const nodes = viewer.checkIsolatedNodes();
        viewer.addNodesToGroup(nodes, "warning");
    }

    function resetWarnings() {
        viewer.removeNodesFromGroup(viewer.getNodesByGroups("seat", "warning"), "warning");
    }

    async function validate() {
        if (viewer.isLoaded()) {
            const selection = viewer.getNodesByState("seat", "selected");
            if (selection.length) {
                const nodes = viewer.checkIsolatedNodes();
                if (nodes.length) {
                    alert(`Invalid selection! The following seats are isolated: ${nodes.map((node) => node.id).join(", ")}`);
                } else {
                    if (await viewer.neighbors.validateNeighbors(selection)) {
                        alert("Valid selection!");
                        return true;
                    } else {
                        alert("No seats isolated, but the current selection is not together!")
                    }
                }
            } else {
                alert("No seats selected!");
            }
        }
        return false;
    }

    // Just for the purpose of having some random availability on the map
    function setRandomAvailability(prob = 0.6) {
        if (viewer && viewer.isLoaded()) {
            viewer.getTypesList().forEach((type) => {
                const availability = viewer.getNodesByType(type).filter(() => Math.random() < prob);
                viewer.setAvailability(type, availability);
            });
        }
    }
}