diff --git a/js/controllers/menu_controller.js b/js/controllers/menu_controller.js
new file mode 100644
index 0000000..e516dec
--- /dev/null
+++ b/js/controllers/menu_controller.js
@@ -0,0 +1,78 @@
+// Global ATON
+import { Controller } from "@hotwired/stimulus"
+import AppState from "../state.js";
+
+const html = String.raw;
+const domParser = new DOMParser;
+
+export default class extends Controller {
+ static targets = ['trigger', 'layers', 'ontology'];
+
+ connect() {
+ console.log('#menu controller connected');
+ }
+ /**
+ * Open settings panel
+ * @param {Event} event
+ */
+ toggleMenu(event) {
+ ATON.UI.setSidePanelRight();
+ ATON.UI.showSidePanel({header: 'Menu'});
+ this.#buildMenuPanel(ATON.UI.elSidePanel);
+ this.#buildLayersMenu(AppState.normalizedNodes, this.layersTarget);
+ }
+ /**
+ * @param {Event} event
+ */
+ toggleNode(event) {
+ /**
+ * The node's id
+ * @type {string}
+ */
+ const id = event.params.node;
+ const status = event.target.checked;
+ ATON.getSceneNode(id).toggle(status);
+ AppState.normalizedNodes.find(n => n.id === id).active = status;
+ }
+ /**
+ * Clone a by id
+ * @param {String} id
+ * @returns {DocumentFragment}
+ */
+ #cloneTemplate(id) {
+ return document.getElementById(id).content.cloneNode(true);
+ }
+ /**
+ * Create the left-side settings panel
+ * content
+ * @param {Element} panel
+ */
+ #buildMenuPanel(panel) {
+ const fragment = this.#cloneTemplate('tmpl-menu-tabs');
+
+ panel.appendChild(fragment);
+ }
+ /**
+ * @todo Don't rebuild it every time, use caching, return a container with checkboxes
+ * @param {Array} nodes The normalized scene nodes (IDs and status)
+ * @param {HTMLElement} tab Tab content element
+ */
+ #buildLayersMenu(nodes, tab) {
+ for(let node of nodes) {
+ const menuItem = html`
+
+
+
+
+ `;
+
+ // Awful?
+ tab.appendChild(
+ domParser.parseFromString(menuItem, 'text/html').querySelector('div')
+ );
+ }
+ }
+}
diff --git a/js/ui.js b/js/ui.js
index c92fae2..63d29cb 100644
--- a/js/ui.js
+++ b/js/ui.js
@@ -1,42 +1,9 @@
import AppState from "./state.js";
-import { changeLightDirection, toggleAmbientOcclusion } from "./utils/environment.js";
-import { resetClipping, addClippingPlane } from "./utils/clipping.js";
import { traverseOntology } from "./ontology.js";
/**
* @module UI
*/
-
-const domParser = new DOMParser;
-
-const contentMenuTabs = `
-
-
- -
-
-
- -
-
-
-
-
-
-
-`;
-
-const audioExample = `
-
-`;
-
/**
*
* @param {String} triggerSelector - Usually, the close modal trigger element(s) selector
@@ -54,73 +21,6 @@ export function pauseAudio(triggerSelector) {
});
}
}
-/**
- * Resets the UI state (essentially hides the clipper toolbar if visible...)
- * @todo Other elements to reset?? Restore inital lighting conditions and viewpoint...
- */
-function reset() {
- document.querySelector('#clipper-bar')?.classList.add('d-none');
- document.querySelector('#clipper')?.classList.remove('border', 'border-2', 'border-white');
-}
-/**
- * Right-side main menu panel
- * @param {String} triggerId - The menu button id
- * @param {String} ontologyJsonPath
- */
-function toggleContentMenu(triggerId, ontologyJsonPath) {
- const btn = document.querySelector(`#${triggerId}`);
-
- btn.addEventListener('click', async () => {
- ATON.UI.setSidePanelRight();
- ATON.UI.showSidePanel({header: 'Menu'});
- // Append tabs, then tab panes
- const tabs = domParser.parseFromString(contentMenuTabs, 'text/html');
- ATON.UI.elSidePanel.appendChild(tabs.querySelector('#content-tabs'));
- ATON.UI.elSidePanel.appendChild(tabs.querySelector('.tab-content'));
- buildLayersMenu(AppState.normalizedNodes, ATON.UI.elSidePanel.querySelector('#layer'));
- buildOntologyMenu(await traverseOntology(ontologyJsonPath), ATON.UI.elSidePanel.querySelector('#content'));
- });
-}
-/**
- * @todo Don't rebuild it every time the side panel is shown...
- * @param {Array} nodes The normalized scene nodes (IDs and status)
- * @param {HTMLElement} sidePanel ATON's side panel element
- */
-function buildLayersMenu(nodes, sidePanel) {
- for(let node of nodes) {
- const menuItem = document.createElement('div');
- menuItem.className = `form-check form-switch ms-${node.depth} ps-${node.depth} mt-2`;
- const checkbox = document.createElement('input');
- checkbox.type = 'checkbox';
- checkbox.className = "form-check-input";
- checkbox.checked = node.active;
- checkbox.role = 'switch';
- checkbox.title = "Mostra / nascondi layer";
-
- menuItem.appendChild(checkbox);
-
- const label = document.createElement('label');
- label.className = "form-check-label";
- label.textContent = node.id;
-
- menuItem.appendChild(label);
-
- sidePanel.appendChild(menuItem);
- // Will this ever work??
- menuItem.addEventListener('change', event => toggleNode(node.id, event.target.checked));
- }
-
- /**
- * This is terrible...
- * @param {String} id
- * @param {Boolean} status
- */
- const toggleNode = (id, status) => {
- ATON.getSceneNode(id).toggle(status);
- AppState.normalizedNodes.find(n => n.id === id).active = status;
- }
-}
-
/**
* @see traverseOntology
* @param {Object} ontology The traversed ontology object (temp)
@@ -146,11 +46,4 @@ function buildOntologyMenu(ontology, sidePanel) {
mainNode.appendChild(domainList);
list.appendChild(mainNode);
sidePanel.appendChild(list);
-}
-/**
- * Initialize required components for scene UI
- * @param {String} ontologyJsonPath
- */
-export async function initUI(ontologyJsonPath) {
- toggleContentMenu('menu', ontologyJsonPath);
}
\ No newline at end of file
diff --git a/js/utils/stimulus.js b/js/utils/stimulus.js
index c233734..1a5336e 100644
--- a/js/utils/stimulus.js
+++ b/js/utils/stimulus.js
@@ -2,6 +2,7 @@ import { Application } from '@hotwired/stimulus';
import SettingController from '../controllers/settings_controller.js';
import ToolbarController from '../controllers/toolbar_controller.js';
import ClipperController from '../controllers/clipper_controller.js';
+import MenuController from '../controllers/menu_controller.js';
/**
* Initialize Stimulus controllers
@@ -11,4 +12,5 @@ export function initStimulus() {
Stimulus.register("settings", SettingController);
Stimulus.register("toolbar", ToolbarController);
Stimulus.register("clipper", ClipperController);
+ Stimulus.register("menu", MenuController);
}
\ No newline at end of file
diff --git a/scenes/ssgp/index.html b/scenes/ssgp/index.html
index b7b3510..881785c 100644
--- a/scenes/ssgp/index.html
+++ b/scenes/ssgp/index.html
@@ -58,7 +58,7 @@
-
+
-
@@ -118,8 +119,24 @@
diff --git a/scenes/ssgp/index.js b/scenes/ssgp/index.js
index f28009b..9691181 100644
--- a/scenes/ssgp/index.js
+++ b/scenes/ssgp/index.js
@@ -2,7 +2,6 @@ import { openScene } from "../../js/scene.js";
import { config } from "../../config.js";
import AppState from "../../js/state.js";
import { normalizeNodes } from "../../js/utils/nodeUtils.js";
-import { initUI } from "../../js/ui.js";
import { initStimulus } from "../../js/utils/stimulus.js";
initStimulus();
@@ -12,4 +11,3 @@ const marker = config.markers.find(m => m.id === 'ssgp');
AppState.normalizedNodes = normalizeNodes(marker.nodes);
openScene(marker, AppState.normalizedNodes);
-initUI(location.pathname + '/ontology.json');