From 07a8effc48a686d525c46cd9d4ec79faa7bcf744 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marie=20Wahlstr=C3=B8m?= Date: Mon, 29 Sep 2025 10:00:19 +0200 Subject: [PATCH 1/4] feat(#7): :sparkles: Created "Evelation Control" section with belonging functionality --- index.html | 5 +- src/main.js | 138 +++++++++++++++++++++++++++++++++++++++++++++++++- src/style.css | 12 ++++- 3 files changed, 152 insertions(+), 3 deletions(-) diff --git a/index.html b/index.html index c77bfb1..9190fa3 100644 --- a/index.html +++ b/index.html @@ -23,6 +23,7 @@ type="text/css" href="/libs/jstree/themes/mixed/style.css" /> + @@ -67,6 +68,7 @@ viewer.loadGUI(() => { viewer.setLanguage('en') + $('#menu_customised').next().show() $('#menu_appearance').next().show() $('#menu_tools').next().show() $('#menu_scene').next().show() @@ -82,11 +84,12 @@ material.pointSizeType = Potree.PointSizeType.ADAPTIVE material.shape = Potree.PointShape.CIRCLE material.activeAttributeName = 'elevation' - material.gradient = Potree.Gradients['RAINBOW'] + material.gradient = Potree.Gradients['VIRIDIS'] viewer.scene.addPointCloud(pointcloud) viewer.fitToScreen() }) + diff --git a/src/main.js b/src/main.js index 79eee5f..578a794 100644 --- a/src/main.js +++ b/src/main.js @@ -1 +1,137 @@ -/* Empty for now, add logic later */ +/** + * Creating and inserting a new customised "Elevation Range" section in the sidebar above Apperance + * with the same css style features as Apperance +*/ +(function () { + + //Insert new the sidebar above Apperance + function insertCustomisedAboveAppearance() { + const appearanceHeader = document.querySelector('#menu_appearance'); + if (!appearanceHeader) return false; + if (document.querySelector('#menu_customised_header')) return true; + + //Clone the header for identical style to apperance + const customHeader = appearanceHeader.cloneNode(true); + customHeader.removeAttribute('id'); + customHeader.id = 'menu_customised_header'; + customHeader.textContent = 'Elevation Control'; + customHeader.style.cursor = 'pointer'; + customHeader.setAttribute('tabindex', '0'); + + //Creating a new "div" in the customised section similar to the Apperance div + const appearanceBody = appearanceHeader.nextElementSibling; + const bodyClass = appearanceBody ? appearanceBody.className : 'pv-menu-list'; + const customBody = document.createElement('div'); + customBody.className = bodyClass; + customBody.id = 'customised_list'; + customBody.style.display = ''; // start expanded + + //Insert both right before Appearance + appearanceHeader.parentElement.insertBefore(customHeader, appearanceHeader); + appearanceHeader.parentElement.insertBefore(customBody, appearanceHeader); + + //collapse/expand + const toggle = () => { + const hidden = customBody.style.display === 'none'; + customBody.style.display = hidden ? '' : 'none'; + }; + customHeader.addEventListener('click', toggle); + customHeader.addEventListener('keydown', (e) => { + if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); toggle(); } + }); + + return true; + } + + function init() { + if (insertCustomisedAboveAppearance()) return; + let tries = 0; + const t = setInterval(() => { + tries++; + if (insertCustomisedAboveAppearance() || tries > 50) clearInterval(t); + }, 200); + } + + if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', init); + else init(); +})(); + + + +/** + * A function that: + * - Autoselects the first pointcloud + * - Move the Elevation block from the Scene section into the custimosed Elevation Control section + * + * Nice to know: In the oroginal code the Elevation section in the Properties panel is only built when the pointcloud is clicked on + */ +(function () { + const $ = (sel, root = document) => root.querySelector(sel); + + //Select the fist pointcloud in the sidebar so that the Elevation section is built + function autoSelectFirstPointCloud() { + const cloudIcon = document.querySelector('#scene_objects i.jstree-themeicon-custom'); + if (cloudIcon) { + cloudIcon.dispatchEvent(new MouseEvent('click', { bubbles: true })); + return true; + } + return false; + } + + //(re)connect the elevation labels to the slider after the container is moved (was not handled by default) + function rebindElevationLabel() { + const slider = window.jQuery ? window.jQuery("#sldHeightRange") : null; + const label = document.getElementById("lblHeightRange"); + if (!slider || !slider.length || !label) return; + + const update = () => { + const low = $slider.slider("values", 0); + const high = $slider.slider("values", 1); + label.textContent = `${low.toFixed(2)} to ${high.toFixed(2)}`; + }; + + //clear any old namespaced handlers and attach fresh ones + slider.off("slide.custom slidestop.custom change.custom"); + slider.on("slide.custom", update); + slider.on("slidestop.custom change.custom", update); + update(); + } + + //Move the elevation range section to the customised "Elevation Control" section + function moveElevationContainer() { + const target = $('#customised_list'); + const elevationContainer = document.querySelector('#materials\\.elevation_container'); + if (!elevationContainer) return false; + target.appendChild(elevationContainer); + rebindElevationLabel(); + return true; + + } + + function init() { + let tries = 0; + const t = setInterval(() => { + const hasCloud = !!(window.viewer?.scene?.pointclouds?.length); + if (hasCloud) { + autoSelectFirstPointCloud(); + // Wait until potree builds the Properties, then move the container + let innerTries = 0; + const t2 = setInterval(() => { + const movedElevation = moveElevationContainer(); + if (movedElevation || ++innerTries > 100) clearInterval(t2); + }, 100); + + clearInterval(t); + } + if (++tries > 30) clearInterval(t); + }, 100); + } + + if (document.readyState === 'loading') { + document.addEventListener('DOMContentLoaded', init); + } else { + init(); + } +})(); + + diff --git a/src/style.css b/src/style.css index 5bc7676..0a4215c 100644 --- a/src/style.css +++ b/src/style.css @@ -1 +1,11 @@ -/* Empty for now, add styles later */ +/* making sure that the divider span the whole sidebar (as the original code) */ +#customised_list > .divider { + margin: 0; + padding: 0; + } + +/* Padding of list items in the elevation control section as the original code*/ +#customised_list li { + list-style-type: none; + padding: 0 20px; + } \ No newline at end of file From 2f4ec32f64d4cc76a806afb9b007bf75f71ad52f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marie=20Wahlstr=C3=B8m?= Date: Mon, 29 Sep 2025 10:10:40 +0200 Subject: [PATCH 2/4] refactor(#7): :truck: Moved paths for evelation control in index.html --- index.html | 2 + src/elevation_control.css | 11 +++ src/elevation_control.js | 138 ++++++++++++++++++++++++++++++++++++++ src/main.js | 137 ------------------------------------- src/style.css | 11 --- 5 files changed, 151 insertions(+), 148 deletions(-) create mode 100644 src/elevation_control.css create mode 100644 src/elevation_control.js diff --git a/index.html b/index.html index 9190fa3..4c10df5 100644 --- a/index.html +++ b/index.html @@ -24,6 +24,7 @@ href="/libs/jstree/themes/mixed/style.css" /> + @@ -91,5 +92,6 @@ }) + diff --git a/src/elevation_control.css b/src/elevation_control.css new file mode 100644 index 0000000..0a4215c --- /dev/null +++ b/src/elevation_control.css @@ -0,0 +1,11 @@ +/* making sure that the divider span the whole sidebar (as the original code) */ +#customised_list > .divider { + margin: 0; + padding: 0; + } + +/* Padding of list items in the elevation control section as the original code*/ +#customised_list li { + list-style-type: none; + padding: 0 20px; + } \ No newline at end of file diff --git a/src/elevation_control.js b/src/elevation_control.js new file mode 100644 index 0000000..e6a0f4e --- /dev/null +++ b/src/elevation_control.js @@ -0,0 +1,138 @@ +/** + * Creating and inserting a new customised "Elevation Range" section in the sidebar above Apperance + * with the same css style features as Apperance +*/ +(function () { + + //Insert new the sidebar above Apperance + function insertCustomisedAboveAppearance() { + const appearanceHeader = document.querySelector('#menu_appearance'); + if (!appearanceHeader) return false; + if (document.querySelector('#menu_customised_header')) return true; + + //Clone the header for identical style to apperance + const customHeader = appearanceHeader.cloneNode(true); + customHeader.removeAttribute('id'); + customHeader.id = 'menu_customised_header'; + customHeader.textContent = 'Elevation Control'; + customHeader.style.cursor = 'pointer'; + customHeader.setAttribute('tabindex', '0'); + + //Creating a new "div" in the customised section similar to the Apperance div + const appearanceBody = appearanceHeader.nextElementSibling; + const bodyClass = appearanceBody ? appearanceBody.className : 'pv-menu-list'; + const customBody = document.createElement('div'); + customBody.className = bodyClass; + customBody.id = 'customised_list'; + customBody.style.display = ''; // start expanded + + //Insert both right before Appearance + appearanceHeader.parentElement.insertBefore(customHeader, appearanceHeader); + appearanceHeader.parentElement.insertBefore(customBody, appearanceHeader); + + //collapse/expand + const toggle = () => { + const hidden = customBody.style.display === 'none'; + customBody.style.display = hidden ? '' : 'none'; + }; + customHeader.addEventListener('click', toggle); + customHeader.addEventListener('keydown', (e) => { + if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); toggle(); } + }); + + return true; + } + + function init() { + if (insertCustomisedAboveAppearance()) return; + let tries = 0; + const t = setInterval(() => { + tries++; + if (insertCustomisedAboveAppearance() || tries > 50) clearInterval(t); + }, 200); + } + + if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', init); + else init(); + })(); + + + + /** + * A function that: + * - Autoselects the first pointcloud + * - Move the Elevation block from the Scene section into the custimosed Elevation Control section + * + * Nice to know: In the oroginal code the Elevation section in the Properties panel is only built when the pointcloud is clicked on + */ + (function () { + const $ = (sel, root = document) => root.querySelector(sel); + + //Select the fist pointcloud in the sidebar so that the Elevation section is built + function autoSelectFirstPointCloud() { + const cloudIcon = document.querySelector('#scene_objects i.jstree-themeicon-custom'); + if (cloudIcon) { + cloudIcon.dispatchEvent(new MouseEvent('click', { bubbles: true })); + return true; + } + return false; + } + + //(re)connect the elevation labels to the slider after the container is moved (was not handled by default) + function rebindElevationLabel() { + const slider = window.jQuery ? window.jQuery("#sldHeightRange") : null; + const label = document.getElementById("lblHeightRange"); + if (!slider || !slider.length || !label) return; + + const update = () => { + const low = $slider.slider("values", 0); + const high = $slider.slider("values", 1); + label.textContent = `${low.toFixed(2)} to ${high.toFixed(2)}`; + }; + + //clear any old namespaced handlers and attach fresh ones + slider.off("slide.custom slidestop.custom change.custom"); + slider.on("slide.custom", update); + slider.on("slidestop.custom change.custom", update); + update(); + } + + //Move the elevation range section to the customised "Elevation Control" section + function moveElevationContainer() { + const target = $('#customised_list'); + const elevationContainer = document.querySelector('#materials\\.elevation_container'); + if (!elevationContainer) return false; + target.appendChild(elevationContainer); + rebindElevationLabel(); + return true; + + } + + function init() { + let tries = 0; + const t = setInterval(() => { + const hasCloud = !!(window.viewer?.scene?.pointclouds?.length); + if (hasCloud) { + autoSelectFirstPointCloud(); + // Wait until potree builds the Properties, then move the container + let innerTries = 0; + const t2 = setInterval(() => { + const movedElevation = moveElevationContainer(); + if (movedElevation || ++innerTries > 100) clearInterval(t2); + }, 100); + + clearInterval(t); + } + if (++tries > 30) clearInterval(t); + }, 100); + } + + if (document.readyState === 'loading') { + document.addEventListener('DOMContentLoaded', init); + } else { + init(); + } + })(); + + + \ No newline at end of file diff --git a/src/main.js b/src/main.js index 578a794..e69de29 100644 --- a/src/main.js +++ b/src/main.js @@ -1,137 +0,0 @@ -/** - * Creating and inserting a new customised "Elevation Range" section in the sidebar above Apperance - * with the same css style features as Apperance -*/ -(function () { - - //Insert new the sidebar above Apperance - function insertCustomisedAboveAppearance() { - const appearanceHeader = document.querySelector('#menu_appearance'); - if (!appearanceHeader) return false; - if (document.querySelector('#menu_customised_header')) return true; - - //Clone the header for identical style to apperance - const customHeader = appearanceHeader.cloneNode(true); - customHeader.removeAttribute('id'); - customHeader.id = 'menu_customised_header'; - customHeader.textContent = 'Elevation Control'; - customHeader.style.cursor = 'pointer'; - customHeader.setAttribute('tabindex', '0'); - - //Creating a new "div" in the customised section similar to the Apperance div - const appearanceBody = appearanceHeader.nextElementSibling; - const bodyClass = appearanceBody ? appearanceBody.className : 'pv-menu-list'; - const customBody = document.createElement('div'); - customBody.className = bodyClass; - customBody.id = 'customised_list'; - customBody.style.display = ''; // start expanded - - //Insert both right before Appearance - appearanceHeader.parentElement.insertBefore(customHeader, appearanceHeader); - appearanceHeader.parentElement.insertBefore(customBody, appearanceHeader); - - //collapse/expand - const toggle = () => { - const hidden = customBody.style.display === 'none'; - customBody.style.display = hidden ? '' : 'none'; - }; - customHeader.addEventListener('click', toggle); - customHeader.addEventListener('keydown', (e) => { - if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); toggle(); } - }); - - return true; - } - - function init() { - if (insertCustomisedAboveAppearance()) return; - let tries = 0; - const t = setInterval(() => { - tries++; - if (insertCustomisedAboveAppearance() || tries > 50) clearInterval(t); - }, 200); - } - - if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', init); - else init(); -})(); - - - -/** - * A function that: - * - Autoselects the first pointcloud - * - Move the Elevation block from the Scene section into the custimosed Elevation Control section - * - * Nice to know: In the oroginal code the Elevation section in the Properties panel is only built when the pointcloud is clicked on - */ -(function () { - const $ = (sel, root = document) => root.querySelector(sel); - - //Select the fist pointcloud in the sidebar so that the Elevation section is built - function autoSelectFirstPointCloud() { - const cloudIcon = document.querySelector('#scene_objects i.jstree-themeicon-custom'); - if (cloudIcon) { - cloudIcon.dispatchEvent(new MouseEvent('click', { bubbles: true })); - return true; - } - return false; - } - - //(re)connect the elevation labels to the slider after the container is moved (was not handled by default) - function rebindElevationLabel() { - const slider = window.jQuery ? window.jQuery("#sldHeightRange") : null; - const label = document.getElementById("lblHeightRange"); - if (!slider || !slider.length || !label) return; - - const update = () => { - const low = $slider.slider("values", 0); - const high = $slider.slider("values", 1); - label.textContent = `${low.toFixed(2)} to ${high.toFixed(2)}`; - }; - - //clear any old namespaced handlers and attach fresh ones - slider.off("slide.custom slidestop.custom change.custom"); - slider.on("slide.custom", update); - slider.on("slidestop.custom change.custom", update); - update(); - } - - //Move the elevation range section to the customised "Elevation Control" section - function moveElevationContainer() { - const target = $('#customised_list'); - const elevationContainer = document.querySelector('#materials\\.elevation_container'); - if (!elevationContainer) return false; - target.appendChild(elevationContainer); - rebindElevationLabel(); - return true; - - } - - function init() { - let tries = 0; - const t = setInterval(() => { - const hasCloud = !!(window.viewer?.scene?.pointclouds?.length); - if (hasCloud) { - autoSelectFirstPointCloud(); - // Wait until potree builds the Properties, then move the container - let innerTries = 0; - const t2 = setInterval(() => { - const movedElevation = moveElevationContainer(); - if (movedElevation || ++innerTries > 100) clearInterval(t2); - }, 100); - - clearInterval(t); - } - if (++tries > 30) clearInterval(t); - }, 100); - } - - if (document.readyState === 'loading') { - document.addEventListener('DOMContentLoaded', init); - } else { - init(); - } -})(); - - diff --git a/src/style.css b/src/style.css index 0a4215c..e69de29 100644 --- a/src/style.css +++ b/src/style.css @@ -1,11 +0,0 @@ -/* making sure that the divider span the whole sidebar (as the original code) */ -#customised_list > .divider { - margin: 0; - padding: 0; - } - -/* Padding of list items in the elevation control section as the original code*/ -#customised_list li { - list-style-type: none; - padding: 0 20px; - } \ No newline at end of file From 2b66727d8531fc916de93d777ac8f0b08d6c0d13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marie=20Wahlstr=C3=B8m?= Date: Mon, 29 Sep 2025 14:14:25 +0200 Subject: [PATCH 3/4] refactor(#7): :recycle: Updated code for consistensy in the sidebar section --- index.html | 13 ++- src/ElevationControl/elevationControl.js | 107 ++++++++++++++++++ src/elevation_control.css | 11 -- src/elevation_control.js | 138 ----------------------- 4 files changed, 117 insertions(+), 152 deletions(-) create mode 100644 src/ElevationControl/elevationControl.js delete mode 100644 src/elevation_control.css delete mode 100644 src/elevation_control.js diff --git a/index.html b/index.html index 4c10df5..eb930b5 100644 --- a/index.html +++ b/index.html @@ -24,7 +24,11 @@ href="/libs/jstree/themes/mixed/style.css" /> - + @@ -55,6 +59,7 @@
+ - diff --git a/src/ElevationControl/elevationControl.js b/src/ElevationControl/elevationControl.js new file mode 100644 index 0000000..276456b --- /dev/null +++ b/src/ElevationControl/elevationControl.js @@ -0,0 +1,107 @@ +//Cerating a customized section "Elevation Control" +window.createElevationPanel = function createElevationPanel(viewer) { + const container = document.getElementById('elevation_list') + let targetContainer = container + if (!targetContainer) { + // Create a new accordion section for Elevation Control + const menu = document.getElementById('potree_menu') + if (menu) { + const header = document.createElement('h3') + header.id = 'menu_elevation' + header.innerHTML = 'Elevation Control' + const panel = document.createElement('div') + panel.className = 'pv-menu-list' + panel.innerHTML = '
' + const about = document.getElementById('menu_appearance') + if (about) { + menu.insertBefore(panel, about) + menu.insertBefore(header, panel) + } else { + menu.appendChild(header) + menu.appendChild(panel) + } + // Activate accordion behavior if jQuery UI accordion already initialized + if ($(menu).accordion) { + try { + $(menu).accordion('refresh') + } catch (e) {} + } + // Toggle on header click if not managed by accordion refresh + header.addEventListener( + 'click', + () => + (panel.style.display = panel.style.display === 'none' ? '' : 'none') + ) + targetContainer = panel.querySelector('#elevation_list') + } + } +} + +//Select the fist pointcloud in the sidebar so that the Elevation section is built +function autoSelectFirstPointCloud() { + const cloudIcon = document.querySelector( + '#scene_objects i.jstree-themeicon-custom' + ) + if (cloudIcon) { + cloudIcon.dispatchEvent(new MouseEvent('click', { bubbles: true })) + return true + } + return false +} + +//(re)connect the elevation labels to the slider after the container is moved (was not handled by default) +function rebindElevationLabel() { + const slider = window.jQuery ? window.jQuery('#sldHeightRange') : null + const label = document.getElementById('lblHeightRange') + if (!slider || !slider.length || !label) return + + const update = () => { + const low = slider.slider('values', 0) + const high = slider.slider('values', 1) + label.textContent = `${low.toFixed(2)} to ${high.toFixed(2)}` + } + + //clear any old namespaced handlers and attach fresh ones + slider.off('slide.custom slidestop.custom change.custom') + slider.on('slide.custom', update) + slider.on('slidestop.custom change.custom', update) + update() +} + +//Move the elevation range section to the customised "Elevation Control" section +function moveElevationContainer() { + const target = document.getElementById('elevation_list') + const elevationContainer = document.querySelector( + '#materials\\.elevation_container' + ) + if (!elevationContainer) return false + target.appendChild(elevationContainer) + rebindElevationLabel() + return true +} + +//initiate and orchestrate all funcitons to render the Evelation control section of the sidebar propperly +window.initElevationControls = function initElevationControls(viewer) { + + //Creates the section + createElevationPanel(viewer) + + //Only move the ElevationContainer if the source container to exist + const menu = + document.getElementById('potree_menu') || + document.getElementById('menu') || + document.body + const observer = new MutationObserver(() => { + const found = document.querySelector('#materials\\.elevation_container') + if (found) { + observer.disconnect() + //Move and rebind once it exists + const ok = moveElevationContainer() + if (!ok) console.warn('[Elevation] moveElevationContainer failed') + } + }) + observer.observe(menu, { childList: true, subtree: true }) + + //Trigger Potree to build Materials UI by selecting the first point cloud (if nothing selected yet) + autoSelectFirstPointCloud() +} diff --git a/src/elevation_control.css b/src/elevation_control.css deleted file mode 100644 index 0a4215c..0000000 --- a/src/elevation_control.css +++ /dev/null @@ -1,11 +0,0 @@ -/* making sure that the divider span the whole sidebar (as the original code) */ -#customised_list > .divider { - margin: 0; - padding: 0; - } - -/* Padding of list items in the elevation control section as the original code*/ -#customised_list li { - list-style-type: none; - padding: 0 20px; - } \ No newline at end of file diff --git a/src/elevation_control.js b/src/elevation_control.js deleted file mode 100644 index e6a0f4e..0000000 --- a/src/elevation_control.js +++ /dev/null @@ -1,138 +0,0 @@ -/** - * Creating and inserting a new customised "Elevation Range" section in the sidebar above Apperance - * with the same css style features as Apperance -*/ -(function () { - - //Insert new the sidebar above Apperance - function insertCustomisedAboveAppearance() { - const appearanceHeader = document.querySelector('#menu_appearance'); - if (!appearanceHeader) return false; - if (document.querySelector('#menu_customised_header')) return true; - - //Clone the header for identical style to apperance - const customHeader = appearanceHeader.cloneNode(true); - customHeader.removeAttribute('id'); - customHeader.id = 'menu_customised_header'; - customHeader.textContent = 'Elevation Control'; - customHeader.style.cursor = 'pointer'; - customHeader.setAttribute('tabindex', '0'); - - //Creating a new "div" in the customised section similar to the Apperance div - const appearanceBody = appearanceHeader.nextElementSibling; - const bodyClass = appearanceBody ? appearanceBody.className : 'pv-menu-list'; - const customBody = document.createElement('div'); - customBody.className = bodyClass; - customBody.id = 'customised_list'; - customBody.style.display = ''; // start expanded - - //Insert both right before Appearance - appearanceHeader.parentElement.insertBefore(customHeader, appearanceHeader); - appearanceHeader.parentElement.insertBefore(customBody, appearanceHeader); - - //collapse/expand - const toggle = () => { - const hidden = customBody.style.display === 'none'; - customBody.style.display = hidden ? '' : 'none'; - }; - customHeader.addEventListener('click', toggle); - customHeader.addEventListener('keydown', (e) => { - if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); toggle(); } - }); - - return true; - } - - function init() { - if (insertCustomisedAboveAppearance()) return; - let tries = 0; - const t = setInterval(() => { - tries++; - if (insertCustomisedAboveAppearance() || tries > 50) clearInterval(t); - }, 200); - } - - if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', init); - else init(); - })(); - - - - /** - * A function that: - * - Autoselects the first pointcloud - * - Move the Elevation block from the Scene section into the custimosed Elevation Control section - * - * Nice to know: In the oroginal code the Elevation section in the Properties panel is only built when the pointcloud is clicked on - */ - (function () { - const $ = (sel, root = document) => root.querySelector(sel); - - //Select the fist pointcloud in the sidebar so that the Elevation section is built - function autoSelectFirstPointCloud() { - const cloudIcon = document.querySelector('#scene_objects i.jstree-themeicon-custom'); - if (cloudIcon) { - cloudIcon.dispatchEvent(new MouseEvent('click', { bubbles: true })); - return true; - } - return false; - } - - //(re)connect the elevation labels to the slider after the container is moved (was not handled by default) - function rebindElevationLabel() { - const slider = window.jQuery ? window.jQuery("#sldHeightRange") : null; - const label = document.getElementById("lblHeightRange"); - if (!slider || !slider.length || !label) return; - - const update = () => { - const low = $slider.slider("values", 0); - const high = $slider.slider("values", 1); - label.textContent = `${low.toFixed(2)} to ${high.toFixed(2)}`; - }; - - //clear any old namespaced handlers and attach fresh ones - slider.off("slide.custom slidestop.custom change.custom"); - slider.on("slide.custom", update); - slider.on("slidestop.custom change.custom", update); - update(); - } - - //Move the elevation range section to the customised "Elevation Control" section - function moveElevationContainer() { - const target = $('#customised_list'); - const elevationContainer = document.querySelector('#materials\\.elevation_container'); - if (!elevationContainer) return false; - target.appendChild(elevationContainer); - rebindElevationLabel(); - return true; - - } - - function init() { - let tries = 0; - const t = setInterval(() => { - const hasCloud = !!(window.viewer?.scene?.pointclouds?.length); - if (hasCloud) { - autoSelectFirstPointCloud(); - // Wait until potree builds the Properties, then move the container - let innerTries = 0; - const t2 = setInterval(() => { - const movedElevation = moveElevationContainer(); - if (movedElevation || ++innerTries > 100) clearInterval(t2); - }, 100); - - clearInterval(t); - } - if (++tries > 30) clearInterval(t); - }, 100); - } - - if (document.readyState === 'loading') { - document.addEventListener('DOMContentLoaded', init); - } else { - init(); - } - })(); - - - \ No newline at end of file From 5a328f84afb1c1aad46d33c5052fa013e6dbb70b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marie=20Wahlstr=C3=B8m?= Date: Wed, 1 Oct 2025 12:56:42 +0200 Subject: [PATCH 4/4] refactor(#7): :fire: Remove link to css not in use --- index.html | 5 ----- 1 file changed, 5 deletions(-) diff --git a/index.html b/index.html index eb930b5..d0563c8 100644 --- a/index.html +++ b/index.html @@ -24,11 +24,6 @@ href="/libs/jstree/themes/mixed/style.css" /> -