-
Notifications
You must be signed in to change notification settings - Fork 563
New Feature: Copy Deep-Link URL for Components and Nets #556
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
09d11b0
7fa3c58
9dbe5e2
01c9466
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -885,4 +885,16 @@ a { | |
|
|
||
| ::-moz-focus-inner { | ||
| padding: 0; | ||
| } | ||
|
|
||
| .copy-link-button { | ||
| font-size: 12px; | ||
| border: none; | ||
| background: transparent; | ||
| cursor: pointer; | ||
| vertical-align: middle; | ||
| } | ||
|
|
||
| .copy-link-button:hover { | ||
| opacity: 0.7; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would rather have the transparency be reversed i.e. more opaque when hovered. |
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -671,6 +671,25 @@ function populateBomBody(placeholderColumn = null, placeHolderElements = null) { | |
| netname = bomentry; | ||
| td = document.createElement("TD"); | ||
| td.innerHTML = highlightFilter(netname ? netname : "<no net>"); | ||
|
|
||
| // Add copy button for net names in netlist mode | ||
| if (settings.bommode === "netlist") { | ||
| var copyButton = document.createElement("button"); | ||
| copyButton.className = "copy-link-button"; | ||
| copyButton.title = "Copy deep-link URL"; | ||
| copyButton.innerHTML = "🔗"; | ||
| copyButton.style.cssText = "margin-left: 5px; font-size: 10pt; border: none; background: transparent; cursor: pointer; height: 100%"; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There are duplicated and overriding properties here, move everything to css. |
||
| (function(currentNetname) { | ||
| copyButton.onclick = function(e) { | ||
| e.stopPropagation(); | ||
| var url = new URL(window.location.href); | ||
| url.searchParams.set("net", "\"" + currentNetname + "\""); | ||
| copyToClipboard(url.toString()); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Change window location to the url as well, will give more visual clues that the click action worked. |
||
| }; | ||
| })(netname); | ||
| td.appendChild(copyButton); | ||
| } | ||
|
|
||
| tr.appendChild(td); | ||
| var color = settings.netColors[netname] || defaultNetColor; | ||
| td = document.createElement("TD"); | ||
|
|
@@ -721,7 +740,31 @@ function populateBomBody(placeholderColumn = null, placeHolderElements = null) { | |
| } | ||
| } else if (column === "References") { | ||
| td = document.createElement("TD"); | ||
| td.innerHTML = highlightFilter(references.map(r => r[0]).join(", ")); | ||
| var refHtml = highlightFilter(references.map(r => r[0]).join(", ")); | ||
| td.innerHTML = refHtml; | ||
|
|
||
| // Add copy button for component references in ungrouped mode | ||
| if (settings.bommode === "ungrouped") { | ||
| var copyButton = document.createElement("button"); | ||
| copyButton.className = "copy-link-button"; | ||
| copyButton.title = "Copy deep-link URL"; | ||
| copyButton.innerHTML = "🔗"; | ||
| copyButton.style.cssText = "margin-left: 5px; font-size: 10pt; border: none; background: transparent; cursor: pointer; height: 100%"; | ||
| var refName = references[0][0]; | ||
| (function(currentRefname) { | ||
| copyButton.onclick = function(e) { | ||
| e.stopPropagation(); | ||
| // Get the first reference to create URL (since we have multiple refs, we'll use the first one) | ||
| var url = new URL(window.location.href); | ||
| url.searchParams.set("ref", "\"" + currentRefname + "\""); | ||
| copyToClipboard(url.toString()); | ||
|
|
||
| }; | ||
| })(refName); | ||
| td.appendChild(copyButton); | ||
| } | ||
|
Comment on lines
+746
to
+765
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A lot of code duplication here with the copy button for nets. Extract it into a helper that creates button based on type (net/ref) and value (net name/ref name) |
||
|
|
||
|
|
||
| tr.appendChild(td); | ||
| } else if (column === "Quantity" && settings.bommode == "grouped") { | ||
| // Quantity | ||
|
|
@@ -783,6 +826,26 @@ function populateBomBody(placeholderColumn = null, placeHolderElements = null) { | |
| }); | ||
| } | ||
|
|
||
| function copyToClipboard(text) { | ||
| var textArea = document.createElement("textarea"); | ||
| textArea.className = "clipboard-temp"; | ||
| textArea.value = text; | ||
| document.body.appendChild(textArea); | ||
| textArea.select(); | ||
| try { | ||
| var successful = document.execCommand('copy'); | ||
| if (!successful) { | ||
| // Fallback for browsers that don't support execCommand | ||
| navigator.clipboard.writeText(text).catch(function(err) { | ||
| console.error('Could not copy text: ', err); | ||
| }); | ||
| } | ||
| } catch (err) { | ||
| console.error('Could not copy text: ', err); | ||
| } | ||
| document.body.removeChild(textArea); | ||
| } | ||
|
|
||
| function highlightPreviousRow() { | ||
| if (!currentHighlightedRowId) { | ||
| highlightHandlers[highlightHandlers.length - 1].handler(); | ||
|
|
@@ -1194,6 +1257,47 @@ function updateCheckboxStats(checkbox) { | |
| td.lastChild.innerHTML = checked + "/" + total + " (" + Math.round(percent) + "%)"; | ||
| } | ||
|
|
||
| function selectComponentByReference(ref) { | ||
| // Find the footprint with matching reference | ||
| var footprintIndex = -1; | ||
| for (var i = 0; i < pcbdata.footprints.length; i++) { | ||
| if (pcbdata.footprints[i].ref === ref) { | ||
| footprintIndex = i; | ||
| break; | ||
| } | ||
| } | ||
|
|
||
| // If we found the component, select it | ||
| if (footprintIndex !== -1) { | ||
| // Use the existing footprintIndexToHandler to trigger selection | ||
| if (footprintIndex in footprintIndexToHandler) { | ||
| footprintIndexToHandler[footprintIndex](); | ||
| // Scroll to the selected row to center it on screen | ||
| if (currentHighlightedRowId) { | ||
| smoothScrollToRow(currentHighlightedRowId); | ||
| } | ||
| } else { | ||
| // If no handler exists, try to find the row manually | ||
| for (var i = 0; i < highlightHandlers.length; i++) { | ||
| var handlerInfo = highlightHandlers[i]; | ||
| if (handlerInfo.handler && handlerInfo.handler.refs) { | ||
| // Check if any of the references in this row match our target ref | ||
| for (var j = 0; j < handlerInfo.handler.refs.length; j++) { | ||
| if (handlerInfo.handler.refs[j][0] === ref) { | ||
| handlerInfo.handler(); | ||
| if (currentHighlightedRowId) { | ||
| smoothScrollToRow(currentHighlightedRowId); | ||
| } | ||
| break; | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } | ||
| // If component not found, do nothing (preserve existing behavior) | ||
| } | ||
|
|
||
| function constrain(number, min, max) { | ||
| return Math.min(Math.max(parseInt(number), min), max); | ||
| } | ||
|
|
@@ -1320,6 +1424,29 @@ window.onload = function (e) { | |
| // Triggers render | ||
| changeBomLayout(settings.bomlayout); | ||
|
|
||
| // Parse URL parameters for deep-linking | ||
| var urlParams = new URLSearchParams(window.location.search); | ||
| var refParam = urlParams.get('ref') || urlParams.get('component'); | ||
| if (refParam) { | ||
| // Change layout to ungrouped | ||
| changeBomMode('ungrouped'); | ||
| // Extract the value from the "" or the '' string | ||
| refParam = refParam.replace(/^["']|["']$/g, ""); | ||
| // Try to find and select the component | ||
| selectComponentByReference(refParam); | ||
| } | ||
|
|
||
| // Handle net parameter for deep-linking to nets | ||
| var netParam = urlParams.get('net'); | ||
| if (netParam && "nets" in pcbdata) { | ||
| // Change layout to netlist | ||
| changeBomMode('netlist'); | ||
| // Extract the value from the "" or the '' string | ||
| netParam = netParam.replace(/^["']|["']$/g, ""); | ||
| // Try to find and select the net | ||
| netClicked(netParam); | ||
| } | ||
|
|
||
| // Users may leave fullscreen without touching the checkbox. Uncheck. | ||
| document.addEventListener('fullscreenchange', () => { | ||
| if (!document.fullscreenElement) | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
use "em" based size