diff --git a/src/menu/physicalPosition.js b/src/menu/physicalPosition.js
index 191dd79..e22cfb1 100644
--- a/src/menu/physicalPosition.js
+++ b/src/menu/physicalPosition.js
@@ -11,7 +11,25 @@ class PhysicalPositionMenu {
{ value: 'downstream', label: '→ Downstream' , icon: '→' }
]
}
- ]
+ ],
+ // Distance contexts for each position
+ distanceContexts: {
+ upstream: {
+ description: 'Distance from parent inlet',
+ placeholder: 'e.g., 2.5 (meters before parent)',
+ helpText: 'How far upstream from the parent equipment'
+ },
+ downstream: {
+ description: 'Distance from parent outlet',
+ placeholder: 'e.g., 3.0 (meters after parent)',
+ helpText: 'How far downstream from the parent equipment'
+ },
+ atEquipment: {
+ description: 'Distance from parent start',
+ placeholder: 'e.g., 1.2 (meters from start)',
+ helpText: 'Position within the parent equipment boundaries'
+ }
+ }
};
}
@@ -26,6 +44,24 @@ class PhysicalPositionMenu {
+
+
+
+
+
+
+
+
+
`;
}
@@ -52,22 +88,40 @@ class PhysicalPositionMenu {
window.EVOLV.nodes.${nodeName}.positionMenu.loadData = function(node) {
const data = window.EVOLV.nodes.${nodeName}.menuData.position;
const sel = document.getElementById('node-input-positionVsParent');
- if (!sel) return;
- sel.innerHTML = '';
- (data.positionGroups||[]).forEach(grp => {
- const optg = document.createElement('optgroup');
- optg.label = grp.group;
- grp.options.forEach(o=>{
- const opt = document.createElement('option');
- opt.value = o.value;
- opt.textContent = o.label;
- opt.setAttribute('data-icon', o.icon);
- optg.appendChild(opt);
+ const hasDistanceCheck = document.getElementById('node-input-hasDistance');
+ const distanceInput = document.getElementById('node-input-distance');
+ const distanceSection = document.getElementById('distance-section');
+
+ //Load position options
+ if (sel) {
+ sel.innerHTML = '';
+ (data.positionGroups||[]).forEach(grp => {
+ const optg = document.createElement('optgroup');
+ optg.label = grp.group;
+ grp.options.forEach(o=>{
+ const opt = document.createElement('option');
+ opt.value = o.value;
+ opt.textContent = o.label;
+ opt.setAttribute('data-icon', o.icon);
+ optg.appendChild(opt);
+ });
+ sel.appendChild(optg);
});
- sel.appendChild(optg);
- });
- // default to “atEquipment” if not set
- sel.value = node.positionVsParent || 'atEquipment';
+ sel.value = node.positionVsParent || 'atEquipment';
+ }
+
+ //Load distance values
+ if (hasDistanceCheck) {
+ hasDistanceCheck.checked = node.hasDistance || false;
+ distanceSection.style.display = hasDistanceCheck.checked ? 'block' : 'none';
+ }
+
+ if (distanceInput) {
+ distanceInput.value = node.distance || '';
+ }
+
+ // Update distance context for current position
+ this.updateDistanceContext(node.positionVsParent || 'atEquipment', data.distanceContexts);
};
`;
}
@@ -77,24 +131,86 @@ class PhysicalPositionMenu {
return `
// PhysicalPosition events for ${nodeName}
window.EVOLV.nodes.${nodeName}.positionMenu.wireEvents = function(node) {
- // no dynamic behavior
+ const positionSel = document.getElementById('node-input-positionVsParent');
+ const hasDistanceCheck = document.getElementById('node-input-hasDistance');
+ const distanceSection = document.getElementById('distance-section');
+ const data = window.EVOLV.nodes.${nodeName}.menuData.position;
+
+ // Toggle distance section visibility
+ if (hasDistanceCheck && distanceSection) {
+ hasDistanceCheck.addEventListener('change', function() {
+ distanceSection.style.display = this.checked ? 'block' : 'none';
+
+ // Clear distance if unchecked
+ if (!this.checked) {
+ const distanceInput = document.getElementById('node-input-distance');
+ if (distanceInput) {
+ distanceInput.value = '';
+ }
+ }
+ });
+ }
+
+ // Update distance context when position changes
+ if (positionSel) {
+ positionSel.addEventListener('change', function() {
+ const position = this.value;
+ window.EVOLV.nodes.${nodeName}.positionMenu.updateDistanceContext(position, data.distanceContexts);
+ });
+ }
+ };
+
+ // Helper function to update distance context
+ window.EVOLV.nodes.${nodeName}.positionMenu.updateDistanceContext = function(position, contexts) {
+ const distanceInput = document.getElementById('node-input-distance');
+ const distanceHelp = document.getElementById('distance-help');
+
+ const context = contexts && contexts[position];
+
+ if (context && distanceInput && distanceHelp) {
+ distanceInput.placeholder = context.placeholder || '0.0';
+ distanceHelp.textContent = context.helpText || 'Enter distance in meters';
+ }
};
`;
}
// 6) Save-logic injector
- getSaveInjectionCode(nodeName) {
- return `
- // PhysicalPosition Save injection for ${nodeName}
- window.EVOLV.nodes.${nodeName}.positionMenu.saveEditor = function(node) {
- const sel = document.getElementById('node-input-positionVsParent');
- node.positionVsParent = sel? sel.value : 'atEquipment';
- node.positionLabel = sel? sel.options[sel.selectedIndex].textContent : 'At Equipment';
- node.positionIcon = sel? sel.options[sel.selectedIndex].getAttribute('data-icon') : 'fa fa-cog';
- return true;
- };
- `;
- }
+getSaveInjectionCode(nodeName) {
+ return `
+ // PhysicalPosition Save injection for ${nodeName}
+ window.EVOLV.nodes.${nodeName}.positionMenu.saveEditor = function(node) {
+ const sel = document.getElementById('node-input-positionVsParent');
+ const hasDistanceCheck = document.getElementById('node-input-hasDistance');
+ const distanceInput = document.getElementById('node-input-distance');
+
+ // Save existing position data
+ node.positionVsParent = sel ? sel.value : 'atEquipment';
+ node.positionLabel = sel ? sel.options[sel.selectedIndex].textContent : 'At Equipment';
+ node.positionIcon = sel ? sel.options[sel.selectedIndex].getAttribute('data-icon') : 'fa fa-cog';
+
+ // Save distance data (NEW)
+ node.hasDistance = hasDistanceCheck ? hasDistanceCheck.checked : false;
+
+ if (node.hasDistance && distanceInput && distanceInput.value) {
+ node.distance = parseFloat(distanceInput.value) || 0;
+ node.distanceUnit = 'm'; // Fixed to meters for now
+
+ // Generate distance description based on position
+ const contexts = window.EVOLV.nodes.${nodeName}.menuData.position.distanceContexts;
+ const context = contexts && contexts[node.positionVsParent];
+ node.distanceDescription = context ? context.description : 'Distance from parent';
+ } else {
+ // Clear distance data if not specified
+ delete node.distance;
+ delete node.distanceUnit;
+ delete node.distanceDescription;
+ }
+
+ return true;
+ };
+ `;
+}
// 7) Compose everything into one client bundle
getClientInitCode(nodeName) {