Half_Bridge_Inverter/bom/ibom.html

4415 lines
255 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: 10px 10px 10px 0px;
}
.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: 5px;
}
.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: 10px 10px 10px 0px;
}
.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 {
width: 100%;
height: 100%;
background-color: white;
transition: background-color 0.3s;
}
#top {
height: 78px;
border-bottom: 2px solid black;
}
.dark #top {
border-bottom: 2px solid #ccc;
}
#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;
}
</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": false, "redraw_on_drag": true, "board_rotation": 0, "checkboxes": "Sourced,Placed", "bom_view": "left-right", "layer_view": "FB", "fields": ["Value", "Footprint"]}
///////////////////////////////////////////////
///////////////////////////////////////////////
var pcbdata = JSON.parse(LZString.decompressFromBase64("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MktALKp3ynyqU5JSqkiCTGpjSkKYIMWoiKjYMmpIwTYKGmpIqmbAOKp5qlyqZapCqmgKSyARanqqb+8rJRlqU/ogUkpqVWpbolsKbCp2SmZqdKp2alfKeMpVqmZSS2pKqk3yUNJ9KryIuWpGMnpSSNk1akDqRwpQ6n1qbmpjan5qYCpPoncqfOJ8amTrnLSjKlwiT2pDhjLqV9JGanfyeupY6lNqRipk6lAqXEpbanKfIZS/YEQqN2plamnqX2pminnqRFJa6mHyaipPyk3qXDJd6k7qQ+pM6k7fN0oSakLqWdJS6mfqempP6mXqX+pFqleyUBpDQCtqUNJHqkQaa+pzsknqWOJPYj9qd+ptam/qQApo6loqeOpzknbqZQp9SnFqTOqk65f8Uepi6mpqbBpNambyURpjGA5qdepW6nAaZRpqqnUabxgGfYRUpBpjCnHqe+puGmQGPhpTykXqVwpxGn/qXmp50m91Ghp84m+brRpVFwVqTBpDymR0V+pEmnwaVJpbGkkaQBpnGmoaVOpsamKaVsBc6ldqdhpImmhqXhpmml6SYOpCGnSaUhplSkoaZPJ96lUaY+p/GmdqfRp0GmMaeppVBI2adopncn2abppMmmbqXJpmKmGKdipdikzKVXJHMn2qSHJTgD1yUIJIACISaspU9TOasQIS6reqfVJ/ik9ycOIUIkHKVGY67KdKRGpaIkxKa5pPGltqQp8hlI6MtqpUDB3KdCpvmmSSQRpm8kvKWup8UmU7IhpDanIaefJV0mFqUZpvGnvYJr8AWA1aYGpmKTtKavJPYhNaVpptamtaZep7WlQ8J1pG6ndaeRpNqmByXMpcWm1yU4ALqlIKeSpd0CmshFS69pbKQuI7litLF5pOqmhINnUnUkcqS5pIGluaUNJKoLdKOvaT8kryccpTITMaR/JRqlzaaapHWkOaV1pTmk9aTUpXGkXKYpprESPabVpQimCMObJtmmGqdvJiKnvKcipi2kcaWFpq2n2KXapCknxaZsALinKAK6pKClpaauy7HBoST6pCBAnaQioUGnHAMnMCUCVxsVp12lcqaBpe6neVgTpWOyvSeX+9ADFac1pH2mw6Sapkqk/acFpjmnoqUWJ/ym9aZfJ/WmVaW0ujOmXAMzp7SnFCJkp72nwqXWp82lZqWOg7GmkaYBpmUko6dFpUCn4qejpm2lNie8JrEnJaYLJbqlT1H9K59xWidlp2yn9iaFAg4lCafhJ7WCuib5pUSljyWVpt2k8acjJcakm6VxATOnOyauJEYkO6e9p1slrSQYpgMk7iYMpfSnPacIpHsmyaYqp1SmliVMpUWm4qTFptYkbaUSpJUnY6TtpnilWgFBCqojTnEdpn8j8aAe6cmCBSbXoWwg+UVdp0Sm9SS7pcik0KZxJ52JVCD0Er0l8JLTJUwCRKf7psYm9KcUp9snGKfwpwynjSXeQDMDKBkjp0emC6YDphmnlaVXpA2lDAdnp4Omo8L84M+kt6Sup3Smh6XGJPCkFKV3pRSlUycJpgzQGBn9p/OkTqaPplekNKW2pSOygLDnwNumZiY3pOPB6qYgkcGkUyaHM7enB6YvplMlOyb3puqz96VDJKukGaTdp3Gnj6Ufpu/BtCKfp+ylLyRfpc+lsqTfpP3A9KYHpK+md6SHpT+klKYup1ZAD6R/pYWlA6dPJbum6yX/pFVrTnA3pI0iX6fPp7OkB6fopUBn9KWvpS+kb6fAZb+mR6aFpiqnhaX2AkWm2qetp2ukp6XWJ1CxlSQbpyClVSZPKdCrXibnpOyl5aWdpLsmFafciZelO6RXp3+nGaRwZsjIF8KNpy8lN6VDpAWly6W1p32kLab9pS2n/aZIpT4lC6TIpIumENLA6pczSGVCpE2lvaQvpoqmc6W8p0VJmqYjpSBnUGerpCema6bFpjBlOKXXJjcn8yenpqWklqVVwMAGSyXxJuWnPyPlp40mDybTJw8mQGOGpNOkKaY9J03rdqgu4tynjaWep02ktaZ9pcOnmGTzpMql6aVHpTMkx6X1pY+niGchJERlbqnXM+hn1aYYZ4CjiadDpBkmzaYkZQizJGSOpIWnLaczJcen0GVrphKmOGQlpLYlkqRnpM6qZNiPmncnm6QuIuylRGQVpbO5CGcQp7Knl6eQpYRk5GfxgGoZAWgUZMRlMacYZM2kJGVzp8OkWGSoZg+npGcPpyqlZGRPpfGCbnNRgL2TRGSvJsRmlGSYZCKlLGUkZyhm86TvpZGl1GVipAcmo6QwZTRmdyU4ZLhltGW4ZIWAdqXyIOelE6Z/IfRl+GXCJARlFacMZjumRqePJnKnjGZxJ0wZv+Eqi/RlmKYUZRxnyGeUZZxmVGRcZKRk1GWoZBanC6VsZlWkA1BMJ18xk6XVpsxm+aSUZCJmLGWYZyJmK6fsAyun6acjp9RlraY0ZDqlbaUlpKWlG6a+g9xxVCHeQeAg8GeawAMCIBoGpFOliSVZpkBiSSaEZ2hn06YbANVq6rH8ZIoks6dLpk2m6SSSZphkSqcsZVRlK6akZVBnrGVIpmhkUacDps8li6RAoV/TSGTKZbOlxGRzppxlkmfQSKJnVGXzp1xk0GVRJ8el4qfYZjxlwKdBJpKlsGbtpjogtfNcpack9GZ/IAkklgIGpoklridgw89TgKMKZoxnRqaKZVUln2hWAXOq1aX3JhxluiVNpxxkLGYqZ55zKmTqwlpmqmWiZu+nqGQCpKBl06VGZs3LCxjcpFmlaXvcpIZlUgPKZcKmImeaZTIBvUJmZlJlqmbUZtpl0GXSZjpkMmZsAjckUADjpVUnewtxJ3pkYScdAvhn8GQCZQxmNaWRJ4ZlgmZGZ5omLeoOoHHAzGQmZ45lgGaaZ8ulKGRSZzgBUmWkZfymamSPpX+k6mUnJqcL9mQuZshmJmVWZ2Sk1mUqZ5xnrmbAAm5nqmRipNhkOmUnpDhlPGU4AAElASSBJYEkQSaoAkEmQSYPiPZmkidaaQ1jgzJsp3xnz4LfI4CQPyIAZcIkLEfGgV4lWMKMKikTAmaVpbMm0GXcZGukOKfMpzRmbAAAAiq0ZbpntGc4+igZuKFlpYImmhgDARLz8GYUqzuB5IPPpIpnlaZVpqGyzBExYUFkiiY84DWkVmWhYy5l1qZYZ1JnUGfmZ6FmtyYyuTFlEiK9JbFlFGQSASCTyGaxpqJnWmarp5Gn8WbYZs8kS5q4oI3TSGWJZeBkmmdxZqxlWGc2p++ncaZVp0mAqWQRGolmLmRxZUMyy6dJZVplXGXJZ8mkqqZVpQlnmCOoqalmmWYhZFllBaTJZ1lmf6bTpAlkQmYxZjlmqWfiZDkAuWcKp8xksae5ZVlmqGTmZtln0WXGphlkK8HcIIlkjKepZoBluWTppHlmRWTaZClmVacpZ8Vn0CM5ZJ5m+aZJZcKmWWVmZslleWeCZU9Qf8LtOygbh6RYphVlcWSVZjZnZmdcZGRmYmQfpE+mVGgYIGgaBWaMpGlnJmWFZaVkRWWsZt6l6WfuZEJkHUtVZJmC1WdeJrlmhWYFpg1mlWZ5ZyBmjWbups8np0pNZ+hlXiZIps1ns6VpZlxkZWTZZ2pmrWa3J61meKNvpLFmZiWUp21khWbtZjVkbmU2Z6JlHWQWZglnLtGdZNVkjKVdZfVlSWeFZi1kHWeVZ05m+Wa9ZUgY9WZ9ZKVlzWXtZ6VnDWc5p3lkVaXGpVVlvWVNZH1lbWV9ZxVk/WU1ZZVnLWXuZx1kQmYJ0swSi9GfpOqkHOP8IKNl2aQtZ6NlLWdYZtJn3GfSZGOkcAPXJrBnMmbjpqMlQmX+gXhlYKUOZiBhSmfgpghlBGeAoIRmTmVjZz1kQmStgUJkF0FzZ9shwmXMZu1kXmWmZV5nDqb9ZUNkA6ZsZ7VmVaSLZNiRxAfwZY2nBWWJp/mnVmaSZl5nkmfLZ5Nl/WTSZtxkQKehZaOlOmYspxUlVga4ZLJmtKGCpBfADmd4Z2ClW6bgp+JltBEegyPQjGSIZYxn9aWgZvZl0KYKo0+lqKWVwzkDEmajZZNm8LEQZAWkmKT3ppSnI2RjZQ+k7mcrZYhnxKW2p0uzNWk7Z0hmh2fCZlsmEyRFs65mkyavpMBmhzGQZl1mJ2RTZkylm2Tipj5mOKS+ZnZn66YzZs8nOdDPaXxk+mbwZw5kBmYcpgRmvaXzZPtkgmc7padmVaa3Z++owmaUpktlEmbrZ55n62bLZhtlXqTpZ25kaGbuZMNnTqXupo9lTGXiZBNkEmdrZxRnT2TDpZpkG2RaZ15m3mc2ZD5mJ6fXZcCluKV8J+FlvGZV86yZttGzZOWnEum7ZQqge2WUEYknjnDLpJWlRqVOZWJlxqQoSybyjtNNZEKjf2dLZs9kK6UbZ91nNWTZZrVlaGf/Ze6mBIkA50+llKaA5cplcWTLZkDkL2bxZ1dkRaWhZilmW2R2ZHADFSTfZzdmkiU7+7WANbB2gPBlhHADAJE6BqTc6rAg0WUCZpCkC2avZh+mENBQ5pczcqK9JauDtTHIZkdm5KZAZQynEGaXZMdkjKYMZfoCK2bmZWpkKWT/pOhkHuhNq8fQ9WXw5QeACOSQZUAj36UYpYjkiOczph0mUGc2ZcjkcOfOJPYF8Km/Z29ntTFeJ9NZryf1ZVslt6cI5YekDKbAZ8dnSmfo5Sdm6WYLZVGkB2eQ5u0oc1lhpS8mqOdY5I8n4GfY5hBm6OU45ZdnP6ZjJkjkGOY9ZRjnp2Qo5pAhU1v45mMmBOX3Zm4kmmQQZJMlB6do5j+mROXAZmYkxOe45I1meOa7p2sltqVw5miJBqLw57SlBOUYZITkQGWE5jjkaOfk5LjmFOW45VdklOew5CTkmOYo5VTma2QQp/DkwqQ05S+laOSXZeTniOUvJRTmdOdDZRaneOZxJlTkJKKIqFjmDOWo5wzmZOaE52Tkx2RE5kznROR05Jtl8WStZcSnzOUWwfTlLOfsZIylpOeo5OjlQOcXZ0BkTObo5Ejn7OdI50VntWSc5NwC+OZHMyjkrOVc56zm2OVk5TgB3OaI5Dzlh6U85tMlSOYvZ1qlU2RbZDxlEOQSJ1Cx4WWQ5nEnuiBs4P6JP2RbplZFd2e/ZPNnpORGAdFkq2YQ0+HRtcGi5INmT2WZZFcDgOamZWDk8WVuZAukp2ZkZBLnziSegz6kkuSs5BhnXOWUZEDlrmVA5N5kPWVFZLZn4OXXZmFkN2QSp1CykOYbpTNmKqNNm6/Doub0ZfBnd2Ti51OlsORVZjohVNj2uh5RsuWS5YDmaWZg53LnYObS5StkMucPZhLnzCsopaGAHGQVZ5LlJmQqZh9lz2cfZPLmn2Y9Z59l2GU+ZVtlOGeK57BnISUA8EahFfDwZPhmc2SOZPdmAmb5p/Nm+2RGZCDmPSd651ebj2ZCpWrnWaRg5XLnc6Q2Z0DnFOXS5y9mp2WNZe2lRuVxAgrADOey5Utk6uYm5ypnJuby5MDlbqc65GFnJ6VhZdNlRAP+ZyLntCeCpsrk/GfK52LmDGbzZlZlIWb/ZpTlr2VGZr6qNuaS5hJlWuWeZB9mrmUm5J9l8uS1ZGxlGuZm5joiLMMWZKDlxuUKZw7mcuVS5erk0uXeZULk12faZF9nCuXApb5kRyZ+ZMclwSQJmdtmSuZP+fknWmlBoCAigWT3JFHA4oCLo2Ll7UNu4qkAxEEq5YbmKWahZ5tkEObC5tNkgAG4pLxm32fbZxS4GVt8mztns2STp5jkXWedplOkX3H7pP9mgmd252RkUqeiAMMKP2SDZL2kcuScZo7nFueO5ZblyaXA5T1l3aSZplOLwqMA5SNlN6bi5CwSFuau5Y7kOuRO5h1kVuYQ5v7n7uR+ZUclfmTBJ0EkAAIIg4ae5VUkO6Ik40dy8QKBZGeih6H8gxeiF6SMp1pAQEC9pPuLCGYPZKFl2mQ0Z7Zm/ucVJTdkSub25MF7oKU25yBgk6Y0g3dnW8EQpIbkD2chZftlbGe85pihyqMRgiCI52VeJYdnxualZQjlNOR3pwLknievpUTmQqZXZBzkamem507moGeU5hLnKnAO0KikjKbnZBbm2OQXZjnlbOeE5LTm7OR55EempuWrp0LnfuTTZOumuKWp5nrnC2WkunulCeR3ZqLqv2Tw5BWkweV/Z6DmsOe+5iHkdWYrmwYlsuRh5p5kJuTR5OHl0eXh5ydk+eW1Zxrl7qSHUVXlQeVAwNXlLmbLpurm0efq5G7mJeVu5SnmuuXC5LHmRydHJ35m/mTIgdblWJKyMtlhgec/ZgTifTN3ZMKCFWMkUH4i0WZOZjHk/ual5IAATeYe503lcwB657pnU7kNYdlh+uaU2kwzXyF15nhaiuDWuCFkhWRypu3kpeUwZdNlp6a8ZQHmsQNEySThatt0ZYImBxjLJ5zajaZv67UncqGGpxnldud05Gdm/eVIStWnjACypaDk62Q1ZaNkpuTM5hrmteTO5v+KhMsUiDDkiAEj5lHl+aaj5UdmluQl5K2lJeUK5VbkiuSAAPMmneQRZ4IBcIPH2BskF2nl42nnSyf6ppcGBqQrJhCntuXi5yrn+2f55JjlM+eG2LPl89NdggUlPCOwAZsl/ObHZmzmAuTk54zmueaQZ7nn4KabJhnleeUvZAKmvecp5+3nYWQzZ6nnISZ9sKll5ODwZZFnZQBRZgalUWeYIzDn1WaV58nmmeS7pj6kF9kxZ0+nJWXb54Nl3WWT5GPnyWUc5PllT1AGERllu+bvZElkk+ZF5Q1mQuXvppTnYmVP+OKjxfCZZlrk7WZpZXvmOufy5WVnoabkwrvn5WeWZSfm2ORDZEfk4OV05V8mPqRG8QfnZ+exZufnfWaT5qfmZWX75ilnISSdRZfk9We755LlFWaTZ4fkK2ZH5vvnR+UNJLvn+WSWZS8kt+ZX5gjm4eeT5rzn6WUNJjfm5WfH5SVkh+ZxZDnmj+T754/nY+RZe604TTuh58Xke+bdZaPne+Zr5abl5mXX5PbkN+ctOG06bWZv5rflh+Yv5e/lR+TD5Gflr+XtO01nXWfqpC/mNeWP5hHmw2Xup45jVWRLp5Hl1WRf5L/mDeYY5h/lIeQH5y059Tmf5f/nD+e35V/kvOe/5R/nuqWAFM04b+ZAFN1nJ+Tv5NfmHWfE5j6lFOAIGD/m/+TNZqAV5+Sn59Hn/WRG5yEmYLrgFeTiP+STZq6noBSQFmNm3+Yppxvm5WQnId3muyUWcNAWSaR35xtmwBTr5Y3m/udBJBvkZeXtpTQRJLkt5GLmqSWBQ4tkuyfVpfPkTqJ25CHmMBZG5gInxLhWps2RE+da5I/mv+Uv5BHlYBfdprTiFLviZSMAkOMaZRAV0BU15uDmfubXZO7nU+VfZ9Pl32d1gqPA+0Zd5N7kv2RpoBXn+GR/ZQZk+5O9ACgVD2Sv5LIyvaKnMdlggORoFy7lYeYoZA3nrubUZugXABdsZA3LOBSg5PXlDuXV5trnUudpZhfmbuXg5X7lU+c+ZcCnFSQB5SLlT1CO4Xf7UOaBZ7KwAwApCmtmg4KaAewq9efB5/gV+efIplWklBXDuLqiS+YF0AgC1AKYFNrnYeXLZy+nReTc5znmqKbZ5sTlRWbEF5XnmeXxpFKilBd3ZcHixBD0F+dm6KQMFzTlDBeXZkTCjBW/58TlTBQ9u27htBYG58wXdBbV572kReUXZivn3Ocr5zjnniSKJoXlL+QK5OQU2BXkFiymHeWx5R7lUAC4prplFBYxGJ7h5Lld5YqBj0H3k+Pk+8c44BcmslHJ5JnnoWVYF27kuuZfZiymNyfYF33kwCIOoz7zaef65UgWBuYq5LDkNBaIZAQVIhaMmMbmXWYu5e9mpBX0F89nRBeiZEwVKBa3JQ9rFcOIBeblEhQqA+9kruWkFa7kZBQa5FPkjeW2Z/AX7ecVJ7im8eUnJ3oCnPmbpg5n56YvK3Pk+UeD5eTjFyQ754blvOUL5HBlG8LtOeiLYGbPpzelg2SM5mjkOOcMFOzmPOS/pW+mIGZkFmPnwOXKFzQU6GYKFfbpe6UAZOBkgGVv5GzmNOVF5qwUgucMFFmn6he/phoXd+d05OwVo9qWwd4DSGcAZaoW2hf858vmbAEC5cvlueQU5ZPQUGVsFcQVeheSo4dAycn6F1oUBhf/5c1kAuSGF5wUuebfpsXnQaQgZboXshcv5TQXV6UWwJqKatpaFmMn+hc04UAVDBWM5FwVZhbqFm+m5hWMFNpl8BbCFdckvBVN5HHmQmHN5nQgUqLEsOXlgiQhkkXYK6DBEXXkcCQYQV4mjhP8q4IW/2S2Fu7mLKdBJttlfeWe5QiqUUHfqIFm5eSN0PJn+mdi5RXniWfz5ZXlUhYkp5PDzuRWpZZkV+cE51HkshdzpGZkwBV35GJnGhW15vZlnObGZp4XBSXuFVHl5+f156Zl8xIAFTrmU+Y8FbrktGel5Z3nAeQ/Jo7RXeRzZ6IUKuW25YQV+BTiF2Nl7aemWYEULuYO52rmfhUW5/QXkheMFU7lY+QhFSXz/4HOg6bLHmTn5JXng2V+FmEVshUN5HIXZBdYFMIVzhW2F4cmseR2FM3kLQN2F124LecMx4gWP5L/Ez8iExF15c2LAGQjoB0Dbee+5s4W2Bc8FjEWTeex5sElUAJBJ3Zn8hci5RHK2JP2FLtm7ZLm0T7hsBbRw1oVHkGCFMKkvef+FdEXiRcSpi4WAecuFevIJPuCRZQUd2dyZOCma6IFJ/JlriYKZoZkTmQeFKrkIYAzphIB7/hc5UzlS6YsFM9n1eRRF+1kvOZSFbkXOPnq2XkUDOUaZxwVkRRhFZIWURWfZBkWVuU8FDEXvmVJFR7n4SGxFtIRn3J1SXEWVFD3knUyB9F15oWKUYFeJOkUhhOS5cEX2KVCFo3mthQlpJkVfBRZ53jIu4EPUNDlJOaFAGQ6a2WD5hCkQ+T2IobkyhX/ZjLkaeaLI0g7mud7pBPnBgGUEednQBdoF1/kyOSvZoUUVFrj5uFD4+QHAlXRE+RHZ00W/hfy5YkXJRa+ZkkVHeT+ZkHCZRe9gxDRsjL4p5QVMNJm0hbQAJPxFZaKCRXDMV+mh+fb5EIUfuYp5XIW1RcxJiLmG+RCZsCgBfk5+V3mSBX3J3dmyBUT5lUWyhY+FyEn0qn9FP/kv6eoFmHmEaeYFY/khRQDZU9R1tFl+29nGBZzE8MUDWdwF6PmzRTcZNEXQhUlFgEWbALyFx0WI3MeQswUkWRnJYsrZQFUFo2k1BZEAdQUpBc9F0PlzOfKFAFl2dFTF29kgqDMARwX1BZS5V4UNeSsF2oUxefWFNwWbBToFOEUPhf1JHMXIuV5aPinw7jzFnQULBdFF7OmnBbc5GYVhhSr5EYWvyJLF+MVwBcY5s8lAdIrF7QUHKYcFPgXyBScFywU1hZmF4Bk6xW05GwW0yWVwvAWJRUx5+3k8yV9FwgVegN4y0IDUqR3ZHPntRVz5+Jk8+TH804WKBezFpoW6yYKFfsW1aVL5bslFyReFQYX2hQr52zlixaC5ngXq+WhgwUXSxfcFtEXExXC5LimFBd9FIgVqIdrRqIVuBadpCrlFeZbFoUBQ+RHFKMUuLmohmC4QBZNFYXm9BZEFwsVYRZO59Lm4RULZpcWyIYNSrcXI+cSFfXmxRfa5W0XNhW7Fe3nveX+5tbkKRQPFq/DMmBXFhFjuBRiFNcXhxY0F/cVHbve8Oh7jnKEF2MUrmZ3FgUWQ2XeFyMVkBch5SXB7xUkFFHmHxQoZX2lRBfFFf4WchdTZuvmzxcVJTJklxY6IlnnZ2dTFWClL4jp5gbkGeYnFwRn1xVvFXjlyxSAYP8V7dPvFIXn6xeHZTIXaabjFoYU6hRnFCdnn+TnFvcUyxYWFE+leXE7M39yjheNFLCntxUsFRMmaxWnFawWq+fbInnmuxS/FMLlvedW5B3n7Ra8F35mxyYIAkEnkxXe8HhmW9CxpG4VUEBSMHdSi0F15laj4SGxZZUUgJf3ZYMWvRa2Zr8XchbPF7YXseTN5BiCcJSjSwCjAWblFYFlPyD9MfJmQ8LBZtMnwWY9F8/nYhVVFb0WyJR9FornFxd7FeLrkKugpRIgQRb8ZGIUwRZvF8EXbxTyAkhn0KY2AxEXnhfU5l4WkhRPF3cWwObnFegUmOZfBtiVeJe+FFLm+JcfFcUVBRXeFecVExe7Fs8UuKUIFIEUecK/i5cV/xc/Zq8VVxTuFn9m1xX1FL0XledlZfpg24TDF6CWQ6SQl/kVCxSfFBfn5hefFg0WtydwqU+hqtgfFlSUjudEl/iVPxdtF08UMJTT5HwmWJaklqR6DnMKFLtkQidbpbAV26aJpzeTGJeDFssVRxb2ZbpGm6WUllgA+6QQFPiXJxaM5WoUP6ZcFrTnXBRXZGCVnxbnFO0Ukxa4pzUDkxcyKqklcbBoldKmhQAypganMqRNFQaizWfi5EMXjWfda5iJxxbqpnAURBQ/FXcVdJT3FLXnYJa4lTAjvJcumnyWCqd8lKZnVJTElp8XuhQTF1UXvRfRFTgA8ySklDPliuGHoscXs+aXBnPm3EOKF+sBhxXpFAvlmeZAlPQCvdJil79lZxYfFaYUHyVrFqCXOhZnF0vka+ZglgKXxJTVFSKWY6Z8FX8UIYGyZiwjyXlyZwaIfuPwZDkVU6dFFLyW4hf1WOQghIpFFvkVqxVElvyU1JZ35cKX1Ja8lU9R6mbkI8l6S6XBZfkXtJfKlMKW1JVRF8KWmJfQlb8WMJfXJnKVWJbAkoBBe5hola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+WqFQ0VN+XHFXFApRVv5bblRAD25Y7l/gDO5TkVXOUAIB7lguXe5TPJPKDySYswbxXh5R8VshWXFXkA8klE5TgVT4DSZefANrajQPOAkEmceXrlkEk4FW4pSnLT5RQAi+VQlWYV18kS5Z4AqolK5aHMVJUK5bSVKuXcQGrlJ4Aa5eIA+QDySQ4VThXZwK4VFADuFeIAnhXeFWAAvhXvCf4VgRUhFfWA4RXw5XYV18nULJx5rwmIBMCAOaXBFdBJtYBGUFCVzxWwlfUVhxWfFY8V4iDySTzJfOXQSS4pcuX4gFTlU2U05bKwQ2W1gIqwZABtgKRUwJWqAJzlrXDglV7lwuU+5eIAH4C1FecVDxWXFVkA8kkkFagV6BWYFdgVeBUEFUQV8YLIFd3lZBUUFa8JVBUzyQAg8kn6FeIAqOUIldsVIAAKQIoVW+UxFTqViJUJlc8VrxXKFa/l7xXqFZoVUmzpldnAKJVolRiV5YBYlRQAOJV4ldnlBJVElcGQJJVklaLlxeWylfKVipXiAMqVQRWqleqVouUt5ZrJhpXGlaaVlOXU5WqVDUDWlbaV9pUc5dkVTpXSZf7wrpWFFR6VHABTQAGV8uU0lbLlxBVbldLlFOVMleoALJVsleuVFJUvFYHl7xW5lRWV1xUvFUoVl5X3FUcVjxXyAPJJyRWpFeIAfxUAlZkVQJXZFa7loJX8ACuVkJWwgEqA6xX7FdvlV5VNFeIAylba5ReV8JXgVccVb8DySRdlQBW/Zedl/2VgFbNlwOWLZVAVR4EwFa9lcOWQVcOVURUUAGXlFeWqFdXlteUxSQ3lTeVAVbsV9JXblVAIdFX7lcrlquW85ayVM8lTwLUVz+UqFfCVpZW7DOWVEFUcANNWluW1AD6Vj5V45ZcJi4AuWGOlUIC/pW4pU6XCwHPFLxnzpdfZc6WGKJ+lHwV7AGulf7kbpcllLinbpVplWOnjpR5llGXJJZpVJcAnpWZlmWUzpZelulU3pWpVJlVnJXSIaGUkqeOluWXqVW+llAAUZVllXZlgZb+ljcn/pQpVjclAZfZV3lWtGeBlDclQZW5VlGX02WBlyWX1yQhlXlUQZShlimVmpZpVxlXeVdhlKVX4ZcZlSGVEZVQSKVVkZSRAhGXUZX5VTcnO4IlVDcmMZTlVlGUsZTMAaGUcZTSJXGUbpdVVWWX8lZso9VVCZQlllGWiZTSJUmWSZQVASmUyZQJl8mV7AIplHwmsSc4IamUaZdL5WmXqZTplaGXqZfplC1ViuXOlLVXXyRGV5mUopZpVVmWnpbZll6VWVa5lYVUuZW5lMwDpVdfJXmXjpWtAvmVTpVplgWUzAJFllGWqeaxlYWWkqQ9VWWXRZTSJsWVCCXoQvmVJZQFlqWVRVe9VGWUVVSQ5c6W5ZWcJZcmXCQwspkCDZcmlEgBzgJcJgEk1pfAAgxV4iRwsZkCbALuA3eS0gMhAQAAA="))
///////////////////////////////////////////////
///////////////////////////////////////////////
/* Utility functions */
var storagePrefix = 'KiCad_HTML_BOM__' + pcbdata.metadata.title + '__' +
pcbdata.metadata.revision + '__#';
var storage;
function initStorage(key) {
try {
window.localStorage.getItem("blank");
storage = window.localStorage;
} catch (e) {
// localStorage not available
}
if (!storage) {
try {
window.sessionStorage.getItem("blank");
storage = window.sessionStorage;
} catch (e) {
// sessionStorage also not available
}
}
}
function readStorage(key) {
if (storage) {
return storage.getItem(storagePrefix + key);
} else {
return null;
}
}
function writeStorage(key, value) {
if (storage) {
storage.setItem(storagePrefix + key, value);
}
}
function fancyDblClickHandler(el, onsingle, ondouble) {
return function() {
if (el.getAttribute("data-dblclick") == null) {
el.setAttribute("data-dblclick", 1);
setTimeout(function() {
if (el.getAttribute("data-dblclick") == 1) {
onsingle();
}
el.removeAttribute("data-dblclick");
}, 200);
} else {
el.removeAttribute("data-dblclick");
ondouble();
}
}
}
function smoothScrollToRow(rowid) {
document.getElementById(rowid).scrollIntoView({
behavior: "smooth",
block: "center",
inline: "nearest"
});
}
function focusInputField(input) {
input.scrollIntoView(false);
input.focus();
input.select();
}
function saveBomTable(output) {
var text = '';
for (var node of bomhead.childNodes[0].childNodes) {
if (node.firstChild) {
text += (output == 'csv' ? `"${node.firstChild.nodeValue}"` : node.firstChild.nodeValue);
}
if (node != bomhead.childNodes[0].lastChild) {
text += (output == 'csv' ? ',' : '\t');
}
}
text += '\n';
for (var row of bombody.childNodes) {
for (var cell of row.childNodes) {
let val = '';
for (var node of cell.childNodes) {
if (node.nodeName == "INPUT") {
if (node.checked) {
val += '✓';
}
} else if (node.nodeName == "MARK") {
val += node.firstChild.nodeValue;
} else {
val += node.nodeValue;
}
}
if (output == 'csv') {
val = val.replace(/\"/g, '\"\"'); // pair of double-quote characters
if (isNumeric(val)) {
val = +val; // use number
} else {
val = `"${val}"`; // enclosed within double-quote
}
}
text += val;
if (cell != row.lastChild) {
text += (output == 'csv' ? ',' : '\t');
}
}
text += '\n';
}
if (output != 'clipboard') {
// To file: csv or txt
var blob = new Blob([text], {
type: `text/${output}`
});
saveFile(`${pcbdata.metadata.title}.${output}`, blob);
} else {
// To clipboard
var textArea = document.createElement("textarea");
textArea.classList.add('clipboard-temp');
textArea.value = text;
document.body.appendChild(textArea);
textArea.focus();
textArea.select();
try {
if (document.execCommand('copy')) {
console.log('Bom copied to clipboard.');
}
} catch (err) {
console.log('Can not copy to clipboard.');
}
document.body.removeChild(textArea);
}
}
function isNumeric(str) {
/* https://stackoverflow.com/a/175787 */
return (typeof str != "string" ? false : !isNaN(str) && !isNaN(parseFloat(str)));
}
function removeGutterNode(node) {
for (var i = 0; i < node.childNodes.length; i++) {
if (node.childNodes[i].classList &&
node.childNodes[i].classList.contains("gutter")) {
node.removeChild(node.childNodes[i]);
break;
}
}
}
function cleanGutters() {
removeGutterNode(document.getElementById("bot"));
removeGutterNode(document.getElementById("canvasdiv"));
}
var units = {
prefixes: {
giga: ["G", "g", "giga", "Giga", "GIGA"],
mega: ["M", "mega", "Mega", "MEGA"],
kilo: ["K", "k", "kilo", "Kilo", "KILO"],
milli: ["m", "milli", "Milli", "MILLI"],
micro: ["U", "u", "micro", "Micro", "MICRO", "μ", "µ"], // different utf8 μ
nano: ["N", "n", "nano", "Nano", "NANO"],
pico: ["P", "p", "pico", "Pico", "PICO"],
},
unitsShort: ["R", "r", "Ω", "F", "f", "H", "h"],
unitsLong: [
"OHM", "Ohm", "ohm", "ohms",
"FARAD", "Farad", "farad",
"HENRY", "Henry", "henry"
],
getMultiplier: function(s) {
if (this.prefixes.giga.includes(s)) return 1e9;
if (this.prefixes.mega.includes(s)) return 1e6;
if (this.prefixes.kilo.includes(s)) return 1e3;
if (this.prefixes.milli.includes(s)) return 1e-3;
if (this.prefixes.micro.includes(s)) return 1e-6;
if (this.prefixes.nano.includes(s)) return 1e-9;
if (this.prefixes.pico.includes(s)) return 1e-12;
return 1;
},
valueRegex: null,
}
function initUtils() {
var allPrefixes = units.prefixes.giga
.concat(units.prefixes.mega)
.concat(units.prefixes.kilo)
.concat(units.prefixes.milli)
.concat(units.prefixes.micro)
.concat(units.prefixes.nano)
.concat(units.prefixes.pico);
var allUnits = units.unitsShort.concat(units.unitsLong);
units.valueRegex = new RegExp("^([0-9\.]+)" +
"\\s*(" + allPrefixes.join("|") + ")?" +
"(" + allUnits.join("|") + ")?" +
"(\\b.*)?$", "");
units.valueAltRegex = new RegExp("^([0-9]*)" +
"(" + units.unitsShort.join("|") + ")?" +
"([GgMmKkUuNnPp])?" +
"([0-9]*)" +
"(\\b.*)?$", "");
if (config.fields.includes("Value")) {
var index = config.fields.indexOf("Value");
pcbdata.bom["parsedValues"] = {};
for (var id in pcbdata.bom.fields) {
pcbdata.bom.parsedValues[id] = parseValue(pcbdata.bom.fields[id][index])
}
}
}
function parseValue(val, ref) {
var inferUnit = (unit, ref) => {
if (unit) {
unit = unit.toLowerCase();
if (unit == 'Ω' || unit == "ohm" || unit == "ohms") {
unit = 'r';
}
unit = unit[0];
} else {
ref = /^([a-z]+)\d+$/i.exec(ref);
if (ref) {
ref = ref[1].toLowerCase();
if (ref == "c") unit = 'f';
else if (ref == "l") unit = 'h';
else if (ref == "r" || ref == "rv") unit = 'r';
else unit = null;
}
}
return unit;
};
val = val.replace(/,/g, "");
var match = units.valueRegex.exec(val);
var unit;
if (match) {
val = parseFloat(match[1]);
if (match[2]) {
val = val * units.getMultiplier(match[2]);
}
unit = inferUnit(match[3], ref);
if (!unit) return null;
else return {
val: val,
unit: unit,
extra: match[4],
}
}
match = units.valueAltRegex.exec(val);
if (match && (match[1] || match[4])) {
val = parseFloat(match[1] + "." + match[4]);
if (match[3]) {
val = val * units.getMultiplier(match[3]);
}
unit = inferUnit(match[2], ref);
if (!unit) return null;
else return {
val: val,
unit: unit,
extra: match[5],
}
}
return null;
}
function valueCompare(a, b, stra, strb) {
if (a === null && b === null) {
// Failed to parse both values, compare them as strings.
if (stra != strb) return stra > strb ? 1 : -1;
else return 0;
} else if (a === null) {
return 1;
} else if (b === null) {
return -1;
} else {
if (a.unit != b.unit) return a.unit > b.unit ? 1 : -1;
else if (a.val != b.val) return a.val > b.val ? 1 : -1;
else if (a.extra != b.extra) return a.extra > b.extra ? 1 : -1;
else return 0;
}
}
function validateSaveImgDimension(element) {
var valid = false;
var intValue = 0;
if (/^[1-9]\d*$/.test(element.value)) {
intValue = parseInt(element.value);
if (intValue <= 16000) {
valid = true;
}
}
if (valid) {
element.classList.remove("invalid");
} else {
element.classList.add("invalid");
}
return intValue;
}
function saveImage(layer) {
var width = validateSaveImgDimension(document.getElementById("render-save-width"));
var height = validateSaveImgDimension(document.getElementById("render-save-height"));
var bgcolor = null;
if (!document.getElementById("render-save-transparent").checked) {
var style = getComputedStyle(topmostdiv);
bgcolor = style.getPropertyValue("background-color");
}
if (!width || !height) return;
// Prepare image
var canvas = document.createElement("canvas");
var layerdict = {
transform: {
x: 0,
y: 0,
s: 1,
panx: 0,
pany: 0,
zoom: 1,
},
bg: canvas,
fab: canvas,
silk: canvas,
highlight: canvas,
layer: layer,
}
// Do the rendering
recalcLayerScale(layerdict, width, height);
prepareLayer(layerdict);
clearCanvas(canvas, bgcolor);
drawBackground(layerdict, false);
drawHighlightsOnLayer(layerdict, false);
// Save image
var imgdata = canvas.toDataURL("image/png");
var filename = pcbdata.metadata.title;
if (pcbdata.metadata.revision) {
filename += `.${pcbdata.metadata.revision}`;
}
filename += `.${layer}.png`;
saveFile(filename, dataURLtoBlob(imgdata));
}
function saveSettings() {
var data = {
type: "InteractiveHtmlBom settings",
version: 1,
pcbmetadata: pcbdata.metadata,
settings: settings,
}
var blob = new Blob([JSON.stringify(data, null, 4)], {
type: "application/json"
});
saveFile(`${pcbdata.metadata.title}.settings.json`, blob);
}
function loadSettings() {
var input = document.createElement("input");
input.type = "file";
input.accept = ".settings.json";
input.onchange = function(e) {
var file = e.target.files[0];
var reader = new FileReader();
reader.onload = readerEvent => {
var content = readerEvent.target.result;
var newSettings;
try {
newSettings = JSON.parse(content);
} catch (e) {
alert("Selected file is not InteractiveHtmlBom settings file.");
return;
}
if (newSettings.type != "InteractiveHtmlBom settings") {
alert("Selected file is not InteractiveHtmlBom settings file.");
return;
}
var metadataMatches = newSettings.hasOwnProperty("pcbmetadata");
if (metadataMatches) {
for (var k in pcbdata.metadata) {
if (!newSettings.pcbmetadata.hasOwnProperty(k) || newSettings.pcbmetadata[k] != pcbdata.metadata[k]) {
metadataMatches = false;
}
}
}
if (!metadataMatches) {
var currentMetadata = JSON.stringify(pcbdata.metadata, null, 4);
var fileMetadata = JSON.stringify(newSettings.pcbmetadata, null, 4);
if (!confirm(
`Settins file metadata does not match current metadata.\n\n` +
`Page metadata:\n${currentMetadata}\n\n` +
`Settings file metadata:\n${fileMetadata}\n\n` +
`Press OK if you would like to import settings anyway.`)) {
return;
}
}
overwriteSettings(newSettings.settings);
}
reader.readAsText(file, 'UTF-8');
}
input.click();
}
function overwriteSettings(newSettings) {
initDone = false;
Object.assign(settings, newSettings);
writeStorage("bomlayout", settings.bomlayout);
writeStorage("bommode", settings.bommode);
writeStorage("canvaslayout", settings.canvaslayout);
writeStorage("bomCheckboxes", settings.checkboxes.join(","));
document.getElementById("bomCheckboxes").value = settings.checkboxes.join(",");
for (var checkbox of settings.checkboxes) {
writeStorage("checkbox_" + checkbox, settings.checkboxStoredRefs[checkbox]);
}
writeStorage("markWhenChecked", settings.markWhenChecked);
padsVisible(settings.renderPads);
document.getElementById("padsCheckbox").checked = settings.renderPads;
fabricationVisible(settings.renderFabrication);
document.getElementById("fabricationCheckbox").checked = settings.renderFabrication;
silkscreenVisible(settings.renderSilkscreen);
document.getElementById("silkscreenCheckbox").checked = settings.renderSilkscreen;
referencesVisible(settings.renderReferences);
document.getElementById("referencesCheckbox").checked = settings.renderReferences;
valuesVisible(settings.renderValues);
document.getElementById("valuesCheckbox").checked = settings.renderValues;
tracksVisible(settings.renderTracks);
document.getElementById("tracksCheckbox").checked = settings.renderTracks;
zonesVisible(settings.renderZones);
document.getElementById("zonesCheckbox").checked = settings.renderZones;
dnpOutline(settings.renderDnpOutline);
document.getElementById("dnpOutlineCheckbox").checked = settings.renderDnpOutline;
setRedrawOnDrag(settings.redrawOnDrag);
document.getElementById("dragCheckbox").checked = settings.redrawOnDrag;
setDarkMode(settings.darkMode);
document.getElementById("darkmodeCheckbox").checked = settings.darkMode;
setHighlightPin1(settings.highlightpin1);
document.getElementById("highlightpin1Checkbox").checked = settings.highlightpin1;
showFootprints(settings.show_footprints);
writeStorage("boardRotation", settings.boardRotation);
document.getElementById("boardRotation").value = settings.boardRotation / 5;
document.getElementById("rotationDegree").textContent = settings.boardRotation;
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: "default",
bomlayout: "default",
bommode: "grouped",
checkboxes: [],
checkboxStoredRefs: {},
darkMode: false,
highlightpin1: false,
redrawOnDrag: true,
boardRotation: 0,
renderPads: true,
renderReferences: true,
renderValues: true,
renderSilkscreen: true,
renderFabrication: true,
renderDnpOutline: false,
renderTracks: true,
renderZones: true,
columnOrder: [],
hiddenColumns: [],
}
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 (!["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;
settings.markWhenChecked = readStorage("markWhenChecked") || "";
populateMarkWhenCheckedOptions();
function initBooleanSetting(storageString, def, elementId, func) {
var b = readStorage(storageString);
if (b === null) {
b = def;
} else {
b = (b == "true");
}
document.getElementById(elementId).checked = b;
func(b);
}
initBooleanSetting("padsVisible", config.show_pads, "padsCheckbox", padsVisible);
initBooleanSetting("fabricationVisible", config.show_fabrication, "fabricationCheckbox", fabricationVisible);
initBooleanSetting("silkscreenVisible", config.show_silkscreen, "silkscreenCheckbox", silkscreenVisible);
initBooleanSetting("referencesVisible", true, "referencesCheckbox", referencesVisible);
initBooleanSetting("valuesVisible", true, "valuesCheckbox", valuesVisible);
if ("tracks" in pcbdata) {
initBooleanSetting("tracksVisible", true, "tracksCheckbox", tracksVisible);
initBooleanSetting("zonesVisible", true, "zonesCheckbox", zonesVisible);
} else {
document.getElementById("tracksAndZonesCheckboxes").style.display = "none";
tracksVisible(false);
zonesVisible(false);
}
initBooleanSetting("dnpOutline", false, "dnpOutlineCheckbox", dnpOutline);
initBooleanSetting("redrawOnDrag", config.redraw_on_drag, "dragCheckbox", setRedrawOnDrag);
initBooleanSetting("darkmode", config.dark_mode, "darkmodeCheckbox", setDarkMode);
initBooleanSetting("highlightpin1", config.highlight_pin1, "highlightpin1Checkbox", setHighlightPin1);
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;
}
// 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 (txt[i][j] == '\t') {
var fourSpaces = 4 * pcbdata.font_data[' '].w * text.width;
offsetx += fourSpaces - offsetx % fourSpaces;
continue;
} else if (txt[i][j] == '~') {
j++;
if (j == txt[i].length)
break;
if (txt[i][j] != '~') {
inOverbar = !inOverbar;
}
}
var glyph = pcbdata.font_data[txt[i][j]];
if (inOverbar) {
var overbarStart = [offsetx, -text.height * 1.4 + offsety];
var overbarEnd = [offsetx + text.width * glyph.w, overbarStart[1]];
if (!lastHadOverbar) {
overbarStart[0] += text.height * 1.4 * tilt;
lastHadOverbar = true;
}
ctx.beginPath();
ctx.moveTo(...overbarStart);
ctx.lineTo(...overbarEnd);
ctx.stroke();
} else {
lastHadOverbar = false;
}
for (var line of glyph.l) {
ctx.beginPath();
ctx.moveTo(...calcFontPoint(line[0], text, offsetx, offsety, tilt));
for (var k = 1; k < line.length; k++) {
ctx.lineTo(...calcFontPoint(line[k], text, offsetx, offsety, tilt));
}
ctx.stroke();
}
offsetx += glyph.w * text.width;
}
offsety += interline;
}
ctx.restore();
}
function drawedge(ctx, scalefactor, edge, color) {
ctx.strokeStyle = color;
ctx.fillStyle = color;
ctx.lineWidth = Math.max(1 / scalefactor, edge.width);
ctx.lineCap = "round";
ctx.lineJoin = "round";
if ("svgpath" in edge) {
ctx.stroke(new Path2D(edge.svgpath));
} else {
ctx.beginPath();
if (edge.type == "segment") {
ctx.moveTo(...edge.start);
ctx.lineTo(...edge.end);
}
if (edge.type == "rect") {
ctx.moveTo(...edge.start);
ctx.lineTo(edge.start[0], edge.end[1]);
ctx.lineTo(...edge.end);
ctx.lineTo(edge.end[0], edge.start[1]);
ctx.lineTo(...edge.start);
}
if (edge.type == "arc") {
ctx.arc(
...edge.start,
edge.radius,
deg2rad(edge.startangle),
deg2rad(edge.endangle));
}
if (edge.type == "circle") {
ctx.arc(
...edge.start,
edge.radius,
0, 2 * Math.PI);
ctx.closePath();
}
if (edge.type == "curve") {
ctx.moveTo(...edge.start);
ctx.bezierCurveTo(...edge.cpa, ...edge.cpb, ...edge.end);
}
if("filled" in edge && edge.filled)
ctx.fill();
else
ctx.stroke();
}
}
function getChamferedRectPath(size, radius, chamfpos, chamfratio) {
// chamfpos is a bitmask, left = 1, right = 2, bottom left = 4, bottom right = 8
var path = new Path2D();
var width = size[0];
var height = size[1];
var x = width * -0.5;
var y = height * -0.5;
var chamfOffset = Math.min(width, height) * chamfratio;
path.moveTo(x, 0);
if (chamfpos & 4) {
path.lineTo(x, y + height - chamfOffset);
path.lineTo(x + chamfOffset, y + height);
path.lineTo(0, y + height);
} else {
path.arcTo(x, y + height, x + width, y + height, radius);
}
if (chamfpos & 8) {
path.lineTo(x + width - chamfOffset, y + height);
path.lineTo(x + width, y + height - chamfOffset);
path.lineTo(x + width, 0);
} else {
path.arcTo(x + width, y + height, x + width, y, radius);
}
if (chamfpos & 2) {
path.lineTo(x + width, y + chamfOffset);
path.lineTo(x + width - chamfOffset, y);
path.lineTo(0, y);
} else {
path.arcTo(x + width, y, x, y, radius);
}
if (chamfpos & 1) {
path.lineTo(x + chamfOffset, y);
path.lineTo(x, y + chamfOffset);
path.lineTo(x, 0);
} else {
path.arcTo(x, y, x, y + height, radius);
}
path.closePath();
return path;
}
function getOblongPath(size) {
return getChamferedRectPath(size, Math.min(size[0], size[1]) / 2, 0, 0);
}
function getPolygonsPath(shape) {
if (shape.path2d) {
return shape.path2d;
}
if ("svgpath" in shape) {
shape.path2d = new Path2D(shape.svgpath);
} else {
var path = new Path2D();
for (var polygon of shape.polygons) {
path.moveTo(...polygon[0]);
for (var i = 1; i < polygon.length; i++) {
path.lineTo(...polygon[i]);
}
path.closePath();
}
shape.path2d = path;
}
return shape.path2d;
}
function drawPolygonShape(ctx, scalefactor, shape, color) {
ctx.save();
if (!("svgpath" in shape)) {
ctx.translate(...shape.pos);
ctx.rotate(deg2rad(-shape.angle));
}
if("filled" in shape && !shape.filled) {
ctx.strokeStyle = color;
ctx.lineWidth = Math.max(1 / scalefactor, shape.width);
ctx.lineCap = "round";
ctx.lineJoin = "round";
ctx.stroke(getPolygonsPath(shape));
} else {
ctx.fillStyle = color;
ctx.fill(getPolygonsPath(shape));
}
ctx.restore();
}
function drawDrawing(ctx, scalefactor, drawing, color) {
if (["segment", "arc", "circle", "curve", "rect"].includes(drawing.type)) {
drawedge(ctx, scalefactor, drawing, color);
} else if (drawing.type == "polygon") {
drawPolygonShape(ctx, scalefactor, drawing, color);
} else {
drawText(ctx, drawing, color);
}
}
function getCirclePath(radius) {
var path = new Path2D();
path.arc(0, 0, radius, 0, 2 * Math.PI);
path.closePath();
return path;
}
function getCachedPadPath(pad) {
if (!pad.path2d) {
// if path2d is not set, build one and cache it on pad object
if (pad.shape == "rect") {
pad.path2d = new Path2D();
pad.path2d.rect(...pad.size.map(c => -c * 0.5), ...pad.size);
} else if (pad.shape == "oval") {
pad.path2d = getOblongPath(pad.size);
} else if (pad.shape == "circle") {
pad.path2d = getCirclePath(pad.size[0] / 2);
} else if (pad.shape == "roundrect") {
pad.path2d = getChamferedRectPath(pad.size, pad.radius, 0, 0);
} else if (pad.shape == "chamfrect") {
pad.path2d = getChamferedRectPath(pad.size, pad.radius, pad.chamfpos, pad.chamfratio)
} else if (pad.shape == "custom") {
pad.path2d = getPolygonsPath(pad);
}
}
return pad.path2d;
}
function drawPad(ctx, pad, color, outline) {
ctx.save();
ctx.translate(...pad.pos);
ctx.rotate(-deg2rad(pad.angle));
if (pad.offset) {
ctx.translate(...pad.offset);
}
ctx.fillStyle = color;
ctx.strokeStyle = color;
var path = getCachedPadPath(pad);
if (outline) {
ctx.stroke(path);
} else {
ctx.fill(path);
}
ctx.restore();
}
function drawPadHole(ctx, pad, padHoleColor) {
if (pad.type != "th") return;
ctx.save();
ctx.translate(...pad.pos);
ctx.rotate(-deg2rad(pad.angle));
ctx.fillStyle = padHoleColor;
if (pad.drillshape == "oblong") {
ctx.fill(getOblongPath(pad.drillsize));
} else {
ctx.fill(getCirclePath(pad.drillsize[0] / 2));
}
ctx.restore();
}
function drawFootprint(ctx, layer, scalefactor, footprint, colors, highlight, outline) {
if (highlight) {
// draw bounding box
if (footprint.layer == layer) {
ctx.save();
ctx.globalAlpha = 0.2;
ctx.translate(...footprint.bbox.pos);
ctx.rotate(deg2rad(-footprint.bbox.angle));
ctx.translate(...footprint.bbox.relpos);
ctx.fillStyle = colors.pad;
ctx.fillRect(0, 0, ...footprint.bbox.size);
ctx.globalAlpha = 1;
ctx.strokeStyle = colors.pad;
ctx.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);
}
}
// 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) {
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, color, highlight) {
ctx = canvas.getContext("2d");
ctx.strokeStyle = color;
ctx.lineCap = "round";
for (var track of pcbdata.tracks[layer]) {
if (highlight && highlightedNet != track.net) continue;
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();
}
}
function drawZones(canvas, layer, color, highlight) {
ctx = canvas.getContext("2d");
ctx.strokeStyle = color;
ctx.fillStyle = color;
ctx.lineJoin = "round";
for (var zone of pcbdata.zones[layer]) {
if (!zone.path2d) {
zone.path2d = getPolygonsPath(zone);
}
if (highlight && highlightedNet != zone.net) continue;
ctx.fill(zone.path2d);
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.renderTracks) {
var trackColor = style.getPropertyValue(highlight ? '--track-color-highlight' : '--track-color');
drawTracks(canvas, layer, trackColor, highlight);
}
if (settings.renderZones) {
var zoneColor = style.getPropertyValue(highlight ? '--zone-color-highlight' : '--zone-color');
drawZones(canvas, layer, zoneColor, 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));
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) {
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));
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 bbox = applyRotation(pcbdata.edges_bbox);
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;
var flip = (layerdict.layer == "B");
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;
if (layerdict.layer == "B") {
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);
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 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();
}
function setShowBOMColumn(field, value) {
if (field === "references") {
var rl = document.getElementById("reflookup");
rl.disabled = !value;
if (!value) {
rl.value = "";
updateRefLookup("");
}
}
var n = settings.hiddenColumns.indexOf(field);
if (value) {
if (n != -1) {
settings.hiddenColumns.splice(n, 1);
}
} else {
if (n == -1) {
settings.hiddenColumns.push(field);
}
}
writeStorage("hiddenColumns", JSON.stringify(settings.hiddenColumns));
if (initDone) {
populateBomTable();
}
redrawIfInitDone();
}
function setFullscreen(value) {
if (value) {
document.documentElement.requestFullscreen();
} else {
document.exitFullscreen();
}
}
function fabricationVisible(value) {
writeStorage("fabricationVisible", value);
settings.renderFabrication = value;
redrawIfInitDone();
}
function silkscreenVisible(value) {
writeStorage("silkscreenVisible", value);
settings.renderSilkscreen = value;
redrawIfInitDone();
}
function setHighlightPin1(value) {
writeStorage("highlightpin1", value);
settings.highlightpin1 = value;
redrawIfInitDone();
}
function getStoredCheckboxRefs(checkbox) {
function convert(ref) {
var intref = parseInt(ref);
if (isNaN(intref)) {
for (var i = 0; i < pcbdata.footprints.length; i++) {
if (pcbdata.footprints[i].ref == ref) {
return i;
}
}
return -1;
} else {
return intref;
}
}
if (!(checkbox in settings.checkboxStoredRefs)) {
var val = readStorage("checkbox_" + checkbox);
settings.checkboxStoredRefs[checkbox] = val ? val : "";
}
if (!settings.checkboxStoredRefs[checkbox]) {
return new Set();
} else {
return new Set(settings.checkboxStoredRefs[checkbox].split(",").map(r => convert(r)).filter(a => a >= 0));
}
}
function getCheckboxState(checkbox, references) {
var storedRefsSet = getStoredCheckboxRefs(checkbox);
var currentRefsSet = new Set(references.map(r => r[1]));
// Get difference of current - stored
var difference = new Set(currentRefsSet);
for (ref of storedRefsSet) {
difference.delete(ref);
}
if (difference.size == 0) {
// All the current refs are stored
return "checked";
} else if (difference.size == currentRefsSet.size) {
// None of the current refs are stored
return "unchecked";
} else {
// Some of the refs are stored
return "indeterminate";
}
}
function setBomCheckboxState(checkbox, element, references) {
var state = getCheckboxState(checkbox, references);
element.checked = (state == "checked");
element.indeterminate = (state == "indeterminate");
}
function createCheckboxChangeHandler(checkbox, references, row) {
return function () {
refsSet = getStoredCheckboxRefs(checkbox);
var markWhenChecked = settings.markWhenChecked == checkbox;
eventArgs = {
checkbox: checkbox,
refs: references,
}
if (this.checked) {
// checkbox ticked
for (var ref of references) {
refsSet.add(ref[1]);
}
if (markWhenChecked) {
row.classList.add("checked");
for (var ref of references) {
markedFootprints.add(ref[1]);
}
drawHighlights();
}
eventArgs.state = 'checked';
} else {
// checkbox unticked
for (var ref of references) {
refsSet.delete(ref[1]);
}
if (markWhenChecked) {
row.classList.remove("checked");
for (var ref of references) {
markedFootprints.delete(ref[1]);
}
drawHighlights();
}
eventArgs.state = 'unchecked';
}
settings.checkboxStoredRefs[checkbox] = [...refsSet].join(",");
writeStorage("checkbox_" + checkbox, settings.checkboxStoredRefs[checkbox]);
updateCheckboxStats(checkbox);
EventHandler.emitEvent(IBOM_EVENT_TYPES.CHECKBOX_CHANGE_EVENT, eventArgs);
}
}
function clearHighlightedFootprints() {
if (currentHighlightedRowId) {
document.getElementById(currentHighlightedRowId).classList.remove("highlighted");
currentHighlightedRowId = null;
highlightedFootprints = [];
highlightedNet = null;
}
}
function createRowHighlightHandler(rowid, refs, net) {
return function () {
if (currentHighlightedRowId) {
if (currentHighlightedRowId == rowid) {
return;
}
document.getElementById(currentHighlightedRowId).classList.remove("highlighted");
}
document.getElementById(rowid).classList.add("highlighted");
currentHighlightedRowId = rowid;
highlightedFootprints = refs ? refs.map(r => r[1]) : [];
highlightedNet = net;
drawHighlights();
EventHandler.emitEvent(
IBOM_EVENT_TYPES.HIGHLIGHT_EVENT, {
rowid: rowid,
refs: refs,
net: net
});
}
}
function 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 (pcbdata.bom.fields[ref[1]][i].toLowerCase().indexOf(filter) >= 0) {
return true;
}
}
}
}
return false;
}
function findRefInEntry(entry) {
return entry.filter(r => r[0].toLowerCase() == reflookup);
}
function highlightFilter(s) {
if (!filter) {
return s;
}
var parts = s.toLowerCase().split(filter);
if (parts.length == 1) {
return s;
}
var r = "";
var pos = 0;
for (var i in parts) {
if (i > 0) {
r += '<mark class="highlight">' +
s.substring(pos, pos + filter.length) +
'</mark>';
pos += filter.length;
}
r += s.substring(pos, pos + parts[i].length);
pos += parts[i].length;
}
return r;
}
function checkboxSetUnsetAllHandler(checkboxname) {
return function () {
var checkboxnum = 0;
while (checkboxnum < settings.checkboxes.length &&
settings.checkboxes[checkboxnum].toLowerCase() != checkboxname.toLowerCase()) {
checkboxnum++;
}
if (checkboxnum >= settings.checkboxes.length) {
return;
}
var allset = true;
var checkbox;
var row;
for (row of bombody.childNodes) {
checkbox = row.childNodes[checkboxnum + 1].childNodes[0];
if (!checkbox.checked || checkbox.indeterminate) {
allset = false;
break;
}
}
for (row of bombody.childNodes) {
checkbox = row.childNodes[checkboxnum + 1].childNodes[0];
checkbox.checked = !allset;
checkbox.indeterminate = false;
checkbox.onchange();
}
}
}
function createColumnHeader(name, cls, comparator, is_checkbox = false) {
var th = document.createElement("TH");
th.innerHTML = name;
th.classList.add(cls);
if (is_checkbox)
th.setAttribute("col_name", "bom-checkbox");
else
th.setAttribute("col_name", name);
var span = document.createElement("SPAN");
span.classList.add("sortmark");
span.classList.add("none");
th.appendChild(span);
var spacer = document.createElement("div");
spacer.className = "column-spacer";
th.appendChild(spacer);
spacer.onclick = function () {
if (currentSortColumn && th !== currentSortColumn) {
// Currently sorted by another column
currentSortColumn.childNodes[1].classList.remove(currentSortOrder);
currentSortColumn.childNodes[1].classList.add("none");
currentSortColumn = null;
currentSortOrder = null;
}
if (currentSortColumn && th === currentSortColumn) {
// Already sorted by this column
if (currentSortOrder == "asc") {
// Sort by this column, descending order
bomSortFunction = function (a, b) {
return -comparator(a, b);
}
currentSortColumn.childNodes[1].classList.remove("asc");
currentSortColumn.childNodes[1].classList.add("desc");
currentSortOrder = "desc";
} else {
// Unsort
bomSortFunction = null;
currentSortColumn.childNodes[1].classList.remove("desc");
currentSortColumn.childNodes[1].classList.add("none");
currentSortColumn = null;
currentSortOrder = null;
}
} else {
// Sort by this column, ascending order
bomSortFunction = comparator;
currentSortColumn = th;
currentSortColumn.childNodes[1].classList.remove("none");
currentSortColumn.childNodes[1].classList.add("asc");
currentSortOrder = "asc";
}
populateBomBody();
}
if (is_checkbox) {
spacer.onclick = fancyDblClickHandler(
spacer, spacer.onclick, checkboxSetUnsetAllHandler(name));
}
return th;
}
function populateBomHeader(placeHolderColumn = null, placeHolderElements = null) {
while (bomhead.firstChild) {
bomhead.removeChild(bomhead.firstChild);
}
var tr = document.createElement("TR");
var th = document.createElement("TH");
th.classList.add("numCol");
var vismenu = document.createElement("div");
vismenu.id = "vismenu";
vismenu.classList.add("menu");
var visbutton = document.createElement("div");
visbutton.classList.add("visbtn");
visbutton.classList.add("hideonprint");
var viscontent = document.createElement("div");
viscontent.classList.add("menu-content");
viscontent.id = "vismenu-content";
settings.columnOrder.forEach(column => {
if (typeof column !== "string")
return;
// Skip empty columns
if (column === "checkboxes" && settings.checkboxes.length == 0)
return;
else if (column === "Quantity" && settings.bommode == "ungrouped")
return;
var label = document.createElement("label");
label.classList.add("menu-label");
var input = document.createElement("input");
input.classList.add("visibility_checkbox");
input.type = "checkbox";
input.onchange = function (e) {
setShowBOMColumn(column, e.target.checked)
};
input.checked = !(settings.hiddenColumns.includes(column));
label.appendChild(input);
if (column.length > 0)
label.append(column[0].toUpperCase() + column.slice(1));
viscontent.appendChild(label);
});
viscontent.childNodes[0].classList.add("menu-label-top");
vismenu.appendChild(visbutton);
if (settings.bommode != "netlist") {
vismenu.appendChild(viscontent);
th.appendChild(vismenu);
}
tr.appendChild(th);
var checkboxCompareClosure = function (checkbox) {
return (a, b) => {
var stateA = getCheckboxState(checkbox, a);
var stateB = getCheckboxState(checkbox, b);
if (stateA > stateB) return -1;
if (stateA < stateB) return 1;
return 0;
}
}
var stringFieldCompareClosure = function (fieldIndex) {
return (a, b) => {
var fa = pcbdata.bom.fields[a[0][1]][fieldIndex];
var fb = pcbdata.bom.fields[b[0][1]][fieldIndex];
if (fa != fb) return fa > fb ? 1 : -1;
else return 0;
}
}
var referenceRegex = /(?<prefix>[^0-9]+)(?<number>[0-9]+)/;
var compareRefs = (a, b) => {
var ra = referenceRegex.exec(a);
var rb = referenceRegex.exec(b);
if (ra === null || rb === null) {
if (a != b) return a > b ? 1 : -1;
return 0;
} else {
if (ra.groups.prefix != rb.groups.prefix) {
return ra.groups.prefix > rb.groups.prefix ? 1 : -1;
}
if (ra.groups.number != rb.groups.number) {
return parseInt(ra.groups.number) > parseInt(rb.groups.number) ? 1 : -1;
}
return 0;
}
}
if (settings.bommode == "netlist") {
th = createColumnHeader("Net name", "bom-netname", (a, b) => {
if (a > b) return -1;
if (a < b) return 1;
return 0;
});
tr.appendChild(th);
} else {
// Filter hidden columns
var columns = settings.columnOrder.filter(e => !settings.hiddenColumns.includes(e));
var valueIndex = config.fields.indexOf("Value");
var footprintIndex = config.fields.indexOf("Footprint");
columns.forEach((column) => {
if (column === placeHolderColumn) {
var n = 1;
if (column === "checkboxes")
n = settings.checkboxes.length;
for (i = 0; i < n; i++) {
td = placeHolderElements.shift();
tr.appendChild(td);
}
return;
} else if (column === "checkboxes") {
for (var checkbox of settings.checkboxes) {
th = createColumnHeader(
checkbox, "bom-checkbox", checkboxCompareClosure(checkbox), true);
tr.appendChild(th);
}
} else if (column === "References") {
tr.appendChild(createColumnHeader("References", "references", (a, b) => {
var i = 0;
while (i < a.length && i < b.length) {
if (a[i] != b[i]) return compareRefs(a[i][0], b[i][0]);
i++;
}
return a.length - b.length;
}));
} else if (column === "Value") {
tr.appendChild(createColumnHeader("Value", "value", (a, b) => {
var ra = a[0][1], rb = b[0][1];
return valueCompare(
pcbdata.bom.parsedValues[ra], pcbdata.bom.parsedValues[rb],
pcbdata.bom.fields[ra][valueIndex], pcbdata.bom.fields[rb][valueIndex]);
}));
return;
} else if (column === "Footprint") {
tr.appendChild(createColumnHeader(
"Footprint", "footprint", stringFieldCompareClosure(footprintIndex)));
} else if (column === "Quantity" && settings.bommode == "grouped") {
tr.appendChild(createColumnHeader("Quantity", "quantity", (a, b) => {
return a.length - b.length;
}));
} else {
// Other fields
var i = config.fields.indexOf(column);
if (i < 0)
return;
tr.appendChild(createColumnHeader(
column, `field${i + 1}`, stringFieldCompareClosure(i)));
}
});
}
bomhead.appendChild(tr);
}
function populateBomBody(placeholderColumn = null, placeHolderElements = null) {
while (bom.firstChild) {
bom.removeChild(bom.firstChild);
}
highlightHandlers = [];
footprintIndexToHandler = {};
netsToHandler = {};
currentHighlightedRowId = null;
var first = true;
if (settings.bommode == "netlist") {
bomtable = pcbdata.nets.slice();
} else {
switch (settings.canvaslayout) {
case 'F':
bomtable = pcbdata.bom.F.slice();
break;
case 'FB':
bomtable = pcbdata.bom.both.slice();
break;
case 'B':
bomtable = pcbdata.bom.B.slice();
break;
}
if (settings.bommode == "ungrouped") {
// expand bom table
expandedTable = []
for (var bomentry of bomtable) {
for (var ref of bomentry) {
expandedTable.push([ref]);
}
}
bomtable = expandedTable;
}
}
if (bomSortFunction) {
bomtable = bomtable.sort(bomSortFunction);
}
for (var i in bomtable) {
var bomentry = bomtable[i];
if (filter && !entryMatches(bomentry)) {
continue;
}
var references = null;
var netname = null;
var tr = document.createElement("TR");
var td = document.createElement("TD");
var rownum = +i + 1;
tr.id = "bomrow" + rownum;
td.textContent = rownum;
tr.appendChild(td);
if (settings.bommode == "netlist") {
netname = bomentry;
td = document.createElement("TD");
td.innerHTML = highlightFilter(netname ? netname : "&lt;no net&gt;");
tr.appendChild(td);
} else {
if (reflookup) {
references = findRefInEntry(bomentry);
if (references.length == 0) {
continue;
}
} else {
references = bomentry;
}
// Filter hidden columns
var columns = settings.columnOrder.filter(e => !settings.hiddenColumns.includes(e));
columns.forEach((column) => {
if (column === placeholderColumn) {
var n = 1;
if (column === "checkboxes")
n = settings.checkboxes.length;
for (i = 0; i < n; i++) {
td = placeHolderElements.shift();
tr.appendChild(td);
}
return;
} else if (column === "checkboxes") {
for (var checkbox of settings.checkboxes) {
if (checkbox) {
td = document.createElement("TD");
var input = document.createElement("input");
input.type = "checkbox";
input.onchange = createCheckboxChangeHandler(checkbox, references, tr);
setBomCheckboxState(checkbox, input, references);
if (input.checked && settings.markWhenChecked == checkbox) {
tr.classList.add("checked");
}
td.appendChild(input);
tr.appendChild(td);
}
}
} else if (column === "References") {
td = document.createElement("TD");
td.innerHTML = highlightFilter(references.map(r => r[0]).join(", "));
tr.appendChild(td);
} else if (column === "Quantity" && settings.bommode == "grouped") {
// Quantity
td = document.createElement("TD");
td.textContent = references.length;
tr.appendChild(td);
} else {
// All the other fields
var field_index = config.fields.indexOf(column)
if (field_index < 0)
return;
var valueSet = new Set();
references.map(r => r[1]).forEach((id) => valueSet.add(pcbdata.bom.fields[id][field_index]));
td = document.createElement("TD");
td.innerHTML = highlightFilter(Array.from(valueSet).join(", "));
tr.appendChild(td);
}
});
}
bom.appendChild(tr);
var handler = createRowHighlightHandler(tr.id, references, netname);
tr.onmousemove = handler;
highlightHandlers.push({
id: tr.id,
handler: handler,
});
if (references !== null) {
for (var refIndex of references.map(r => r[1])) {
footprintIndexToHandler[refIndex] = handler;
}
}
if (netname !== null) {
netsToHandler[netname] = handler;
}
if ((filter || reflookup) && first) {
handler();
first = false;
}
}
EventHandler.emitEvent(
IBOM_EVENT_TYPES.BOM_BODY_CHANGE_EVENT, {
filter: filter,
reflookup: reflookup,
checkboxes: settings.checkboxes,
bommode: settings.bommode,
});
}
function highlightPreviousRow() {
if (!currentHighlightedRowId) {
highlightHandlers[highlightHandlers.length - 1].handler();
} else {
if (highlightHandlers.length > 1 &&
highlightHandlers[0].id == currentHighlightedRowId) {
highlightHandlers[highlightHandlers.length - 1].handler();
} else {
for (var i = 0; i < highlightHandlers.length - 1; i++) {
if (highlightHandlers[i + 1].id == currentHighlightedRowId) {
highlightHandlers[i].handler();
break;
}
}
}
}
smoothScrollToRow(currentHighlightedRowId);
}
function highlightNextRow() {
if (!currentHighlightedRowId) {
highlightHandlers[0].handler();
} else {
if (highlightHandlers.length > 1 &&
highlightHandlers[highlightHandlers.length - 1].id == currentHighlightedRowId) {
highlightHandlers[0].handler();
} else {
for (var i = 1; i < highlightHandlers.length; i++) {
if (highlightHandlers[i - 1].id == currentHighlightedRowId) {
highlightHandlers[i].handler();
break;
}
}
}
}
smoothScrollToRow(currentHighlightedRowId);
}
function populateBomTable() {
populateBomHeader();
populateBomBody();
setBomHandlers();
resizableGrid(bomhead);
}
function footprintsClicked(footprintIndexes) {
var lastClickedIndex = footprintIndexes.indexOf(lastClicked);
for (var i = 1; i <= footprintIndexes.length; i++) {
var refIndex = footprintIndexes[(lastClickedIndex + i) % footprintIndexes.length];
if (refIndex in footprintIndexToHandler) {
lastClicked = refIndex;
footprintIndexToHandler[refIndex]();
smoothScrollToRow(currentHighlightedRowId);
break;
}
}
}
function netClicked(net) {
if (net in netsToHandler) {
netsToHandler[net]();
smoothScrollToRow(currentHighlightedRowId);
} else {
clearHighlightedFootprints();
highlightedNet = net;
drawHighlights();
}
}
function updateFilter(input) {
filter = input.toLowerCase();
populateBomTable();
}
function updateRefLookup(input) {
reflookup = input.toLowerCase();
populateBomTable();
}
function changeCanvasLayout(layout) {
document.getElementById("fl-btn").classList.remove("depressed");
document.getElementById("fb-btn").classList.remove("depressed");
document.getElementById("bl-btn").classList.remove("depressed");
switch (layout) {
case 'F':
document.getElementById("fl-btn").classList.add("depressed");
if (settings.bomlayout != "bom-only") {
canvassplit.collapse(1);
}
break;
case 'B':
document.getElementById("bl-btn").classList.add("depressed");
if (settings.bomlayout != "bom-only") {
canvassplit.collapse(0);
}
break;
default:
document.getElementById("fb-btn").classList.add("depressed");
if (settings.bomlayout != "bom-only") {
canvassplit.setSizes([50, 50]);
}
}
settings.canvaslayout = layout;
writeStorage("canvaslayout", layout);
resizeAll();
changeBomMode(settings.bommode);
}
function populateMetadata() {
document.getElementById("title").innerHTML = pcbdata.metadata.title;
document.getElementById("revision").innerHTML = "Rev: " + pcbdata.metadata.revision;
document.getElementById("company").innerHTML = pcbdata.metadata.company;
document.getElementById("filedate").innerHTML = pcbdata.metadata.date;
if (pcbdata.metadata.title != "") {
document.title = pcbdata.metadata.title + " BOM";
}
// Calculate board stats
var fp_f = 0,
fp_b = 0,
pads_f = 0,
pads_b = 0,
pads_th = 0;
for (var i = 0; i < pcbdata.footprints.length; i++) {
if (pcbdata.bom.skipped.includes(i)) continue;
var mod = pcbdata.footprints[i];
if (mod.layer == "F") {
fp_f++;
} else {
fp_b++;
}
for (var pad of mod.pads) {
if (pad.type == "th") {
pads_th++;
} else {
if (pad.layers.includes("F")) {
pads_f++;
}
if (pad.layers.includes("B")) {
pads_b++;
}
}
}
}
document.getElementById("stats-components-front").innerHTML = fp_f;
document.getElementById("stats-components-back").innerHTML = fp_b;
document.getElementById("stats-components-total").innerHTML = fp_f + fp_b;
document.getElementById("stats-groups-front").innerHTML = pcbdata.bom.F.length;
document.getElementById("stats-groups-back").innerHTML = pcbdata.bom.B.length;
document.getElementById("stats-groups-total").innerHTML = pcbdata.bom.both.length;
document.getElementById("stats-smd-pads-front").innerHTML = pads_f;
document.getElementById("stats-smd-pads-back").innerHTML = pads_b;
document.getElementById("stats-smd-pads-total").innerHTML = pads_f + pads_b;
document.getElementById("stats-th-pads").innerHTML = pads_th;
// Update version string
document.getElementById("github-link").innerHTML = "InteractiveHtmlBom&nbsp;" +
/^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("bot").style.height = "";
break;
case 'top-bottom':
document.getElementById("tb-btn").classList.add("depressed");
document.getElementById("frontcanvas").style.display = "";
document.getElementById("backcanvas").style.display = "";
document.getElementById("bot").style.height = "calc(100% - 80px)";
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("bot").style.height = "calc(100% - 80px)";
document.getElementById("bomdiv").classList.add("split-horizontal");
document.getElementById("canvasdiv").classList.add("split-horizontal");
document.getElementById("frontcanvas").classList.remove("split-horizontal");
document.getElementById("backcanvas").classList.remove("split-horizontal");
if (bomsplit) {
bomsplit.destroy();
bomsplit = null;
canvassplit.destroy();
canvassplit = null;
}
bomsplit = Split(['#bomdiv', '#canvasdiv'], {
sizes: [50, 50],
onDragEnd: resizeAll,
gutterSize: 5
});
canvassplit = Split(['#frontcanvas', '#backcanvas'], {
sizes: [50, 50],
gutterSize: 5,
direction: "vertical",
onDragEnd: resizeAll
});
}
settings.bomlayout = layout;
writeStorage("bomlayout", layout);
changeCanvasLayout(settings.canvaslayout);
}
function changeBomMode(mode) {
document.getElementById("bom-grouped-btn").classList.remove("depressed");
document.getElementById("bom-ungrouped-btn").classList.remove("depressed");
document.getElementById("bom-netlist-btn").classList.remove("depressed");
var chkbxs = document.getElementsByClassName("visibility_checkbox");
switch (mode) {
case 'grouped':
document.getElementById("bom-grouped-btn").classList.add("depressed");
for (var i = 0; i < chkbxs.length; i++) {
chkbxs[i].disabled = false;
}
break;
case 'ungrouped':
document.getElementById("bom-ungrouped-btn").classList.add("depressed");
for (var i = 0; i < chkbxs.length; i++) {
chkbxs[i].disabled = false;
}
break;
case 'netlist':
document.getElementById("bom-netlist-btn").classList.add("depressed");
for (var i = 0; i < chkbxs.length; i++) {
chkbxs[i].disabled = true;
}
}
writeStorage("bommode", mode);
if (mode != settings.bommode) {
settings.bommode = mode;
bomSortFunction = null;
currentSortColumn = null;
currentSortOrder = null;
clearHighlightedFootprints();
}
populateBomTable();
}
function focusFilterField() {
focusInputField(document.getElementById("filter"));
}
function focusRefLookupField() {
focusInputField(document.getElementById("reflookup"));
}
function toggleBomCheckbox(bomrowid, checkboxnum) {
if (!bomrowid || checkboxnum > settings.checkboxes.length) {
return;
}
var bomrow = document.getElementById(bomrowid);
var checkbox = bomrow.childNodes[checkboxnum].childNodes[0];
checkbox.checked = !checkbox.checked;
checkbox.indeterminate = false;
checkbox.onchange();
}
function checkBomCheckbox(bomrowid, checkboxname) {
var checkboxnum = 0;
while (checkboxnum < settings.checkboxes.length &&
settings.checkboxes[checkboxnum].toLowerCase() != checkboxname.toLowerCase()) {
checkboxnum++;
}
if (!bomrowid || checkboxnum >= settings.checkboxes.length) {
return;
}
var bomrow = document.getElementById(bomrowid);
var checkbox = bomrow.childNodes[checkboxnum + 1].childNodes[0];
checkbox.checked = true;
checkbox.indeterminate = false;
checkbox.onchange();
}
function setBomCheckboxes(value) {
writeStorage("bomCheckboxes", value);
settings.checkboxes = value.split(",").map((e) => e.trim()).filter((e) => e);
prepCheckboxes();
populateMarkWhenCheckedOptions();
setMarkWhenChecked(settings.markWhenChecked);
}
function setMarkWhenChecked(value) {
writeStorage("markWhenChecked", value);
settings.markWhenChecked = value;
markedFootprints.clear();
for (var ref of (value ? getStoredCheckboxRefs(value) : [])) {
markedFootprints.add(ref);
}
populateBomTable();
drawHighlights();
}
function prepCheckboxes() {
var table = document.getElementById("checkbox-stats");
while (table.childElementCount > 1) {
table.removeChild(table.lastChild);
}
if (settings.checkboxes.length) {
table.style.display = "";
} else {
table.style.display = "none";
}
for (var checkbox of settings.checkboxes) {
var tr = document.createElement("TR");
var td = document.createElement("TD");
td.innerHTML = checkbox;
tr.appendChild(td);
td = document.createElement("TD");
td.id = "checkbox-stats-" + checkbox;
var progressbar = document.createElement("div");
progressbar.classList.add("bar");
td.appendChild(progressbar);
var text = document.createElement("div");
text.classList.add("text");
td.appendChild(text);
tr.appendChild(td);
table.appendChild(tr);
updateCheckboxStats(checkbox);
}
}
function populateMarkWhenCheckedOptions() {
var container = document.getElementById("markWhenCheckedContainer");
if (settings.checkboxes.length == 0) {
container.parentElement.style.display = "none";
return;
}
container.innerHTML = '';
container.parentElement.style.display = "inline-block";
function createOption(name, displayName) {
var id = "markWhenChecked-" + name;
var div = document.createElement("div");
div.classList.add("radio-container");
var input = document.createElement("input");
input.type = "radio";
input.name = "markWhenChecked";
input.value = name;
input.id = id;
input.onchange = () => setMarkWhenChecked(name);
div.appendChild(input);
// Preserve the selected element when the checkboxes change
if (name == settings.markWhenChecked) {
input.checked = true;
}
var label = document.createElement("label");
label.innerHTML = displayName;
label.htmlFor = id;
div.appendChild(label);
container.appendChild(div);
}
createOption("", "None");
for (var checkbox of settings.checkboxes) {
createOption(checkbox, checkbox);
}
}
function updateCheckboxStats(checkbox) {
var checked = getStoredCheckboxRefs(checkbox).size;
var total = pcbdata.footprints.length - pcbdata.bom.skipped.length;
var percent = checked * 100.0 / total;
var td = document.getElementById("checkbox-stats-" + checkbox);
td.firstChild.style.width = percent + "%";
td.lastChild.innerHTML = checked + "/" + total + " (" + Math.round(percent) + "%)";
}
function constrain(number, min, max){
return Math.min(Math.max(parseInt(number), min), max);
}
document.onkeydown = function (e) {
switch (e.key) {
case "n":
if (document.activeElement.type == "text") {
return;
}
if (currentHighlightedRowId !== null) {
checkBomCheckbox(currentHighlightedRowId, "placed");
highlightNextRow();
e.preventDefault();
}
break;
case "ArrowUp":
highlightPreviousRow();
e.preventDefault();
break;
case "ArrowDown":
highlightNextRow();
e.preventDefault();
break;
case "ArrowLeft":
case "ArrowRight":
if (document.activeElement.type != "text"){
e.preventDefault();
let boardRotationElement = document.getElementById("boardRotation")
settings.boardRotation = parseInt(boardRotationElement.value); // degrees / 5
if (e.key == "ArrowLeft"){
settings.boardRotation += 3; // 15 degrees
}
else{
settings.boardRotation -= 3;
}
settings.boardRotation = constrain(settings.boardRotation, boardRotationElement.min, boardRotationElement.max);
boardRotationElement.value = settings.boardRotation
setBoardRotation(settings.boardRotation);
}
break;
default:
break;
}
if (e.altKey) {
switch (e.key) {
case "f":
focusFilterField();
e.preventDefault();
break;
case "r":
focusRefLookupField();
e.preventDefault();
break;
case "z":
changeBomLayout("bom-only");
e.preventDefault();
break;
case "x":
changeBomLayout("left-right");
e.preventDefault();
break;
case "c":
changeBomLayout("top-bottom");
e.preventDefault();
break;
case "v":
changeCanvasLayout("F");
e.preventDefault();
break;
case "b":
changeCanvasLayout("FB");
e.preventDefault();
break;
case "n":
changeCanvasLayout("B");
e.preventDefault();
break;
default:
break;
}
if (e.key >= '1' && e.key <= '9') {
toggleBomCheckbox(currentHighlightedRowId, parseInt(e.key));
e.preventDefault();
}
}
}
function hideNetlistButton() {
document.getElementById("bom-ungrouped-btn").classList.remove("middle-button");
document.getElementById("bom-ungrouped-btn").classList.add("right-most-button");
document.getElementById("bom-netlist-btn").style.display = "none";
}
window.onload = function (e) {
initUtils();
initRender();
initStorage();
initDefaults();
cleanGutters();
populateMetadata();
dbgdiv = document.getElementById("dbg");
bom = document.getElementById("bombody");
bomhead = document.getElementById("bomhead");
filter = "";
reflookup = "";
if (!("nets" in pcbdata)) {
hideNetlistButton();
}
initDone = true;
setBomCheckboxes(document.getElementById("bomCheckboxes").value);
// Triggers render
changeBomLayout(settings.bomlayout);
// Users may leave fullscreen without touching the checkbox. Uncheck.
document.addEventListener('fullscreenchange', () => {
if (!document.fullscreenElement)
document.getElementById('fullscreenCheckbox').checked = false;
});
}
window.onresize = resizeAll;
window.matchMedia("print").addListener(resizeAll);
///////////////////////////////////////////////
///////////////////////////////////////////////
///////////////////////////////////////////////
</script>
</head>
<body>
<div id="topmostdiv" class="topmostdiv">
<div id="top">
<div style="float: right; height: 100%;">
<div class="hideonprint menu" style="float: right; top: 8px;">
<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="highlightpin1Checkbox" type="checkbox" onchange="setHighlightPin1(this.checked)">
Highlight first pin
</label>
<label class="menu-label">
<input id="dragCheckbox" type="checkbox" checked onchange="setRedrawOnDrag(this.checked)">
Continuous redraw on drag
</label>
<label class="menu-label">
<span>Board rotation</span>
<span style="float: right"><span id="rotationDegree">0</span>&#176;</span>
<input id="boardRotation" type="range" min="-36" max="36" value="0" class="slider" oninput="setBoardRotation(this.value)">
</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"
style="float: right; position: relative; top: 8px">
<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"
style="float: right; position: relative; top: 8px">
<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"
style="float: right; position: relative; top: 8px">
<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" style="float: right; top: 8px;">
<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" style="float: right; top: 8px;">
<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>
</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 id="fileinfodiv" style="overflow: auto;">
<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>
<div id="bot" class="split" style="height: calc(100% - 80px)">
<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>