4710 lines
301 KiB
HTML
4710 lines
301 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;
|
|
min-height: 100%;
|
|
}
|
|
|
|
#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;
|
|
}
|
|
|
|
</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": false, "show_pads": true, "show_fabrication": false, "show_silkscreen": true, "highlight_pin1": "none", "redraw_on_drag": true, "board_rotation": 0, "checkboxes": "Sourced,Placed", "bom_view": "left-right", "layer_view": "FB", "offset_back_rotation": false, "kicad_text_formatting": true, "fields": ["Value", "Footprint", "Description", "Material"]}
|
|
///////////////////////////////////////////////
|
|
|
|
///////////////////////////////////////////////
|
|
var pcbdata = JSON.parse(LZString.decompressFromBase64("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IdWBxCHCHvdBxp717tqe48IXIeqe14AOntzB/p71gdMAICA8MORgBiHzwcDe4t7ZgfvB/iHy/uugPDDOftBozQHhfvBe8X7nwfHBxqjfIdaezyHkgA6h9p7L7t6e4rjqId3B5cAxIcb+2SHLQcUh28H1wcfB8v7BGAiB3x7loczB+SHg3uD+1SHHQeHB5IAqgPKB+WARgfwB/gHzIcQe6yHKIdle28A4of7ALoAAYfqB0yHhAeuB8iHggd5GOwjgQcBB34HKbvBBwW7oQcY+2NDDoeTe207lgBEAPAA5YDA+4cAzfvoqqalqPvo+5j7TQDY+xVgoPvi+/kHNIcbeznA9Icxh/CHzgeIhxYHiYcOh+X7IADe2P6H7AecB00HNLJbu34wzHtBcNUHGvtPe2YAQIisAIMAeIDj4ypATofOh937TweSB9KH8wdVB02HnQcgAFxg4oerh40H+vsbh/EHtoftBzcHDod3B6eAkocnh9IHZ4eehxeHIocgALHAbYewhw4HCAcIhyyH3Ydsh4UHp1rkB4eHjwfHh3EHd4eyh3aH8odPhxGAr4fd83CHH4edh1+H2gduB4IHi4AsB+v7a4dAR7MH7ocLB2b7eIcW+7+H+YcgAJP7b4eMh5+HIYffh2GHG3sXAAeHLoeYh5uHOIdyh7hHZXsPAPDD6nzRh0RHgYcmB/GHxAfL+6o46QdnB1kHOweXB9uHOEcFB4xHWocERzCH0Efvh0GHnEc6B9xHdwfk+89AlPv/B4CH+wDAh0L7oIdxe+CHhQfMgCwHpweZBw77Svu5B/RHIkcbe2qAKEf8e097WgCf++Q7zUM/+3/7AAdAByAHYAeT1t6HTAC+e7xH+kfZB4JHuIfUh7uH04BQR2M7MEfSRy4HXEdPh4pHdgfth7BHmgddhwhHPYdhR90HMYA3h8BHrwegR+eH9odhR32HhEeSR8RHcEekR7FHP4dle+cAzEexwKxH2UfsR3GHIUeyR2FHYkctu3L7Wwf8RxcHzvvGR82HEfvXgOZH1EdSh6eHqUcPh+lH7IdGeyf7BYdEAEWHJYeiAPAAYwBgAPwAdoqo+/T70XtA+6NHYvvIwFOHggeYpv+HAEekh66H1oeYR0JHvkeHByPW89aROxI7wjvwuyxDYjvIu2Yj3hNSOzwrMjuhO8gzBrt/O2YjKjuhO0Y7T/JyO94TZ0exLPo790fTO3aIEjtmO8dHZiOWO787prtnK2s7truN6w47mLuN6847lruCO+47JjteOw67wMe+O/9HdIBrO6yIQTsFO5M7jetfs8fmiTtGOzS7UsPPO4K7rEPCkxI9UTsXR+jH90feE9k790fSw8+W+Tv8u0DHGTtIM887MMc8K2U7GrvAx6T7QVbExzU7HcT1O9o7nMcZO807WTvHR+07WTvIuwxzzzuYu5Zb0LuTO0wTgzuzOyM7szvOO/LH0zuxwLM7TNsLO1M7b0cyx8Rr6ztTO5s7trvb69o7KBRHOwc7szvHO48ApzvCO6M7LBOXO4K7PfM3O8bHu1skJo7HTzvy9JbHbztMx4s7nzuOx++rWQT+xwC77scgu0LHVLvQu2bHJYveEzC7sTu9o167kLudw1UWCLvIMyvSCLtfs6C8CLvYu5HHU0N4u9nHhLuQu9M7RrJUu+S7ort/O0vTF0c0u0vTdLuUx6a7jLsFcZo7LLv8u2y7KceIxxk7kTPPO4c7QrtfswK7DLvzO6XHprviuySm8rveE8LkGqOyuyGI8rsdO0q7I8equ/E7YcdjO1q7cxhKu/M7d0fAx0a70Ltsx8zz1Mdsx9a7jLiaOx4T9ruCu067uXhHx267q8dWu8gz3rsRO30jIyMUQ7W78AAIO3wAXEMj1gQA3DvwACSAHUPT1iMATAAkgOsiNABt8EAAA"))
|
|
///////////////////////////////////////////////
|
|
|
|
///////////////////////////////////////////////
|
|
/* 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) {
|
|
var name = node.firstChild.nodeValue ?? "";
|
|
text += (output == 'csv' ? `"${name}"` : name);
|
|
}
|
|
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,
|
|
valueAltRegex: 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"] = {};
|
|
var allList = getBomListByLayer('FB').flat();
|
|
for (var id in pcbdata.bom.fields) {
|
|
var ref_key = allList.find(item => item[1] == Number(id)) || [];
|
|
pcbdata.bom.parsedValues[id] = parseValue(pcbdata.bom.fields[id][index], ref_key[0] || '');
|
|
}
|
|
}
|
|
}
|
|
|
|
function parseValue(val, ref) {
|
|
var inferUnit = (unit, ref) => {
|
|
if (unit) {
|
|
unit = unit.toLowerCase();
|
|
if (unit == 'Ω' || unit == "ohm" || unit == "ohms") {
|
|
unit = 'r';
|
|
}
|
|
return unit[0];
|
|
}
|
|
|
|
var resarr = /^([a-z]+)\d+$/i.exec(ref);
|
|
switch (Array.isArray(resarr) && resarr[1].toLowerCase()) {
|
|
case "c": return 'f';
|
|
case "l": return 'h';
|
|
case "r":
|
|
case "rv": return 'r';
|
|
}
|
|
return null;
|
|
};
|
|
val = val.replace(/,/g, "");
|
|
var match = units.valueRegex.exec(val);
|
|
if (Array.isArray(match)) {
|
|
var unit = inferUnit(match[3], ref);
|
|
var val_i = parseFloat(match[1]);
|
|
if (!unit) return null;
|
|
if (match[2]) {
|
|
val_i = val_i * units.getMultiplier(match[2]);
|
|
}
|
|
return {
|
|
val: val_i,
|
|
unit: unit,
|
|
extra: match[4],
|
|
}
|
|
}
|
|
|
|
match = units.valueAltRegex.exec(val);
|
|
if (Array.isArray(match) && (match[1] || match[4])) {
|
|
var unit = inferUnit(match[2], ref);
|
|
var val_i = parseFloat(match[1] + "." + match[4]);
|
|
if (!unit) return null;
|
|
if (match[3]) {
|
|
val_i = val_i * units.getMultiplier(match[3]);
|
|
}
|
|
return {
|
|
val: val_i,
|
|
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;
|
|
setHighlightRowOnClick(settings.highlightRowOnClick);
|
|
document.getElementById("highlightRowOnClickCheckbox").checked = settings.highlightRowOnClick;
|
|
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("highlightRowOnClick", false, "highlightRowOnClickCheckbox", setHighlightRowOnClick);
|
|
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 if (pad.drillshape == "rect") {
|
|
ctx.fill(getChamferedRectPath(pad.drillsize, 0, 0, 0));
|
|
} 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 setHighlightRowOnClick(value) {
|
|
settings.highlightRowOnClick = value;
|
|
writeStorage("highlightRowOnClick", value);
|
|
if (initDone) {
|
|
populateBomTable();
|
|
}
|
|
}
|
|
|
|
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 createCheckboxHandlers(input, checkbox, references, row) {
|
|
var clickHandler = () => {
|
|
refsSet = getStoredCheckboxRefs(checkbox);
|
|
var markWhenChecked = settings.markWhenChecked == checkbox;
|
|
eventArgs = {
|
|
checkbox: checkbox,
|
|
refs: references,
|
|
}
|
|
if (input.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);
|
|
}
|
|
|
|
return [
|
|
(e) => {
|
|
clickHandler();
|
|
},
|
|
(e) => {
|
|
e.preventDefault();
|
|
if (row.onmousemove) row.onmousemove();
|
|
},
|
|
(e) => {
|
|
e.preventDefault();
|
|
input.checked = !input.checked;
|
|
input.indeterminate = false;
|
|
clickHandler();
|
|
}
|
|
];
|
|
}
|
|
|
|
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 getBomListByLayer(layer) {
|
|
switch (layer) {
|
|
case 'F': return pcbdata.bom.F.slice();
|
|
case 'B': return pcbdata.bom.B.slice();
|
|
case 'FB': return pcbdata.bom.both.slice();
|
|
}
|
|
return [];
|
|
}
|
|
|
|
function getSelectedBomList() {
|
|
if (settings.bommode == "netlist") {
|
|
return pcbdata.nets.slice();
|
|
}
|
|
var out = getBomListByLayer(settings.canvaslayout);
|
|
|
|
if (settings.bommode == "ungrouped") {
|
|
// expand bom table
|
|
var expandedTable = [];
|
|
for (var bomentry of out) {
|
|
for (var ref of bomentry) {
|
|
expandedTable.push([ref]);
|
|
}
|
|
}
|
|
return expandedTable;
|
|
}
|
|
|
|
return out;
|
|
}
|
|
|
|
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][0] != b[i][0]) 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();
|
|
|
|
bomtable = getSelectedBomList();
|
|
|
|
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, td.ontouchstart, td.ontouchend] = createCheckboxHandlers(input, 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);
|
|
if (settings.highlightRowOnClick) {
|
|
tr.onmousedown = handler;
|
|
} else {
|
|
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 childNum = checkboxnum + settings.columnOrder.indexOf("checkboxes");
|
|
var checkbox = bomrow.childNodes[childNum].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 childNum = checkboxnum + 1 + settings.columnOrder.indexOf("checkboxes");
|
|
var checkbox = bomrow.childNodes[childNum].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) {
|
|
initRender();
|
|
initStorage();
|
|
initDefaults();
|
|
initUtils();
|
|
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);
|
|
|
|
///////////////////////////////////////////////
|
|
|
|
///////////////////////////////////////////////
|
|
|
|
///////////////////////////////////////////////
|
|
</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="highlightRowOnClickCheckbox" type="checkbox" checked onchange="setHighlightRowOnClick(this.checked)">
|
|
Highlight row on click
|
|
</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>
|