4670 lines
288 KiB
HTML
4670 lines
288 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Interactive BOM for KiCAD</title>
|
|
<style type="text/css">
|
|
:root {
|
|
--pcb-edge-color: black;
|
|
--pad-color: #878787;
|
|
--pad-hole-color: #CCCCCC;
|
|
--pad-color-highlight: #D04040;
|
|
--pad-color-highlight-both: #D0D040;
|
|
--pad-color-highlight-marked: #44a344;
|
|
--pin1-outline-color: #ffb629;
|
|
--pin1-outline-color-highlight: #ffb629;
|
|
--pin1-outline-color-highlight-both: #fcbb39;
|
|
--pin1-outline-color-highlight-marked: #fdbe41;
|
|
--silkscreen-edge-color: #aa4;
|
|
--silkscreen-polygon-color: #4aa;
|
|
--silkscreen-text-color: #4aa;
|
|
--fabrication-edge-color: #907651;
|
|
--fabrication-polygon-color: #907651;
|
|
--fabrication-text-color: #a27c24;
|
|
--track-color: #def5f1;
|
|
--track-color-highlight: #D04040;
|
|
--zone-color: #def5f1;
|
|
--zone-color-highlight: #d0404080;
|
|
}
|
|
|
|
html,
|
|
body {
|
|
margin: 0px;
|
|
height: 100%;
|
|
font-family: Verdana, sans-serif;
|
|
}
|
|
|
|
.dark.topmostdiv {
|
|
--pcb-edge-color: #eee;
|
|
--pad-color: #808080;
|
|
--pin1-outline-color: #ffa800;
|
|
--pin1-outline-color-highlight: #ccff00;
|
|
--track-color: #42524f;
|
|
--zone-color: #42524f;
|
|
background-color: #252c30;
|
|
color: #eee;
|
|
}
|
|
|
|
button {
|
|
background-color: #eee;
|
|
border: 1px solid #888;
|
|
color: black;
|
|
height: 44px;
|
|
width: 44px;
|
|
text-align: center;
|
|
text-decoration: none;
|
|
display: inline-block;
|
|
font-size: 14px;
|
|
font-weight: bolder;
|
|
}
|
|
|
|
.dark button {
|
|
/* This will be inverted */
|
|
background-color: #c3b7b5;
|
|
}
|
|
|
|
button.depressed {
|
|
background-color: #0a0;
|
|
color: white;
|
|
}
|
|
|
|
.dark button.depressed {
|
|
/* This will be inverted */
|
|
background-color: #b3b;
|
|
}
|
|
|
|
button:focus {
|
|
outline: 0;
|
|
}
|
|
|
|
button#tb-btn {
|
|
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8.47 8.47'%3E%3Crect transform='translate(0 -288.53)' ry='1.17' y='288.8' x='.27' height='7.94' width='7.94' fill='%23f9f9f9'/%3E%3Cg transform='translate(0 -288.53)'%3E%3Crect width='7.94' height='7.94' x='.27' y='288.8' ry='1.17' fill='none' stroke='%23000' stroke-width='.4' stroke-linejoin='round'/%3E%3Cpath d='M1.32 290.12h5.82M1.32 291.45h5.82' fill='none' stroke='%23000' stroke-width='.4'/%3E%3Cpath d='M4.37 292.5v4.23M.26 292.63H8.2' fill='none' stroke='%23000' stroke-width='.3'/%3E%3Ctext font-weight='700' font-size='3.17' font-family='sans-serif'%3E%3Ctspan x='1.35' y='295.73'%3EF%3C/tspan%3E%3Ctspan x='5.03' y='295.68'%3EB%3C/tspan%3E%3C/text%3E%3C/g%3E%3C/svg%3E%0A");
|
|
}
|
|
|
|
button#lr-btn {
|
|
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8.47 8.47'%3E%3Crect transform='translate(0 -288.53)' ry='1.17' y='288.8' x='.27' height='7.94' width='7.94' fill='%23f9f9f9'/%3E%3Cg transform='translate(0 -288.53)'%3E%3Crect width='7.94' height='7.94' x='.27' y='288.8' ry='1.17' fill='none' stroke='%23000' stroke-width='.4' stroke-linejoin='round'/%3E%3Cpath d='M1.06 290.12H3.7m-2.64 1.33H3.7m-2.64 1.32H3.7m-2.64 1.3H3.7m-2.64 1.33H3.7' fill='none' stroke='%23000' stroke-width='.4'/%3E%3Cpath d='M4.37 288.8v7.94m0-4.11h3.96' fill='none' stroke='%23000' stroke-width='.3'/%3E%3Ctext font-weight='700' font-size='3.17' font-family='sans-serif'%3E%3Ctspan x='5.11' y='291.96'%3EF%3C/tspan%3E%3Ctspan x='5.03' y='295.68'%3EB%3C/tspan%3E%3C/text%3E%3C/g%3E%3C/svg%3E%0A");
|
|
}
|
|
|
|
button#bom-btn {
|
|
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8.47 8.47'%3E%3Crect transform='translate(0 -288.53)' ry='1.17' y='288.8' x='.27' height='7.94' width='7.94' fill='%23f9f9f9'/%3E%3Cg transform='translate(0 -288.53)' fill='none' stroke='%23000' stroke-width='.4'%3E%3Crect width='7.94' height='7.94' x='.27' y='288.8' ry='1.17' stroke-linejoin='round'/%3E%3Cpath d='M1.59 290.12h5.29M1.59 291.45h5.33M1.59 292.75h5.33M1.59 294.09h5.33M1.59 295.41h5.33'/%3E%3C/g%3E%3C/svg%3E");
|
|
}
|
|
|
|
button#bom-grouped-btn {
|
|
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='32' height='32'%3E%3Cg stroke='%23000' stroke-linejoin='round' class='layer'%3E%3Crect width='29' height='29' x='1.5' y='1.5' stroke-width='2' fill='%23fff' rx='5' ry='5'/%3E%3Cpath stroke-linecap='square' stroke-width='2' d='M6 10h4m4 0h5m4 0h3M6.1 22h3m3.9 0h5m4 0h4m-16-8h4m4 0h4'/%3E%3Cpath stroke-linecap='null' d='M5 17.5h22M5 26.6h22M5 5.5h22'/%3E%3C/g%3E%3C/svg%3E");
|
|
}
|
|
|
|
button#bom-ungrouped-btn {
|
|
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='32' height='32'%3E%3Cg stroke='%23000' stroke-linejoin='round' class='layer'%3E%3Crect width='29' height='29' x='1.5' y='1.5' stroke-width='2' fill='%23fff' rx='5' ry='5'/%3E%3Cpath stroke-linecap='square' stroke-width='2' d='M6 10h4m-4 8h3m-3 8h4'/%3E%3Cpath stroke-linecap='null' d='M5 13.5h22m-22 8h22M5 5.5h22'/%3E%3C/g%3E%3C/svg%3E");
|
|
}
|
|
|
|
button#bom-netlist-btn {
|
|
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='32' height='32'%3E%3Cg fill='none' stroke='%23000' class='layer'%3E%3Crect width='29' height='29' x='1.5' y='1.5' stroke-width='2' fill='%23fff' rx='5' ry='5'/%3E%3Cpath stroke-width='2' d='M6 26l6-6v-8m13.8-6.3l-6 6v8'/%3E%3Ccircle cx='11.8' cy='9.5' r='2.8' stroke-width='2'/%3E%3Ccircle cx='19.8' cy='22.8' r='2.8' stroke-width='2'/%3E%3C/g%3E%3C/svg%3E");
|
|
}
|
|
|
|
button#copy {
|
|
background-image: url("data:image/svg+xml,%3Csvg height='48' viewBox='0 0 48 48' width='48' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M0 0h48v48h-48z' fill='none'/%3E%3Cpath d='M32 2h-24c-2.21 0-4 1.79-4 4v28h4v-28h24v-4zm6 8h-22c-2.21 0-4 1.79-4 4v28c0 2.21 1.79 4 4 4h22c2.21 0 4-1.79 4-4v-28c0-2.21-1.79-4-4-4zm0 32h-22v-28h22v28z'/%3E%3C/svg%3E");
|
|
background-position: 6px 6px;
|
|
background-repeat: no-repeat;
|
|
background-size: 26px 26px;
|
|
border-radius: 6px;
|
|
height: 40px;
|
|
width: 40px;
|
|
margin: 10px 5px;
|
|
}
|
|
|
|
button#copy:active {
|
|
box-shadow: inset 0px 0px 5px #6c6c6c;
|
|
}
|
|
|
|
textarea.clipboard-temp {
|
|
position: fixed;
|
|
top: 0;
|
|
left: 0;
|
|
width: 2em;
|
|
height: 2em;
|
|
padding: 0;
|
|
border: None;
|
|
outline: None;
|
|
box-shadow: None;
|
|
background: transparent;
|
|
}
|
|
|
|
.left-most-button {
|
|
border-right: 0;
|
|
border-top-left-radius: 6px;
|
|
border-bottom-left-radius: 6px;
|
|
}
|
|
|
|
.middle-button {
|
|
border-right: 0;
|
|
}
|
|
|
|
.right-most-button {
|
|
border-top-right-radius: 6px;
|
|
border-bottom-right-radius: 6px;
|
|
}
|
|
|
|
.button-container {
|
|
font-size: 0;
|
|
margin: 0.4rem 0.4rem 0.4rem 0;
|
|
}
|
|
|
|
.dark .button-container {
|
|
filter: invert(1);
|
|
}
|
|
|
|
.button-container button {
|
|
background-size: 32px 32px;
|
|
background-position: 5px 5px;
|
|
background-repeat: no-repeat;
|
|
}
|
|
|
|
@media print {
|
|
.hideonprint {
|
|
display: none;
|
|
}
|
|
}
|
|
|
|
canvas {
|
|
cursor: crosshair;
|
|
}
|
|
|
|
canvas:active {
|
|
cursor: grabbing;
|
|
}
|
|
|
|
.fileinfo {
|
|
width: 100%;
|
|
max-width: 1000px;
|
|
border: none;
|
|
padding: 3px;
|
|
}
|
|
|
|
.fileinfo .title {
|
|
font-size: 20pt;
|
|
font-weight: bold;
|
|
}
|
|
|
|
.fileinfo td {
|
|
overflow: hidden;
|
|
white-space: nowrap;
|
|
max-width: 1px;
|
|
width: 50%;
|
|
text-overflow: ellipsis;
|
|
}
|
|
|
|
.bom {
|
|
border-collapse: collapse;
|
|
font-family: Consolas, "DejaVu Sans Mono", Monaco, monospace;
|
|
font-size: 10pt;
|
|
table-layout: fixed;
|
|
width: 100%;
|
|
margin-top: 1px;
|
|
position: relative;
|
|
}
|
|
|
|
.bom th,
|
|
.bom td {
|
|
border: 1px solid black;
|
|
padding: 5px;
|
|
word-wrap: break-word;
|
|
text-align: center;
|
|
position: relative;
|
|
}
|
|
|
|
.dark .bom th,
|
|
.dark .bom td {
|
|
border: 1px solid #777;
|
|
}
|
|
|
|
.bom th {
|
|
background-color: #CCCCCC;
|
|
background-clip: padding-box;
|
|
}
|
|
|
|
.dark .bom th {
|
|
background-color: #3b4749;
|
|
}
|
|
|
|
.bom tr.highlighted:nth-child(n) {
|
|
background-color: #cfc;
|
|
}
|
|
|
|
.dark .bom tr.highlighted:nth-child(n) {
|
|
background-color: #226022;
|
|
}
|
|
|
|
.bom tr:nth-child(even) {
|
|
background-color: #f2f2f2;
|
|
}
|
|
|
|
.dark .bom tr:nth-child(even) {
|
|
background-color: #313b40;
|
|
}
|
|
|
|
.bom tr.checked {
|
|
color: #1cb53d;
|
|
}
|
|
|
|
.dark .bom tr.checked {
|
|
color: #2cce54;
|
|
}
|
|
|
|
.bom tr {
|
|
transition: background-color 0.2s;
|
|
}
|
|
|
|
.bom .numCol {
|
|
width: 30px;
|
|
}
|
|
|
|
.bom .value {
|
|
width: 15%;
|
|
}
|
|
|
|
.bom .quantity {
|
|
width: 65px;
|
|
}
|
|
|
|
.bom th .sortmark {
|
|
position: absolute;
|
|
right: 1px;
|
|
top: 1px;
|
|
margin-top: -5px;
|
|
border-width: 5px;
|
|
border-style: solid;
|
|
border-color: transparent transparent #221 transparent;
|
|
transform-origin: 50% 85%;
|
|
transition: opacity 0.2s, transform 0.4s;
|
|
}
|
|
|
|
.dark .bom th .sortmark {
|
|
filter: invert(1);
|
|
}
|
|
|
|
.bom th .sortmark.none {
|
|
opacity: 0;
|
|
}
|
|
|
|
.bom th .sortmark.desc {
|
|
transform: rotate(180deg);
|
|
}
|
|
|
|
.bom th:hover .sortmark.none {
|
|
opacity: 0.5;
|
|
}
|
|
|
|
.bom .bom-checkbox {
|
|
width: 30px;
|
|
position: relative;
|
|
user-select: none;
|
|
-moz-user-select: none;
|
|
}
|
|
|
|
.bom .bom-checkbox:before {
|
|
content: "";
|
|
position: absolute;
|
|
border-width: 15px;
|
|
border-style: solid;
|
|
border-color: #51829f transparent transparent transparent;
|
|
visibility: hidden;
|
|
top: -15px;
|
|
}
|
|
|
|
.bom .bom-checkbox:after {
|
|
content: "Double click to set/unset all";
|
|
position: absolute;
|
|
color: white;
|
|
top: -35px;
|
|
left: -26px;
|
|
background: #51829f;
|
|
padding: 5px 15px;
|
|
border-radius: 8px;
|
|
white-space: nowrap;
|
|
visibility: hidden;
|
|
}
|
|
|
|
.bom .bom-checkbox:hover:before,
|
|
.bom .bom-checkbox:hover:after {
|
|
visibility: visible;
|
|
transition: visibility 0.2s linear 1s;
|
|
}
|
|
|
|
.split {
|
|
-webkit-box-sizing: border-box;
|
|
-moz-box-sizing: border-box;
|
|
box-sizing: border-box;
|
|
overflow-y: auto;
|
|
overflow-x: hidden;
|
|
background-color: inherit;
|
|
}
|
|
|
|
.split.split-horizontal,
|
|
.gutter.gutter-horizontal {
|
|
height: 100%;
|
|
float: left;
|
|
}
|
|
|
|
.gutter {
|
|
background-color: #ddd;
|
|
background-repeat: no-repeat;
|
|
background-position: 50%;
|
|
transition: background-color 0.3s;
|
|
}
|
|
|
|
.dark .gutter {
|
|
background-color: #777;
|
|
}
|
|
|
|
.gutter.gutter-horizontal {
|
|
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAeCAYAAADkftS9AAAAIklEQVQoU2M4c+bMfxAGAgYYmwGrIIiDjrELjpo5aiZeMwF+yNnOs5KSvgAAAABJRU5ErkJggg==');
|
|
cursor: ew-resize;
|
|
width: 5px;
|
|
}
|
|
|
|
.gutter.gutter-vertical {
|
|
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAFAQMAAABo7865AAAABlBMVEVHcEzMzMzyAv2sAAAAAXRSTlMAQObYZgAAABBJREFUeF5jOAMEEAIEEFwAn3kMwcB6I2AAAAAASUVORK5CYII=');
|
|
cursor: ns-resize;
|
|
height: 5px;
|
|
}
|
|
|
|
.searchbox {
|
|
float: left;
|
|
height: 40px;
|
|
margin: 10px 5px;
|
|
padding: 12px 32px;
|
|
font-family: Consolas, "DejaVu Sans Mono", Monaco, monospace;
|
|
font-size: 18px;
|
|
box-sizing: border-box;
|
|
border: 1px solid #888;
|
|
border-radius: 6px;
|
|
outline: none;
|
|
background-color: #eee;
|
|
transition: background-color 0.2s, border 0.2s;
|
|
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABNklEQVQ4T8XSMUvDQBQH8P/LElFa/AIZHcTBQSz0I/gFstTBRR2KUC4ldDxw7h0Bl3RRUATxi4iiODgoiLNrbQYp5J6cpJJqomkX33Z37/14d/dIa33MzDuYI4johOI4XhyNRteO46zNYjDzAxE1yBZprVeZ+QbAUhXEGJMA2Ox2u4+fQIa0mPmsCgCgJYQ4t7lfgF0opQYAdv9ABkKI/UnOFCClXKjX61cA1osQY8x9kiRNKeV7IWA3oyhaSdP0FkAtjxhj3hzH2RBCPOf3pzqYHCilfAAX+URm9oMguPzeWSGQvUcMYC8rOBJCHBRdqxTo9/vbRHRqi8bj8XKv1xvODbiuW2u32/bvf0SlDv4XYOY7z/Mavu+nM1+BmQ+NMc0wDF/LprP0DbTWW0T00ul0nn4b7Q87+X4Qmfiq2wAAAABJRU5ErkJggg==');
|
|
background-position: 10px 10px;
|
|
background-repeat: no-repeat;
|
|
}
|
|
|
|
.dark .searchbox {
|
|
background-color: #111;
|
|
color: #eee;
|
|
}
|
|
|
|
.searchbox::placeholder {
|
|
color: #ccc;
|
|
}
|
|
|
|
.dark .searchbox::placeholder {
|
|
color: #666;
|
|
}
|
|
|
|
.filter {
|
|
width: calc(60% - 64px);
|
|
}
|
|
|
|
.reflookup {
|
|
width: calc(40% - 10px);
|
|
}
|
|
|
|
input[type=text]:focus {
|
|
background-color: white;
|
|
border: 1px solid #333;
|
|
}
|
|
|
|
.dark input[type=text]:focus {
|
|
background-color: #333;
|
|
border: 1px solid #ccc;
|
|
}
|
|
|
|
mark.highlight {
|
|
background-color: #5050ff;
|
|
color: #fff;
|
|
padding: 2px;
|
|
border-radius: 6px;
|
|
}
|
|
|
|
.dark mark.highlight {
|
|
background-color: #76a6da;
|
|
color: #111;
|
|
}
|
|
|
|
.menubtn {
|
|
background-color: white;
|
|
border: none;
|
|
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='36' height='36' viewBox='0 0 20 20'%3E%3Cpath fill='none' d='M0 0h20v20H0V0z'/%3E%3Cpath d='M15.95 10.78c.03-.25.05-.51.05-.78s-.02-.53-.06-.78l1.69-1.32c.15-.12.19-.34.1-.51l-1.6-2.77c-.1-.18-.31-.24-.49-.18l-1.99.8c-.42-.32-.86-.58-1.35-.78L12 2.34c-.03-.2-.2-.34-.4-.34H8.4c-.2 0-.36.14-.39.34l-.3 2.12c-.49.2-.94.47-1.35.78l-1.99-.8c-.18-.07-.39 0-.49.18l-1.6 2.77c-.1.18-.06.39.1.51l1.69 1.32c-.04.25-.07.52-.07.78s.02.53.06.78L2.37 12.1c-.15.12-.19.34-.1.51l1.6 2.77c.1.18.31.24.49.18l1.99-.8c.42.32.86.58 1.35.78l.3 2.12c.04.2.2.34.4.34h3.2c.2 0 .37-.14.39-.34l.3-2.12c.49-.2.94-.47 1.35-.78l1.99.8c.18.07.39 0 .49-.18l1.6-2.77c.1-.18.06-.39-.1-.51l-1.67-1.32zM10 13c-1.65 0-3-1.35-3-3s1.35-3 3-3 3 1.35 3 3-1.35 3-3 3z'/%3E%3C/svg%3E%0A");
|
|
background-position: center;
|
|
background-repeat: no-repeat;
|
|
}
|
|
|
|
.statsbtn {
|
|
background-color: white;
|
|
border: none;
|
|
background-image: url("data:image/svg+xml,%3Csvg width='36' height='36' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M4 6h28v24H4V6zm0 8h28v8H4m9-16v24h10V5.8' fill='none' stroke='%23000' stroke-width='2'/%3E%3C/svg%3E");
|
|
background-position: center;
|
|
background-repeat: no-repeat;
|
|
}
|
|
|
|
.iobtn {
|
|
background-color: white;
|
|
border: none;
|
|
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='36' height='36'%3E%3Cpath fill='none' stroke='%23000' stroke-width='2' d='M3 33v-7l6.8-7h16.5l6.7 7v7H3zM3.2 26H33M21 9l5-5.9 5 6h-2.5V15h-5V9H21zm-4.9 0l-5 6-5-6h2.5V3h5v6h2.5z'/%3E%3Cpath fill='none' stroke='%23000' d='M6.1 29.5H10'/%3E%3C/svg%3E");
|
|
background-position: center;
|
|
background-repeat: no-repeat;
|
|
}
|
|
|
|
.visbtn {
|
|
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24'%3E%3Cpath fill='none' stroke='%23333' d='M2.5 4.5h5v15h-5zM9.5 4.5h5v15h-5zM16.5 4.5h5v15h-5z'/%3E%3C/svg%3E");
|
|
background-position: center;
|
|
background-repeat: no-repeat;
|
|
padding: 15px;
|
|
}
|
|
|
|
#vismenu-content {
|
|
left: 0px;
|
|
font-family: Verdana, sans-serif;
|
|
}
|
|
|
|
.dark .statsbtn,
|
|
.dark .savebtn,
|
|
.dark .menubtn,
|
|
.dark .iobtn,
|
|
.dark .visbtn {
|
|
filter: invert(1);
|
|
}
|
|
|
|
.flexbox {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
width: 100%;
|
|
}
|
|
|
|
.savebtn {
|
|
background-color: #d6d6d6;
|
|
width: auto;
|
|
height: 30px;
|
|
flex-grow: 1;
|
|
margin: 5px;
|
|
border-radius: 4px;
|
|
}
|
|
|
|
.savebtn:active {
|
|
background-color: #0a0;
|
|
color: white;
|
|
}
|
|
|
|
.dark .savebtn:active {
|
|
/* This will be inverted */
|
|
background-color: #b3b;
|
|
}
|
|
|
|
.stats {
|
|
border-collapse: collapse;
|
|
font-size: 12pt;
|
|
table-layout: fixed;
|
|
width: 100%;
|
|
min-width: 450px;
|
|
}
|
|
|
|
.dark .stats td {
|
|
border: 1px solid #bbb;
|
|
}
|
|
|
|
.stats td {
|
|
border: 1px solid black;
|
|
padding: 5px;
|
|
word-wrap: break-word;
|
|
text-align: center;
|
|
position: relative;
|
|
}
|
|
|
|
#checkbox-stats div {
|
|
position: absolute;
|
|
left: 0;
|
|
top: 0;
|
|
height: 100%;
|
|
width: 100%;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
}
|
|
|
|
#checkbox-stats .bar {
|
|
background-color: rgba(28, 251, 0, 0.6);
|
|
}
|
|
|
|
.menu {
|
|
position: relative;
|
|
display: inline-block;
|
|
margin: 0.4rem 0.4rem 0.4rem 0;
|
|
}
|
|
|
|
.menu-content {
|
|
font-size: 12pt !important;
|
|
text-align: left !important;
|
|
font-weight: normal !important;
|
|
display: none;
|
|
position: absolute;
|
|
background-color: white;
|
|
right: 0;
|
|
min-width: 300px;
|
|
box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.2);
|
|
z-index: 100;
|
|
padding: 8px;
|
|
}
|
|
|
|
.dark .menu-content {
|
|
background-color: #111;
|
|
}
|
|
|
|
.menu:hover .menu-content {
|
|
display: block;
|
|
}
|
|
|
|
.menu:hover .menubtn,
|
|
.menu:hover .iobtn,
|
|
.menu:hover .statsbtn {
|
|
background-color: #eee;
|
|
}
|
|
|
|
.menu-label {
|
|
display: inline-block;
|
|
padding: 8px;
|
|
border: 1px solid #ccc;
|
|
border-top: 0;
|
|
width: calc(100% - 18px);
|
|
}
|
|
|
|
.menu-label-top {
|
|
border-top: 1px solid #ccc;
|
|
}
|
|
|
|
.menu-textbox {
|
|
float: left;
|
|
height: 24px;
|
|
margin: 10px 5px;
|
|
padding: 5px 5px;
|
|
font-family: Consolas, "DejaVu Sans Mono", Monaco, monospace;
|
|
font-size: 14px;
|
|
box-sizing: border-box;
|
|
border: 1px solid #888;
|
|
border-radius: 4px;
|
|
outline: none;
|
|
background-color: #eee;
|
|
transition: background-color 0.2s, border 0.2s;
|
|
width: calc(100% - 10px);
|
|
}
|
|
|
|
.menu-textbox.invalid,
|
|
.dark .menu-textbox.invalid {
|
|
color: red;
|
|
}
|
|
|
|
.dark .menu-textbox {
|
|
background-color: #222;
|
|
color: #eee;
|
|
}
|
|
|
|
.radio-container {
|
|
margin: 4px;
|
|
}
|
|
|
|
.topmostdiv {
|
|
display: flex;
|
|
flex-direction: column;
|
|
width: 100%;
|
|
background-color: white;
|
|
transition: background-color 0.3s;
|
|
}
|
|
|
|
#top {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
justify-content: flex-end;
|
|
align-items: center;
|
|
}
|
|
|
|
#topdivider {
|
|
border-bottom: 2px solid black;
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
}
|
|
|
|
.dark #topdivider {
|
|
border-bottom: 2px solid #ccc;
|
|
}
|
|
|
|
#topdivider>div {
|
|
position: relative;
|
|
}
|
|
|
|
#toptoggle {
|
|
cursor: pointer;
|
|
user-select: none;
|
|
position: absolute;
|
|
padding: 0.1rem 0.3rem;
|
|
top: -0.4rem;
|
|
left: -1rem;
|
|
font-size: 1.4rem;
|
|
line-height: 60%;
|
|
border: 1px solid black;
|
|
border-radius: 1rem;
|
|
background-color: #fff;
|
|
z-index: 100;
|
|
}
|
|
|
|
.flipped {
|
|
transform: rotate(0.5turn);
|
|
}
|
|
|
|
.dark #toptoggle {
|
|
border: 1px solid #fff;
|
|
background-color: #222;
|
|
}
|
|
|
|
#fileinfodiv {
|
|
flex: 20rem 1 0;
|
|
overflow: auto;
|
|
}
|
|
|
|
#bomcontrols {
|
|
display: flex;
|
|
flex-direction: row-reverse;
|
|
}
|
|
|
|
#bomcontrols>* {
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
#dbg {
|
|
display: block;
|
|
}
|
|
|
|
::-webkit-scrollbar {
|
|
width: 8px;
|
|
}
|
|
|
|
::-webkit-scrollbar-track {
|
|
background: #aaa;
|
|
}
|
|
|
|
::-webkit-scrollbar-thumb {
|
|
background: #666;
|
|
border-radius: 3px;
|
|
}
|
|
|
|
::-webkit-scrollbar-thumb:hover {
|
|
background: #555;
|
|
}
|
|
|
|
.slider {
|
|
-webkit-appearance: none;
|
|
width: 100%;
|
|
margin: 3px 0;
|
|
padding: 0;
|
|
outline: none;
|
|
opacity: 0.7;
|
|
-webkit-transition: .2s;
|
|
transition: opacity .2s;
|
|
border-radius: 3px;
|
|
}
|
|
|
|
.slider:hover {
|
|
opacity: 1;
|
|
}
|
|
|
|
.slider:focus {
|
|
outline: none;
|
|
}
|
|
|
|
.slider::-webkit-slider-runnable-track {
|
|
-webkit-appearance: none;
|
|
width: 100%;
|
|
height: 8px;
|
|
background: #d3d3d3;
|
|
border-radius: 3px;
|
|
border: none;
|
|
}
|
|
|
|
.slider::-webkit-slider-thumb {
|
|
-webkit-appearance: none;
|
|
width: 15px;
|
|
height: 15px;
|
|
border-radius: 50%;
|
|
background: #0a0;
|
|
cursor: pointer;
|
|
margin-top: -4px;
|
|
}
|
|
|
|
.dark .slider::-webkit-slider-thumb {
|
|
background: #3d3;
|
|
}
|
|
|
|
.slider::-moz-range-thumb {
|
|
width: 15px;
|
|
height: 15px;
|
|
border-radius: 50%;
|
|
background: #0a0;
|
|
cursor: pointer;
|
|
}
|
|
|
|
.slider::-moz-range-track {
|
|
height: 8px;
|
|
background: #d3d3d3;
|
|
border-radius: 3px;
|
|
}
|
|
|
|
.dark .slider::-moz-range-thumb {
|
|
background: #3d3;
|
|
}
|
|
|
|
.slider::-ms-track {
|
|
width: 100%;
|
|
height: 8px;
|
|
border-width: 3px 0;
|
|
background: transparent;
|
|
border-color: transparent;
|
|
color: transparent;
|
|
transition: opacity .2s;
|
|
}
|
|
|
|
.slider::-ms-fill-lower {
|
|
background: #d3d3d3;
|
|
border: none;
|
|
border-radius: 3px;
|
|
}
|
|
|
|
.slider::-ms-fill-upper {
|
|
background: #d3d3d3;
|
|
border: none;
|
|
border-radius: 3px;
|
|
}
|
|
|
|
.slider::-ms-thumb {
|
|
width: 15px;
|
|
height: 15px;
|
|
border-radius: 50%;
|
|
background: #0a0;
|
|
cursor: pointer;
|
|
margin: 0;
|
|
}
|
|
|
|
.shameless-plug {
|
|
font-size: 0.8em;
|
|
text-align: center;
|
|
display: block;
|
|
}
|
|
|
|
a {
|
|
color: #0278a4;
|
|
}
|
|
|
|
.dark a {
|
|
color: #00b9fd;
|
|
}
|
|
|
|
#frontcanvas,
|
|
#backcanvas {
|
|
touch-action: none;
|
|
}
|
|
|
|
.placeholder {
|
|
border: 1px dashed #9f9fda !important;
|
|
background-color: #edf2f7 !important;
|
|
}
|
|
|
|
.dragging {
|
|
z-index: 999;
|
|
}
|
|
|
|
.dark .dragging>table>tbody>tr {
|
|
background-color: #252c30;
|
|
}
|
|
|
|
.dark .placeholder {
|
|
filter: invert(1);
|
|
}
|
|
|
|
.column-spacer {
|
|
top: 0;
|
|
left: 0;
|
|
width: calc(100% - 4px);
|
|
position: absolute;
|
|
cursor: pointer;
|
|
user-select: none;
|
|
height: 100%;
|
|
}
|
|
|
|
.column-width-handle {
|
|
top: 0;
|
|
right: 0;
|
|
width: 4px;
|
|
position: absolute;
|
|
cursor: col-resize;
|
|
user-select: none;
|
|
height: 100%;
|
|
}
|
|
|
|
.column-width-handle:hover {
|
|
background-color: #4f99bd;
|
|
}
|
|
|
|
.help-link {
|
|
border: 1px solid #0278a4;
|
|
padding-inline: 0.3rem;
|
|
border-radius: 3px;
|
|
cursor: pointer;
|
|
}
|
|
|
|
.dark .help-link {
|
|
border: 1px solid #00b9fd;
|
|
}
|
|
|
|
.bom-color {
|
|
width: 20%;
|
|
}
|
|
|
|
.color-column input {
|
|
width: 1.6rem;
|
|
height: 1rem;
|
|
border: 1px solid black;
|
|
cursor: pointer;
|
|
padding: 0;
|
|
}
|
|
|
|
/* removes default styling from input color element */
|
|
::-webkit-color-swatch {
|
|
border: none;
|
|
}
|
|
|
|
::-webkit-color-swatch-wrapper {
|
|
padding: 0;
|
|
}
|
|
|
|
::-moz-color-swatch,
|
|
::-moz-focus-inner {
|
|
border: none;
|
|
}
|
|
|
|
::-moz-focus-inner {
|
|
padding: 0;
|
|
}
|
|
/* #bomhead {
|
|
position: sticky;
|
|
top: 0px;
|
|
z-index: 1;
|
|
} */
|
|
</style>
|
|
<script type="text/javascript" >
|
|
///////////////////////////////////////////////
|
|
/*
|
|
Split.js - v1.3.5
|
|
MIT License
|
|
https://github.com/nathancahill/Split.js
|
|
*/
|
|
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):e.Split=t()}(this,function(){"use strict";var e=window,t=e.document,n="addEventListener",i="removeEventListener",r="getBoundingClientRect",s=function(){return!1},o=e.attachEvent&&!e[n],a=["","-webkit-","-moz-","-o-"].filter(function(e){var n=t.createElement("div");return n.style.cssText="width:"+e+"calc(9px)",!!n.style.length}).shift()+"calc",l=function(e){return"string"==typeof e||e instanceof String?t.querySelector(e):e};return function(u,c){function z(e,t,n){var i=A(y,t,n);Object.keys(i).forEach(function(t){return e.style[t]=i[t]})}function h(e,t){var n=B(y,t);Object.keys(n).forEach(function(t){return e.style[t]=n[t]})}function f(e){var t=E[this.a],n=E[this.b],i=t.size+n.size;t.size=e/this.size*i,n.size=i-e/this.size*i,z(t.element,t.size,this.aGutterSize),z(n.element,n.size,this.bGutterSize)}function m(e){var t;this.dragging&&((t="touches"in e?e.touches[0][b]-this.start:e[b]-this.start)<=E[this.a].minSize+M+this.aGutterSize?t=E[this.a].minSize+this.aGutterSize:t>=this.size-(E[this.b].minSize+M+this.bGutterSize)&&(t=this.size-(E[this.b].minSize+this.bGutterSize)),f.call(this,t),c.onDrag&&c.onDrag())}function g(){var e=E[this.a].element,t=E[this.b].element;this.size=e[r]()[y]+t[r]()[y]+this.aGutterSize+this.bGutterSize,this.start=e[r]()[G]}function d(){var t=this,n=E[t.a].element,r=E[t.b].element;t.dragging&&c.onDragEnd&&c.onDragEnd(),t.dragging=!1,e[i]("mouseup",t.stop),e[i]("touchend",t.stop),e[i]("touchcancel",t.stop),t.parent[i]("mousemove",t.move),t.parent[i]("touchmove",t.move),delete t.stop,delete t.move,n[i]("selectstart",s),n[i]("dragstart",s),r[i]("selectstart",s),r[i]("dragstart",s),n.style.userSelect="",n.style.webkitUserSelect="",n.style.MozUserSelect="",n.style.pointerEvents="",r.style.userSelect="",r.style.webkitUserSelect="",r.style.MozUserSelect="",r.style.pointerEvents="",t.gutter.style.cursor="",t.parent.style.cursor=""}function S(t){var i=this,r=E[i.a].element,o=E[i.b].element;!i.dragging&&c.onDragStart&&c.onDragStart(),t.preventDefault(),i.dragging=!0,i.move=m.bind(i),i.stop=d.bind(i),e[n]("mouseup",i.stop),e[n]("touchend",i.stop),e[n]("touchcancel",i.stop),i.parent[n]("mousemove",i.move),i.parent[n]("touchmove",i.move),r[n]("selectstart",s),r[n]("dragstart",s),o[n]("selectstart",s),o[n]("dragstart",s),r.style.userSelect="none",r.style.webkitUserSelect="none",r.style.MozUserSelect="none",r.style.pointerEvents="none",o.style.userSelect="none",o.style.webkitUserSelect="none",o.style.MozUserSelect="none",o.style.pointerEvents="none",i.gutter.style.cursor=j,i.parent.style.cursor=j,g.call(i)}function v(e){e.forEach(function(t,n){if(n>0){var i=F[n-1],r=E[i.a],s=E[i.b];r.size=e[n-1],s.size=t,z(r.element,r.size,i.aGutterSize),z(s.element,s.size,i.bGutterSize)}})}function p(){F.forEach(function(e){e.parent.removeChild(e.gutter),E[e.a].element.style[y]="",E[e.b].element.style[y]=""})}void 0===c&&(c={});var y,b,G,E,w=l(u[0]).parentNode,D=e.getComputedStyle(w).flexDirection,U=c.sizes||u.map(function(){return 100/u.length}),k=void 0!==c.minSize?c.minSize:100,x=Array.isArray(k)?k:u.map(function(){return k}),L=void 0!==c.gutterSize?c.gutterSize:10,M=void 0!==c.snapOffset?c.snapOffset:30,O=c.direction||"horizontal",j=c.cursor||("horizontal"===O?"ew-resize":"ns-resize"),C=c.gutter||function(e,n){var i=t.createElement("div");return i.className="gutter gutter-"+n,i},A=c.elementStyle||function(e,t,n){var i={};return"string"==typeof t||t instanceof String?i[e]=t:i[e]=o?t+"%":a+"("+t+"% - "+n+"px)",i},B=c.gutterStyle||function(e,t){return n={},n[e]=t+"px",n;var n};"horizontal"===O?(y="width","clientWidth",b="clientX",G="left","paddingLeft"):"vertical"===O&&(y="height","clientHeight",b="clientY",G="top","paddingTop");var F=[];return E=u.map(function(e,t){var i,s={element:l(e),size:U[t],minSize:x[t]};if(t>0&&(i={a:t-1,b:t,dragging:!1,isFirst:1===t,isLast:t===u.length-1,direction:O,parent:w},i.aGutterSize=L,i.bGutterSize=L,i.isFirst&&(i.aGutterSize=L/2),i.isLast&&(i.bGutterSize=L/2),"row-reverse"===D||"column-reverse"===D)){var a=i.a;i.a=i.b,i.b=a}if(!o&&t>0){var c=C(t,O);h(c,L),c[n]("mousedown",S.bind(i)),c[n]("touchstart",S.bind(i)),w.insertBefore(c,s.element),i.gutter=c}0===t||t===u.length-1?z(s.element,s.size,L/2):z(s.element,s.size,L);var f=s.element[r]()[y];return f<s.minSize&&(s.minSize=f),t>0&&F.push(i),s}),o?{setSizes:v,destroy:p}:{setSizes:v,getSizes:function(){return E.map(function(e){return e.size})},collapse:function(e){if(e===F.length){var t=F[e-1];g.call(t),o||f.call(t,t.size-t.bGutterSize)}else{var n=F[e];g.call(n),o||f.call(n,n.aGutterSize)}},destroy:p}}});
|
|
|
|
///////////////////////////////////////////////
|
|
|
|
///////////////////////////////////////////////
|
|
// Copyright (c) 2013 Pieroxy <pieroxy@pieroxy.net>
|
|
// This work is free. You can redistribute it and/or modify it
|
|
// under the terms of the WTFPL, Version 2
|
|
// For more information see LICENSE.txt or http://www.wtfpl.net/
|
|
//
|
|
// For more information, the home page:
|
|
// http://pieroxy.net/blog/pages/lz-string/testing.html
|
|
//
|
|
// LZ-based compression algorithm, version 1.4.4
|
|
var LZString=function(){var o=String.fromCharCode,i={};var n={decompressFromBase64:function(o){return null==o?"":""==o?null:n._decompress(o.length,32,function(n){return function(o,n){if(!i[o]){i[o]={};for(var t=0;t<o.length;t++)i[o][o.charAt(t)]=t}return i[o][n]}("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",o.charAt(n))})},_decompress:function(i,n,t){var r,e,a,s,p,u,l,f=[],c=4,d=4,h=3,v="",g=[],m={val:t(0),position:n,index:1};for(r=0;r<3;r+=1)f[r]=r;for(a=0,p=Math.pow(2,2),u=1;u!=p;)s=m.val&m.position,m.position>>=1,0==m.position&&(m.position=n,m.val=t(m.index++)),a|=(s>0?1:0)*u,u<<=1;switch(a){case 0:for(a=0,p=Math.pow(2,8),u=1;u!=p;)s=m.val&m.position,m.position>>=1,0==m.position&&(m.position=n,m.val=t(m.index++)),a|=(s>0?1:0)*u,u<<=1;l=o(a);break;case 1:for(a=0,p=Math.pow(2,16),u=1;u!=p;)s=m.val&m.position,m.position>>=1,0==m.position&&(m.position=n,m.val=t(m.index++)),a|=(s>0?1:0)*u,u<<=1;l=o(a);break;case 2:return""}for(f[3]=l,e=l,g.push(l);;){if(m.index>i)return"";for(a=0,p=Math.pow(2,h),u=1;u!=p;)s=m.val&m.position,m.position>>=1,0==m.position&&(m.position=n,m.val=t(m.index++)),a|=(s>0?1:0)*u,u<<=1;switch(l=a){case 0:for(a=0,p=Math.pow(2,8),u=1;u!=p;)s=m.val&m.position,m.position>>=1,0==m.position&&(m.position=n,m.val=t(m.index++)),a|=(s>0?1:0)*u,u<<=1;f[d++]=o(a),l=d-1,c--;break;case 1:for(a=0,p=Math.pow(2,16),u=1;u!=p;)s=m.val&m.position,m.position>>=1,0==m.position&&(m.position=n,m.val=t(m.index++)),a|=(s>0?1:0)*u,u<<=1;f[d++]=o(a),l=d-1,c--;break;case 2:return g.join("")}if(0==c&&(c=Math.pow(2,h),h++),f[l])v=f[l];else{if(l!==d)return null;v=e+e.charAt(0)}g.push(v),f[d++]=e+v.charAt(0),e=v,0==--c&&(c=Math.pow(2,h),h++)}}};return n}();"function"==typeof define&&define.amd?define(function(){return LZString}):"undefined"!=typeof module&&null!=module?module.exports=LZString:"undefined"!=typeof angular&&null!=angular&&angular.module("LZString",[]).factory("LZString",function(){return LZString});
|
|
///////////////////////////////////////////////
|
|
|
|
///////////////////////////////////////////////
|
|
/*!
|
|
* PEP v0.4.3 | https://github.com/jquery/PEP
|
|
* Copyright jQuery Foundation and other contributors | http://jquery.org/license
|
|
*/
|
|
!function(a,b){"object"==typeof exports&&"undefined"!=typeof module?module.exports=b():"function"==typeof define&&define.amd?define(b):a.PointerEventsPolyfill=b()}(this,function(){"use strict";function a(a,b){b=b||Object.create(null);var c=document.createEvent("Event");c.initEvent(a,b.bubbles||!1,b.cancelable||!1);
|
|
for(var d,e=2;e<m.length;e++)d=m[e],c[d]=b[d]||n[e];c.buttons=b.buttons||0;
|
|
var f=0;return f=b.pressure&&c.buttons?b.pressure:c.buttons?.5:0,c.x=c.clientX,c.y=c.clientY,c.pointerId=b.pointerId||0,c.width=b.width||0,c.height=b.height||0,c.pressure=f,c.tiltX=b.tiltX||0,c.tiltY=b.tiltY||0,c.twist=b.twist||0,c.tangentialPressure=b.tangentialPressure||0,c.pointerType=b.pointerType||"",c.hwTimestamp=b.hwTimestamp||0,c.isPrimary=b.isPrimary||!1,c}function b(){this.array=[],this.size=0}function c(a,b,c,d){this.addCallback=a.bind(d),this.removeCallback=b.bind(d),this.changedCallback=c.bind(d),A&&(this.observer=new A(this.mutationWatcher.bind(this)))}function d(a){return"body /shadow-deep/ "+e(a)}function e(a){return'[touch-action="'+a+'"]'}function f(a){return"{ -ms-touch-action: "+a+"; touch-action: "+a+"; }"}function g(){if(F){D.forEach(function(a){String(a)===a?(E+=e(a)+f(a)+"\n",G&&(E+=d(a)+f(a)+"\n")):(E+=a.selectors.map(e)+f(a.rule)+"\n",G&&(E+=a.selectors.map(d)+f(a.rule)+"\n"))});var a=document.createElement("style");a.textContent=E,document.head.appendChild(a)}}function h(){if(!window.PointerEvent){if(window.PointerEvent=a,window.navigator.msPointerEnabled){var b=window.navigator.msMaxTouchPoints;Object.defineProperty(window.navigator,"maxTouchPoints",{value:b,enumerable:!0}),u.registerSource("ms",_)}else Object.defineProperty(window.navigator,"maxTouchPoints",{value:0,enumerable:!0}),u.registerSource("mouse",N),void 0!==window.ontouchstart&&u.registerSource("touch",V);u.register(document)}}function i(a){if(!u.pointermap.has(a)){var b=new Error("InvalidPointerId");throw b.name="InvalidPointerId",b}}function j(a){for(var b=a.parentNode;b&&b!==a.ownerDocument;)b=b.parentNode;if(!b){var c=new Error("InvalidStateError");throw c.name="InvalidStateError",c}}function k(a){var b=u.pointermap.get(a);return 0!==b.buttons}function l(){window.Element&&!Element.prototype.setPointerCapture&&Object.defineProperties(Element.prototype,{setPointerCapture:{value:W},releasePointerCapture:{value:X},hasPointerCapture:{value:Y}})}
|
|
var m=["bubbles","cancelable","view","detail","screenX","screenY","clientX","clientY","ctrlKey","altKey","shiftKey","metaKey","button","relatedTarget","pageX","pageY"],n=[!1,!1,null,null,0,0,0,0,!1,!1,!1,!1,0,null,0,0],o=window.Map&&window.Map.prototype.forEach,p=o?Map:b;b.prototype={set:function(a,b){return void 0===b?this["delete"](a):(this.has(a)||this.size++,void(this.array[a]=b))},has:function(a){return void 0!==this.array[a]},"delete":function(a){this.has(a)&&(delete this.array[a],this.size--)},get:function(a){return this.array[a]},clear:function(){this.array.length=0,this.size=0},forEach:function(a,b){return this.array.forEach(function(c,d){a.call(b,c,d,this)},this)}};var q=["bubbles","cancelable","view","detail","screenX","screenY","clientX","clientY","ctrlKey","altKey","shiftKey","metaKey","button","relatedTarget","buttons","pointerId","width","height","pressure","tiltX","tiltY","pointerType","hwTimestamp","isPrimary","type","target","currentTarget","which","pageX","pageY","timeStamp"],r=[!1,!1,null,null,0,0,0,0,!1,!1,!1,!1,0,null,0,0,0,0,0,0,0,"",0,!1,"",null,null,0,0,0,0],s={pointerover:1,pointerout:1,pointerenter:1,pointerleave:1},t="undefined"!=typeof SVGElementInstance,u={pointermap:new p,eventMap:Object.create(null),captureInfo:Object.create(null),eventSources:Object.create(null),eventSourceList:[],registerSource:function(a,b){var c=b,d=c.events;d&&(d.forEach(function(a){c[a]&&(this.eventMap[a]=c[a].bind(c))},this),this.eventSources[a]=c,this.eventSourceList.push(c))},register:function(a){for(var b,c=this.eventSourceList.length,d=0;d<c&&(b=this.eventSourceList[d]);d++)
|
|
b.register.call(b,a)},unregister:function(a){for(var b,c=this.eventSourceList.length,d=0;d<c&&(b=this.eventSourceList[d]);d++)
|
|
b.unregister.call(b,a)},contains:function(a,b){try{return a.contains(b)}catch(c){return!1}},down:function(a){a.bubbles=!0,this.fireEvent("pointerdown",a)},move:function(a){a.bubbles=!0,this.fireEvent("pointermove",a)},up:function(a){a.bubbles=!0,this.fireEvent("pointerup",a)},enter:function(a){a.bubbles=!1,this.fireEvent("pointerenter",a)},leave:function(a){a.bubbles=!1,this.fireEvent("pointerleave",a)},over:function(a){a.bubbles=!0,this.fireEvent("pointerover",a)},out:function(a){a.bubbles=!0,this.fireEvent("pointerout",a)},cancel:function(a){a.bubbles=!0,this.fireEvent("pointercancel",a)},leaveOut:function(a){this.out(a),this.propagate(a,this.leave,!1)},enterOver:function(a){this.over(a),this.propagate(a,this.enter,!0)},eventHandler:function(a){if(!a._handledByPE){var b=a.type,c=this.eventMap&&this.eventMap[b];c&&c(a),a._handledByPE=!0}},listen:function(a,b){b.forEach(function(b){this.addEvent(a,b)},this)},unlisten:function(a,b){b.forEach(function(b){this.removeEvent(a,b)},this)},addEvent:function(a,b){a.addEventListener(b,this.boundHandler)},removeEvent:function(a,b){a.removeEventListener(b,this.boundHandler)},makeEvent:function(b,c){this.captureInfo[c.pointerId]&&(c.relatedTarget=null);var d=new a(b,c);return c.preventDefault&&(d.preventDefault=c.preventDefault),d._target=d._target||c.target,d},fireEvent:function(a,b){var c=this.makeEvent(a,b);return this.dispatchEvent(c)},cloneEvent:function(a){for(var b,c=Object.create(null),d=0;d<q.length;d++)b=q[d],c[b]=a[b]||r[d],!t||"target"!==b&&"relatedTarget"!==b||c[b]instanceof SVGElementInstance&&(c[b]=c[b].correspondingUseElement);return a.preventDefault&&(c.preventDefault=function(){a.preventDefault()}),c},getTarget:function(a){var b=this.captureInfo[a.pointerId];return b?a._target!==b&&a.type in s?void 0:b:a._target},propagate:function(a,b,c){for(var d=a.target,e=[];d!==document&&!d.contains(a.relatedTarget);) if(e.push(d),d=d.parentNode,!d)return;c&&e.reverse(),e.forEach(function(c){a.target=c,b.call(this,a)},this)},setCapture:function(b,c,d){this.captureInfo[b]&&this.releaseCapture(b,d),this.captureInfo[b]=c,this.implicitRelease=this.releaseCapture.bind(this,b,d),document.addEventListener("pointerup",this.implicitRelease),document.addEventListener("pointercancel",this.implicitRelease);var e=new a("gotpointercapture");e.pointerId=b,e._target=c,d||this.asyncDispatchEvent(e)},releaseCapture:function(b,c){var d=this.captureInfo[b];if(d){this.captureInfo[b]=void 0,document.removeEventListener("pointerup",this.implicitRelease),document.removeEventListener("pointercancel",this.implicitRelease);var e=new a("lostpointercapture");e.pointerId=b,e._target=d,c||this.asyncDispatchEvent(e)}},dispatchEvent:/*scope.external.dispatchEvent || */function(a){var b=this.getTarget(a);if(b)return b.dispatchEvent(a)},asyncDispatchEvent:function(a){requestAnimationFrame(this.dispatchEvent.bind(this,a))}};u.boundHandler=u.eventHandler.bind(u);var v={shadow:function(a){if(a)return a.shadowRoot||a.webkitShadowRoot},canTarget:function(a){return a&&Boolean(a.elementFromPoint)},targetingShadow:function(a){var b=this.shadow(a);if(this.canTarget(b))return b},olderShadow:function(a){var b=a.olderShadowRoot;if(!b){var c=a.querySelector("shadow");c&&(b=c.olderShadowRoot)}return b},allShadows:function(a){for(var b=[],c=this.shadow(a);c;)b.push(c),c=this.olderShadow(c);return b},searchRoot:function(a,b,c){if(a){var d,e,f=a.elementFromPoint(b,c);for(e=this.targetingShadow(f);e;){if(d=e.elementFromPoint(b,c)){var g=this.targetingShadow(d);return this.searchRoot(g,b,c)||d} e=this.olderShadow(e)} return f}},owner:function(a){
|
|
for(var b=a;b.parentNode;)b=b.parentNode;
|
|
return b.nodeType!==Node.DOCUMENT_NODE&&b.nodeType!==Node.DOCUMENT_FRAGMENT_NODE&&(b=document),b},findTarget:function(a){var b=a.clientX,c=a.clientY,d=this.owner(a.target);
|
|
return d.elementFromPoint(b,c)||(d=document),this.searchRoot(d,b,c)}},w=Array.prototype.forEach.call.bind(Array.prototype.forEach),x=Array.prototype.map.call.bind(Array.prototype.map),y=Array.prototype.slice.call.bind(Array.prototype.slice),z=Array.prototype.filter.call.bind(Array.prototype.filter),A=window.MutationObserver||window.WebKitMutationObserver,B="[touch-action]",C={subtree:!0,childList:!0,attributes:!0,attributeOldValue:!0,attributeFilter:["touch-action"]};c.prototype={watchSubtree:function(a){
|
|
//
|
|
this.observer&&v.canTarget(a)&&this.observer.observe(a,C)},enableOnSubtree:function(a){this.watchSubtree(a),a===document&&"complete"!==document.readyState?this.installOnLoad():this.installNewSubtree(a)},installNewSubtree:function(a){w(this.findElements(a),this.addElement,this)},findElements:function(a){return a.querySelectorAll?a.querySelectorAll(B):[]},removeElement:function(a){this.removeCallback(a)},addElement:function(a){this.addCallback(a)},elementChanged:function(a,b){this.changedCallback(a,b)},concatLists:function(a,b){return a.concat(y(b))},
|
|
installOnLoad:function(){document.addEventListener("readystatechange",function(){"complete"===document.readyState&&this.installNewSubtree(document)}.bind(this))},isElement:function(a){return a.nodeType===Node.ELEMENT_NODE},flattenMutationTree:function(a){
|
|
var b=x(a,this.findElements,this);
|
|
return b.push(z(a,this.isElement)),b.reduce(this.concatLists,[])},mutationWatcher:function(a){a.forEach(this.mutationHandler,this)},mutationHandler:function(a){if("childList"===a.type){var b=this.flattenMutationTree(a.addedNodes);b.forEach(this.addElement,this);var c=this.flattenMutationTree(a.removedNodes);c.forEach(this.removeElement,this)}else"attributes"===a.type&&this.elementChanged(a.target,a.oldValue)}};var D=["none","auto","pan-x","pan-y",{rule:"pan-x pan-y",selectors:["pan-x pan-y","pan-y pan-x"]}],E="",F=window.PointerEvent||window.MSPointerEvent,G=!window.ShadowDOMPolyfill&&document.head.createShadowRoot,H=u.pointermap,I=25,J=[1,4,2,8,16],K=!1;try{K=1===new MouseEvent("test",{buttons:1}).buttons}catch(L){}
|
|
var M,N={POINTER_ID:1,POINTER_TYPE:"mouse",events:["mousedown","mousemove","mouseup","mouseover","mouseout"],register:function(a){u.listen(a,this.events)},unregister:function(a){u.unlisten(a,this.events)},lastTouches:[],
|
|
isEventSimulatedFromTouch:function(a){for(var b,c=this.lastTouches,d=a.clientX,e=a.clientY,f=0,g=c.length;f<g&&(b=c[f]);f++){
|
|
var h=Math.abs(d-b.x),i=Math.abs(e-b.y);if(h<=I&&i<=I)return!0}},prepareEvent:function(a){var b=u.cloneEvent(a),c=b.preventDefault;return b.preventDefault=function(){a.preventDefault(),c()},b.pointerId=this.POINTER_ID,b.isPrimary=!0,b.pointerType=this.POINTER_TYPE,b},prepareButtonsForMove:function(a,b){var c=H.get(this.POINTER_ID);
|
|
0!==b.which&&c?a.buttons=c.buttons:a.buttons=0,b.buttons=a.buttons},mousedown:function(a){if(!this.isEventSimulatedFromTouch(a)){var b=H.get(this.POINTER_ID),c=this.prepareEvent(a);K||(c.buttons=J[c.button],b&&(c.buttons|=b.buttons),a.buttons=c.buttons),H.set(this.POINTER_ID,a),b&&0!==b.buttons?u.move(c):u.down(c)}},mousemove:function(a){if(!this.isEventSimulatedFromTouch(a)){var b=this.prepareEvent(a);K||this.prepareButtonsForMove(b,a),b.button=-1,H.set(this.POINTER_ID,a),u.move(b)}},mouseup:function(a){if(!this.isEventSimulatedFromTouch(a)){var b=H.get(this.POINTER_ID),c=this.prepareEvent(a);if(!K){var d=J[c.button];
|
|
c.buttons=b?b.buttons&~d:0,a.buttons=c.buttons}H.set(this.POINTER_ID,a),
|
|
c.buttons&=~J[c.button],0===c.buttons?u.up(c):u.move(c)}},mouseover:function(a){if(!this.isEventSimulatedFromTouch(a)){var b=this.prepareEvent(a);K||this.prepareButtonsForMove(b,a),b.button=-1,H.set(this.POINTER_ID,a),u.enterOver(b)}},mouseout:function(a){if(!this.isEventSimulatedFromTouch(a)){var b=this.prepareEvent(a);K||this.prepareButtonsForMove(b,a),b.button=-1,u.leaveOut(b)}},cancel:function(a){var b=this.prepareEvent(a);u.cancel(b),this.deactivateMouse()},deactivateMouse:function(){H["delete"](this.POINTER_ID)}},O=u.captureInfo,P=v.findTarget.bind(v),Q=v.allShadows.bind(v),R=u.pointermap,S=2500,T=200,U="touch-action",V={events:["touchstart","touchmove","touchend","touchcancel"],register:function(a){M.enableOnSubtree(a)},unregister:function(){},elementAdded:function(a){var b=a.getAttribute(U),c=this.touchActionToScrollType(b);c&&(a._scrollType=c,u.listen(a,this.events),
|
|
Q(a).forEach(function(a){a._scrollType=c,u.listen(a,this.events)},this))},elementRemoved:function(a){a._scrollType=void 0,u.unlisten(a,this.events),
|
|
Q(a).forEach(function(a){a._scrollType=void 0,u.unlisten(a,this.events)},this)},elementChanged:function(a,b){var c=a.getAttribute(U),d=this.touchActionToScrollType(c),e=this.touchActionToScrollType(b);
|
|
d&&e?(a._scrollType=d,Q(a).forEach(function(a){a._scrollType=d},this)):e?this.elementRemoved(a):d&&this.elementAdded(a)},scrollTypes:{EMITTER:"none",XSCROLLER:"pan-x",YSCROLLER:"pan-y",SCROLLER:/^(?:pan-x pan-y)|(?:pan-y pan-x)|auto$/},touchActionToScrollType:function(a){var b=a,c=this.scrollTypes;return"none"===b?"none":b===c.XSCROLLER?"X":b===c.YSCROLLER?"Y":c.SCROLLER.exec(b)?"XY":void 0},POINTER_TYPE:"touch",firstTouch:null,isPrimaryTouch:function(a){return this.firstTouch===a.identifier},setPrimaryTouch:function(a){
|
|
(0===R.size||1===R.size&&R.has(1))&&(this.firstTouch=a.identifier,this.firstXY={X:a.clientX,Y:a.clientY},this.scrolling=!1,this.cancelResetClickCount())},removePrimaryPointer:function(a){a.isPrimary&&(this.firstTouch=null,this.firstXY=null,this.resetClickCount())},clickCount:0,resetId:null,resetClickCount:function(){var a=function(){this.clickCount=0,this.resetId=null}.bind(this);this.resetId=setTimeout(a,T)},cancelResetClickCount:function(){this.resetId&&clearTimeout(this.resetId)},typeToButtons:function(a){var b=0;return"touchstart"!==a&&"touchmove"!==a||(b=1),b},touchToPointer:function(a){var b=this.currentTouchEvent,c=u.cloneEvent(a),d=c.pointerId=a.identifier+2;c.target=O[d]||P(c),c.bubbles=!0,c.cancelable=!0,c.detail=this.clickCount,c.button=0,c.buttons=this.typeToButtons(b.type),c.width=2*(a.radiusX||a.webkitRadiusX||0),c.height=2*(a.radiusY||a.webkitRadiusY||0),c.pressure=a.force||a.webkitForce||.5,c.isPrimary=this.isPrimaryTouch(a),c.pointerType=this.POINTER_TYPE,
|
|
c.altKey=b.altKey,c.ctrlKey=b.ctrlKey,c.metaKey=b.metaKey,c.shiftKey=b.shiftKey;
|
|
var e=this;return c.preventDefault=function(){e.scrolling=!1,e.firstXY=null,b.preventDefault()},c},processTouches:function(a,b){var c=a.changedTouches;this.currentTouchEvent=a;for(var d,e=0;e<c.length;e++)d=c[e],b.call(this,this.touchToPointer(d))},
|
|
shouldScroll:function(a){if(this.firstXY){var b,c=a.currentTarget._scrollType;if("none"===c)
|
|
b=!1;else if("XY"===c)
|
|
b=!0;else{var d=a.changedTouches[0],e=c,f="Y"===c?"X":"Y",g=Math.abs(d["client"+e]-this.firstXY[e]),h=Math.abs(d["client"+f]-this.firstXY[f]);
|
|
b=g>=h}return this.firstXY=null,b}},findTouch:function(a,b){for(var c,d=0,e=a.length;d<e&&(c=a[d]);d++)if(c.identifier===b)return!0},
|
|
vacuumTouches:function(a){var b=a.touches;
|
|
if(R.size>=b.length){var c=[];R.forEach(function(a,d){
|
|
if(1!==d&&!this.findTouch(b,d-2)){var e=a.out;c.push(e)}},this),c.forEach(this.cancelOut,this)}},touchstart:function(a){this.vacuumTouches(a),this.setPrimaryTouch(a.changedTouches[0]),this.dedupSynthMouse(a),this.scrolling||(this.clickCount++,this.processTouches(a,this.overDown))},overDown:function(a){R.set(a.pointerId,{target:a.target,out:a,outTarget:a.target}),u.enterOver(a),u.down(a)},touchmove:function(a){this.scrolling||(this.shouldScroll(a)?(this.scrolling=!0,this.touchcancel(a)):(a.preventDefault(),this.processTouches(a,this.moveOverOut)))},moveOverOut:function(a){var b=a,c=R.get(b.pointerId);
|
|
if(c){var d=c.out,e=c.outTarget;u.move(b),d&&e!==b.target&&(d.relatedTarget=b.target,b.relatedTarget=e,
|
|
d.target=e,b.target?(u.leaveOut(d),u.enterOver(b)):(
|
|
b.target=e,b.relatedTarget=null,this.cancelOut(b))),c.out=b,c.outTarget=b.target}},touchend:function(a){this.dedupSynthMouse(a),this.processTouches(a,this.upOut)},upOut:function(a){this.scrolling||(u.up(a),u.leaveOut(a)),this.cleanUpPointer(a)},touchcancel:function(a){this.processTouches(a,this.cancelOut)},cancelOut:function(a){u.cancel(a),u.leaveOut(a),this.cleanUpPointer(a)},cleanUpPointer:function(a){R["delete"](a.pointerId),this.removePrimaryPointer(a)},
|
|
dedupSynthMouse:function(a){var b=N.lastTouches,c=a.changedTouches[0];
|
|
if(this.isPrimaryTouch(c)){
|
|
var d={x:c.clientX,y:c.clientY};b.push(d);var e=function(a,b){var c=a.indexOf(b);c>-1&&a.splice(c,1)}.bind(null,b,d);setTimeout(e,S)}}};M=new c(V.elementAdded,V.elementRemoved,V.elementChanged,V);var W,X,Y,Z=u.pointermap,$=window.MSPointerEvent&&"number"==typeof window.MSPointerEvent.MSPOINTER_TYPE_MOUSE,_={events:["MSPointerDown","MSPointerMove","MSPointerUp","MSPointerOut","MSPointerOver","MSPointerCancel","MSGotPointerCapture","MSLostPointerCapture"],register:function(a){u.listen(a,this.events)},unregister:function(a){u.unlisten(a,this.events)},POINTER_TYPES:["","unavailable","touch","pen","mouse"],prepareEvent:function(a){var b=a;return $&&(b=u.cloneEvent(a),b.pointerType=this.POINTER_TYPES[a.pointerType]),b},cleanup:function(a){Z["delete"](a)},MSPointerDown:function(a){Z.set(a.pointerId,a);var b=this.prepareEvent(a);u.down(b)},MSPointerMove:function(a){var b=this.prepareEvent(a);u.move(b)},MSPointerUp:function(a){var b=this.prepareEvent(a);u.up(b),this.cleanup(a.pointerId)},MSPointerOut:function(a){var b=this.prepareEvent(a);u.leaveOut(b)},MSPointerOver:function(a){var b=this.prepareEvent(a);u.enterOver(b)},MSPointerCancel:function(a){var b=this.prepareEvent(a);u.cancel(b),this.cleanup(a.pointerId)},MSLostPointerCapture:function(a){var b=u.makeEvent("lostpointercapture",a);u.dispatchEvent(b)},MSGotPointerCapture:function(a){var b=u.makeEvent("gotpointercapture",a);u.dispatchEvent(b)}},aa=window.navigator;aa.msPointerEnabled?(W=function(a){i(a),j(this),k(a)&&(u.setCapture(a,this,!0),this.msSetPointerCapture(a))},X=function(a){i(a),u.releaseCapture(a,!0),this.msReleasePointerCapture(a)}):(W=function(a){i(a),j(this),k(a)&&u.setCapture(a,this)},X=function(a){i(a),u.releaseCapture(a)}),Y=function(a){return!!u.captureInfo[a]},g(),h(),l();var ba={dispatcher:u,Installer:c,PointerEvent:a,PointerMap:p,targetFinding:v};return ba});
|
|
|
|
///////////////////////////////////////////////
|
|
|
|
///////////////////////////////////////////////
|
|
var config = {"dark_mode": true, "show_pads": true, "show_fabrication": false, "show_silkscreen": true, "highlight_pin1": "all", "redraw_on_drag": true, "board_rotation": 0, "checkboxes": "Sourced,Placed", "bom_view": "left-right", "layer_view": "F", "offset_back_rotation": false, "kicad_text_formatting": true, "fields": ["Value", "Footprint"]}
|
|
///////////////////////////////////////////////
|
|
|
|
///////////////////////////////////////////////
|
|
var pcbdata = JSON.parse(LZString.decompressFromBase64("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AHJCd4OHQ21DCkPHQyFCWAD6AElCyUMjQ6NCqUI6QvRDaUL0Q+lC6AEZQvRDmUNZQ9lDOUNHgHlC+UIcQgVCO0OFQhhdu0IlQldCy0Kw3ZWAB0MEAIdCMSAXQsdDQ0P7nBGAhnh3gn7d94M+3Q+CiYBvg0+DfAHPgohCbwNIQmT4/4JU3eXd74JU3R+DMJlK3W8C34Ngwz+DRJm/g0hDCEJTGf+DSEN/gohDgEOpRHDDXEIgQ0sYoENQQkjCQAHgQzBCkEKIQ+BDUEKJwdBDMEJgwohCcjxwQpjC6EPwQ2hC2MKvgiDDcMKDfO+CCMIEw6hD9ER4wgTDvoN8ARhC1j1oPfud4cDFQ+AAK4KEAWGB+52+QoQBKYEBgchcIDym7W6AH83MlNqBZ1R/1BJtqYEdAEAA1cm+VW6ANpBQMTRBfACswkQhjMLo3MzCwQB0wsaB3cH0w26A3MPswwQATMNHg5zCSuzGgF0RD/kBtW6BAsKMw7zDHMPMw+ssxoDsw3XRbMLuYMLCWAB8wxkBIsOZ5XTD4sP2VMaA9MK8wxLCIsL8wuERboBykILDY1DygXwBCsISwkAAksL7gvLCTuBKwz2FPMNDEVzD0sJkYBzDTMJSwmrC0sP7JZSUOsMP+FnAWsN8w2UB7O26wsuchsOywirDcsIGwzzsQsKawgkQDMNCw0bDKsKcwibD8sLGgYGDTZCkw6bD7lT6w5LDqsNE4bXhfAHqwtPg9sLqwjbDesPCw1rCdsMNEW6BXfHMlcvRfAGuw+bDxsJaAHbtGsM6w2xRawH2wk7CzoC2wqrClsLlUArCNsKrUf7DOsNOwnLDzsN+w5KdLMIBw4rDIcOBwr7CzsP6wp7CFGBswz2FVsIgjFbDPsPVwb7DFsMRwodgPP09hLLC/lXAwjHC+oCxwtrCIcLGge7CGsLuw4nDKoFJwi7DDZACwqHDvmwTfZ/0esLhw0HCEcKBgSbCKcKZw+g4ecNhwzHD4cO2w8HCAn2iw3nDqFxhwtnDBcI5w4XCccMLYZHChZ2swjzCacJBAOnCRcPeoUrDxcMUXMaAysIewsHC5cJy4FnCCcMlHEbDmsKFwn7CDcKr4fnCisJbUQfxqcIFwknDzcOxwrnDy+xewm3CW5zdw8rCFsLJw+FcrsK1w1zdrcK9wx7CXcMLYI7CipHdwiXCdcJVwmkA1cMt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J6OUI2AjPOJiI9LjlsL6Ikwjw8MnIyQiTJWVw7gjasLC4oOjJiLy47LjUCPK4nziEuNaIxLhVCO0I3PDDMMGIvpj4iP6ImLi0uIcIowimCNq47wicuN64hRgw8JGI54jSuJ64gwizWNsIkoiZuKK4qLjcpwi42nkluN844rjRRwGIyZj8uMfYhbjycOS4qnDUuPm4lNjBuISI47jDuPOIqfCZCLBIuQiGuKq49rCqCIJEcrjaCMq4ioj1uO64oFjjCO24pMiDMKe4pGj7uOe4vziRuLyI2QiguLO4wiiluKSolbibuJe4sKiNuP3orbjIuKTIo3DIiKR4obipuPuIubifXT+41biduI9wpwj2HUh46XC0ePlIlnCfuKTwjHjPuPgo2HjgePh4/7i1uL+w/rj3uIZ49rjVyNa4sQijyxB45njF6NO4kg1PCNp4nHiw3154m2imeIp43Mip8NqIsFU8CJF49UjG8OnwlLjZeKl4j8jZ8I6IpXjUeMS4nOiJuPSIgniq8KJ46XjJePZ5PXi+eMR4jXjqGDx4znjL8Oa46ojruMJ4tXixGWF4ggw7eMN4ynjBeNBbB3jsePLIoAi2ePrnDniFeJ2VP7iIeK6Ix3j8OM64p3Q3uLN4khgxiPF4lFiqeLd4p3jTCOcIkgifCNy4oEjyePt4gPiY+IY47njAiLKIsPiosMy42LCauNB4n5jveJNw4vjA+NXI6QiOiIr41XjGuNxom/Co+Lz4hHj0eOD4rPj5eMb4mcjm+Ie4j7i2+PL4lPjqePaI6vjbuI1o8HjriNN4n3jeiOz41siJ+O74j8jWuMj4kfj/CMT44bjfqNL4+viDuJz41LCO+NV5Lviy+MV4oHiruNL49PjrqL34iGigeMP48CiHeNX44ojC+K54qnjgsOj4qHiAeKW7P3jzGKx4h/i6eNtdZ/jbcKAIp7iz+M1Yg3jfuJp43/jw+ON455steJzYwficSMo4/EioBO24hki9EPLIl4iK52A4j/CtiJbIyLi4BKTI1Ei1GTuEaASryKDYxATtiNCnAkiliVU42viOSMdogblAyJTEcgTPSIDI+VjreMcwlci4aJjInGpsmJYEgDUzyKTIo0jCuBMI40jOBLfYwhiAbWrIwQT+BIA4msiLSMwdSsif2PHwpgS/+O1I5ATsiPkE0QSe+MRY1cRbBFUEoBd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"))
|
|
///////////////////////////////////////////////
|
|
|
|
///////////////////////////////////////////////
|
|
/* Utility functions */
|
|
|
|
var storagePrefix = 'KiCad_HTML_BOM__' + pcbdata.metadata.title + '__' +
|
|
pcbdata.metadata.revision + '__#';
|
|
var storage;
|
|
|
|
function initStorage(key) {
|
|
try {
|
|
window.localStorage.getItem("blank");
|
|
storage = window.localStorage;
|
|
} catch (e) {
|
|
// localStorage not available
|
|
}
|
|
if (!storage) {
|
|
try {
|
|
window.sessionStorage.getItem("blank");
|
|
storage = window.sessionStorage;
|
|
} catch (e) {
|
|
// sessionStorage also not available
|
|
}
|
|
}
|
|
}
|
|
|
|
function readStorage(key) {
|
|
if (storage) {
|
|
return storage.getItem(storagePrefix + key);
|
|
} else {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
function writeStorage(key, value) {
|
|
if (storage) {
|
|
storage.setItem(storagePrefix + key, value);
|
|
}
|
|
}
|
|
|
|
function fancyDblClickHandler(el, onsingle, ondouble) {
|
|
return function () {
|
|
if (el.getAttribute("data-dblclick") == null) {
|
|
el.setAttribute("data-dblclick", 1);
|
|
setTimeout(function () {
|
|
if (el.getAttribute("data-dblclick") == 1) {
|
|
onsingle();
|
|
}
|
|
el.removeAttribute("data-dblclick");
|
|
}, 200);
|
|
} else {
|
|
el.removeAttribute("data-dblclick");
|
|
ondouble();
|
|
}
|
|
}
|
|
}
|
|
|
|
function smoothScrollToRow(rowid) {
|
|
document.getElementById(rowid).scrollIntoView({
|
|
behavior: "smooth",
|
|
block: "center",
|
|
inline: "nearest"
|
|
});
|
|
}
|
|
|
|
function focusInputField(input) {
|
|
input.scrollIntoView(false);
|
|
input.focus();
|
|
input.select();
|
|
}
|
|
|
|
function saveBomTable(output) {
|
|
var text = '';
|
|
for (var node of bomhead.childNodes[0].childNodes) {
|
|
if (node.firstChild) {
|
|
text += (output == 'csv' ? `"${node.firstChild.nodeValue}"` : node.firstChild.nodeValue);
|
|
}
|
|
if (node != bomhead.childNodes[0].lastChild) {
|
|
text += (output == 'csv' ? ',' : '\t');
|
|
}
|
|
}
|
|
text += '\n';
|
|
for (var row of bombody.childNodes) {
|
|
for (var cell of row.childNodes) {
|
|
let val = '';
|
|
for (var node of cell.childNodes) {
|
|
if (node.nodeName == "INPUT") {
|
|
if (node.checked) {
|
|
val += '✓';
|
|
}
|
|
} else if ((node.nodeName == "MARK") || (node.nodeName == "A")) {
|
|
val += node.firstChild.nodeValue;
|
|
} else {
|
|
val += node.nodeValue;
|
|
}
|
|
}
|
|
if (output == 'csv') {
|
|
val = val.replace(/\"/g, '\"\"'); // pair of double-quote characters
|
|
if (isNumeric(val)) {
|
|
val = +val; // use number
|
|
} else {
|
|
val = `"${val}"`; // enclosed within double-quote
|
|
}
|
|
}
|
|
text += val;
|
|
if (cell != row.lastChild) {
|
|
text += (output == 'csv' ? ',' : '\t');
|
|
}
|
|
}
|
|
text += '\n';
|
|
}
|
|
|
|
if (output != 'clipboard') {
|
|
// To file: csv or txt
|
|
var blob = new Blob([text], {
|
|
type: `text/${output}`
|
|
});
|
|
saveFile(`${pcbdata.metadata.title}.${output}`, blob);
|
|
} else {
|
|
// To clipboard
|
|
var textArea = document.createElement("textarea");
|
|
textArea.classList.add('clipboard-temp');
|
|
textArea.value = text;
|
|
|
|
document.body.appendChild(textArea);
|
|
textArea.focus();
|
|
textArea.select();
|
|
|
|
try {
|
|
if (document.execCommand('copy')) {
|
|
console.log('Bom copied to clipboard.');
|
|
}
|
|
} catch (err) {
|
|
console.log('Can not copy to clipboard.');
|
|
}
|
|
|
|
document.body.removeChild(textArea);
|
|
}
|
|
}
|
|
|
|
function isNumeric(str) {
|
|
/* https://stackoverflow.com/a/175787 */
|
|
return (typeof str != "string" ? false : !isNaN(str) && !isNaN(parseFloat(str)));
|
|
}
|
|
|
|
function removeGutterNode(node) {
|
|
for (var i = 0; i < node.childNodes.length; i++) {
|
|
if (node.childNodes[i].classList &&
|
|
node.childNodes[i].classList.contains("gutter")) {
|
|
node.removeChild(node.childNodes[i]);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
function cleanGutters() {
|
|
removeGutterNode(document.getElementById("bot"));
|
|
removeGutterNode(document.getElementById("canvasdiv"));
|
|
}
|
|
|
|
var units = {
|
|
prefixes: {
|
|
giga: ["G", "g", "giga", "Giga", "GIGA"],
|
|
mega: ["M", "mega", "Mega", "MEGA"],
|
|
kilo: ["K", "k", "kilo", "Kilo", "KILO"],
|
|
milli: ["m", "milli", "Milli", "MILLI"],
|
|
micro: ["U", "u", "micro", "Micro", "MICRO", "μ", "µ"], // different utf8 μ
|
|
nano: ["N", "n", "nano", "Nano", "NANO"],
|
|
pico: ["P", "p", "pico", "Pico", "PICO"],
|
|
},
|
|
unitsShort: ["R", "r", "Ω", "F", "f", "H", "h"],
|
|
unitsLong: [
|
|
"OHM", "Ohm", "ohm", "ohms",
|
|
"FARAD", "Farad", "farad",
|
|
"HENRY", "Henry", "henry"
|
|
],
|
|
getMultiplier: function (s) {
|
|
if (this.prefixes.giga.includes(s)) return 1e9;
|
|
if (this.prefixes.mega.includes(s)) return 1e6;
|
|
if (this.prefixes.kilo.includes(s)) return 1e3;
|
|
if (this.prefixes.milli.includes(s)) return 1e-3;
|
|
if (this.prefixes.micro.includes(s)) return 1e-6;
|
|
if (this.prefixes.nano.includes(s)) return 1e-9;
|
|
if (this.prefixes.pico.includes(s)) return 1e-12;
|
|
return 1;
|
|
},
|
|
valueRegex: null,
|
|
}
|
|
|
|
function initUtils() {
|
|
var allPrefixes = units.prefixes.giga
|
|
.concat(units.prefixes.mega)
|
|
.concat(units.prefixes.kilo)
|
|
.concat(units.prefixes.milli)
|
|
.concat(units.prefixes.micro)
|
|
.concat(units.prefixes.nano)
|
|
.concat(units.prefixes.pico);
|
|
var allUnits = units.unitsShort.concat(units.unitsLong);
|
|
units.valueRegex = new RegExp("^([0-9\.]+)" +
|
|
"\\s*(" + allPrefixes.join("|") + ")?" +
|
|
"(" + allUnits.join("|") + ")?" +
|
|
"(\\b.*)?$", "");
|
|
units.valueAltRegex = new RegExp("^([0-9]*)" +
|
|
"(" + units.unitsShort.join("|") + ")?" +
|
|
"([GgMmKkUuNnPp])?" +
|
|
"([0-9]*)" +
|
|
"(\\b.*)?$", "");
|
|
if (config.fields.includes("Value")) {
|
|
var index = config.fields.indexOf("Value");
|
|
pcbdata.bom["parsedValues"] = {};
|
|
for (var id in pcbdata.bom.fields) {
|
|
pcbdata.bom.parsedValues[id] = parseValue(pcbdata.bom.fields[id][index])
|
|
}
|
|
}
|
|
}
|
|
|
|
function parseValue(val, ref) {
|
|
var inferUnit = (unit, ref) => {
|
|
if (unit) {
|
|
unit = unit.toLowerCase();
|
|
if (unit == 'Ω' || unit == "ohm" || unit == "ohms") {
|
|
unit = 'r';
|
|
}
|
|
unit = unit[0];
|
|
} else {
|
|
ref = /^([a-z]+)\d+$/i.exec(ref);
|
|
if (ref) {
|
|
ref = ref[1].toLowerCase();
|
|
if (ref == "c") unit = 'f';
|
|
else if (ref == "l") unit = 'h';
|
|
else if (ref == "r" || ref == "rv") unit = 'r';
|
|
else unit = null;
|
|
}
|
|
}
|
|
return unit;
|
|
};
|
|
val = val.replace(/,/g, "");
|
|
var match = units.valueRegex.exec(val);
|
|
var unit;
|
|
if (match) {
|
|
val = parseFloat(match[1]);
|
|
if (match[2]) {
|
|
val = val * units.getMultiplier(match[2]);
|
|
}
|
|
unit = inferUnit(match[3], ref);
|
|
if (!unit) return null;
|
|
else return {
|
|
val: val,
|
|
unit: unit,
|
|
extra: match[4],
|
|
}
|
|
}
|
|
match = units.valueAltRegex.exec(val);
|
|
if (match && (match[1] || match[4])) {
|
|
val = parseFloat(match[1] + "." + match[4]);
|
|
if (match[3]) {
|
|
val = val * units.getMultiplier(match[3]);
|
|
}
|
|
unit = inferUnit(match[2], ref);
|
|
if (!unit) return null;
|
|
else return {
|
|
val: val,
|
|
unit: unit,
|
|
extra: match[5],
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
function valueCompare(a, b, stra, strb) {
|
|
if (a === null && b === null) {
|
|
// Failed to parse both values, compare them as strings.
|
|
if (stra != strb) return stra > strb ? 1 : -1;
|
|
else return 0;
|
|
} else if (a === null) {
|
|
return 1;
|
|
} else if (b === null) {
|
|
return -1;
|
|
} else {
|
|
if (a.unit != b.unit) return a.unit > b.unit ? 1 : -1;
|
|
else if (a.val != b.val) return a.val > b.val ? 1 : -1;
|
|
else if (a.extra != b.extra) return a.extra > b.extra ? 1 : -1;
|
|
else return 0;
|
|
}
|
|
}
|
|
|
|
function validateSaveImgDimension(element) {
|
|
var valid = false;
|
|
var intValue = 0;
|
|
if (/^[1-9]\d*$/.test(element.value)) {
|
|
intValue = parseInt(element.value);
|
|
if (intValue <= 16000) {
|
|
valid = true;
|
|
}
|
|
}
|
|
if (valid) {
|
|
element.classList.remove("invalid");
|
|
} else {
|
|
element.classList.add("invalid");
|
|
}
|
|
return intValue;
|
|
}
|
|
|
|
function saveImage(layer) {
|
|
var width = validateSaveImgDimension(document.getElementById("render-save-width"));
|
|
var height = validateSaveImgDimension(document.getElementById("render-save-height"));
|
|
var bgcolor = null;
|
|
if (!document.getElementById("render-save-transparent").checked) {
|
|
var style = getComputedStyle(topmostdiv);
|
|
bgcolor = style.getPropertyValue("background-color");
|
|
}
|
|
if (!width || !height) return;
|
|
|
|
// Prepare image
|
|
var canvas = document.createElement("canvas");
|
|
var layerdict = {
|
|
transform: {
|
|
x: 0,
|
|
y: 0,
|
|
s: 1,
|
|
panx: 0,
|
|
pany: 0,
|
|
zoom: 1,
|
|
},
|
|
bg: canvas,
|
|
fab: canvas,
|
|
silk: canvas,
|
|
highlight: canvas,
|
|
layer: layer,
|
|
}
|
|
// Do the rendering
|
|
recalcLayerScale(layerdict, width, height);
|
|
prepareLayer(layerdict);
|
|
clearCanvas(canvas, bgcolor);
|
|
drawBackground(layerdict, false);
|
|
drawHighlightsOnLayer(layerdict, false);
|
|
|
|
// Save image
|
|
var imgdata = canvas.toDataURL("image/png");
|
|
|
|
var filename = pcbdata.metadata.title;
|
|
if (pcbdata.metadata.revision) {
|
|
filename += `.${pcbdata.metadata.revision}`;
|
|
}
|
|
filename += `.${layer}.png`;
|
|
saveFile(filename, dataURLtoBlob(imgdata));
|
|
}
|
|
|
|
function saveSettings() {
|
|
var data = {
|
|
type: "InteractiveHtmlBom settings",
|
|
version: 1,
|
|
pcbmetadata: pcbdata.metadata,
|
|
settings: settings,
|
|
}
|
|
var blob = new Blob([JSON.stringify(data, null, 4)], {
|
|
type: "application/json"
|
|
});
|
|
saveFile(`${pcbdata.metadata.title}.settings.json`, blob);
|
|
}
|
|
|
|
function loadSettings() {
|
|
var input = document.createElement("input");
|
|
input.type = "file";
|
|
input.accept = ".settings.json";
|
|
input.onchange = function (e) {
|
|
var file = e.target.files[0];
|
|
var reader = new FileReader();
|
|
reader.onload = readerEvent => {
|
|
var content = readerEvent.target.result;
|
|
var newSettings;
|
|
try {
|
|
newSettings = JSON.parse(content);
|
|
} catch (e) {
|
|
alert("Selected file is not InteractiveHtmlBom settings file.");
|
|
return;
|
|
}
|
|
if (newSettings.type != "InteractiveHtmlBom settings") {
|
|
alert("Selected file is not InteractiveHtmlBom settings file.");
|
|
return;
|
|
}
|
|
var metadataMatches = newSettings.hasOwnProperty("pcbmetadata");
|
|
if (metadataMatches) {
|
|
for (var k in pcbdata.metadata) {
|
|
if (!newSettings.pcbmetadata.hasOwnProperty(k) || newSettings.pcbmetadata[k] != pcbdata.metadata[k]) {
|
|
metadataMatches = false;
|
|
}
|
|
}
|
|
}
|
|
if (!metadataMatches) {
|
|
var currentMetadata = JSON.stringify(pcbdata.metadata, null, 4);
|
|
var fileMetadata = JSON.stringify(newSettings.pcbmetadata, null, 4);
|
|
if (!confirm(
|
|
`Settins file metadata does not match current metadata.\n\n` +
|
|
`Page metadata:\n${currentMetadata}\n\n` +
|
|
`Settings file metadata:\n${fileMetadata}\n\n` +
|
|
`Press OK if you would like to import settings anyway.`)) {
|
|
return;
|
|
}
|
|
}
|
|
overwriteSettings(newSettings.settings);
|
|
}
|
|
reader.readAsText(file, 'UTF-8');
|
|
}
|
|
input.click();
|
|
}
|
|
|
|
function resetSettings() {
|
|
if (!confirm(
|
|
`This will reset all checkbox states and other settings.\n\n` +
|
|
`Press OK if you want to continue.`)) {
|
|
return;
|
|
}
|
|
if (storage) {
|
|
var keys = [];
|
|
for (var i = 0; i < storage.length; i++) {
|
|
var key = storage.key(i);
|
|
if (key.startsWith(storagePrefix)) keys.push(key);
|
|
}
|
|
for (var key of keys) storage.removeItem(key);
|
|
}
|
|
location.reload();
|
|
}
|
|
|
|
function overwriteSettings(newSettings) {
|
|
initDone = false;
|
|
Object.assign(settings, newSettings);
|
|
writeStorage("bomlayout", settings.bomlayout);
|
|
writeStorage("bommode", settings.bommode);
|
|
writeStorage("canvaslayout", settings.canvaslayout);
|
|
writeStorage("bomCheckboxes", settings.checkboxes.join(","));
|
|
document.getElementById("bomCheckboxes").value = settings.checkboxes.join(",");
|
|
for (var checkbox of settings.checkboxes) {
|
|
writeStorage("checkbox_" + checkbox, settings.checkboxStoredRefs[checkbox]);
|
|
}
|
|
writeStorage("markWhenChecked", settings.markWhenChecked);
|
|
padsVisible(settings.renderPads);
|
|
document.getElementById("padsCheckbox").checked = settings.renderPads;
|
|
fabricationVisible(settings.renderFabrication);
|
|
document.getElementById("fabricationCheckbox").checked = settings.renderFabrication;
|
|
silkscreenVisible(settings.renderSilkscreen);
|
|
document.getElementById("silkscreenCheckbox").checked = settings.renderSilkscreen;
|
|
referencesVisible(settings.renderReferences);
|
|
document.getElementById("referencesCheckbox").checked = settings.renderReferences;
|
|
valuesVisible(settings.renderValues);
|
|
document.getElementById("valuesCheckbox").checked = settings.renderValues;
|
|
tracksVisible(settings.renderTracks);
|
|
document.getElementById("tracksCheckbox").checked = settings.renderTracks;
|
|
zonesVisible(settings.renderZones);
|
|
document.getElementById("zonesCheckbox").checked = settings.renderZones;
|
|
dnpOutline(settings.renderDnpOutline);
|
|
document.getElementById("dnpOutlineCheckbox").checked = settings.renderDnpOutline;
|
|
setRedrawOnDrag(settings.redrawOnDrag);
|
|
document.getElementById("dragCheckbox").checked = settings.redrawOnDrag;
|
|
setDarkMode(settings.darkMode);
|
|
document.getElementById("darkmodeCheckbox").checked = settings.darkMode;
|
|
setHighlightPin1(settings.highlightpin1);
|
|
document.forms.highlightpin1.highlightpin1.value = settings.highlightpin1;
|
|
writeStorage("boardRotation", settings.boardRotation);
|
|
document.getElementById("boardRotation").value = settings.boardRotation / 5;
|
|
document.getElementById("rotationDegree").textContent = settings.boardRotation;
|
|
setOffsetBackRotation(settings.offsetBackRotation);
|
|
document.getElementById("offsetBackRotationCheckbox").checked = settings.offsetBackRotation;
|
|
initDone = true;
|
|
prepCheckboxes();
|
|
changeBomLayout(settings.bomlayout);
|
|
}
|
|
|
|
function saveFile(filename, blob) {
|
|
var link = document.createElement("a");
|
|
var objurl = URL.createObjectURL(blob);
|
|
link.download = filename;
|
|
link.href = objurl;
|
|
link.click();
|
|
}
|
|
|
|
function dataURLtoBlob(dataurl) {
|
|
var arr = dataurl.split(','),
|
|
mime = arr[0].match(/:(.*?);/)[1],
|
|
bstr = atob(arr[1]),
|
|
n = bstr.length,
|
|
u8arr = new Uint8Array(n);
|
|
while (n--) {
|
|
u8arr[n] = bstr.charCodeAt(n);
|
|
}
|
|
return new Blob([u8arr], {
|
|
type: mime
|
|
});
|
|
}
|
|
|
|
var settings = {
|
|
canvaslayout: "FB",
|
|
bomlayout: "left-right",
|
|
bommode: "grouped",
|
|
checkboxes: [],
|
|
checkboxStoredRefs: {},
|
|
darkMode: false,
|
|
highlightpin1: "none",
|
|
redrawOnDrag: true,
|
|
boardRotation: 0,
|
|
offsetBackRotation: false,
|
|
renderPads: true,
|
|
renderReferences: true,
|
|
renderValues: true,
|
|
renderSilkscreen: true,
|
|
renderFabrication: true,
|
|
renderDnpOutline: false,
|
|
renderTracks: true,
|
|
renderZones: true,
|
|
columnOrder: [],
|
|
hiddenColumns: [],
|
|
netColors: {},
|
|
}
|
|
|
|
function initDefaults() {
|
|
settings.bomlayout = readStorage("bomlayout");
|
|
if (settings.bomlayout === null) {
|
|
settings.bomlayout = config.bom_view;
|
|
}
|
|
if (!['bom-only', 'left-right', 'top-bottom'].includes(settings.bomlayout)) {
|
|
settings.bomlayout = config.bom_view;
|
|
}
|
|
settings.bommode = readStorage("bommode");
|
|
if (settings.bommode === null) {
|
|
settings.bommode = "grouped";
|
|
}
|
|
if (settings.bommode == "netlist" && !pcbdata.nets) {
|
|
settings.bommode = "grouped";
|
|
}
|
|
if (!["grouped", "ungrouped", "netlist"].includes(settings.bommode)) {
|
|
settings.bommode = "grouped";
|
|
}
|
|
settings.canvaslayout = readStorage("canvaslayout");
|
|
if (settings.canvaslayout === null) {
|
|
settings.canvaslayout = config.layer_view;
|
|
}
|
|
var bomCheckboxes = readStorage("bomCheckboxes");
|
|
if (bomCheckboxes === null) {
|
|
bomCheckboxes = config.checkboxes;
|
|
}
|
|
settings.checkboxes = bomCheckboxes.split(",").filter((e) => e);
|
|
document.getElementById("bomCheckboxes").value = bomCheckboxes;
|
|
|
|
var highlightpin1 = readStorage("highlightpin1") || config.highlight_pin1;
|
|
if (highlightpin1 === "false") highlightpin1 = "none";
|
|
if (highlightpin1 === "true") highlightpin1 = "all";
|
|
setHighlightPin1(highlightpin1);
|
|
document.forms.highlightpin1.highlightpin1.value = highlightpin1;
|
|
|
|
settings.markWhenChecked = readStorage("markWhenChecked") || "";
|
|
populateMarkWhenCheckedOptions();
|
|
|
|
function initBooleanSetting(storageString, def, elementId, func) {
|
|
var b = readStorage(storageString);
|
|
if (b === null) {
|
|
b = def;
|
|
} else {
|
|
b = (b == "true");
|
|
}
|
|
document.getElementById(elementId).checked = b;
|
|
func(b);
|
|
}
|
|
|
|
initBooleanSetting("padsVisible", config.show_pads, "padsCheckbox", padsVisible);
|
|
initBooleanSetting("fabricationVisible", config.show_fabrication, "fabricationCheckbox", fabricationVisible);
|
|
initBooleanSetting("silkscreenVisible", config.show_silkscreen, "silkscreenCheckbox", silkscreenVisible);
|
|
initBooleanSetting("referencesVisible", true, "referencesCheckbox", referencesVisible);
|
|
initBooleanSetting("valuesVisible", true, "valuesCheckbox", valuesVisible);
|
|
if ("tracks" in pcbdata) {
|
|
initBooleanSetting("tracksVisible", true, "tracksCheckbox", tracksVisible);
|
|
initBooleanSetting("zonesVisible", true, "zonesCheckbox", zonesVisible);
|
|
} else {
|
|
document.getElementById("tracksAndZonesCheckboxes").style.display = "none";
|
|
tracksVisible(false);
|
|
zonesVisible(false);
|
|
}
|
|
initBooleanSetting("dnpOutline", false, "dnpOutlineCheckbox", dnpOutline);
|
|
initBooleanSetting("redrawOnDrag", config.redraw_on_drag, "dragCheckbox", setRedrawOnDrag);
|
|
initBooleanSetting("darkmode", config.dark_mode, "darkmodeCheckbox", setDarkMode);
|
|
|
|
var fields = ["checkboxes", "References"].concat(config.fields).concat(["Quantity"]);
|
|
var hcols = JSON.parse(readStorage("hiddenColumns"));
|
|
if (hcols === null) {
|
|
hcols = [];
|
|
}
|
|
settings.hiddenColumns = hcols.filter(e => fields.includes(e));
|
|
|
|
var cord = JSON.parse(readStorage("columnOrder"));
|
|
if (cord === null) {
|
|
cord = fields;
|
|
} else {
|
|
cord = cord.filter(e => fields.includes(e));
|
|
if (cord.length != fields.length)
|
|
cord = fields;
|
|
}
|
|
settings.columnOrder = cord;
|
|
|
|
settings.boardRotation = readStorage("boardRotation");
|
|
if (settings.boardRotation === null) {
|
|
settings.boardRotation = config.board_rotation * 5;
|
|
} else {
|
|
settings.boardRotation = parseInt(settings.boardRotation);
|
|
}
|
|
document.getElementById("boardRotation").value = settings.boardRotation / 5;
|
|
document.getElementById("rotationDegree").textContent = settings.boardRotation;
|
|
initBooleanSetting("offsetBackRotation", config.offset_back_rotation, "offsetBackRotationCheckbox", setOffsetBackRotation);
|
|
|
|
settings.netColors = JSON.parse(readStorage("netColors")) || {};
|
|
}
|
|
|
|
// Helper classes for user js callbacks.
|
|
|
|
const IBOM_EVENT_TYPES = {
|
|
ALL: "all",
|
|
HIGHLIGHT_EVENT: "highlightEvent",
|
|
CHECKBOX_CHANGE_EVENT: "checkboxChangeEvent",
|
|
BOM_BODY_CHANGE_EVENT: "bomBodyChangeEvent",
|
|
}
|
|
|
|
const EventHandler = {
|
|
callbacks: {},
|
|
init: function () {
|
|
for (eventType of Object.values(IBOM_EVENT_TYPES))
|
|
this.callbacks[eventType] = [];
|
|
},
|
|
registerCallback: function (eventType, callback) {
|
|
this.callbacks[eventType].push(callback);
|
|
},
|
|
emitEvent: function (eventType, eventArgs) {
|
|
event = {
|
|
eventType: eventType,
|
|
args: eventArgs,
|
|
}
|
|
var callback;
|
|
for (callback of this.callbacks[eventType])
|
|
callback(event);
|
|
for (callback of this.callbacks[IBOM_EVENT_TYPES.ALL])
|
|
callback(event);
|
|
}
|
|
}
|
|
EventHandler.init();
|
|
|
|
///////////////////////////////////////////////
|
|
|
|
///////////////////////////////////////////////
|
|
/* PCB rendering code */
|
|
|
|
var emptyContext2d = document.createElement("canvas").getContext("2d");
|
|
|
|
function deg2rad(deg) {
|
|
return deg * Math.PI / 180;
|
|
}
|
|
|
|
function calcFontPoint(linepoint, text, offsetx, offsety, tilt) {
|
|
var point = [
|
|
linepoint[0] * text.width + offsetx,
|
|
linepoint[1] * text.height + offsety
|
|
];
|
|
// This approximates pcbnew behavior with how text tilts depending on horizontal justification
|
|
point[0] -= (linepoint[1] + 0.5 * (1 + text.justify[0])) * text.height * tilt;
|
|
return point;
|
|
}
|
|
|
|
function drawText(ctx, text, color) {
|
|
if ("ref" in text && !settings.renderReferences) return;
|
|
if ("val" in text && !settings.renderValues) return;
|
|
ctx.save();
|
|
ctx.fillStyle = color;
|
|
ctx.strokeStyle = color;
|
|
ctx.lineCap = "round";
|
|
ctx.lineJoin = "round";
|
|
ctx.lineWidth = text.thickness;
|
|
if ("svgpath" in text) {
|
|
ctx.stroke(new Path2D(text.svgpath));
|
|
ctx.restore();
|
|
return;
|
|
}
|
|
if ("polygons" in text) {
|
|
ctx.fill(getPolygonsPath(text));
|
|
ctx.restore();
|
|
return;
|
|
}
|
|
ctx.translate(...text.pos);
|
|
ctx.translate(text.thickness * 0.5, 0);
|
|
var angle = -text.angle;
|
|
if (text.attr.includes("mirrored")) {
|
|
ctx.scale(-1, 1);
|
|
angle = -angle;
|
|
}
|
|
var tilt = 0;
|
|
if (text.attr.includes("italic")) {
|
|
tilt = 0.125;
|
|
}
|
|
var interline = text.height * 1.5 + text.thickness;
|
|
var txt = text.text.split("\n");
|
|
// KiCad ignores last empty line.
|
|
if (txt[txt.length - 1] == '') txt.pop();
|
|
ctx.rotate(deg2rad(angle));
|
|
var offsety = (1 - text.justify[1]) / 2 * text.height; // One line offset
|
|
offsety -= (txt.length - 1) * (text.justify[1] + 1) / 2 * interline; // Multiline offset
|
|
for (var i in txt) {
|
|
var lineWidth = text.thickness + interline / 2 * tilt;
|
|
for (var j = 0; j < txt[i].length; j++) {
|
|
if (txt[i][j] == '\t') {
|
|
var fourSpaces = 4 * pcbdata.font_data[' '].w * text.width;
|
|
lineWidth += fourSpaces - lineWidth % fourSpaces;
|
|
} else {
|
|
if (txt[i][j] == '~') {
|
|
j++;
|
|
if (j == txt[i].length)
|
|
break;
|
|
}
|
|
lineWidth += pcbdata.font_data[txt[i][j]].w * text.width;
|
|
}
|
|
}
|
|
var offsetx = -lineWidth * (text.justify[0] + 1) / 2;
|
|
var inOverbar = false;
|
|
for (var j = 0; j < txt[i].length; j++) {
|
|
if (config.kicad_text_formatting) {
|
|
if (txt[i][j] == '\t') {
|
|
var fourSpaces = 4 * pcbdata.font_data[' '].w * text.width;
|
|
offsetx += fourSpaces - offsetx % fourSpaces;
|
|
continue;
|
|
} else if (txt[i][j] == '~') {
|
|
j++;
|
|
if (j == txt[i].length)
|
|
break;
|
|
if (txt[i][j] != '~') {
|
|
inOverbar = !inOverbar;
|
|
}
|
|
}
|
|
}
|
|
var glyph = pcbdata.font_data[txt[i][j]];
|
|
if (inOverbar) {
|
|
var overbarStart = [offsetx, -text.height * 1.4 + offsety];
|
|
var overbarEnd = [offsetx + text.width * glyph.w, overbarStart[1]];
|
|
|
|
if (!lastHadOverbar) {
|
|
overbarStart[0] += text.height * 1.4 * tilt;
|
|
lastHadOverbar = true;
|
|
}
|
|
ctx.beginPath();
|
|
ctx.moveTo(...overbarStart);
|
|
ctx.lineTo(...overbarEnd);
|
|
ctx.stroke();
|
|
} else {
|
|
lastHadOverbar = false;
|
|
}
|
|
for (var line of glyph.l) {
|
|
ctx.beginPath();
|
|
ctx.moveTo(...calcFontPoint(line[0], text, offsetx, offsety, tilt));
|
|
for (var k = 1; k < line.length; k++) {
|
|
ctx.lineTo(...calcFontPoint(line[k], text, offsetx, offsety, tilt));
|
|
}
|
|
ctx.stroke();
|
|
}
|
|
offsetx += glyph.w * text.width;
|
|
}
|
|
offsety += interline;
|
|
}
|
|
ctx.restore();
|
|
}
|
|
|
|
function drawedge(ctx, scalefactor, edge, color) {
|
|
ctx.strokeStyle = color;
|
|
ctx.fillStyle = color;
|
|
ctx.lineWidth = Math.max(1 / scalefactor, edge.width);
|
|
ctx.lineCap = "round";
|
|
ctx.lineJoin = "round";
|
|
if ("svgpath" in edge) {
|
|
ctx.stroke(new Path2D(edge.svgpath));
|
|
} else {
|
|
ctx.beginPath();
|
|
if (edge.type == "segment") {
|
|
ctx.moveTo(...edge.start);
|
|
ctx.lineTo(...edge.end);
|
|
}
|
|
if (edge.type == "rect") {
|
|
ctx.moveTo(...edge.start);
|
|
ctx.lineTo(edge.start[0], edge.end[1]);
|
|
ctx.lineTo(...edge.end);
|
|
ctx.lineTo(edge.end[0], edge.start[1]);
|
|
ctx.lineTo(...edge.start);
|
|
}
|
|
if (edge.type == "arc") {
|
|
ctx.arc(
|
|
...edge.start,
|
|
edge.radius,
|
|
deg2rad(edge.startangle),
|
|
deg2rad(edge.endangle));
|
|
}
|
|
if (edge.type == "circle") {
|
|
ctx.arc(
|
|
...edge.start,
|
|
edge.radius,
|
|
0, 2 * Math.PI);
|
|
ctx.closePath();
|
|
}
|
|
if (edge.type == "curve") {
|
|
ctx.moveTo(...edge.start);
|
|
ctx.bezierCurveTo(...edge.cpa, ...edge.cpb, ...edge.end);
|
|
}
|
|
if("filled" in edge && edge.filled)
|
|
ctx.fill();
|
|
else
|
|
ctx.stroke();
|
|
}
|
|
}
|
|
|
|
function getChamferedRectPath(size, radius, chamfpos, chamfratio) {
|
|
// chamfpos is a bitmask, left = 1, right = 2, bottom left = 4, bottom right = 8
|
|
var path = new Path2D();
|
|
var width = size[0];
|
|
var height = size[1];
|
|
var x = width * -0.5;
|
|
var y = height * -0.5;
|
|
var chamfOffset = Math.min(width, height) * chamfratio;
|
|
path.moveTo(x, 0);
|
|
if (chamfpos & 4) {
|
|
path.lineTo(x, y + height - chamfOffset);
|
|
path.lineTo(x + chamfOffset, y + height);
|
|
path.lineTo(0, y + height);
|
|
} else {
|
|
path.arcTo(x, y + height, x + width, y + height, radius);
|
|
}
|
|
if (chamfpos & 8) {
|
|
path.lineTo(x + width - chamfOffset, y + height);
|
|
path.lineTo(x + width, y + height - chamfOffset);
|
|
path.lineTo(x + width, 0);
|
|
} else {
|
|
path.arcTo(x + width, y + height, x + width, y, radius);
|
|
}
|
|
if (chamfpos & 2) {
|
|
path.lineTo(x + width, y + chamfOffset);
|
|
path.lineTo(x + width - chamfOffset, y);
|
|
path.lineTo(0, y);
|
|
} else {
|
|
path.arcTo(x + width, y, x, y, radius);
|
|
}
|
|
if (chamfpos & 1) {
|
|
path.lineTo(x + chamfOffset, y);
|
|
path.lineTo(x, y + chamfOffset);
|
|
path.lineTo(x, 0);
|
|
} else {
|
|
path.arcTo(x, y, x, y + height, radius);
|
|
}
|
|
path.closePath();
|
|
return path;
|
|
}
|
|
|
|
function getOblongPath(size) {
|
|
return getChamferedRectPath(size, Math.min(size[0], size[1]) / 2, 0, 0);
|
|
}
|
|
|
|
function getPolygonsPath(shape) {
|
|
if (shape.path2d) {
|
|
return shape.path2d;
|
|
}
|
|
if ("svgpath" in shape) {
|
|
shape.path2d = new Path2D(shape.svgpath);
|
|
} else {
|
|
var path = new Path2D();
|
|
for (var polygon of shape.polygons) {
|
|
path.moveTo(...polygon[0]);
|
|
for (var i = 1; i < polygon.length; i++) {
|
|
path.lineTo(...polygon[i]);
|
|
}
|
|
path.closePath();
|
|
}
|
|
shape.path2d = path;
|
|
}
|
|
return shape.path2d;
|
|
}
|
|
|
|
function drawPolygonShape(ctx, scalefactor, shape, color) {
|
|
ctx.save();
|
|
if (!("svgpath" in shape)) {
|
|
ctx.translate(...shape.pos);
|
|
ctx.rotate(deg2rad(-shape.angle));
|
|
}
|
|
if("filled" in shape && !shape.filled) {
|
|
ctx.strokeStyle = color;
|
|
ctx.lineWidth = Math.max(1 / scalefactor, shape.width);
|
|
ctx.lineCap = "round";
|
|
ctx.lineJoin = "round";
|
|
ctx.stroke(getPolygonsPath(shape));
|
|
} else {
|
|
ctx.fillStyle = color;
|
|
ctx.fill(getPolygonsPath(shape));
|
|
}
|
|
ctx.restore();
|
|
}
|
|
|
|
function drawDrawing(ctx, scalefactor, drawing, color) {
|
|
if (["segment", "arc", "circle", "curve", "rect"].includes(drawing.type)) {
|
|
drawedge(ctx, scalefactor, drawing, color);
|
|
} else if (drawing.type == "polygon") {
|
|
drawPolygonShape(ctx, scalefactor, drawing, color);
|
|
} else {
|
|
drawText(ctx, drawing, color);
|
|
}
|
|
}
|
|
|
|
function getCirclePath(radius) {
|
|
var path = new Path2D();
|
|
path.arc(0, 0, radius, 0, 2 * Math.PI);
|
|
path.closePath();
|
|
return path;
|
|
}
|
|
|
|
function getCachedPadPath(pad) {
|
|
if (!pad.path2d) {
|
|
// if path2d is not set, build one and cache it on pad object
|
|
if (pad.shape == "rect") {
|
|
pad.path2d = new Path2D();
|
|
pad.path2d.rect(...pad.size.map(c => -c * 0.5), ...pad.size);
|
|
} else if (pad.shape == "oval") {
|
|
pad.path2d = getOblongPath(pad.size);
|
|
} else if (pad.shape == "circle") {
|
|
pad.path2d = getCirclePath(pad.size[0] / 2);
|
|
} else if (pad.shape == "roundrect") {
|
|
pad.path2d = getChamferedRectPath(pad.size, pad.radius, 0, 0);
|
|
} else if (pad.shape == "chamfrect") {
|
|
pad.path2d = getChamferedRectPath(pad.size, pad.radius, pad.chamfpos, pad.chamfratio)
|
|
} else if (pad.shape == "custom") {
|
|
pad.path2d = getPolygonsPath(pad);
|
|
}
|
|
}
|
|
return pad.path2d;
|
|
}
|
|
|
|
function drawPad(ctx, pad, color, outline) {
|
|
ctx.save();
|
|
ctx.translate(...pad.pos);
|
|
ctx.rotate(-deg2rad(pad.angle));
|
|
if (pad.offset) {
|
|
ctx.translate(...pad.offset);
|
|
}
|
|
ctx.fillStyle = color;
|
|
ctx.strokeStyle = color;
|
|
var path = getCachedPadPath(pad);
|
|
if (outline) {
|
|
ctx.stroke(path);
|
|
} else {
|
|
ctx.fill(path);
|
|
}
|
|
ctx.restore();
|
|
}
|
|
|
|
function drawPadHole(ctx, pad, padHoleColor) {
|
|
if (pad.type != "th") return;
|
|
ctx.save();
|
|
ctx.translate(...pad.pos);
|
|
ctx.rotate(-deg2rad(pad.angle));
|
|
ctx.fillStyle = padHoleColor;
|
|
if (pad.drillshape == "oblong") {
|
|
ctx.fill(getOblongPath(pad.drillsize));
|
|
} else {
|
|
ctx.fill(getCirclePath(pad.drillsize[0] / 2));
|
|
}
|
|
ctx.restore();
|
|
}
|
|
|
|
function drawFootprint(ctx, layer, scalefactor, footprint, colors, highlight, outline) {
|
|
if (highlight) {
|
|
// draw bounding box
|
|
if (footprint.layer == layer) {
|
|
ctx.save();
|
|
ctx.globalAlpha = 0.2;
|
|
ctx.translate(...footprint.bbox.pos);
|
|
ctx.rotate(deg2rad(-footprint.bbox.angle));
|
|
ctx.translate(...footprint.bbox.relpos);
|
|
ctx.fillStyle = colors.pad;
|
|
ctx.fillRect(0, 0, ...footprint.bbox.size);
|
|
ctx.globalAlpha = 1;
|
|
ctx.strokeStyle = colors.pad;
|
|
ctx.lineWidth = 3 / scalefactor;
|
|
ctx.strokeRect(0, 0, ...footprint.bbox.size);
|
|
ctx.restore();
|
|
}
|
|
}
|
|
// draw drawings
|
|
for (var drawing of footprint.drawings) {
|
|
if (drawing.layer == layer) {
|
|
drawDrawing(ctx, scalefactor, drawing.drawing, colors.pad);
|
|
}
|
|
}
|
|
ctx.lineWidth = 3 / scalefactor;
|
|
// draw pads
|
|
if (settings.renderPads) {
|
|
for (var pad of footprint.pads) {
|
|
if (pad.layers.includes(layer)) {
|
|
drawPad(ctx, pad, colors.pad, outline);
|
|
if (pad.pin1 &&
|
|
(settings.highlightpin1 == "all" ||
|
|
settings.highlightpin1 == "selected" && highlight)) {
|
|
drawPad(ctx, pad, colors.outline, true);
|
|
}
|
|
}
|
|
}
|
|
for (var pad of footprint.pads) {
|
|
drawPadHole(ctx, pad, colors.padHole);
|
|
}
|
|
}
|
|
}
|
|
|
|
function drawEdgeCuts(canvas, scalefactor) {
|
|
var ctx = canvas.getContext("2d");
|
|
var edgecolor = getComputedStyle(topmostdiv).getPropertyValue('--pcb-edge-color');
|
|
for (var edge of pcbdata.edges) {
|
|
drawDrawing(ctx, scalefactor, edge, edgecolor);
|
|
}
|
|
}
|
|
|
|
function drawFootprints(canvas, layer, scalefactor, highlight) {
|
|
var ctx = canvas.getContext("2d");
|
|
ctx.lineWidth = 3 / scalefactor;
|
|
var style = getComputedStyle(topmostdiv);
|
|
|
|
var colors = {
|
|
pad: style.getPropertyValue('--pad-color'),
|
|
padHole: style.getPropertyValue('--pad-hole-color'),
|
|
outline: style.getPropertyValue('--pin1-outline-color'),
|
|
}
|
|
|
|
for (var i = 0; i < pcbdata.footprints.length; i++) {
|
|
var mod = pcbdata.footprints[i];
|
|
var outline = settings.renderDnpOutline && pcbdata.bom.skipped.includes(i);
|
|
var h = highlightedFootprints.includes(i);
|
|
var d = markedFootprints.has(i);
|
|
if (highlight) {
|
|
if(h && d) {
|
|
colors.pad = style.getPropertyValue('--pad-color-highlight-both');
|
|
colors.outline = style.getPropertyValue('--pin1-outline-color-highlight-both');
|
|
} else if (h) {
|
|
colors.pad = style.getPropertyValue('--pad-color-highlight');
|
|
colors.outline = style.getPropertyValue('--pin1-outline-color-highlight');
|
|
} else if (d) {
|
|
colors.pad = style.getPropertyValue('--pad-color-highlight-marked');
|
|
colors.outline = style.getPropertyValue('--pin1-outline-color-highlight-marked');
|
|
}
|
|
}
|
|
if( h || d || !highlight) {
|
|
drawFootprint(ctx, layer, scalefactor, mod, colors, highlight, outline);
|
|
}
|
|
}
|
|
}
|
|
|
|
function drawBgLayer(layername, canvas, layer, scalefactor, edgeColor, polygonColor, textColor) {
|
|
var ctx = canvas.getContext("2d");
|
|
for (var d of pcbdata.drawings[layername][layer]) {
|
|
if (["segment", "arc", "circle", "curve", "rect"].includes(d.type)) {
|
|
drawedge(ctx, scalefactor, d, edgeColor);
|
|
} else if (d.type == "polygon") {
|
|
drawPolygonShape(ctx, scalefactor, d, polygonColor);
|
|
} else {
|
|
drawText(ctx, d, textColor);
|
|
}
|
|
}
|
|
}
|
|
|
|
function drawTracks(canvas, layer, defaultColor, highlight) {
|
|
ctx = canvas.getContext("2d");
|
|
ctx.lineCap = "round";
|
|
|
|
var hasHole = (track) => (
|
|
'drillsize' in track &&
|
|
track.start[0] == track.end[0] &&
|
|
track.start[1] == track.end[1]);
|
|
|
|
// First draw tracks and tented vias
|
|
for (var track of pcbdata.tracks[layer]) {
|
|
if (highlight && highlightedNet != track.net) continue;
|
|
if (!hasHole(track)) {
|
|
ctx.strokeStyle = highlight ? defaultColor : settings.netColors[track.net] || defaultColor;
|
|
ctx.lineWidth = track.width;
|
|
ctx.beginPath();
|
|
if ('radius' in track) {
|
|
ctx.arc(
|
|
...track.center,
|
|
track.radius,
|
|
deg2rad(track.startangle),
|
|
deg2rad(track.endangle));
|
|
} else {
|
|
ctx.moveTo(...track.start);
|
|
ctx.lineTo(...track.end);
|
|
}
|
|
ctx.stroke();
|
|
}
|
|
}
|
|
// Second pass to draw untented vias
|
|
var style = getComputedStyle(topmostdiv);
|
|
var holeColor = style.getPropertyValue('--pad-hole-color')
|
|
|
|
for (var track of pcbdata.tracks[layer]) {
|
|
if (highlight && highlightedNet != track.net) continue;
|
|
if (hasHole(track)) {
|
|
ctx.strokeStyle = highlight ? defaultColor : settings.netColors[track.net] || defaultColor;
|
|
ctx.lineWidth = track.width;
|
|
ctx.beginPath();
|
|
ctx.moveTo(...track.start);
|
|
ctx.lineTo(...track.end);
|
|
ctx.stroke();
|
|
ctx.strokeStyle = holeColor;
|
|
ctx.lineWidth = track.drillsize;
|
|
ctx.lineTo(...track.end);
|
|
ctx.stroke();
|
|
}
|
|
}
|
|
}
|
|
|
|
function drawZones(canvas, layer, defaultColor, highlight) {
|
|
ctx = canvas.getContext("2d");
|
|
ctx.lineJoin = "round";
|
|
for (var zone of pcbdata.zones[layer]) {
|
|
if (highlight && highlightedNet != zone.net) continue;
|
|
ctx.strokeStyle = highlight ? defaultColor : settings.netColors[zone.net] || defaultColor;
|
|
ctx.fillStyle = highlight ? defaultColor : settings.netColors[zone.net] || defaultColor;
|
|
if (!zone.path2d) {
|
|
zone.path2d = getPolygonsPath(zone);
|
|
}
|
|
ctx.fill(zone.path2d, zone.fillrule || "nonzero");
|
|
if (zone.width > 0) {
|
|
ctx.lineWidth = zone.width;
|
|
ctx.stroke(zone.path2d);
|
|
}
|
|
}
|
|
}
|
|
|
|
function clearCanvas(canvas, color = null) {
|
|
var ctx = canvas.getContext("2d");
|
|
ctx.save();
|
|
ctx.setTransform(1, 0, 0, 1, 0, 0);
|
|
if (color) {
|
|
ctx.fillStyle = color;
|
|
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
|
} else {
|
|
if (!window.matchMedia("print").matches)
|
|
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
}
|
|
ctx.restore();
|
|
}
|
|
|
|
function drawNets(canvas, layer, highlight) {
|
|
var style = getComputedStyle(topmostdiv);
|
|
if (settings.renderZones) {
|
|
var zoneColor = style.getPropertyValue(highlight ? '--zone-color-highlight' : '--zone-color');
|
|
drawZones(canvas, layer, zoneColor, highlight);
|
|
}
|
|
if (settings.renderTracks) {
|
|
var trackColor = style.getPropertyValue(highlight ? '--track-color-highlight' : '--track-color');
|
|
drawTracks(canvas, layer, trackColor, highlight);
|
|
}
|
|
if (highlight && settings.renderPads) {
|
|
var padColor = style.getPropertyValue('--pad-color-highlight');
|
|
var padHoleColor = style.getPropertyValue('--pad-hole-color');
|
|
var ctx = canvas.getContext("2d");
|
|
for (var footprint of pcbdata.footprints) {
|
|
// draw pads
|
|
var padDrawn = false;
|
|
for (var pad of footprint.pads) {
|
|
if (highlightedNet != pad.net) continue;
|
|
if (pad.layers.includes(layer)) {
|
|
drawPad(ctx, pad, padColor, false);
|
|
padDrawn = true;
|
|
}
|
|
}
|
|
if (padDrawn) {
|
|
// redraw all pad holes because some pads may overlap
|
|
for (var pad of footprint.pads) {
|
|
drawPadHole(ctx, pad, padHoleColor);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function drawHighlightsOnLayer(canvasdict, clear = true) {
|
|
if (clear) {
|
|
clearCanvas(canvasdict.highlight);
|
|
}
|
|
if (markedFootprints.size > 0 || highlightedFootprints.length > 0) {
|
|
drawFootprints(canvasdict.highlight, canvasdict.layer,
|
|
canvasdict.transform.s * canvasdict.transform.zoom, true);
|
|
}
|
|
if (highlightedNet !== null) {
|
|
drawNets(canvasdict.highlight, canvasdict.layer, true);
|
|
}
|
|
}
|
|
|
|
function drawHighlights() {
|
|
drawHighlightsOnLayer(allcanvas.front);
|
|
drawHighlightsOnLayer(allcanvas.back);
|
|
}
|
|
|
|
function drawBackground(canvasdict, clear = true) {
|
|
if (clear) {
|
|
clearCanvas(canvasdict.bg);
|
|
clearCanvas(canvasdict.fab);
|
|
clearCanvas(canvasdict.silk);
|
|
}
|
|
|
|
drawNets(canvasdict.bg, canvasdict.layer, false);
|
|
drawFootprints(canvasdict.bg, canvasdict.layer,
|
|
canvasdict.transform.s * canvasdict.transform.zoom, false);
|
|
|
|
drawEdgeCuts(canvasdict.bg, canvasdict.transform.s * canvasdict.transform.zoom);
|
|
|
|
var style = getComputedStyle(topmostdiv);
|
|
var edgeColor = style.getPropertyValue('--silkscreen-edge-color');
|
|
var polygonColor = style.getPropertyValue('--silkscreen-polygon-color');
|
|
var textColor = style.getPropertyValue('--silkscreen-text-color');
|
|
if (settings.renderSilkscreen) {
|
|
drawBgLayer(
|
|
"silkscreen", canvasdict.silk, canvasdict.layer,
|
|
canvasdict.transform.s * canvasdict.transform.zoom,
|
|
edgeColor, polygonColor, textColor);
|
|
}
|
|
edgeColor = style.getPropertyValue('--fabrication-edge-color');
|
|
polygonColor = style.getPropertyValue('--fabrication-polygon-color');
|
|
textColor = style.getPropertyValue('--fabrication-text-color');
|
|
if (settings.renderFabrication) {
|
|
drawBgLayer(
|
|
"fabrication", canvasdict.fab, canvasdict.layer,
|
|
canvasdict.transform.s * canvasdict.transform.zoom,
|
|
edgeColor, polygonColor, textColor);
|
|
}
|
|
}
|
|
|
|
function prepareCanvas(canvas, flip, transform) {
|
|
var ctx = canvas.getContext("2d");
|
|
ctx.setTransform(1, 0, 0, 1, 0, 0);
|
|
ctx.scale(transform.zoom, transform.zoom);
|
|
ctx.translate(transform.panx, transform.pany);
|
|
if (flip) {
|
|
ctx.scale(-1, 1);
|
|
}
|
|
ctx.translate(transform.x, transform.y);
|
|
ctx.rotate(deg2rad(settings.boardRotation + (flip && settings.offsetBackRotation ? - 180 : 0)));
|
|
ctx.scale(transform.s, transform.s);
|
|
}
|
|
|
|
function prepareLayer(canvasdict) {
|
|
var flip = (canvasdict.layer === "B");
|
|
for (var c of ["bg", "fab", "silk", "highlight"]) {
|
|
prepareCanvas(canvasdict[c], flip, canvasdict.transform);
|
|
}
|
|
}
|
|
|
|
function rotateVector(v, angle) {
|
|
angle = deg2rad(angle);
|
|
return [
|
|
v[0] * Math.cos(angle) - v[1] * Math.sin(angle),
|
|
v[0] * Math.sin(angle) + v[1] * Math.cos(angle)
|
|
];
|
|
}
|
|
|
|
function applyRotation(bbox, flip) {
|
|
var corners = [
|
|
[bbox.minx, bbox.miny],
|
|
[bbox.minx, bbox.maxy],
|
|
[bbox.maxx, bbox.miny],
|
|
[bbox.maxx, bbox.maxy],
|
|
];
|
|
corners = corners.map((v) => rotateVector(v, settings.boardRotation + (flip && settings.offsetBackRotation ? - 180 : 0)));
|
|
return {
|
|
minx: corners.reduce((a, v) => Math.min(a, v[0]), Infinity),
|
|
miny: corners.reduce((a, v) => Math.min(a, v[1]), Infinity),
|
|
maxx: corners.reduce((a, v) => Math.max(a, v[0]), -Infinity),
|
|
maxy: corners.reduce((a, v) => Math.max(a, v[1]), -Infinity),
|
|
}
|
|
}
|
|
|
|
function recalcLayerScale(layerdict, width, height) {
|
|
var flip = (layerdict.layer === "B");
|
|
var bbox = applyRotation(pcbdata.edges_bbox, flip);
|
|
var scalefactor = 0.98 * Math.min(
|
|
width / (bbox.maxx - bbox.minx),
|
|
height / (bbox.maxy - bbox.miny)
|
|
);
|
|
if (scalefactor < 0.1) {
|
|
scalefactor = 1;
|
|
}
|
|
layerdict.transform.s = scalefactor;
|
|
if (flip) {
|
|
layerdict.transform.x = -((bbox.maxx + bbox.minx) * scalefactor + width) * 0.5;
|
|
} else {
|
|
layerdict.transform.x = -((bbox.maxx + bbox.minx) * scalefactor - width) * 0.5;
|
|
}
|
|
layerdict.transform.y = -((bbox.maxy + bbox.miny) * scalefactor - height) * 0.5;
|
|
for (var c of ["bg", "fab", "silk", "highlight"]) {
|
|
canvas = layerdict[c];
|
|
canvas.width = width;
|
|
canvas.height = height;
|
|
canvas.style.width = (width / devicePixelRatio) + "px";
|
|
canvas.style.height = (height / devicePixelRatio) + "px";
|
|
}
|
|
}
|
|
|
|
function redrawCanvas(layerdict) {
|
|
prepareLayer(layerdict);
|
|
drawBackground(layerdict);
|
|
drawHighlightsOnLayer(layerdict);
|
|
}
|
|
|
|
function resizeCanvas(layerdict) {
|
|
var canvasdivid = {
|
|
"F": "frontcanvas",
|
|
"B": "backcanvas"
|
|
} [layerdict.layer];
|
|
var width = document.getElementById(canvasdivid).clientWidth * devicePixelRatio;
|
|
var height = document.getElementById(canvasdivid).clientHeight * devicePixelRatio;
|
|
recalcLayerScale(layerdict, width, height);
|
|
redrawCanvas(layerdict);
|
|
}
|
|
|
|
function resizeAll() {
|
|
resizeCanvas(allcanvas.front);
|
|
resizeCanvas(allcanvas.back);
|
|
}
|
|
|
|
function pointWithinDistanceToSegment(x, y, x1, y1, x2, y2, d) {
|
|
var A = x - x1;
|
|
var B = y - y1;
|
|
var C = x2 - x1;
|
|
var D = y2 - y1;
|
|
|
|
var dot = A * C + B * D;
|
|
var len_sq = C * C + D * D;
|
|
var dx, dy;
|
|
if (len_sq == 0) {
|
|
// start and end of the segment coincide
|
|
dx = x - x1;
|
|
dy = y - y1;
|
|
} else {
|
|
var param = dot / len_sq;
|
|
var xx, yy;
|
|
if (param < 0) {
|
|
xx = x1;
|
|
yy = y1;
|
|
} else if (param > 1) {
|
|
xx = x2;
|
|
yy = y2;
|
|
} else {
|
|
xx = x1 + param * C;
|
|
yy = y1 + param * D;
|
|
}
|
|
dx = x - xx;
|
|
dy = y - yy;
|
|
}
|
|
return dx * dx + dy * dy <= d * d;
|
|
}
|
|
|
|
function modulo(n, mod) {
|
|
return ((n % mod) + mod) % mod;
|
|
}
|
|
|
|
function pointWithinDistanceToArc(x, y, xc, yc, radius, startangle, endangle, d) {
|
|
var dx = x - xc;
|
|
var dy = y - yc;
|
|
var r_sq = dx * dx + dy * dy;
|
|
var rmin = Math.max(0, radius - d);
|
|
var rmax = radius + d;
|
|
|
|
if (r_sq < rmin * rmin || r_sq > rmax * rmax)
|
|
return false;
|
|
|
|
var angle1 = modulo(deg2rad(startangle), 2 * Math.PI);
|
|
var dx1 = xc + radius * Math.cos(angle1) - x;
|
|
var dy1 = yc + radius * Math.sin(angle1) - y;
|
|
if (dx1 * dx1 + dy1 * dy1 <= d * d)
|
|
return true;
|
|
|
|
var angle2 = modulo(deg2rad(endangle), 2 * Math.PI);
|
|
var dx2 = xc + radius * Math.cos(angle2) - x;
|
|
var dy2 = yc + radius * Math.sin(angle2) - y;
|
|
if (dx2 * dx2 + dy2 * dy2 <= d * d)
|
|
return true;
|
|
|
|
var angle = modulo(Math.atan2(dy, dx), 2 * Math.PI);
|
|
if (angle1 > angle2)
|
|
return (angle >= angle2 || angle <= angle1);
|
|
else
|
|
return (angle >= angle1 && angle <= angle2);
|
|
}
|
|
|
|
function pointWithinPad(x, y, pad) {
|
|
var v = [x - pad.pos[0], y - pad.pos[1]];
|
|
v = rotateVector(v, pad.angle);
|
|
if (pad.offset) {
|
|
v[0] -= pad.offset[0];
|
|
v[1] -= pad.offset[1];
|
|
}
|
|
return emptyContext2d.isPointInPath(getCachedPadPath(pad), ...v);
|
|
}
|
|
|
|
function netHitScan(layer, x, y) {
|
|
// Check track segments
|
|
if (settings.renderTracks && pcbdata.tracks) {
|
|
for (var track of pcbdata.tracks[layer]) {
|
|
if ('radius' in track) {
|
|
if (pointWithinDistanceToArc(x, y, ...track.center, track.radius, track.startangle, track.endangle, track.width / 2)) {
|
|
return track.net;
|
|
}
|
|
} else {
|
|
if (pointWithinDistanceToSegment(x, y, ...track.start, ...track.end, track.width / 2)) {
|
|
return track.net;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// Check pads
|
|
if (settings.renderPads) {
|
|
for (var footprint of pcbdata.footprints) {
|
|
for (var pad of footprint.pads) {
|
|
if (pad.layers.includes(layer) && pointWithinPad(x, y, pad)) {
|
|
return pad.net;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
function pointWithinFootprintBbox(x, y, bbox) {
|
|
var v = [x - bbox.pos[0], y - bbox.pos[1]];
|
|
v = rotateVector(v, bbox.angle);
|
|
return bbox.relpos[0] <= v[0] && v[0] <= bbox.relpos[0] + bbox.size[0] &&
|
|
bbox.relpos[1] <= v[1] && v[1] <= bbox.relpos[1] + bbox.size[1];
|
|
}
|
|
|
|
function bboxHitScan(layer, x, y) {
|
|
var result = [];
|
|
for (var i = 0; i < pcbdata.footprints.length; i++) {
|
|
var footprint = pcbdata.footprints[i];
|
|
if (footprint.layer == layer) {
|
|
if (pointWithinFootprintBbox(x, y, footprint.bbox)) {
|
|
result.push(i);
|
|
}
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
function handlePointerDown(e, layerdict) {
|
|
if (e.button != 0 && e.button != 1) {
|
|
return;
|
|
}
|
|
e.preventDefault();
|
|
e.stopPropagation();
|
|
|
|
if (!e.hasOwnProperty("offsetX")) {
|
|
// The polyfill doesn't set this properly
|
|
e.offsetX = e.pageX - e.currentTarget.offsetLeft;
|
|
e.offsetY = e.pageY - e.currentTarget.offsetTop;
|
|
}
|
|
|
|
layerdict.pointerStates[e.pointerId] = {
|
|
distanceTravelled: 0,
|
|
lastX: e.offsetX,
|
|
lastY: e.offsetY,
|
|
downTime: Date.now(),
|
|
};
|
|
}
|
|
|
|
function handleMouseClick(e, layerdict) {
|
|
if (!e.hasOwnProperty("offsetX")) {
|
|
// The polyfill doesn't set this properly
|
|
e.offsetX = e.pageX - e.currentTarget.offsetLeft;
|
|
e.offsetY = e.pageY - e.currentTarget.offsetTop;
|
|
}
|
|
|
|
var x = e.offsetX;
|
|
var y = e.offsetY;
|
|
var t = layerdict.transform;
|
|
var flip = layerdict.layer === "B";
|
|
if (flip) {
|
|
x = (devicePixelRatio * x / t.zoom - t.panx + t.x) / -t.s;
|
|
} else {
|
|
x = (devicePixelRatio * x / t.zoom - t.panx - t.x) / t.s;
|
|
}
|
|
y = (devicePixelRatio * y / t.zoom - t.y - t.pany) / t.s;
|
|
var v = rotateVector([x, y], -settings.boardRotation + (flip && settings.offsetBackRotation ? - 180 : 0));
|
|
if ("nets" in pcbdata) {
|
|
var net = netHitScan(layerdict.layer, ...v);
|
|
if (net !== highlightedNet) {
|
|
netClicked(net);
|
|
}
|
|
}
|
|
if (highlightedNet === null) {
|
|
var footprints = bboxHitScan(layerdict.layer, ...v);
|
|
if (footprints.length > 0) {
|
|
footprintsClicked(footprints);
|
|
}
|
|
}
|
|
}
|
|
|
|
function handlePointerLeave(e, layerdict) {
|
|
e.preventDefault();
|
|
e.stopPropagation();
|
|
|
|
if (!settings.redrawOnDrag) {
|
|
redrawCanvas(layerdict);
|
|
}
|
|
|
|
delete layerdict.pointerStates[e.pointerId];
|
|
}
|
|
|
|
function resetTransform(layerdict) {
|
|
layerdict.transform.panx = 0;
|
|
layerdict.transform.pany = 0;
|
|
layerdict.transform.zoom = 1;
|
|
redrawCanvas(layerdict);
|
|
}
|
|
|
|
function handlePointerUp(e, layerdict) {
|
|
if (!e.hasOwnProperty("offsetX")) {
|
|
// The polyfill doesn't set this properly
|
|
e.offsetX = e.pageX - e.currentTarget.offsetLeft;
|
|
e.offsetY = e.pageY - e.currentTarget.offsetTop;
|
|
}
|
|
|
|
e.preventDefault();
|
|
e.stopPropagation();
|
|
|
|
if (e.button == 2) {
|
|
// Reset pan and zoom on right click.
|
|
resetTransform(layerdict);
|
|
layerdict.anotherPointerTapped = false;
|
|
return;
|
|
}
|
|
|
|
// We haven't necessarily had a pointermove event since the interaction started, so make sure we update this now
|
|
var ptr = layerdict.pointerStates[e.pointerId];
|
|
ptr.distanceTravelled += Math.abs(e.offsetX - ptr.lastX) + Math.abs(e.offsetY - ptr.lastY);
|
|
|
|
if (e.button == 0 && ptr.distanceTravelled < 10 && Date.now() - ptr.downTime <= 500) {
|
|
if (Object.keys(layerdict.pointerStates).length == 1) {
|
|
if (layerdict.anotherPointerTapped) {
|
|
// This is the second pointer coming off of a two-finger tap
|
|
resetTransform(layerdict);
|
|
} else {
|
|
// This is just a regular tap
|
|
handleMouseClick(e, layerdict);
|
|
}
|
|
layerdict.anotherPointerTapped = false;
|
|
} else {
|
|
// This is the first finger coming off of what could become a two-finger tap
|
|
layerdict.anotherPointerTapped = true;
|
|
}
|
|
} else {
|
|
if (!settings.redrawOnDrag) {
|
|
redrawCanvas(layerdict);
|
|
}
|
|
layerdict.anotherPointerTapped = false;
|
|
}
|
|
|
|
delete layerdict.pointerStates[e.pointerId];
|
|
}
|
|
|
|
function handlePointerMove(e, layerdict) {
|
|
if (!layerdict.pointerStates.hasOwnProperty(e.pointerId)) {
|
|
return;
|
|
}
|
|
e.preventDefault();
|
|
e.stopPropagation();
|
|
|
|
if (!e.hasOwnProperty("offsetX")) {
|
|
// The polyfill doesn't set this properly
|
|
e.offsetX = e.pageX - e.currentTarget.offsetLeft;
|
|
e.offsetY = e.pageY - e.currentTarget.offsetTop;
|
|
}
|
|
|
|
var thisPtr = layerdict.pointerStates[e.pointerId];
|
|
|
|
var dx = e.offsetX - thisPtr.lastX;
|
|
var dy = e.offsetY - thisPtr.lastY;
|
|
|
|
// If this number is low on pointer up, we count the action as a click
|
|
thisPtr.distanceTravelled += Math.abs(dx) + Math.abs(dy);
|
|
|
|
if (Object.keys(layerdict.pointerStates).length == 1) {
|
|
// This is a simple drag
|
|
layerdict.transform.panx += devicePixelRatio * dx / layerdict.transform.zoom;
|
|
layerdict.transform.pany += devicePixelRatio * dy / layerdict.transform.zoom;
|
|
} else if (Object.keys(layerdict.pointerStates).length == 2) {
|
|
var otherPtr = Object.values(layerdict.pointerStates).filter((ptr) => ptr != thisPtr)[0];
|
|
|
|
var oldDist = Math.sqrt(Math.pow(thisPtr.lastX - otherPtr.lastX, 2) + Math.pow(thisPtr.lastY - otherPtr.lastY, 2));
|
|
var newDist = Math.sqrt(Math.pow(e.offsetX - otherPtr.lastX, 2) + Math.pow(e.offsetY - otherPtr.lastY, 2));
|
|
|
|
var scaleFactor = newDist / oldDist;
|
|
|
|
if (scaleFactor != NaN) {
|
|
layerdict.transform.zoom *= scaleFactor;
|
|
|
|
var zoomd = (1 - scaleFactor) / layerdict.transform.zoom;
|
|
layerdict.transform.panx += devicePixelRatio * otherPtr.lastX * zoomd;
|
|
layerdict.transform.pany += devicePixelRatio * otherPtr.lastY * zoomd;
|
|
}
|
|
}
|
|
|
|
thisPtr.lastX = e.offsetX;
|
|
thisPtr.lastY = e.offsetY;
|
|
|
|
if (settings.redrawOnDrag) {
|
|
redrawCanvas(layerdict);
|
|
}
|
|
}
|
|
|
|
function handleMouseWheel(e, layerdict) {
|
|
e.preventDefault();
|
|
e.stopPropagation();
|
|
var t = layerdict.transform;
|
|
var wheeldelta = e.deltaY;
|
|
if (e.deltaMode == 1) {
|
|
// FF only, scroll by lines
|
|
wheeldelta *= 30;
|
|
} else if (e.deltaMode == 2) {
|
|
wheeldelta *= 300;
|
|
}
|
|
var m = Math.pow(1.1, -wheeldelta / 40);
|
|
// Limit amount of zoom per tick.
|
|
if (m > 2) {
|
|
m = 2;
|
|
} else if (m < 0.5) {
|
|
m = 0.5;
|
|
}
|
|
t.zoom *= m;
|
|
var zoomd = (1 - m) / t.zoom;
|
|
t.panx += devicePixelRatio * e.offsetX * zoomd;
|
|
t.pany += devicePixelRatio * e.offsetY * zoomd;
|
|
redrawCanvas(layerdict);
|
|
}
|
|
|
|
function addMouseHandlers(div, layerdict) {
|
|
div.addEventListener("pointerdown", function(e) {
|
|
handlePointerDown(e, layerdict);
|
|
});
|
|
div.addEventListener("pointermove", function(e) {
|
|
handlePointerMove(e, layerdict);
|
|
});
|
|
div.addEventListener("pointerup", function(e) {
|
|
handlePointerUp(e, layerdict);
|
|
});
|
|
var pointerleave = function(e) {
|
|
handlePointerLeave(e, layerdict);
|
|
}
|
|
div.addEventListener("pointercancel", pointerleave);
|
|
div.addEventListener("pointerleave", pointerleave);
|
|
div.addEventListener("pointerout", pointerleave);
|
|
|
|
div.onwheel = function(e) {
|
|
handleMouseWheel(e, layerdict);
|
|
}
|
|
for (var element of [div, layerdict.bg, layerdict.fab, layerdict.silk, layerdict.highlight]) {
|
|
element.addEventListener("contextmenu", function(e) {
|
|
e.preventDefault();
|
|
}, false);
|
|
}
|
|
}
|
|
|
|
function setRedrawOnDrag(value) {
|
|
settings.redrawOnDrag = value;
|
|
writeStorage("redrawOnDrag", value);
|
|
}
|
|
|
|
function setBoardRotation(value) {
|
|
settings.boardRotation = value * 5;
|
|
writeStorage("boardRotation", settings.boardRotation);
|
|
document.getElementById("rotationDegree").textContent = settings.boardRotation;
|
|
resizeAll();
|
|
}
|
|
|
|
function setOffsetBackRotation(value) {
|
|
settings.offsetBackRotation = value;
|
|
writeStorage("offsetBackRotation", value);
|
|
resizeAll();
|
|
}
|
|
|
|
function initRender() {
|
|
allcanvas = {
|
|
front: {
|
|
transform: {
|
|
x: 0,
|
|
y: 0,
|
|
s: 1,
|
|
panx: 0,
|
|
pany: 0,
|
|
zoom: 1,
|
|
},
|
|
pointerStates: {},
|
|
anotherPointerTapped: false,
|
|
bg: document.getElementById("F_bg"),
|
|
fab: document.getElementById("F_fab"),
|
|
silk: document.getElementById("F_slk"),
|
|
highlight: document.getElementById("F_hl"),
|
|
layer: "F",
|
|
},
|
|
back: {
|
|
transform: {
|
|
x: 0,
|
|
y: 0,
|
|
s: 1,
|
|
panx: 0,
|
|
pany: 0,
|
|
zoom: 1,
|
|
},
|
|
pointerStates: {},
|
|
anotherPointerTapped: false,
|
|
bg: document.getElementById("B_bg"),
|
|
fab: document.getElementById("B_fab"),
|
|
silk: document.getElementById("B_slk"),
|
|
highlight: document.getElementById("B_hl"),
|
|
layer: "B",
|
|
}
|
|
};
|
|
addMouseHandlers(document.getElementById("frontcanvas"), allcanvas.front);
|
|
addMouseHandlers(document.getElementById("backcanvas"), allcanvas.back);
|
|
}
|
|
|
|
///////////////////////////////////////////////
|
|
|
|
///////////////////////////////////////////////
|
|
/*
|
|
* Table reordering via Drag'n'Drop
|
|
* Inspired by: https://htmldom.dev/drag-and-drop-table-column
|
|
*/
|
|
|
|
function setBomHandlers() {
|
|
|
|
const bom = document.getElementById('bomtable');
|
|
|
|
let dragName;
|
|
let placeHolderElements;
|
|
let draggingElement;
|
|
let forcePopulation;
|
|
let xOffset;
|
|
let yOffset;
|
|
let wasDragged;
|
|
|
|
const mouseUpHandler = function(e) {
|
|
// Delete dragging element
|
|
draggingElement.remove();
|
|
|
|
// Make BOM selectable again
|
|
bom.style.removeProperty("userSelect");
|
|
|
|
// Remove listeners
|
|
document.removeEventListener('mousemove', mouseMoveHandler);
|
|
document.removeEventListener('mouseup', mouseUpHandler);
|
|
|
|
if (wasDragged) {
|
|
// Redraw whole BOM
|
|
populateBomTable();
|
|
}
|
|
}
|
|
|
|
const mouseMoveHandler = function(e) {
|
|
// Notice the dragging
|
|
wasDragged = true;
|
|
|
|
// Make the dragged element visible
|
|
draggingElement.style.removeProperty("display");
|
|
|
|
// Set elements position to mouse position
|
|
draggingElement.style.left = `${e.screenX - xOffset}px`;
|
|
draggingElement.style.top = `${e.screenY - yOffset}px`;
|
|
|
|
// Forced redrawing of BOM table
|
|
if (forcePopulation) {
|
|
forcePopulation = false;
|
|
// Copy array
|
|
phe = Array.from(placeHolderElements);
|
|
// populate BOM table again
|
|
populateBomHeader(dragName, phe);
|
|
populateBomBody(dragName, phe);
|
|
}
|
|
|
|
// Set up array of hidden columns
|
|
var hiddenColumns = Array.from(settings.hiddenColumns);
|
|
// In the ungrouped mode, quantity don't exist
|
|
if (settings.bommode === "ungrouped")
|
|
hiddenColumns.push("Quantity");
|
|
// If no checkbox fields can be found, we consider them hidden
|
|
if (settings.checkboxes.length == 0)
|
|
hiddenColumns.push("checkboxes");
|
|
|
|
// Get table headers and group them into checkboxes, extrafields and normal headers
|
|
const bh = document.getElementById("bomhead");
|
|
headers = Array.from(bh.querySelectorAll("th"))
|
|
headers.shift() // numCol is not part of the columnOrder
|
|
headerGroups = []
|
|
lastCompoundClass = null;
|
|
for (i = 0; i < settings.columnOrder.length; i++) {
|
|
cElem = settings.columnOrder[i];
|
|
if (hiddenColumns.includes(cElem)) {
|
|
// Hidden columns appear as a dummy element
|
|
headerGroups.push([]);
|
|
continue;
|
|
}
|
|
elem = headers.filter(e => getColumnOrderName(e) === cElem)[0];
|
|
if (elem.classList.contains("bom-checkbox")) {
|
|
if (lastCompoundClass === "bom-checkbox") {
|
|
cbGroup = headerGroups.pop();
|
|
cbGroup.push(elem);
|
|
headerGroups.push(cbGroup);
|
|
} else {
|
|
lastCompoundClass = "bom-checkbox";
|
|
headerGroups.push([elem])
|
|
}
|
|
} else {
|
|
headerGroups.push([elem])
|
|
}
|
|
}
|
|
|
|
// Copy settings.columnOrder
|
|
var columns = Array.from(settings.columnOrder)
|
|
|
|
// Set up array with indices of hidden columns
|
|
var hiddenIndices = hiddenColumns.map(e => settings.columnOrder.indexOf(e));
|
|
var dragIndex = columns.indexOf(dragName);
|
|
var swapIndex = dragIndex;
|
|
var swapDone = false;
|
|
|
|
// Check if the current dragged element is swapable with the left or right element
|
|
if (dragIndex > 0) {
|
|
// Get left headers boundingbox
|
|
swapIndex = dragIndex - 1;
|
|
while (hiddenIndices.includes(swapIndex) && swapIndex > 0)
|
|
swapIndex--;
|
|
if (!hiddenIndices.includes(swapIndex)) {
|
|
box = getBoundingClientRectFromMultiple(headerGroups[swapIndex]);
|
|
if (e.clientX < box.left + window.scrollX + (box.width / 2)) {
|
|
swapElement = columns[dragIndex];
|
|
columns.splice(dragIndex, 1);
|
|
columns.splice(swapIndex, 0, swapElement);
|
|
forcePopulation = true;
|
|
swapDone = true;
|
|
}
|
|
}
|
|
}
|
|
if ((!swapDone) && dragIndex < headerGroups.length - 1) {
|
|
// Get right headers boundingbox
|
|
swapIndex = dragIndex + 1;
|
|
while (hiddenIndices.includes(swapIndex))
|
|
swapIndex++;
|
|
if (swapIndex < headerGroups.length) {
|
|
box = getBoundingClientRectFromMultiple(headerGroups[swapIndex]);
|
|
if (e.clientX > box.left + window.scrollX + (box.width / 2)) {
|
|
swapElement = columns[dragIndex];
|
|
columns.splice(dragIndex, 1);
|
|
columns.splice(swapIndex, 0, swapElement);
|
|
forcePopulation = true;
|
|
swapDone = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Write back change to storage
|
|
if (swapDone) {
|
|
settings.columnOrder = columns
|
|
writeStorage("columnOrder", JSON.stringify(columns));
|
|
}
|
|
|
|
}
|
|
|
|
const mouseDownHandler = function(e) {
|
|
var target = e.target;
|
|
if (target.tagName.toLowerCase() != "td")
|
|
target = target.parentElement;
|
|
|
|
// Used to check if a dragging has ever happened
|
|
wasDragged = false;
|
|
|
|
// Create new element which will be displayed as the dragged column
|
|
draggingElement = document.createElement("div")
|
|
draggingElement.classList.add("dragging");
|
|
draggingElement.style.display = "none";
|
|
draggingElement.style.position = "absolute";
|
|
draggingElement.style.overflow = "hidden";
|
|
|
|
// Get bomhead and bombody elements
|
|
const bh = document.getElementById("bomhead");
|
|
const bb = document.getElementById("bombody");
|
|
|
|
// Get all compound headers for the current column
|
|
var compoundHeaders;
|
|
if (target.classList.contains("bom-checkbox")) {
|
|
compoundHeaders = Array.from(bh.querySelectorAll("th.bom-checkbox"));
|
|
} else {
|
|
compoundHeaders = [target];
|
|
}
|
|
|
|
// Create new table which will display the column
|
|
var newTable = document.createElement("table");
|
|
newTable.classList.add("bom");
|
|
newTable.style.background = "white";
|
|
draggingElement.append(newTable);
|
|
|
|
// Create new header element
|
|
var newHeader = document.createElement("thead");
|
|
newTable.append(newHeader);
|
|
|
|
// Set up array for storing all placeholder elements
|
|
placeHolderElements = [];
|
|
|
|
// Add all compound headers to the new thead element and placeholders
|
|
compoundHeaders.forEach(function(h) {
|
|
clone = cloneElementWithDimensions(h);
|
|
newHeader.append(clone);
|
|
placeHolderElements.push(clone);
|
|
});
|
|
|
|
// Create new body element
|
|
var newBody = document.createElement("tbody");
|
|
newTable.append(newBody);
|
|
|
|
// Get indices for compound headers
|
|
var idxs = compoundHeaders.map(e => getBomTableHeaderIndex(e));
|
|
|
|
// For each row in the BOM body...
|
|
var rows = bb.querySelectorAll("tr");
|
|
rows.forEach(function(row) {
|
|
// ..get the cells for the compound column
|
|
const tds = row.querySelectorAll("td");
|
|
var copytds = idxs.map(i => tds[i]);
|
|
// Add them to the new element and the placeholders
|
|
var newRow = document.createElement("tr");
|
|
copytds.forEach(function(td) {
|
|
clone = cloneElementWithDimensions(td);
|
|
newRow.append(clone);
|
|
placeHolderElements.push(clone);
|
|
});
|
|
newBody.append(newRow);
|
|
});
|
|
|
|
// Compute width for compound header
|
|
var width = compoundHeaders.reduce((acc, x) => acc + x.clientWidth, 0);
|
|
draggingElement.style.width = `${width}px`;
|
|
|
|
// Insert the new dragging element and disable selection on BOM
|
|
bom.insertBefore(draggingElement, null);
|
|
bom.style.userSelect = "none";
|
|
|
|
// Determine the mouse position offset
|
|
xOffset = e.screenX - compoundHeaders.reduce((acc, x) => Math.min(acc, x.offsetLeft), compoundHeaders[0].offsetLeft);
|
|
yOffset = e.screenY - compoundHeaders[0].offsetTop;
|
|
|
|
// Get name for the column in settings.columnOrder
|
|
dragName = getColumnOrderName(target);
|
|
|
|
// Change text and class for placeholder elements
|
|
placeHolderElements = placeHolderElements.map(function(e) {
|
|
newElem = cloneElementWithDimensions(e);
|
|
newElem.textContent = "";
|
|
newElem.classList.add("placeholder");
|
|
return newElem;
|
|
});
|
|
|
|
// On next mouse move, the whole BOM needs to be redrawn to show the placeholders
|
|
forcePopulation = true;
|
|
|
|
// Add listeners for move and up on mouse
|
|
document.addEventListener('mousemove', mouseMoveHandler);
|
|
document.addEventListener('mouseup', mouseUpHandler);
|
|
}
|
|
|
|
// In netlist mode, there is nothing to reorder
|
|
if (settings.bommode === "netlist")
|
|
return;
|
|
|
|
// Add mouseDownHandler to every column except the numCol
|
|
bom.querySelectorAll("th")
|
|
.forEach(function(head) {
|
|
if (!head.classList.contains("numCol")) {
|
|
head.onmousedown = mouseDownHandler;
|
|
}
|
|
});
|
|
|
|
}
|
|
|
|
function getBoundingClientRectFromMultiple(elements) {
|
|
var elems = Array.from(elements);
|
|
|
|
if (elems.length == 0)
|
|
return null;
|
|
|
|
var box = elems.shift()
|
|
.getBoundingClientRect();
|
|
|
|
elems.forEach(function(elem) {
|
|
var elembox = elem.getBoundingClientRect();
|
|
box.left = Math.min(elembox.left, box.left);
|
|
box.top = Math.min(elembox.top, box.top);
|
|
box.width += elembox.width;
|
|
box.height = Math.max(elembox.height, box.height);
|
|
});
|
|
|
|
return box;
|
|
}
|
|
|
|
function cloneElementWithDimensions(elem) {
|
|
var newElem = elem.cloneNode(true);
|
|
newElem.style.height = window.getComputedStyle(elem).height;
|
|
newElem.style.width = window.getComputedStyle(elem).width;
|
|
return newElem;
|
|
}
|
|
|
|
function getBomTableHeaderIndex(elem) {
|
|
const bh = document.getElementById('bomhead');
|
|
const ths = Array.from(bh.querySelectorAll("th"));
|
|
return ths.indexOf(elem);
|
|
}
|
|
|
|
function getColumnOrderName(elem) {
|
|
var cname = elem.getAttribute("col_name");
|
|
if (cname === "bom-checkbox")
|
|
return "checkboxes";
|
|
else
|
|
return cname;
|
|
}
|
|
|
|
function resizableGrid(tablehead) {
|
|
var cols = tablehead.firstElementChild.children;
|
|
var rowWidth = tablehead.offsetWidth;
|
|
|
|
for (var i = 1; i < cols.length; i++) {
|
|
if (cols[i].classList.contains("bom-checkbox"))
|
|
continue;
|
|
cols[i].style.width = ((cols[i].clientWidth - paddingDiff(cols[i])) * 100 / rowWidth) + '%';
|
|
}
|
|
|
|
for (var i = 1; i < cols.length - 1; i++) {
|
|
var div = document.createElement('div');
|
|
div.className = "column-width-handle";
|
|
cols[i].appendChild(div);
|
|
setListeners(div);
|
|
}
|
|
|
|
function setListeners(div) {
|
|
var startX, curCol, nxtCol, curColWidth, nxtColWidth, rowWidth;
|
|
|
|
div.addEventListener('mousedown', function(e) {
|
|
e.preventDefault();
|
|
e.stopPropagation();
|
|
|
|
curCol = e.target.parentElement;
|
|
nxtCol = curCol.nextElementSibling;
|
|
startX = e.pageX;
|
|
|
|
var padding = paddingDiff(curCol);
|
|
|
|
rowWidth = curCol.parentElement.offsetWidth;
|
|
curColWidth = curCol.clientWidth - padding;
|
|
nxtColWidth = nxtCol.clientWidth - padding;
|
|
});
|
|
|
|
document.addEventListener('mousemove', function(e) {
|
|
if (startX) {
|
|
var diffX = e.pageX - startX;
|
|
diffX = -Math.min(-diffX, curColWidth - 20);
|
|
diffX = Math.min(diffX, nxtColWidth - 20);
|
|
|
|
curCol.style.width = ((curColWidth + diffX) * 100 / rowWidth) + '%';
|
|
nxtCol.style.width = ((nxtColWidth - diffX) * 100 / rowWidth) + '%';
|
|
console.log(`${curColWidth + nxtColWidth} ${(curColWidth + diffX) * 100 / rowWidth + (nxtColWidth - diffX) * 100 / rowWidth}`);
|
|
}
|
|
});
|
|
|
|
document.addEventListener('mouseup', function(e) {
|
|
curCol = undefined;
|
|
nxtCol = undefined;
|
|
startX = undefined;
|
|
nxtColWidth = undefined;
|
|
curColWidth = undefined
|
|
});
|
|
}
|
|
|
|
function paddingDiff(col) {
|
|
|
|
if (getStyleVal(col, 'box-sizing') == 'border-box') {
|
|
return 0;
|
|
}
|
|
|
|
var padLeft = getStyleVal(col, 'padding-left');
|
|
var padRight = getStyleVal(col, 'padding-right');
|
|
return (parseInt(padLeft) + parseInt(padRight));
|
|
|
|
}
|
|
|
|
function getStyleVal(elm, css) {
|
|
return (window.getComputedStyle(elm, null).getPropertyValue(css))
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////
|
|
|
|
///////////////////////////////////////////////
|
|
/* DOM manipulation and misc code */
|
|
|
|
var bomsplit;
|
|
var canvassplit;
|
|
var initDone = false;
|
|
var bomSortFunction = null;
|
|
var currentSortColumn = null;
|
|
var currentSortOrder = null;
|
|
var currentHighlightedRowId;
|
|
var highlightHandlers = [];
|
|
var footprintIndexToHandler = {};
|
|
var netsToHandler = {};
|
|
var markedFootprints = new Set();
|
|
var highlightedFootprints = [];
|
|
var highlightedNet = null;
|
|
var lastClicked;
|
|
|
|
function dbg(html) {
|
|
dbgdiv.innerHTML = html;
|
|
}
|
|
|
|
function redrawIfInitDone() {
|
|
if (initDone) {
|
|
redrawCanvas(allcanvas.front);
|
|
redrawCanvas(allcanvas.back);
|
|
}
|
|
}
|
|
|
|
function padsVisible(value) {
|
|
writeStorage("padsVisible", value);
|
|
settings.renderPads = value;
|
|
redrawIfInitDone();
|
|
}
|
|
|
|
function referencesVisible(value) {
|
|
writeStorage("referencesVisible", value);
|
|
settings.renderReferences = value;
|
|
redrawIfInitDone();
|
|
}
|
|
|
|
function valuesVisible(value) {
|
|
writeStorage("valuesVisible", value);
|
|
settings.renderValues = value;
|
|
redrawIfInitDone();
|
|
}
|
|
|
|
function tracksVisible(value) {
|
|
writeStorage("tracksVisible", value);
|
|
settings.renderTracks = value;
|
|
redrawIfInitDone();
|
|
}
|
|
|
|
function zonesVisible(value) {
|
|
writeStorage("zonesVisible", value);
|
|
settings.renderZones = value;
|
|
redrawIfInitDone();
|
|
}
|
|
|
|
function dnpOutline(value) {
|
|
writeStorage("dnpOutline", value);
|
|
settings.renderDnpOutline = value;
|
|
redrawIfInitDone();
|
|
}
|
|
|
|
function setDarkMode(value) {
|
|
if (value) {
|
|
topmostdiv.classList.add("dark");
|
|
} else {
|
|
topmostdiv.classList.remove("dark");
|
|
}
|
|
writeStorage("darkmode", value);
|
|
settings.darkMode = value;
|
|
redrawIfInitDone();
|
|
if (initDone) {
|
|
populateBomTable();
|
|
}
|
|
}
|
|
|
|
function setShowBOMColumn(field, value) {
|
|
if (field === "references") {
|
|
var rl = document.getElementById("reflookup");
|
|
rl.disabled = !value;
|
|
if (!value) {
|
|
rl.value = "";
|
|
updateRefLookup("");
|
|
}
|
|
}
|
|
|
|
var n = settings.hiddenColumns.indexOf(field);
|
|
if (value) {
|
|
if (n != -1) {
|
|
settings.hiddenColumns.splice(n, 1);
|
|
}
|
|
} else {
|
|
if (n == -1) {
|
|
settings.hiddenColumns.push(field);
|
|
}
|
|
}
|
|
|
|
writeStorage("hiddenColumns", JSON.stringify(settings.hiddenColumns));
|
|
|
|
if (initDone) {
|
|
populateBomTable();
|
|
}
|
|
|
|
redrawIfInitDone();
|
|
}
|
|
|
|
|
|
function setFullscreen(value) {
|
|
if (value) {
|
|
document.documentElement.requestFullscreen();
|
|
} else {
|
|
document.exitFullscreen();
|
|
}
|
|
}
|
|
|
|
function fabricationVisible(value) {
|
|
writeStorage("fabricationVisible", value);
|
|
settings.renderFabrication = value;
|
|
redrawIfInitDone();
|
|
}
|
|
|
|
function silkscreenVisible(value) {
|
|
writeStorage("silkscreenVisible", value);
|
|
settings.renderSilkscreen = value;
|
|
redrawIfInitDone();
|
|
}
|
|
|
|
function setHighlightPin1(value) {
|
|
writeStorage("highlightpin1", value);
|
|
settings.highlightpin1 = value;
|
|
redrawIfInitDone();
|
|
}
|
|
|
|
function getStoredCheckboxRefs(checkbox) {
|
|
function convert(ref) {
|
|
var intref = parseInt(ref);
|
|
if (isNaN(intref)) {
|
|
for (var i = 0; i < pcbdata.footprints.length; i++) {
|
|
if (pcbdata.footprints[i].ref == ref) {
|
|
return i;
|
|
}
|
|
}
|
|
return -1;
|
|
} else {
|
|
return intref;
|
|
}
|
|
}
|
|
if (!(checkbox in settings.checkboxStoredRefs)) {
|
|
var val = readStorage("checkbox_" + checkbox);
|
|
settings.checkboxStoredRefs[checkbox] = val ? val : "";
|
|
}
|
|
if (!settings.checkboxStoredRefs[checkbox]) {
|
|
return new Set();
|
|
} else {
|
|
return new Set(settings.checkboxStoredRefs[checkbox].split(",").map(r => convert(r)).filter(a => a >= 0));
|
|
}
|
|
}
|
|
|
|
function getCheckboxState(checkbox, references) {
|
|
var storedRefsSet = getStoredCheckboxRefs(checkbox);
|
|
var currentRefsSet = new Set(references.map(r => r[1]));
|
|
// Get difference of current - stored
|
|
var difference = new Set(currentRefsSet);
|
|
for (ref of storedRefsSet) {
|
|
difference.delete(ref);
|
|
}
|
|
if (difference.size == 0) {
|
|
// All the current refs are stored
|
|
return "checked";
|
|
} else if (difference.size == currentRefsSet.size) {
|
|
// None of the current refs are stored
|
|
return "unchecked";
|
|
} else {
|
|
// Some of the refs are stored
|
|
return "indeterminate";
|
|
}
|
|
}
|
|
|
|
function setBomCheckboxState(checkbox, element, references) {
|
|
var state = getCheckboxState(checkbox, references);
|
|
element.checked = (state == "checked");
|
|
element.indeterminate = (state == "indeterminate");
|
|
}
|
|
|
|
function createCheckboxChangeHandler(checkbox, references, row) {
|
|
return function () {
|
|
refsSet = getStoredCheckboxRefs(checkbox);
|
|
var markWhenChecked = settings.markWhenChecked == checkbox;
|
|
eventArgs = {
|
|
checkbox: checkbox,
|
|
refs: references,
|
|
}
|
|
if (this.checked) {
|
|
// checkbox ticked
|
|
for (var ref of references) {
|
|
refsSet.add(ref[1]);
|
|
}
|
|
if (markWhenChecked) {
|
|
row.classList.add("checked");
|
|
for (var ref of references) {
|
|
markedFootprints.add(ref[1]);
|
|
}
|
|
drawHighlights();
|
|
}
|
|
eventArgs.state = 'checked';
|
|
} else {
|
|
// checkbox unticked
|
|
for (var ref of references) {
|
|
refsSet.delete(ref[1]);
|
|
}
|
|
if (markWhenChecked) {
|
|
row.classList.remove("checked");
|
|
for (var ref of references) {
|
|
markedFootprints.delete(ref[1]);
|
|
}
|
|
drawHighlights();
|
|
}
|
|
eventArgs.state = 'unchecked';
|
|
}
|
|
settings.checkboxStoredRefs[checkbox] = [...refsSet].join(",");
|
|
writeStorage("checkbox_" + checkbox, settings.checkboxStoredRefs[checkbox]);
|
|
updateCheckboxStats(checkbox);
|
|
EventHandler.emitEvent(IBOM_EVENT_TYPES.CHECKBOX_CHANGE_EVENT, eventArgs);
|
|
}
|
|
}
|
|
|
|
function clearHighlightedFootprints() {
|
|
if (currentHighlightedRowId) {
|
|
document.getElementById(currentHighlightedRowId).classList.remove("highlighted");
|
|
currentHighlightedRowId = null;
|
|
highlightedFootprints = [];
|
|
highlightedNet = null;
|
|
}
|
|
}
|
|
|
|
function createRowHighlightHandler(rowid, refs, net) {
|
|
return function () {
|
|
if (currentHighlightedRowId) {
|
|
if (currentHighlightedRowId == rowid) {
|
|
return;
|
|
}
|
|
document.getElementById(currentHighlightedRowId).classList.remove("highlighted");
|
|
}
|
|
document.getElementById(rowid).classList.add("highlighted");
|
|
currentHighlightedRowId = rowid;
|
|
highlightedFootprints = refs ? refs.map(r => r[1]) : [];
|
|
highlightedNet = net;
|
|
drawHighlights();
|
|
EventHandler.emitEvent(
|
|
IBOM_EVENT_TYPES.HIGHLIGHT_EVENT, {
|
|
rowid: rowid,
|
|
refs: refs,
|
|
net: net
|
|
});
|
|
}
|
|
}
|
|
|
|
function updateNetColors() {
|
|
writeStorage("netColors", JSON.stringify(settings.netColors));
|
|
redrawIfInitDone();
|
|
}
|
|
|
|
function netColorChangeHandler(net) {
|
|
return (event) => {
|
|
settings.netColors[net] = event.target.value;
|
|
updateNetColors();
|
|
}
|
|
}
|
|
|
|
function netColorRightClick(net) {
|
|
return (event) => {
|
|
if(event.button == 2) {
|
|
event.preventDefault();
|
|
event.stopPropagation();
|
|
|
|
var style = getComputedStyle(topmostdiv);
|
|
var defaultNetColor = style.getPropertyValue('--track-color').trim();
|
|
event.target.value = defaultNetColor;
|
|
delete settings.netColors[net];
|
|
updateNetColors();
|
|
}
|
|
}
|
|
}
|
|
|
|
function entryMatches(entry) {
|
|
if (settings.bommode == "netlist") {
|
|
// entry is just a net name
|
|
return entry.toLowerCase().indexOf(filter) >= 0;
|
|
}
|
|
// check refs
|
|
if (!settings.hiddenColumns.includes("references")) {
|
|
for (var ref of entry) {
|
|
if (ref[0].toLowerCase().indexOf(filter) >= 0) {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
// check fields
|
|
for (var i in config.fields) {
|
|
var f = config.fields[i];
|
|
if (!settings.hiddenColumns.includes(f)) {
|
|
for (var ref of entry) {
|
|
if (String(pcbdata.bom.fields[ref[1]][i]).toLowerCase().indexOf(filter) >= 0) {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
function findRefInEntry(entry) {
|
|
return entry.filter(r => r[0].toLowerCase() == reflookup);
|
|
}
|
|
|
|
function highlightFilter(s) {
|
|
if (!filter) {
|
|
return s;
|
|
}
|
|
var parts = s.toLowerCase().split(filter);
|
|
if (parts.length == 1) {
|
|
return s;
|
|
}
|
|
var r = "";
|
|
var pos = 0;
|
|
for (var i in parts) {
|
|
if (i > 0) {
|
|
r += '<mark class="highlight">' +
|
|
s.substring(pos, pos + filter.length) +
|
|
'</mark>';
|
|
pos += filter.length;
|
|
}
|
|
r += s.substring(pos, pos + parts[i].length);
|
|
pos += parts[i].length;
|
|
}
|
|
return r;
|
|
}
|
|
|
|
function checkboxSetUnsetAllHandler(checkboxname) {
|
|
return function () {
|
|
var checkboxnum = 0;
|
|
while (checkboxnum < settings.checkboxes.length &&
|
|
settings.checkboxes[checkboxnum].toLowerCase() != checkboxname.toLowerCase()) {
|
|
checkboxnum++;
|
|
}
|
|
if (checkboxnum >= settings.checkboxes.length) {
|
|
return;
|
|
}
|
|
var allset = true;
|
|
var checkbox;
|
|
var row;
|
|
for (row of bombody.childNodes) {
|
|
checkbox = row.childNodes[checkboxnum + 1].childNodes[0];
|
|
if (!checkbox.checked || checkbox.indeterminate) {
|
|
allset = false;
|
|
break;
|
|
}
|
|
}
|
|
for (row of bombody.childNodes) {
|
|
checkbox = row.childNodes[checkboxnum + 1].childNodes[0];
|
|
checkbox.checked = !allset;
|
|
checkbox.indeterminate = false;
|
|
checkbox.onchange();
|
|
}
|
|
}
|
|
}
|
|
|
|
function createColumnHeader(name, cls, comparator, is_checkbox = false) {
|
|
var th = document.createElement("TH");
|
|
th.innerHTML = name;
|
|
th.classList.add(cls);
|
|
if (is_checkbox)
|
|
th.setAttribute("col_name", "bom-checkbox");
|
|
else
|
|
th.setAttribute("col_name", name);
|
|
var span = document.createElement("SPAN");
|
|
span.classList.add("sortmark");
|
|
span.classList.add("none");
|
|
th.appendChild(span);
|
|
var spacer = document.createElement("div");
|
|
spacer.className = "column-spacer";
|
|
th.appendChild(spacer);
|
|
spacer.onclick = function () {
|
|
if (currentSortColumn && th !== currentSortColumn) {
|
|
// Currently sorted by another column
|
|
currentSortColumn.childNodes[1].classList.remove(currentSortOrder);
|
|
currentSortColumn.childNodes[1].classList.add("none");
|
|
currentSortColumn = null;
|
|
currentSortOrder = null;
|
|
}
|
|
if (currentSortColumn && th === currentSortColumn) {
|
|
// Already sorted by this column
|
|
if (currentSortOrder == "asc") {
|
|
// Sort by this column, descending order
|
|
bomSortFunction = function (a, b) {
|
|
return -comparator(a, b);
|
|
}
|
|
currentSortColumn.childNodes[1].classList.remove("asc");
|
|
currentSortColumn.childNodes[1].classList.add("desc");
|
|
currentSortOrder = "desc";
|
|
} else {
|
|
// Unsort
|
|
bomSortFunction = null;
|
|
currentSortColumn.childNodes[1].classList.remove("desc");
|
|
currentSortColumn.childNodes[1].classList.add("none");
|
|
currentSortColumn = null;
|
|
currentSortOrder = null;
|
|
}
|
|
} else {
|
|
// Sort by this column, ascending order
|
|
bomSortFunction = comparator;
|
|
currentSortColumn = th;
|
|
currentSortColumn.childNodes[1].classList.remove("none");
|
|
currentSortColumn.childNodes[1].classList.add("asc");
|
|
currentSortOrder = "asc";
|
|
}
|
|
populateBomBody();
|
|
}
|
|
if (is_checkbox) {
|
|
spacer.onclick = fancyDblClickHandler(
|
|
spacer, spacer.onclick, checkboxSetUnsetAllHandler(name));
|
|
}
|
|
return th;
|
|
}
|
|
|
|
function populateBomHeader(placeHolderColumn = null, placeHolderElements = null) {
|
|
while (bomhead.firstChild) {
|
|
bomhead.removeChild(bomhead.firstChild);
|
|
}
|
|
var tr = document.createElement("TR");
|
|
var th = document.createElement("TH");
|
|
th.classList.add("numCol");
|
|
|
|
var vismenu = document.createElement("div");
|
|
vismenu.id = "vismenu";
|
|
vismenu.classList.add("menu");
|
|
|
|
var visbutton = document.createElement("div");
|
|
visbutton.classList.add("visbtn");
|
|
visbutton.classList.add("hideonprint");
|
|
|
|
var viscontent = document.createElement("div");
|
|
viscontent.classList.add("menu-content");
|
|
viscontent.id = "vismenu-content";
|
|
|
|
settings.columnOrder.forEach(column => {
|
|
if (typeof column !== "string")
|
|
return;
|
|
|
|
// Skip empty columns
|
|
if (column === "checkboxes" && settings.checkboxes.length == 0)
|
|
return;
|
|
else if (column === "Quantity" && settings.bommode == "ungrouped")
|
|
return;
|
|
|
|
var label = document.createElement("label");
|
|
label.classList.add("menu-label");
|
|
|
|
var input = document.createElement("input");
|
|
input.classList.add("visibility_checkbox");
|
|
input.type = "checkbox";
|
|
input.onchange = function (e) {
|
|
setShowBOMColumn(column, e.target.checked)
|
|
};
|
|
input.checked = !(settings.hiddenColumns.includes(column));
|
|
|
|
label.appendChild(input);
|
|
if (column.length > 0)
|
|
label.append(column[0].toUpperCase() + column.slice(1));
|
|
|
|
viscontent.appendChild(label);
|
|
});
|
|
|
|
viscontent.childNodes[0].classList.add("menu-label-top");
|
|
|
|
vismenu.appendChild(visbutton);
|
|
if (settings.bommode != "netlist") {
|
|
vismenu.appendChild(viscontent);
|
|
th.appendChild(vismenu);
|
|
}
|
|
tr.appendChild(th);
|
|
|
|
var checkboxCompareClosure = function (checkbox) {
|
|
return (a, b) => {
|
|
var stateA = getCheckboxState(checkbox, a);
|
|
var stateB = getCheckboxState(checkbox, b);
|
|
if (stateA > stateB) return -1;
|
|
if (stateA < stateB) return 1;
|
|
return 0;
|
|
}
|
|
}
|
|
var stringFieldCompareClosure = function (fieldIndex) {
|
|
return (a, b) => {
|
|
var fa = pcbdata.bom.fields[a[0][1]][fieldIndex];
|
|
var fb = pcbdata.bom.fields[b[0][1]][fieldIndex];
|
|
if (fa != fb) return fa > fb ? 1 : -1;
|
|
else return 0;
|
|
}
|
|
}
|
|
var referenceRegex = /(?<prefix>[^0-9]+)(?<number>[0-9]+)/;
|
|
var compareRefs = (a, b) => {
|
|
var ra = referenceRegex.exec(a);
|
|
var rb = referenceRegex.exec(b);
|
|
if (ra === null || rb === null) {
|
|
if (a != b) return a > b ? 1 : -1;
|
|
return 0;
|
|
} else {
|
|
if (ra.groups.prefix != rb.groups.prefix) {
|
|
return ra.groups.prefix > rb.groups.prefix ? 1 : -1;
|
|
}
|
|
if (ra.groups.number != rb.groups.number) {
|
|
return parseInt(ra.groups.number) > parseInt(rb.groups.number) ? 1 : -1;
|
|
}
|
|
return 0;
|
|
}
|
|
}
|
|
if (settings.bommode == "netlist") {
|
|
tr.appendChild(createColumnHeader("Net name", "bom-netname", (a, b) => {
|
|
if (a > b) return -1;
|
|
if (a < b) return 1;
|
|
return 0;
|
|
}));
|
|
tr.appendChild(createColumnHeader("Color", "bom-color", (a, b) => {
|
|
return 0;
|
|
}));
|
|
} else {
|
|
// Filter hidden columns
|
|
var columns = settings.columnOrder.filter(e => !settings.hiddenColumns.includes(e));
|
|
var valueIndex = config.fields.indexOf("Value");
|
|
var footprintIndex = config.fields.indexOf("Footprint");
|
|
columns.forEach((column) => {
|
|
if (column === placeHolderColumn) {
|
|
var n = 1;
|
|
if (column === "checkboxes")
|
|
n = settings.checkboxes.length;
|
|
for (i = 0; i < n; i++) {
|
|
td = placeHolderElements.shift();
|
|
tr.appendChild(td);
|
|
}
|
|
return;
|
|
} else if (column === "checkboxes") {
|
|
for (var checkbox of settings.checkboxes) {
|
|
th = createColumnHeader(
|
|
checkbox, "bom-checkbox", checkboxCompareClosure(checkbox), true);
|
|
tr.appendChild(th);
|
|
}
|
|
} else if (column === "References") {
|
|
tr.appendChild(createColumnHeader("References", "references", (a, b) => {
|
|
var i = 0;
|
|
while (i < a.length && i < b.length) {
|
|
if (a[i] != b[i]) return compareRefs(a[i][0], b[i][0]);
|
|
i++;
|
|
}
|
|
return a.length - b.length;
|
|
}));
|
|
} else if (column === "Value") {
|
|
tr.appendChild(createColumnHeader("Value", "value", (a, b) => {
|
|
var ra = a[0][1], rb = b[0][1];
|
|
return valueCompare(
|
|
pcbdata.bom.parsedValues[ra], pcbdata.bom.parsedValues[rb],
|
|
pcbdata.bom.fields[ra][valueIndex], pcbdata.bom.fields[rb][valueIndex]);
|
|
}));
|
|
return;
|
|
} else if (column === "Footprint") {
|
|
tr.appendChild(createColumnHeader(
|
|
"Footprint", "footprint", stringFieldCompareClosure(footprintIndex)));
|
|
} else if (column === "Quantity" && settings.bommode == "grouped") {
|
|
tr.appendChild(createColumnHeader("Quantity", "quantity", (a, b) => {
|
|
return a.length - b.length;
|
|
}));
|
|
} else {
|
|
// Other fields
|
|
var i = config.fields.indexOf(column);
|
|
if (i < 0)
|
|
return;
|
|
tr.appendChild(createColumnHeader(
|
|
column, `field${i + 1}`, stringFieldCompareClosure(i)));
|
|
}
|
|
});
|
|
}
|
|
bomhead.appendChild(tr);
|
|
}
|
|
|
|
function populateBomBody(placeholderColumn = null, placeHolderElements = null) {
|
|
const urlRegex = /^(https?:\/\/[^\s\/$.?#][^\s]*|file:\/\/([a-zA-Z]:|\/)[^\x00]+)$/;
|
|
while (bom.firstChild) {
|
|
bom.removeChild(bom.firstChild);
|
|
}
|
|
highlightHandlers = [];
|
|
footprintIndexToHandler = {};
|
|
netsToHandler = {};
|
|
currentHighlightedRowId = null;
|
|
var first = true;
|
|
var style = getComputedStyle(topmostdiv);
|
|
var defaultNetColor = style.getPropertyValue('--track-color').trim();
|
|
if (settings.bommode == "netlist") {
|
|
bomtable = pcbdata.nets.slice();
|
|
} else {
|
|
switch (settings.canvaslayout) {
|
|
case 'F':
|
|
bomtable = pcbdata.bom.F.slice();
|
|
break;
|
|
case 'FB':
|
|
bomtable = pcbdata.bom.both.slice();
|
|
break;
|
|
case 'B':
|
|
bomtable = pcbdata.bom.B.slice();
|
|
break;
|
|
}
|
|
if (settings.bommode == "ungrouped") {
|
|
// expand bom table
|
|
expandedTable = []
|
|
for (var bomentry of bomtable) {
|
|
for (var ref of bomentry) {
|
|
expandedTable.push([ref]);
|
|
}
|
|
}
|
|
bomtable = expandedTable;
|
|
}
|
|
}
|
|
if (bomSortFunction) {
|
|
bomtable = bomtable.sort(bomSortFunction);
|
|
}
|
|
for (var i in bomtable) {
|
|
var bomentry = bomtable[i];
|
|
if (filter && !entryMatches(bomentry)) {
|
|
continue;
|
|
}
|
|
var references = null;
|
|
var netname = null;
|
|
var tr = document.createElement("TR");
|
|
var td = document.createElement("TD");
|
|
var rownum = +i + 1;
|
|
tr.id = "bomrow" + rownum;
|
|
td.textContent = rownum;
|
|
tr.appendChild(td);
|
|
if (settings.bommode == "netlist") {
|
|
netname = bomentry;
|
|
td = document.createElement("TD");
|
|
td.innerHTML = highlightFilter(netname ? netname : "<no net>");
|
|
tr.appendChild(td);
|
|
var color = settings.netColors[netname] || defaultNetColor;
|
|
td = document.createElement("TD");
|
|
var colorBox = document.createElement("INPUT");
|
|
colorBox.type = "color";
|
|
colorBox.value = color;
|
|
colorBox.onchange = netColorChangeHandler(netname);
|
|
colorBox.onmouseup = netColorRightClick(netname);
|
|
colorBox.oncontextmenu = (e) => e.preventDefault();
|
|
td.appendChild(colorBox);
|
|
td.classList.add("color-column");
|
|
tr.appendChild(td);
|
|
} else {
|
|
if (reflookup) {
|
|
references = findRefInEntry(bomentry);
|
|
if (references.length == 0) {
|
|
continue;
|
|
}
|
|
} else {
|
|
references = bomentry;
|
|
}
|
|
// Filter hidden columns
|
|
var columns = settings.columnOrder.filter(e => !settings.hiddenColumns.includes(e));
|
|
columns.forEach((column) => {
|
|
if (column === placeholderColumn) {
|
|
var n = 1;
|
|
if (column === "checkboxes")
|
|
n = settings.checkboxes.length;
|
|
for (i = 0; i < n; i++) {
|
|
td = placeHolderElements.shift();
|
|
tr.appendChild(td);
|
|
}
|
|
return;
|
|
} else if (column === "checkboxes") {
|
|
for (var checkbox of settings.checkboxes) {
|
|
if (checkbox) {
|
|
td = document.createElement("TD");
|
|
var input = document.createElement("input");
|
|
input.type = "checkbox";
|
|
input.onchange = createCheckboxChangeHandler(checkbox, references, tr);
|
|
setBomCheckboxState(checkbox, input, references);
|
|
if (input.checked && settings.markWhenChecked == checkbox) {
|
|
tr.classList.add("checked");
|
|
}
|
|
td.appendChild(input);
|
|
tr.appendChild(td);
|
|
}
|
|
}
|
|
} else if (column === "References") {
|
|
td = document.createElement("TD");
|
|
td.innerHTML = highlightFilter(references.map(r => r[0]).join(", "));
|
|
tr.appendChild(td);
|
|
} else if (column === "Quantity" && settings.bommode == "grouped") {
|
|
// Quantity
|
|
td = document.createElement("TD");
|
|
td.textContent = references.length;
|
|
tr.appendChild(td);
|
|
} else {
|
|
// All the other fields
|
|
var field_index = config.fields.indexOf(column)
|
|
if (field_index < 0)
|
|
return;
|
|
var valueSet = new Set();
|
|
references.map(r => r[1]).forEach((id) => valueSet.add(pcbdata.bom.fields[id][field_index]));
|
|
td = document.createElement("TD");
|
|
var output = new Array();
|
|
for (let item of valueSet) {
|
|
const visible = highlightFilter(String(item));
|
|
if (typeof item === 'string' && item.match(urlRegex)) {
|
|
output.push(`<a href="${item}" target="_blank">${visible}</a>`);
|
|
} else {
|
|
output.push(visible);
|
|
}
|
|
}
|
|
td.innerHTML = output.join(", ");
|
|
tr.appendChild(td);
|
|
}
|
|
});
|
|
}
|
|
bom.appendChild(tr);
|
|
var handler = createRowHighlightHandler(tr.id, references, netname);
|
|
tr.onmousemove = handler;
|
|
highlightHandlers.push({
|
|
id: tr.id,
|
|
handler: handler,
|
|
});
|
|
if (references !== null) {
|
|
for (var refIndex of references.map(r => r[1])) {
|
|
footprintIndexToHandler[refIndex] = handler;
|
|
}
|
|
}
|
|
if (netname !== null) {
|
|
netsToHandler[netname] = handler;
|
|
}
|
|
if ((filter || reflookup) && first) {
|
|
handler();
|
|
first = false;
|
|
}
|
|
}
|
|
EventHandler.emitEvent(
|
|
IBOM_EVENT_TYPES.BOM_BODY_CHANGE_EVENT, {
|
|
filter: filter,
|
|
reflookup: reflookup,
|
|
checkboxes: settings.checkboxes,
|
|
bommode: settings.bommode,
|
|
});
|
|
}
|
|
|
|
function highlightPreviousRow() {
|
|
if (!currentHighlightedRowId) {
|
|
highlightHandlers[highlightHandlers.length - 1].handler();
|
|
} else {
|
|
if (highlightHandlers.length > 1 &&
|
|
highlightHandlers[0].id == currentHighlightedRowId) {
|
|
highlightHandlers[highlightHandlers.length - 1].handler();
|
|
} else {
|
|
for (var i = 0; i < highlightHandlers.length - 1; i++) {
|
|
if (highlightHandlers[i + 1].id == currentHighlightedRowId) {
|
|
highlightHandlers[i].handler();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
smoothScrollToRow(currentHighlightedRowId);
|
|
}
|
|
|
|
function highlightNextRow() {
|
|
if (!currentHighlightedRowId) {
|
|
highlightHandlers[0].handler();
|
|
} else {
|
|
if (highlightHandlers.length > 1 &&
|
|
highlightHandlers[highlightHandlers.length - 1].id == currentHighlightedRowId) {
|
|
highlightHandlers[0].handler();
|
|
} else {
|
|
for (var i = 1; i < highlightHandlers.length; i++) {
|
|
if (highlightHandlers[i - 1].id == currentHighlightedRowId) {
|
|
highlightHandlers[i].handler();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
smoothScrollToRow(currentHighlightedRowId);
|
|
}
|
|
|
|
function populateBomTable() {
|
|
populateBomHeader();
|
|
populateBomBody();
|
|
setBomHandlers();
|
|
resizableGrid(bomhead);
|
|
}
|
|
|
|
function footprintsClicked(footprintIndexes) {
|
|
var lastClickedIndex = footprintIndexes.indexOf(lastClicked);
|
|
for (var i = 1; i <= footprintIndexes.length; i++) {
|
|
var refIndex = footprintIndexes[(lastClickedIndex + i) % footprintIndexes.length];
|
|
if (refIndex in footprintIndexToHandler) {
|
|
lastClicked = refIndex;
|
|
footprintIndexToHandler[refIndex]();
|
|
smoothScrollToRow(currentHighlightedRowId);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
function netClicked(net) {
|
|
if (net in netsToHandler) {
|
|
netsToHandler[net]();
|
|
smoothScrollToRow(currentHighlightedRowId);
|
|
} else {
|
|
clearHighlightedFootprints();
|
|
highlightedNet = net;
|
|
drawHighlights();
|
|
}
|
|
}
|
|
|
|
function updateFilter(input) {
|
|
filter = input.toLowerCase();
|
|
populateBomTable();
|
|
}
|
|
|
|
function updateRefLookup(input) {
|
|
reflookup = input.toLowerCase();
|
|
populateBomTable();
|
|
}
|
|
|
|
function changeCanvasLayout(layout) {
|
|
document.getElementById("fl-btn").classList.remove("depressed");
|
|
document.getElementById("fb-btn").classList.remove("depressed");
|
|
document.getElementById("bl-btn").classList.remove("depressed");
|
|
switch (layout) {
|
|
case 'F':
|
|
document.getElementById("fl-btn").classList.add("depressed");
|
|
if (settings.bomlayout != "bom-only") {
|
|
canvassplit.collapse(1);
|
|
}
|
|
break;
|
|
case 'B':
|
|
document.getElementById("bl-btn").classList.add("depressed");
|
|
if (settings.bomlayout != "bom-only") {
|
|
canvassplit.collapse(0);
|
|
}
|
|
break;
|
|
default:
|
|
document.getElementById("fb-btn").classList.add("depressed");
|
|
if (settings.bomlayout != "bom-only") {
|
|
canvassplit.setSizes([50, 50]);
|
|
}
|
|
}
|
|
settings.canvaslayout = layout;
|
|
writeStorage("canvaslayout", layout);
|
|
resizeAll();
|
|
changeBomMode(settings.bommode);
|
|
}
|
|
|
|
function populateMetadata() {
|
|
document.getElementById("title").innerHTML = pcbdata.metadata.title;
|
|
document.getElementById("revision").innerHTML = "Rev: " + pcbdata.metadata.revision;
|
|
document.getElementById("company").innerHTML = pcbdata.metadata.company;
|
|
document.getElementById("filedate").innerHTML = pcbdata.metadata.date;
|
|
if (pcbdata.metadata.title != "") {
|
|
document.title = pcbdata.metadata.title + " BOM";
|
|
}
|
|
// Calculate board stats
|
|
var fp_f = 0,
|
|
fp_b = 0,
|
|
pads_f = 0,
|
|
pads_b = 0,
|
|
pads_th = 0;
|
|
for (var i = 0; i < pcbdata.footprints.length; i++) {
|
|
if (pcbdata.bom.skipped.includes(i)) continue;
|
|
var mod = pcbdata.footprints[i];
|
|
if (mod.layer == "F") {
|
|
fp_f++;
|
|
} else {
|
|
fp_b++;
|
|
}
|
|
for (var pad of mod.pads) {
|
|
if (pad.type == "th") {
|
|
pads_th++;
|
|
} else {
|
|
if (pad.layers.includes("F")) {
|
|
pads_f++;
|
|
}
|
|
if (pad.layers.includes("B")) {
|
|
pads_b++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
document.getElementById("stats-components-front").innerHTML = fp_f;
|
|
document.getElementById("stats-components-back").innerHTML = fp_b;
|
|
document.getElementById("stats-components-total").innerHTML = fp_f + fp_b;
|
|
document.getElementById("stats-groups-front").innerHTML = pcbdata.bom.F.length;
|
|
document.getElementById("stats-groups-back").innerHTML = pcbdata.bom.B.length;
|
|
document.getElementById("stats-groups-total").innerHTML = pcbdata.bom.both.length;
|
|
document.getElementById("stats-smd-pads-front").innerHTML = pads_f;
|
|
document.getElementById("stats-smd-pads-back").innerHTML = pads_b;
|
|
document.getElementById("stats-smd-pads-total").innerHTML = pads_f + pads_b;
|
|
document.getElementById("stats-th-pads").innerHTML = pads_th;
|
|
// Update version string
|
|
document.getElementById("github-link").innerHTML = "InteractiveHtmlBom " +
|
|
/^v\d+\.\d+/.exec(pcbdata.ibom_version)[0];
|
|
}
|
|
|
|
function changeBomLayout(layout) {
|
|
document.getElementById("bom-btn").classList.remove("depressed");
|
|
document.getElementById("lr-btn").classList.remove("depressed");
|
|
document.getElementById("tb-btn").classList.remove("depressed");
|
|
switch (layout) {
|
|
case 'bom-only':
|
|
document.getElementById("bom-btn").classList.add("depressed");
|
|
if (bomsplit) {
|
|
bomsplit.destroy();
|
|
bomsplit = null;
|
|
canvassplit.destroy();
|
|
canvassplit = null;
|
|
}
|
|
document.getElementById("frontcanvas").style.display = "none";
|
|
document.getElementById("backcanvas").style.display = "none";
|
|
document.getElementById("topmostdiv").style.height = "";
|
|
document.getElementById("topmostdiv").style.display = "block";
|
|
break;
|
|
case 'top-bottom':
|
|
document.getElementById("tb-btn").classList.add("depressed");
|
|
document.getElementById("frontcanvas").style.display = "";
|
|
document.getElementById("backcanvas").style.display = "";
|
|
document.getElementById("topmostdiv").style.height = "100%";
|
|
document.getElementById("topmostdiv").style.display = "flex";
|
|
document.getElementById("bomdiv").classList.remove("split-horizontal");
|
|
document.getElementById("canvasdiv").classList.remove("split-horizontal");
|
|
document.getElementById("frontcanvas").classList.add("split-horizontal");
|
|
document.getElementById("backcanvas").classList.add("split-horizontal");
|
|
if (bomsplit) {
|
|
bomsplit.destroy();
|
|
bomsplit = null;
|
|
canvassplit.destroy();
|
|
canvassplit = null;
|
|
}
|
|
bomsplit = Split(['#bomdiv', '#canvasdiv'], {
|
|
sizes: [50, 50],
|
|
onDragEnd: resizeAll,
|
|
direction: "vertical",
|
|
gutterSize: 5
|
|
});
|
|
canvassplit = Split(['#frontcanvas', '#backcanvas'], {
|
|
sizes: [50, 50],
|
|
gutterSize: 5,
|
|
onDragEnd: resizeAll
|
|
});
|
|
break;
|
|
case 'left-right':
|
|
document.getElementById("lr-btn").classList.add("depressed");
|
|
document.getElementById("frontcanvas").style.display = "";
|
|
document.getElementById("backcanvas").style.display = "";
|
|
document.getElementById("topmostdiv").style.height = "100%";
|
|
document.getElementById("topmostdiv").style.display = "flex";
|
|
document.getElementById("bomdiv").classList.add("split-horizontal");
|
|
document.getElementById("canvasdiv").classList.add("split-horizontal");
|
|
document.getElementById("frontcanvas").classList.remove("split-horizontal");
|
|
document.getElementById("backcanvas").classList.remove("split-horizontal");
|
|
if (bomsplit) {
|
|
bomsplit.destroy();
|
|
bomsplit = null;
|
|
canvassplit.destroy();
|
|
canvassplit = null;
|
|
}
|
|
bomsplit = Split(['#bomdiv', '#canvasdiv'], {
|
|
sizes: [50, 50],
|
|
onDragEnd: resizeAll,
|
|
gutterSize: 5
|
|
});
|
|
canvassplit = Split(['#frontcanvas', '#backcanvas'], {
|
|
sizes: [50, 50],
|
|
gutterSize: 5,
|
|
direction: "vertical",
|
|
onDragEnd: resizeAll
|
|
});
|
|
}
|
|
settings.bomlayout = layout;
|
|
writeStorage("bomlayout", layout);
|
|
changeCanvasLayout(settings.canvaslayout);
|
|
}
|
|
|
|
function changeBomMode(mode) {
|
|
document.getElementById("bom-grouped-btn").classList.remove("depressed");
|
|
document.getElementById("bom-ungrouped-btn").classList.remove("depressed");
|
|
document.getElementById("bom-netlist-btn").classList.remove("depressed");
|
|
var chkbxs = document.getElementsByClassName("visibility_checkbox");
|
|
|
|
switch (mode) {
|
|
case 'grouped':
|
|
document.getElementById("bom-grouped-btn").classList.add("depressed");
|
|
for (var i = 0; i < chkbxs.length; i++) {
|
|
chkbxs[i].disabled = false;
|
|
}
|
|
break;
|
|
case 'ungrouped':
|
|
document.getElementById("bom-ungrouped-btn").classList.add("depressed");
|
|
for (var i = 0; i < chkbxs.length; i++) {
|
|
chkbxs[i].disabled = false;
|
|
}
|
|
break;
|
|
case 'netlist':
|
|
document.getElementById("bom-netlist-btn").classList.add("depressed");
|
|
for (var i = 0; i < chkbxs.length; i++) {
|
|
chkbxs[i].disabled = true;
|
|
}
|
|
}
|
|
|
|
writeStorage("bommode", mode);
|
|
if (mode != settings.bommode) {
|
|
settings.bommode = mode;
|
|
bomSortFunction = null;
|
|
currentSortColumn = null;
|
|
currentSortOrder = null;
|
|
clearHighlightedFootprints();
|
|
}
|
|
populateBomTable();
|
|
}
|
|
|
|
function focusFilterField() {
|
|
focusInputField(document.getElementById("filter"));
|
|
}
|
|
|
|
function focusRefLookupField() {
|
|
focusInputField(document.getElementById("reflookup"));
|
|
}
|
|
|
|
function toggleBomCheckbox(bomrowid, checkboxnum) {
|
|
if (!bomrowid || checkboxnum > settings.checkboxes.length) {
|
|
return;
|
|
}
|
|
var bomrow = document.getElementById(bomrowid);
|
|
var checkbox = bomrow.childNodes[checkboxnum].childNodes[0];
|
|
checkbox.checked = !checkbox.checked;
|
|
checkbox.indeterminate = false;
|
|
checkbox.onchange();
|
|
}
|
|
|
|
function checkBomCheckbox(bomrowid, checkboxname) {
|
|
var checkboxnum = 0;
|
|
while (checkboxnum < settings.checkboxes.length &&
|
|
settings.checkboxes[checkboxnum].toLowerCase() != checkboxname.toLowerCase()) {
|
|
checkboxnum++;
|
|
}
|
|
if (!bomrowid || checkboxnum >= settings.checkboxes.length) {
|
|
return;
|
|
}
|
|
var bomrow = document.getElementById(bomrowid);
|
|
var checkbox = bomrow.childNodes[checkboxnum + 1].childNodes[0];
|
|
checkbox.checked = true;
|
|
checkbox.indeterminate = false;
|
|
checkbox.onchange();
|
|
}
|
|
|
|
function setBomCheckboxes(value) {
|
|
writeStorage("bomCheckboxes", value);
|
|
settings.checkboxes = value.split(",").map((e) => e.trim()).filter((e) => e);
|
|
prepCheckboxes();
|
|
populateMarkWhenCheckedOptions();
|
|
setMarkWhenChecked(settings.markWhenChecked);
|
|
}
|
|
|
|
function setMarkWhenChecked(value) {
|
|
writeStorage("markWhenChecked", value);
|
|
settings.markWhenChecked = value;
|
|
markedFootprints.clear();
|
|
for (var ref of (value ? getStoredCheckboxRefs(value) : [])) {
|
|
markedFootprints.add(ref);
|
|
}
|
|
populateBomTable();
|
|
drawHighlights();
|
|
}
|
|
|
|
function prepCheckboxes() {
|
|
var table = document.getElementById("checkbox-stats");
|
|
while (table.childElementCount > 1) {
|
|
table.removeChild(table.lastChild);
|
|
}
|
|
if (settings.checkboxes.length) {
|
|
table.style.display = "";
|
|
} else {
|
|
table.style.display = "none";
|
|
}
|
|
for (var checkbox of settings.checkboxes) {
|
|
var tr = document.createElement("TR");
|
|
var td = document.createElement("TD");
|
|
td.innerHTML = checkbox;
|
|
tr.appendChild(td);
|
|
td = document.createElement("TD");
|
|
td.id = "checkbox-stats-" + checkbox;
|
|
var progressbar = document.createElement("div");
|
|
progressbar.classList.add("bar");
|
|
td.appendChild(progressbar);
|
|
var text = document.createElement("div");
|
|
text.classList.add("text");
|
|
td.appendChild(text);
|
|
tr.appendChild(td);
|
|
table.appendChild(tr);
|
|
updateCheckboxStats(checkbox);
|
|
}
|
|
}
|
|
|
|
function populateMarkWhenCheckedOptions() {
|
|
var container = document.getElementById("markWhenCheckedContainer");
|
|
|
|
if (settings.checkboxes.length == 0) {
|
|
container.parentElement.style.display = "none";
|
|
return;
|
|
}
|
|
|
|
container.innerHTML = '';
|
|
container.parentElement.style.display = "inline-block";
|
|
|
|
function createOption(name, displayName) {
|
|
var id = "markWhenChecked-" + name;
|
|
|
|
var div = document.createElement("div");
|
|
div.classList.add("radio-container");
|
|
|
|
var input = document.createElement("input");
|
|
input.type = "radio";
|
|
input.name = "markWhenChecked";
|
|
input.value = name;
|
|
input.id = id;
|
|
input.onchange = () => setMarkWhenChecked(name);
|
|
div.appendChild(input);
|
|
|
|
// Preserve the selected element when the checkboxes change
|
|
if (name == settings.markWhenChecked) {
|
|
input.checked = true;
|
|
}
|
|
|
|
var label = document.createElement("label");
|
|
label.innerHTML = displayName;
|
|
label.htmlFor = id;
|
|
div.appendChild(label);
|
|
|
|
container.appendChild(div);
|
|
}
|
|
createOption("", "None");
|
|
for (var checkbox of settings.checkboxes) {
|
|
createOption(checkbox, checkbox);
|
|
}
|
|
}
|
|
|
|
function updateCheckboxStats(checkbox) {
|
|
var checked = getStoredCheckboxRefs(checkbox).size;
|
|
var total = pcbdata.footprints.length - pcbdata.bom.skipped.length;
|
|
var percent = checked * 100.0 / total;
|
|
var td = document.getElementById("checkbox-stats-" + checkbox);
|
|
td.firstChild.style.width = percent + "%";
|
|
td.lastChild.innerHTML = checked + "/" + total + " (" + Math.round(percent) + "%)";
|
|
}
|
|
|
|
function constrain(number, min, max){
|
|
return Math.min(Math.max(parseInt(number), min), max);
|
|
}
|
|
|
|
document.onkeydown = function (e) {
|
|
switch (e.key) {
|
|
case "n":
|
|
if (document.activeElement.type == "text") {
|
|
return;
|
|
}
|
|
if (currentHighlightedRowId !== null) {
|
|
checkBomCheckbox(currentHighlightedRowId, "placed");
|
|
highlightNextRow();
|
|
e.preventDefault();
|
|
}
|
|
break;
|
|
case "ArrowUp":
|
|
highlightPreviousRow();
|
|
e.preventDefault();
|
|
break;
|
|
case "ArrowDown":
|
|
highlightNextRow();
|
|
e.preventDefault();
|
|
break;
|
|
case "ArrowLeft":
|
|
case "ArrowRight":
|
|
if (document.activeElement.type != "text"){
|
|
e.preventDefault();
|
|
let boardRotationElement = document.getElementById("boardRotation")
|
|
settings.boardRotation = parseInt(boardRotationElement.value); // degrees / 5
|
|
if (e.key == "ArrowLeft"){
|
|
settings.boardRotation += 3; // 15 degrees
|
|
}
|
|
else{
|
|
settings.boardRotation -= 3;
|
|
}
|
|
settings.boardRotation = constrain(settings.boardRotation, boardRotationElement.min, boardRotationElement.max);
|
|
boardRotationElement.value = settings.boardRotation
|
|
setBoardRotation(settings.boardRotation);
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
if (e.altKey) {
|
|
switch (e.key) {
|
|
case "f":
|
|
focusFilterField();
|
|
e.preventDefault();
|
|
break;
|
|
case "r":
|
|
focusRefLookupField();
|
|
e.preventDefault();
|
|
break;
|
|
case "z":
|
|
changeBomLayout("bom-only");
|
|
e.preventDefault();
|
|
break;
|
|
case "x":
|
|
changeBomLayout("left-right");
|
|
e.preventDefault();
|
|
break;
|
|
case "c":
|
|
changeBomLayout("top-bottom");
|
|
e.preventDefault();
|
|
break;
|
|
case "v":
|
|
changeCanvasLayout("F");
|
|
e.preventDefault();
|
|
break;
|
|
case "b":
|
|
changeCanvasLayout("FB");
|
|
e.preventDefault();
|
|
break;
|
|
case "n":
|
|
changeCanvasLayout("B");
|
|
e.preventDefault();
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
if (e.key >= '1' && e.key <= '9') {
|
|
toggleBomCheckbox(currentHighlightedRowId, parseInt(e.key));
|
|
e.preventDefault();
|
|
}
|
|
}
|
|
}
|
|
|
|
function hideNetlistButton() {
|
|
document.getElementById("bom-ungrouped-btn").classList.remove("middle-button");
|
|
document.getElementById("bom-ungrouped-btn").classList.add("right-most-button");
|
|
document.getElementById("bom-netlist-btn").style.display = "none";
|
|
}
|
|
|
|
function topToggle() {
|
|
var top = document.getElementById("top");
|
|
var toptoggle = document.getElementById("toptoggle");
|
|
if (top.style.display === "none") {
|
|
top.style.display = "flex";
|
|
toptoggle.classList.remove("flipped");
|
|
} else {
|
|
top.style.display = "none";
|
|
toptoggle.classList.add("flipped");
|
|
}
|
|
}
|
|
|
|
window.onload = function (e) {
|
|
initUtils();
|
|
initRender();
|
|
initStorage();
|
|
initDefaults();
|
|
cleanGutters();
|
|
populateMetadata();
|
|
dbgdiv = document.getElementById("dbg");
|
|
bom = document.getElementById("bombody");
|
|
bomhead = document.getElementById("bomhead");
|
|
filter = "";
|
|
reflookup = "";
|
|
if (!("nets" in pcbdata)) {
|
|
hideNetlistButton();
|
|
}
|
|
initDone = true;
|
|
setBomCheckboxes(document.getElementById("bomCheckboxes").value);
|
|
// Triggers render
|
|
changeBomLayout(settings.bomlayout);
|
|
|
|
// Users may leave fullscreen without touching the checkbox. Uncheck.
|
|
document.addEventListener('fullscreenchange', () => {
|
|
if (!document.fullscreenElement)
|
|
document.getElementById('fullscreenCheckbox').checked = false;
|
|
});
|
|
}
|
|
|
|
window.onresize = resizeAll;
|
|
window.matchMedia("print").addListener(resizeAll);
|
|
|
|
///////////////////////////////////////////////
|
|
|
|
///////////////////////////////////////////////
|
|
// EventHandler.registerCallback(IBOM_EVENT_TYPES.BOM_BODY_CHANGE_EVENT, () => {
|
|
// for(var tr of bom.childNodes) {
|
|
// tr.onclick = tr.onmousemove;
|
|
// tr.onmousemove = null;
|
|
// };
|
|
// });
|
|
|
|
///////////////////////////////////////////////
|
|
</script>
|
|
</head>
|
|
|
|
<body>
|
|
|
|
<div id="topmostdiv" class="topmostdiv">
|
|
<div id="top">
|
|
<div id="fileinfodiv">
|
|
<table class="fileinfo">
|
|
<tbody>
|
|
<tr>
|
|
<td id="title" class="title" style="width: 70%">
|
|
Title
|
|
</td>
|
|
<td id="revision" class="title" style="width: 30%">
|
|
Revision
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td id="company">
|
|
Company
|
|
</td>
|
|
<td id="filedate">
|
|
Date
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
<div id="bomcontrols">
|
|
<div class="hideonprint menu">
|
|
<button class="menubtn"></button>
|
|
<div class="menu-content">
|
|
<label class="menu-label menu-label-top" style="width: calc(50% - 18px)">
|
|
<input id="darkmodeCheckbox" type="checkbox" onchange="setDarkMode(this.checked)">
|
|
Dark mode
|
|
</label><!-- This comment eats space! All of it!
|
|
--><label class="menu-label menu-label-top" style="width: calc(50% - 17px); border-left: 0;">
|
|
<input id="fullscreenCheckbox" type="checkbox" onchange="setFullscreen(this.checked)">
|
|
Full Screen
|
|
</label>
|
|
<label class="menu-label" style="width: calc(50% - 18px)">
|
|
<input id="fabricationCheckbox" type="checkbox" checked onchange="fabricationVisible(this.checked)">
|
|
Fab layer
|
|
</label><!-- This comment eats space! All of it!
|
|
--><label class="menu-label" style="width: calc(50% - 17px); border-left: 0;">
|
|
<input id="silkscreenCheckbox" type="checkbox" checked onchange="silkscreenVisible(this.checked)">
|
|
Silkscreen
|
|
</label>
|
|
<label class="menu-label" style="width: calc(50% - 18px)">
|
|
<input id="referencesCheckbox" type="checkbox" checked onchange="referencesVisible(this.checked)">
|
|
References
|
|
</label><!-- This comment eats space! All of it!
|
|
--><label class="menu-label" style="width: calc(50% - 17px); border-left: 0;">
|
|
<input id="valuesCheckbox" type="checkbox" checked onchange="valuesVisible(this.checked)">
|
|
Values
|
|
</label>
|
|
<div id="tracksAndZonesCheckboxes">
|
|
<label class="menu-label" style="width: calc(50% - 18px)">
|
|
<input id="tracksCheckbox" type="checkbox" checked onchange="tracksVisible(this.checked)">
|
|
Tracks
|
|
</label><!-- This comment eats space! All of it!
|
|
--><label class="menu-label" style="width: calc(50% - 17px); border-left: 0;">
|
|
<input id="zonesCheckbox" type="checkbox" checked onchange="zonesVisible(this.checked)">
|
|
Zones
|
|
</label>
|
|
</div>
|
|
<label class="menu-label" style="width: calc(50% - 18px)">
|
|
<input id="padsCheckbox" type="checkbox" checked onchange="padsVisible(this.checked)">
|
|
Pads
|
|
</label><!-- This comment eats space! All of it!
|
|
--><label class="menu-label" style="width: calc(50% - 17px); border-left: 0;">
|
|
<input id="dnpOutlineCheckbox" type="checkbox" checked onchange="dnpOutline(this.checked)">
|
|
DNP outlined
|
|
</label>
|
|
<label class="menu-label">
|
|
<input id="dragCheckbox" type="checkbox" checked onchange="setRedrawOnDrag(this.checked)">
|
|
Continuous redraw on drag
|
|
</label>
|
|
<label class="menu-label">
|
|
Highlight first pin
|
|
<form id="highlightpin1">
|
|
<div class="flexbox">
|
|
<label>
|
|
<input type="radio" name="highlightpin1" value="none" onchange="setHighlightPin1('none')">
|
|
None
|
|
</label>
|
|
<label>
|
|
<input type="radio" name="highlightpin1" value="all" onchange="setHighlightPin1('all')">
|
|
All
|
|
</label>
|
|
<label>
|
|
<input type="radio" name="highlightpin1" value="selected" onchange="setHighlightPin1('selected')">
|
|
Selected
|
|
</label>
|
|
</div>
|
|
</form>
|
|
</label>
|
|
<label class="menu-label">
|
|
<span>Board rotation</span>
|
|
<span style="float: right"><span id="rotationDegree">0</span>°</span>
|
|
<input id="boardRotation" type="range" min="-36" max="36" value="0" class="slider" oninput="setBoardRotation(this.value)">
|
|
</label>
|
|
<label class="menu-label">
|
|
<input id="offsetBackRotationCheckbox" type="checkbox" onchange="setOffsetBackRotation(this.checked)">
|
|
Offset back rotation
|
|
</label>
|
|
<label class="menu-label">
|
|
<div style="margin-left: 5px">Bom checkboxes</div>
|
|
<input id="bomCheckboxes" class="menu-textbox" type=text
|
|
oninput="setBomCheckboxes(this.value)">
|
|
</label>
|
|
<label class="menu-label">
|
|
<div style="margin-left: 5px">Mark when checked</div>
|
|
<div id="markWhenCheckedContainer"></div>
|
|
</label>
|
|
<label class="menu-label">
|
|
<span class="shameless-plug">
|
|
<span>Created using</span>
|
|
<a id="github-link" target="blank" href="https://github.com/openscopeproject/InteractiveHtmlBom">InteractiveHtmlBom</a>
|
|
<a target="blank" title="Mouse and keyboard help" href="https://github.com/openscopeproject/InteractiveHtmlBom/wiki/Usage#bom-page-mouse-actions" style="text-decoration: none;"><label class="help-link">?</label></a>
|
|
</span>
|
|
</label>
|
|
</div>
|
|
</div>
|
|
<div class="button-container hideonprint">
|
|
<button id="fl-btn" class="left-most-button" onclick="changeCanvasLayout('F')"
|
|
title="Front only">F
|
|
</button>
|
|
<button id="fb-btn" class="middle-button" onclick="changeCanvasLayout('FB')"
|
|
title="Front and Back">FB
|
|
</button>
|
|
<button id="bl-btn" class="right-most-button" onclick="changeCanvasLayout('B')"
|
|
title="Back only">B
|
|
</button>
|
|
</div>
|
|
<div class="button-container hideonprint">
|
|
<button id="bom-btn" class="left-most-button" onclick="changeBomLayout('bom-only')"
|
|
title="BOM only"></button>
|
|
<button id="lr-btn" class="middle-button" onclick="changeBomLayout('left-right')"
|
|
title="BOM left, drawings right"></button>
|
|
<button id="tb-btn" class="right-most-button" onclick="changeBomLayout('top-bottom')"
|
|
title="BOM top, drawings bot"></button>
|
|
</div>
|
|
<div class="button-container hideonprint">
|
|
<button id="bom-grouped-btn" class="left-most-button" onclick="changeBomMode('grouped')"
|
|
title="Grouped BOM"></button>
|
|
<button id="bom-ungrouped-btn" class="middle-button" onclick="changeBomMode('ungrouped')"
|
|
title="Ungrouped BOM"></button>
|
|
<button id="bom-netlist-btn" class="right-most-button" onclick="changeBomMode('netlist')"
|
|
title="Netlist"></button>
|
|
</div>
|
|
<div class="hideonprint menu">
|
|
<button class="statsbtn"></button>
|
|
<div class="menu-content">
|
|
<table class="stats">
|
|
<tbody>
|
|
<tr>
|
|
<td width="40%">Board stats</td>
|
|
<td>Front</td>
|
|
<td>Back</td>
|
|
<td>Total</td>
|
|
</tr>
|
|
<tr>
|
|
<td>Components</td>
|
|
<td id="stats-components-front">~</td>
|
|
<td id="stats-components-back">~</td>
|
|
<td id="stats-components-total">~</td>
|
|
</tr>
|
|
<tr>
|
|
<td>Groups</td>
|
|
<td id="stats-groups-front">~</td>
|
|
<td id="stats-groups-back">~</td>
|
|
<td id="stats-groups-total">~</td>
|
|
</tr>
|
|
<tr>
|
|
<td>SMD pads</td>
|
|
<td id="stats-smd-pads-front">~</td>
|
|
<td id="stats-smd-pads-back">~</td>
|
|
<td id="stats-smd-pads-total">~</td>
|
|
</tr>
|
|
<tr>
|
|
<td>TH pads</td>
|
|
<td colspan=3 id="stats-th-pads">~</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
<table class="stats">
|
|
<col width="40%"/><col />
|
|
<tbody id="checkbox-stats">
|
|
<tr>
|
|
<td colspan=2 style="border-top: 0">Checkboxes</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
<div class="hideonprint menu">
|
|
<button class="iobtn"></button>
|
|
<div class="menu-content">
|
|
<div class="menu-label menu-label-top">
|
|
<div style="margin-left: 5px;">Save board image</div>
|
|
<div class="flexbox">
|
|
<input id="render-save-width" class="menu-textbox" type="text" value="1000" placeholder="Width"
|
|
style="flex-grow: 1; width: 50px;" oninput="validateSaveImgDimension(this)">
|
|
<span>X</span>
|
|
<input id="render-save-height" class="menu-textbox" type="text" value="1000" placeholder="Height"
|
|
style="flex-grow: 1; width: 50px;" oninput="validateSaveImgDimension(this)">
|
|
</div>
|
|
<label>
|
|
<input id="render-save-transparent" type="checkbox">
|
|
Transparent background
|
|
</label>
|
|
<div class="flexbox">
|
|
<button class="savebtn" onclick="saveImage('F')">Front</button>
|
|
<button class="savebtn" onclick="saveImage('B')">Back</button>
|
|
</div>
|
|
</div>
|
|
<div class="menu-label">
|
|
<span style="margin-left: 5px;">Config and checkbox state</span>
|
|
<div class="flexbox">
|
|
<button class="savebtn" onclick="saveSettings()">Export</button>
|
|
<button class="savebtn" onclick="loadSettings()">Import</button>
|
|
<button class="savebtn" onclick="resetSettings()">Reset</button>
|
|
</div>
|
|
</div>
|
|
<div class="menu-label">
|
|
<span style="margin-left: 5px;">Save bom table as</span>
|
|
<div class="flexbox">
|
|
<button class="savebtn" onclick="saveBomTable('csv')">csv</button>
|
|
<button class="savebtn" onclick="saveBomTable('txt')">txt</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div id="topdivider">
|
|
<div class="hideonprint">
|
|
<div id="toptoggle" onclick="topToggle()">︽</div>
|
|
</div>
|
|
</div>
|
|
<div id="bot" class="split" style="flex: 1 1">
|
|
<div id="bomdiv" class="split split-horizontal">
|
|
<div style="width: 100%">
|
|
<input id="reflookup" class="textbox searchbox reflookup hideonprint" type="text" placeholder="Ref lookup"
|
|
oninput="updateRefLookup(this.value)">
|
|
<input id="filter" class="textbox searchbox filter hideonprint" type="text" placeholder="Filter"
|
|
oninput="updateFilter(this.value)">
|
|
<div class="button-container hideonprint" style="float: left; margin: 0;">
|
|
<button id="copy" title="Copy bom table to clipboard"
|
|
onclick="saveBomTable('clipboard')"></button>
|
|
</div>
|
|
</div>
|
|
<div id="dbg"></div>
|
|
<table class="bom" id="bomtable">
|
|
<thead id="bomhead">
|
|
</thead>
|
|
<tbody id="bombody">
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
<div id="canvasdiv" class="split split-horizontal">
|
|
<div id="frontcanvas" class="split" touch-action="none" style="overflow: hidden">
|
|
<div style="position: relative; width: 100%; height: 100%;">
|
|
<canvas id="F_bg" style="position: absolute; left: 0; top: 0; z-index: 0;"></canvas>
|
|
<canvas id="F_fab" style="position: absolute; left: 0; top: 0; z-index: 1;"></canvas>
|
|
<canvas id="F_slk" style="position: absolute; left: 0; top: 0; z-index: 2;"></canvas>
|
|
<canvas id="F_hl" style="position: absolute; left: 0; top: 0; z-index: 3;"></canvas>
|
|
</div>
|
|
</div>
|
|
<div id="backcanvas" class="split" touch-action="none" style="overflow: hidden">
|
|
<div style="position: relative; width: 100%; height: 100%;">
|
|
<canvas id="B_bg" style="position: absolute; left: 0; top: 0; z-index: 0;"></canvas>
|
|
<canvas id="B_fab" style="position: absolute; left: 0; top: 0; z-index: 1;"></canvas>
|
|
<canvas id="B_slk" style="position: absolute; left: 0; top: 0; z-index: 2;"></canvas>
|
|
<canvas id="B_hl" style="position: absolute; left: 0; top: 0; z-index: 3;"></canvas>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
</body>
|
|
|
|
</html>
|