4670 lines
290 KiB
HTML
4670 lines
290 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": "selected", "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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Y5zGaEaaxtzGVMY8xtrHlMc6xnLGBYd0xgrHw0f6x0SHu4bCx5xGP5h5mGezKseIxybH60emx2rGHADmxl4Ah4BSxrTHVsa8x9rGtMa6xsQp8sbDRzlG9sZzhkrHDschRszHn7K14cbHi6GqxqbGk4ZmxlFHbsYWx+EgXsbSxtTGMse8x5bGNsbzRrbGPsaXRoLGDMbKAIzG/sclRr9GLMeBxkjHi6BqxxtG6sfmxhrHFsdhxlbHWseex9bHtMe6xu1H0ccKx77GDsaGxkzHdYeu0fHHlUZix0HHLsfBx67GUQChx8nGYcdpxp7HMsdexzbHOMZ6x9DHp32jR/bHP4Zxx2ZHaXs5xw2HNsYuxlOGiEYhxhzGksfuxpbGOsYSxhwB1McRxvXG3sfogbjH9MeiRiDHuUfhh9dGEkc3R9yHkkYcAUqHTQXuR8VGaocERz6Jg/CPci+GM0flRz5Hs0e5DFXGUcdVRwtHU4afRzVGS0blxstHe4Y9x+tz3EYAR+FHgEcRRqTH+cZ6R4xGrUYxR6HHYAFZRs3GMcaq7WxGnUeZxnVHo8ZfbFVZmeHGxhPGTUfVxo4BAMf1xv1G08ZbRjPGhcazxjtHPsZXRy3G10d5RjdH+UftxuNHHcepgdJHk0cVxv3Hd6tER33H2ockRn9GVUdIgAFGwcaqRxRGakdBR2XGfsYhRlNHeQleCSfHRkapRpPGGYZJxulH68ZnRqhGg0blh7FHGcbxRvudMMaKxyPH+0ZGxlE518fLxzxHx0Z3x81GIEf3xoJHD8ZtRhdGGcd6x45HV0biRm3Gl8auRoVGuEewh0VGXccHxkiG6NlFFJlqhpmJh6iHr4a+RiKICccfhziGwcbDx+fGtUavxkrG8McgJxjKN8dxRwKGQkEfRlPHUUdfx/pGpYHihz/HQ0dPx7tHHUd7RzAmV8fdx+OxDAr9aSlGn4AIR3nH1kdrx1PHLUYbx8gnM8ezxwLHCsd/xnlGzAD5R3wBACcwhm5G0kaTRgRGSIYXhQ3YUtnPRwIBxEcVRnNGCceDxuRGi0fDxl9GBsddR0lFcCJS2UdHvUbBx2fCZMb3xngmD8cDRj/H20ZPx7/GMMYJRtBHdCbZxvp68YXKsQwn48Yfx7fHuIdMJ+zGX8YsJt/GrCbbR0MABCZ2xzlHhCetxzvHbce7xwVHJCZSR7CHncYPR13HIUc4+f6UrjhhmJQnmgDahmkBb4bwJuVgBoCfh1Am58eBRhfGLACXx4lHo8aHacmLIJlYJ5SHFdg6R4gnp4ZAxgInjIf4JlvHqCchhntHCUfoJvQmWcvZRPGLbhHvxggmQEcegzgnNkcaJ6dHmibih1onbCelxiNG/8ciJgAnY0aAJuIns3MSJ8AnSUYSvNFL0iZ9xuAnaIf9xu+HiMeQJyOF6iaBRviGMCeXxnonnv35YNFKH8RqJ4BG6ifEgUYngMe2R9PG+CabxkInW8eQR8/GHCawxpwm8MaH9a4nHwD3aQYm2CcIJwond8brx/wmyCZdgCgmbCalxnjGoYfoxq3Gt4cWJrdGHcZRAAABxLGGwCdkJhWBzWhdpXJGdieUJ0bxCkYAY8bHWXFYAEGozYYrDZ9HF8aMx/4m5Fjo0of5WkaTgeTdecZ8Jrgm3kcCR2hGc8YdR74mC8axx/jH/ic6I4pk9eAJx1kmSmgGh5/GxYYmJnknBCd2xwUm/ifCxkUmGeUy8cUnlkclJidHfCZlJ7kmQ0d5JhUmwUaFJ8LHGSeEGM7HNsYlJ6kne505Jpom5SdCJtvGkSY7x0Qmu8fEJpYnYib7xgfHcSd6J2Os/zVHx3Ynx8aVRwPGeoY0J9VHaSdKJ+kno8bl4R6HAyYWhsdGvCbNRyjGSCahJ6WGQkfeJtom7Cfbhn4nL8YuJ5wmXJyadf+G4Uc8Jn1GzCchJponoSZTJ4/H4SfNxn/H28fmJp0moiZdJtEne8ZRAXCGKoePho9GICe0VfoVFdgyJ1qH4Cf2J3In2IYLRmzG1kaKJs4mI8ezJ7AnOyfSKkEnaiaIJiEnuCdLJ5MnqEYrJr/Hpcc6JxwnuiZzJyIqyKBBOZbo7ifYJqvHKkfnJxMnFydnRsGgVyaoJ9Mm5iZEJsQmJCbeR+NHKAA9Jx5HTMazRse4D+h7JlQmECYDxojHNseDJkwnJIFDJw0mlSaOx+ZyGkXTgQYnYyctJhomXid4Jl2BrCeCJtMm1ydoJromJyZGx73MoqHzJr1HE8agp48nxib6Rpcmj8dtJz4mLcYdJ2snbyddJ+8m+8dAJtYnPSbwA+QUvgF9J5Qms0Ynx9Qnp8bVR2fHTiZBRsMmjSZApmFiM2T3Jjwmt8aLJ7UmSyYmJssm50YvJ/UmaCf5JugnUKd4pmkI4iogp4wnecegp/1HLCdbR6YnKydzx6snSKZvJ50m7yf9h7CH90bbJt3GpoeZULb4P6o/JgpGY4b53aMmE4dKRpOHykY4J0cmuKaApzcn/ifMp/wwByeHhsuHHidUp0gmlyb2RuEnVyYRJ9cnfifcp8LHPKfw1bynlkd8pkYn/KaTJ2dGgqYQpmYmESevJiIm6ydRJnvHlib7xw+GaKefJ+0kUstH+TIUPyeYpgMmfyaDxtimQ8e4hl+HAKbKJovGQKdrJY0VxySMJ7CmwcZrxsYmYKfUpxvHJKflJ6Sn88dkp8onGqYL/RSmucfwJyCn2qc1xvwnTyffxoImfwA+J9onXYfCJlEmd4cbJnKmUQB3R7En8qfbJzmHueCcoZFKPyahPOiHTrVyJ0vVaYecGHCmNUfQJ8cmWcZAAYbH5KcxqI1YGkHGxyBpKSeCWjinpSZRAQ3G7seJgB7G4cfuAb6nacYAR16nsAEgaNHGrycLxjBGFcY7Jq96nqZeusamQabBpj6mEycBpoXG/qapx+HG1seax++HEafepkKmqyd4xyGn6kehp3amBQClkAnHmYCtAYSnrSdlJ36ndccex6nGxcfYxgsm5gFNccGmkKZkplCnbqfup5ImSvgFAfBoKaeWR9pHcoGPJ1Gnksfpp/6mDcYRxynHkcdZHVmn4afxp7SnCacVJzcmSacAQcTQjVnexsam+QGWRlLYaUeLJtgAxaZ1xmWnOSbFp43GJcZMoFbB2abSpomnfsdZx/4mAiU1p+iBWkbaoYSSVKdFp6WnocfRplrHMaZpx7GmOMctp8MkpKeCxlWnsybVp8UkG5AVcs2YXad1p6mnRccRx42mRccZpo3HxcZRxkSIraa0ppnHQ6e5prcncMAGgKOmCcddpvWmRac+pw2nPabRpiWmMaYBp8umkceQxwOnFdmDpzHG3KbDp+2nwselsx8ABae1pr3bhIGFpp/GUaZrpxOnsafjpk2mPCflp+/pG6b6x7On5cdbp3inzvQJAcmmu6cpp3unuIeIJo2m6aZNp4emgaZZpvqHraYJpmXHscZnpyFHhHDRGzum7KbYhpem46eTpn6nVIG9p02ma6fNpl6Gx6d3ppWn96dCxw+nJUepAMmnkUtaRi+nkaYNpkAA16ZvpyumfaerprGna6dHpnenM6YNJ+qmoaffp93GRcwJAU+mKqZ6h3+n3adLpgBmB6fXppOnfaaZp7LHH6cgZxWms6ebpnOnsCZ1Gr+nzvh/poWnL6ZwZhOmsGaHpq+mt6fwZgtHn6aIZmBniabgZiAnMIn5pvGnkGf5h1BnDyeFh/+nAGbAx4Bm76bAZh+m5aYIZy8nZidtpwbG7qdzpwZNyGcsxvhmqGb/pkSmy6bAZwena6c3p/2nt6eYZqBmvsanp2Bn5GeFJxhAjVnyNcbHg4DKRh4m+6aEZzBmgGY3phhndGZRxoumWGegZg+mTGejx/BoVVgsZsamrGccpmxmV6Y9pzRm6Ge0ZpxnwGc2x1xmDGftJzTHkSajR1ansqbdJsqHViZMpo+n42nrc5GlSqb9xlimu6b/J3nHaqe0JukmeKbSZqlwy3LjxgsmhKcmphKmZqcCJzSnCGbPxgamuaYapkpnzkmYmxXZWqcrx8jHqmbEpgin4KfmpxCm0qeWp+JnEkbWppJmMYcTRnEmCqa9JiWRd6G9x2AmmKb2JnImkCfyJlAn8mbQJ4onziaGp5InB7jdmoYwZyfuJ4nH0Gbwp9FG3id6pu0mvicaZjcm5Ke2Z5tVo5twRwSnQSeGJjXHumfwps8nYSZSp6JmlqZrJvSn6yYMprhHKkCfJnam05ViK4dGmECsp/PEECa98BGmnsiFpzUnQ8ZcpkoniGeaZyVGLcDfSYBMxqaBScNhH/kOZhMnjmdeJmWHhMLqZ6RnQqeQpq5mtmZRZkFmneCkfDFnViT6h5enq8amp8wmamd2RwlnUydSpven0qZWpkZnEmcopsqG8qdSZjRHJpxJbCblGKcyJsqm1CdyZqqnNCZnwgCnCme4p4CnkiYaNclHlGc3xian2SatJzqm1KcmJvaG5qfqABan0ybCprMnyWfdxnUaXkYpRwSm1WYEZp6DcKa6p7Vm4Kd1ZxwB9WdmJoZn/8YSZmIneWbYAAABVLamBWaeRrUBUeVrgQ6mboBvh5ng8CcNhbAAAlrBxgpnrqZ0JzAn/id/ho6r78epZAonecY6p54mtWfEpvtQHWebx9lmX6aNZqNGP6a1mI3Sk2ZWZ44nk8ZtZjNnAqbXDM5niKeOR22nSGaFAeaqS2b6h4cmGWZeZk5mZYerZoinFqcnppFn/8clRhNmA2ebZocmcWf/pvFnYKajE7NmnWZtpoxmFicLZk2HhBmHZlNmrWbTZqdHXmaoRrNmiWYnputnZ2cypwVnFYDwtJdnVmZXZxlnRKfXZxlHN2bZZz5ne2bYZvdmnkcHZhKIj2bLZ2zH22fxZydmt2b6pkOm+2bnZv1mi2cumM+ntJRbZ0dn1GZPJnpmkqa7ZvUnP2abp29mG2cIiaOnR6dLZ1tmeAFXZ6amwOY3ZiDnKCe3Z5Wnv2awJ8LG5WCxasIUPEaMSBuHgOetJ21nxKcxEKdmBmb3pw1nZGcuJsw5EqG3NQjmPCeI5i01SOc1ZgKnZ0co5j9nzmZvZ8MnGqdLhM+JcvHvxxvwhP3pZ5DnT2YXJtDnGUe45q9n6mcMZnDmGCYgJwTmVhgEpgsnRObySdjn02c45qhHZOZrZntmd2cU5+jmR9jobB9la4A8RjTmZBC05tdmO2dL5Kjnc2dYZ/jnkiZU5l2l2mY8JyzmwhS6ZitmdOZk50zn9OYhp3dmlOf0ZUznltJE5sQAxOes51Dnz2e19Pznu2YC5ozmFGZc52mkwuY4hqzmqme85xKndOdi5yDneOcM529mgudCZELmgejU5l6GPOfE5q7GMueZZ+EBsucw5qDm+OeKZwVmkufn6FLm9QDS51NnJOdA56LnqueSp/pmHOfcZhrn3caa5yPoWuYi59LmjmfI5pcm9Obi5mRnAueM5mMECObwJsTmOIc858tnxucrZrjmaueCp4lmOWbo5xLnszjUyEbnNObG53FmJuY25nrm9Weo5vNnduYbZnaJqWYA5vJJlufK5vnHKuek5mLnzucdZy7nHOYG5iAnwSHplD+qiOY05lbmX2Ze5rrmPQE25j5n5Oa/Z/LnjOfU5P7nFuYe5kjnjubHZ07msufe5nNnr2by5pznBWbLAOHn78dY5nhmvObW5nzm3ufs5jHnsOeh5hRntoFx5mln8eaB555mQeds581o0eenZnbnZudzpuJpqefu52nmnuZQ5plnXue650nnIeeg5rHnf2cVlO7neGdGR7nnIub550HmPwHB53rmyedfphVmB2aLZqix/uZY5wHmeeY658dnuqbB55nnPuf655Xn72Z9sx4JxeYB58LmCedW5k7n1udR5wXntuau5tnn42aLZpjn4eal5pHmQOZ15u1m7OZ452tnyeZF5qaH8OYFldXmCybd59rnX2YnZpnm7eaw5pXmIqd4p/RhOIncJ9TmLeba5k9nw+d15uXn9eb65hTmKef+J+PmIwjc5pPnUubp5ttmGebfZyPmfeYM5v3nvuafGOBBjBAkwQ7mU+cJ563nieYF5ivn4uZz58LG8+ZspBvni+Yk5tPmvefL5uTn7ea+5o3mpoa755LmaWbK56Xmz2cZ5qbmcud95mPnrmclR8fnQucn55Pne+Yq5onnMud85zPnFefzZqPG4+dr58BkC+dK59fmtef75ijn5eYu5rPmoef95mvn4/GKZczn3ObP56fmpOdl573mh+ej5/fnr8cP5h/npybX5ovnz+dL5iPm5+dq53Lmq+dH5lQVLXvUu9Fmuec151/nOudn5q/mPuZv54Xnq+b1Rv/mstJ75oAWt+aq5vXmo+bq5zHn0BagFBdnAsBepy17PcAQFm0n5+cr5xfnjWamh3KQFubx5+AX3ebI5m3md+YIF8AW6BeRZ+BnG2eN22AWJedxR0PnU+eAF9PmP+f85mbmEuewJnHn+BeY5kPmWBbD50QWB+dAFrbmv+eu56PHHmiYFmnmFBZEF3AX+efwFtvnJBY75xqnfudkF13mdBab55Hn2BZJ5wwXBme+ZjKnyKdGZj1mA4dbJw9HTKdTAYNxw4ZgJyOHrKZMgIpGz6cTh5OHj/gRZzZmeBZIh0KyhJLNJtOnYqZwF5vnt+d2RzgWF+do5x3ne4YiF/uGYqeEgOKn6eb0F9/n88FsFjlmXWYWJt1nt0Zwh9x7JmaBZvADjRTnRLJmUWC/Jg4nNsaOJpDmPQDqpu/mZIf6YJJz9mYPJ/WmPeZR5wNH3mYV5oXm88Yvx9QWHqb36DoWaWaGJwJn4yasFlvnTmem5uwXdKYcF/SmKKeFRsoXtqfcFvVGMUCjJt5H5mbFZ7JnyqdaRvJmrWZCFm6mwhdJR5nx4XUwpmtHlKeOFpQXxKcIpmgWDWdJZ8Kml+aeRrhpMgx9JiYXLWe6FtgXZhftZ/IW82cKFzKnihfRJtgAd0dcFpImNEZmhDeBuyaJJzInL0Zvh69HtadrXe9GmYDnJq6mNmdOF4xmeaahFhXYxsa7ptXHLBY952mmHGewZ0Bm/aYiZ6IX6ceH5hpnhhbZ58OmUKNjmQjGqsdIxhAXBcfFpxxmaGZHpiXH/Mb353bmGRcWYHyFmRfOxnnHdBYTJ9kWtGb1xnRnKRZ6hyXHBhaIFpwmBRaZhGERlccEFkHHWRdYF2bHtcdC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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>
|