// ---- 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) {
// FLAGS
var selection = 1; // How many seats are selected at once
var filter_single_seats = false;
window.viewer = viewer;
viewer.subscribe("click", onClick);
viewer.subscribe("enter", onEnter);
viewer.subscribe("leave", onLeave);
// ---- LOADING ----
viewer.loadMap({
venue_id: "eu-es-00008-default" // Venue to be loaded. MMC will provide these IDs
})
.then(function (obj) {
// Disable automatic selection and hover
viewer.flags.automatic_selection = false;
viewer.flags.automatic_hover = false;
overrideStyles(viewer);
// Get sections availability
var available_sections = getSectionAvailability();
// Apply sections availabilitfy
viewer.setAvailability("section", available_sections);
// Get seats availability
var available_seats = getSeatAvailability();
// Apply seats availability
viewer.setAvailability("seat", available_seats);
filterRows(selection, filter_single_seats);
console.log("LOADED!");
})
.catch(function (err) {
// Error while loading
console.error(err);
});
// CALLBACKS
function onClick(obj) {
var node = obj.nodes[0];
if (node && node.type === "seat") {
if (node.state === "available" || node.state === "selected") {
var nodes = obj.instance.getNeighbors(node, selection, filter_single_seats);
if (nodes.length === selection) {
obj.instance.unselectAll();
obj.instance.select(nodes);
}
}
}
}
function onEnter(obj) {
var node = obj.nodes[0];
if (node) {
// If there are neighbors that fulfill the requirements, we hover all the seats, otherwise we hover only the original node.
if (node.type === "seat" && (node.state === "available" || node.state === "selected")) {
var nodes = obj.instance.getNeighbors(node, selection, filter_single_seats);
if (nodes.length === selection) {
obj.instance.hover(nodes);
return;
}
}
obj.instance.hover(node);
}
}
// called on node mouse leave
function onLeave(obj) {
// reset hover nodes
obj.instance.hover(null);
}
// ROWS
/**
*
* This function will filter the nodes that cannot form part of a group of adjacent
* nodes given a certain 'quantity' and previously applied availability. In addition,
* we specify with 'filter_single_seats' if selections that leaves single seats
* are allowed or not.
*
* In addition, the function will add the filtered nodes to a group ('filtered')
* and assign them a tag with the same name to be able to paint them differently on the map.
*
* @param {number} quantity - Quantity of adjacent nodes to be selected.
* @param {boolean} filter_single_seats - if the adjacent nodes may allow single seats (false)
* or not (true).
*/
function filterRows(quantity, filter_single_seats) {
// We make sure that there is no node selected
viewer.unselectAll();
// Get all nodes in group 'filtered' from a previous filterRows call
var old_filtered_nodes = viewer.getNodesByGroups("seat", "filtered", false);
// Remove nodes from 'filtered' group
viewer.removeNodesFromGroup(old_filtered_nodes, "filtered");
// Remove tag 'filtered' from nodes
viewer.setNodesTag(old_filtered_nodes, null);
// get the filter nodes
var filtered_nodes = viewer.filterRows(quantity, filter_single_seats);
// add nodes to 'filtered' group
viewer.addNodesToGroup(filtered_nodes, "filtered");
// Apply 'filtered' tag to nodes
viewer.setNodesTag(filtered_nodes, "filtered");
}
// INPUT ELEMENTS
var input_selection = document.getElementById("selection_input");
var input_single_seats = document.getElementById("single_seats_input");
if (input_selection && input_single_seats) {
input_single_seats.addEventListener("change", function (e) {
filter_single_seats = input_single_seats.checked;
filterRows(selection, filter_single_seats);
});
input_selection.addEventListener("input", function (e) {
var val = parseInt(input_selection.value);
if (!isNaN(val)) {
selection = clamp(val, 1, 10);
input_selection.value = selection;
viewer.max_selection = selection;
filterRows(selection, filter_single_seats);
}
});
}
// ---- 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;
}
// Get seats availability. For the purpose, we generate a RANDOM availability.
function getSeatAvailability() {
// Only generate availability for seats with an AVAILABLE parent section
var available_sections = viewer.getNodesByState("section", "available");
var available_seats = [];
for (var i = 0; i < available_sections.length; ++i) {
var section = available_sections[i];
var seats = viewer.getNodesByParent(section.id);
for (var j = 0; j < seats.length; ++j) {
var seat = seats[j];
if (Math.random() < 0.7) {
available_seats.push(seat.id);
}
}
}
return available_seats;
}
// HELPERS
// The purpose of this function is just keep the default styles and add to them styles for 'filtered' tag
function overrideStyles(instance) {
var styles = instance.getStyles();
for (var i = 0; i < styles.length; ++i) {
if (styles[i] && styles[i].seat) {
if (styles[i].seat.available.normal && styles[i].seat.available.normal.none) {
styles[i].seat.available.normal.filtered = JSON.parse(JSON.stringify(styles[i].seat.available.normal.none));
styles[i].seat.available.normal.filtered.opacity = 0.4;
if (styles[i].seat.available.hover && styles[i].seat.available.hover.none) {
styles[i].seat.available.hover.filtered = JSON.parse(JSON.stringify(styles[i].seat.available.normal.none));
styles[i].seat.available.hover.filtered.opacity = 0.4;
}
}
}
}
instance.setStyles(styles);
}
function clamp(a,b,c){
return Math.max(b,Math.min(c,a));
}
}