(tagName, containerId, options = {})
| 14119 | return; |
| 14120 | } |
| 14121 | selectSingleModel(fileElement, filePath); |
| 14122 | showModelDetails(filePath); |
| 14123 | } |
| 14124 | |
| 14125 | function openModelPreviewFromTile(filePath) { |
| 14126 | if (typeof window.openPreview === 'function') { |
| 14127 | window.openPreview(filePath); |
| 14128 | } |
| 14129 | } |
| 14130 | |
| 14131 | // Update the toggleModelSelection function` |
| 14132 | async function toggleModelSelection(fileElement, filePath) { |
| 14133 | if (fileElement?._suppressTap) return; |
| 14134 | if (!isMultiSelectMode) { |
| 14135 | const wasSelected = fileElement.classList.contains('selected'); |
| 14136 | |
| 14137 | // Clear previous selections |
| 14138 | selectedModels.clear(); |
| 14139 | document.querySelectorAll('.file-item').forEach(item => { |
| 14140 | item.classList.remove('selected'); |
| 14141 | }); |
| 14142 | |
| 14143 | if (wasSelected) { |
| 14144 | // If it was already selected, just deselect and close details |
| 14145 | const detailsPanel = document.getElementById('model-details'); |
| 14146 | if (detailsPanel) { |
| 14147 | detailsPanel.classList.add('hidden'); |
| 14148 | } |
| 14149 | } else { |
| 14150 | // Add selection to the clicked item |
| 14151 | addToSelectedModels(filePath); |
| 14152 | |
| 14153 | // Only select this specific element, not all elements with the same filePath |
| 14154 | fileElement.classList.add('selected'); |
| 14155 | |
| 14156 | // Show model details |
| 14157 | showModelDetails(filePath); |
| 14158 | } |
| 14159 | } else { |
| 14160 | // Multi-select mode |
| 14161 | if (fileElement.classList.contains('selected') || isInSelectedModels(filePath)) { |
| 14162 | // Deselect |
| 14163 | removeFromSelectedModels(filePath); |
| 14164 | fileElement.classList.remove('selected'); |
| 14165 | } else { |
| 14166 | // Select |
| 14167 | addToSelectedModels(filePath); |
| 14168 | fileElement.classList.add('selected'); |
| 14169 | } |
| 14170 | await updateSelectedCount(); // This will clear form fields if selection is now 0 |
| 14171 | } |
| 14172 | } |
| 14173 | |
| 14174 | // NOTE: loadModel function is defined earlier in the file (around line 2840) |
| 14175 | // This duplicate has been removed to use the enhanced version that checks for embedded images |
| 14176 | |
| 14177 | function fitCameraToObject(camera, object, scene, renderer) { |
| 14178 | // Orient first, then measure — otherwise large flat STLs (e.g. 400×420×4 plates) |
no test coverage detected