Skip to content

4 - Managing user input

This example shows how to use callbacks to manage the user input from mouse or touch.

Map Viewer

  • Hover: none
  • Selected: none

Code

// ---- LOADING MODULE ----
DVM.loadModule("map_viewer", {
    container: "viewer-container", // Container where the viewer will be appended
})
    .then(function(viewer) {
        console.log(`Module '${viewer.getModuleName()}' initialized:`, viewer);
        start(viewer);

    })
    .catch(function(err) {
        console.error(err);
    });


function start(viewer) {
    // ---- SUBSCRIPTIONS ----
    // "first_seen" will be called the first time a section is painted on the map at level 1 (close enough to show seats)
    viewer.subscribe("first_seen", onFirstSeen);

    // Called when user clicks the map
    viewer.subscribe("click", onClick);

    // Called when cursor enters a node
    viewer.subscribe("enter", onEnter);

    // Called when cursor leaves a node
    viewer.subscribe("leave", onLeave);

    // Called when a node change its state to selected
    viewer.subscribe("select", onSelect);

    // Called when a node leaves its state from selected
    viewer.subscribe("onUnselect", onUnselect);

    // ---- LOADING MAP ----
    viewer.loadMap({
        venue_id: "eu-es-00008-default" // Venue to be loaded. 3ddigitalvenue will provide these IDs
    })
        .then(function (obj) {
            // Successfully loaded

            // We disable automatic selection because we are going to manage it with some viewer callbacks
            viewer.flags.automatic_selection = false;

            // Node selection is limited to 1
            viewer.max_selection = 1;

            // Get sections availability
            var available_sections = getSectionAvailability();
            // Apply sections availability
            viewer.setAvailability("section", available_sections);

            console.log("LOADED!");
        })
        .catch(function (err) {
            // Error while loading
            console.error(err);
        });


    // ---- AVAILABILITY FUNCTIONS ----
    // Get sections availability. For the purpose, we generate a RANDOM availability.
    function getSectionAvailability() {
        var sections = viewer.getNodesByType("section");
        var available_sections = [];

        for (var i = 0; i < sections.length; ++i) {
            var section = sections[i];
            if (Math.random() < 0.7) {
                available_sections.push(section.id);
            }
        }

        return available_sections;
    }
}

// ---- VIEWER CALLBACKS ----
function onClick(obj) {
    var viewer = obj.instance;
    var node = obj.nodes[0];
    // First, check if the click was made on a node (it can be triggered on empty space)
    if (node) {
        console.log("Click:", node.id);
        // Check if is a seat
        if ( node.type === "seat") {
            if (node.state === "available") {
                // If is available, unselect previous elements and select the new one
                viewer.unselectAll();
                viewer.select(node);
            } else if (node.state === "selected") {
                // If is already selected, unselect it
                viewer.unselect(node);
            }
        }
    }
}

function onEnter(obj) {
    var node = obj.nodes[0];
    if (node) {
        var label = document.getElementById("hover-text");
        if (label) {
            label.innerText = node.id;
        }
    }
}

function onLeave(obj) {
    var label = document.getElementById("hover-text");
    if (label) {
        label.innerText = "none";
    }
}

function onSelect(obj) {
    var node = obj.nodes[0];
    if (node) {
        var label = document.getElementById("selected-text");
        if (label) {
            label.innerText = node.id;
        }
    }
}

function onUnselect(obj) {
    var node = obj.nodes[0];
    if (node) {
        var label = document.getElementById("selected-text");
        if (label) {
            label.innerText = "none";
        }
    }
}

// Called when the viewer emits "first_seen"
function onFirstSeen(obj) {
    var viewer = obj.instance;
    // Get the node or nodes affected
    var nodes = obj.nodes;

    for (var i = 0; i < nodes.length; ++i) {
        var node = nodes[i];

        console.log("first seen:", node.id);

        // Check if the node is available and is a section
        if (node && node.state === "available" && node.type === "section") {
            // Get all seats with this section as a parent
            var seats = viewer.getNodesByParent(node);
            var available = [];
            // SET RANDOM SEAT AVAILABILITY
            for (var j = 0; j < seats.length; ++j) {
                var seat = seats[j];
                if (Math.random() < 0.6) {
                    available.push(seat.id);
                }
            }

            delayAvailability(available, node.id);
        }
    }

    // Add a random timeout to see the effect on the map. This also simulates getting availability asynchronously on demand.
    function delayAvailability(availability, node_id) {
        setTimeout(function () {
            viewer.setAvailability("seat", availability, node_id);
        }, rand(250, 1000));
    }
}

// ---- HELPERS ----
function rand(min, max) {
    return Math.floor(Math.random() * (max - min + 1) + min);
}