Sylvain Munaut | 1599a58 | 2020-09-14 10:45:06 +0200 | [diff] [blame] | 1 | <!DOCTYPE html> |
| 2 | <html lang="en"> |
| 3 | |
| 4 | <head> |
| 5 | <meta charset="UTF-8"> |
| 6 | <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
| 7 | <title>Interactive BOM for KiCAD</title> |
| 8 | <style type="text/css"> |
| 9 | :root { |
| 10 | --pcb-edge-color: black; |
| 11 | --pad-color: #878787; |
| 12 | --pad-color-highlight: #D04040; |
| 13 | --pin1-outline-color: #ffb629; |
| 14 | --pin1-outline-color-highlight: #b4ff03; |
| 15 | --silkscreen-edge-color: #aa4; |
| 16 | --silkscreen-polygon-color: #4aa; |
| 17 | --silkscreen-text-color: #4aa; |
| 18 | --fabrication-edge-color: #907651; |
| 19 | --fabrication-polygon-color: #907651; |
| 20 | --fabrication-text-color: #a27c24; |
| 21 | --track-color: #def5f1; |
| 22 | --track-color-highlight: #D04040; |
| 23 | --zone-color: #def5f1; |
| 24 | --zone-color-highlight: #d0404080; |
| 25 | } |
| 26 | |
| 27 | html, body { |
| 28 | margin: 0px; |
| 29 | height: 100%; |
| 30 | font-family: Verdana, sans-serif; |
| 31 | } |
| 32 | |
| 33 | .dark.topmostdiv { |
| 34 | --pcb-edge-color: #eee; |
| 35 | --pad-color: #808080; |
| 36 | --pin1-outline-color: #ffa800; |
| 37 | --pin1-outline-color-highlight: #ccff00; |
| 38 | --track-color: #42524f; |
| 39 | --zone-color: #42524f; |
| 40 | background-color: #252c30; |
| 41 | color: #eee; |
| 42 | } |
| 43 | |
| 44 | button { |
| 45 | background-color: #eee; |
| 46 | border: 1px solid #888; |
| 47 | color: black; |
| 48 | height: 44px; |
| 49 | width: 44px; |
| 50 | text-align: center; |
| 51 | text-decoration: none; |
| 52 | display: inline-block; |
| 53 | font-size: 14px; |
| 54 | font-weight: bolder; |
| 55 | } |
| 56 | |
| 57 | .dark button { |
| 58 | /* This will be inverted */ |
| 59 | background-color: #c3b7b5; |
| 60 | } |
| 61 | |
| 62 | button.depressed { |
| 63 | background-color: #0a0; |
| 64 | color: white; |
| 65 | } |
| 66 | |
| 67 | .dark button.depressed { |
| 68 | /* This will be inverted */ |
| 69 | background-color: #b3b; |
| 70 | } |
| 71 | |
| 72 | button:focus { |
| 73 | outline: 0; |
| 74 | } |
| 75 | |
| 76 | button#tb-btn { |
| 77 | 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"); |
| 78 | } |
| 79 | |
| 80 | button#lr-btn { |
| 81 | 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"); |
| 82 | } |
| 83 | |
| 84 | button#bom-btn { |
| 85 | 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"); |
| 86 | } |
| 87 | |
| 88 | button#bom-grouped-btn { |
| 89 | 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"); |
| 90 | } |
| 91 | |
| 92 | button#bom-ungrouped-btn { |
| 93 | 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"); |
| 94 | } |
| 95 | |
| 96 | button#bom-netlist-btn { |
| 97 | 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"); |
| 98 | } |
| 99 | |
| 100 | button#copy { |
| 101 | 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"); |
| 102 | background-position: 6px 6px; |
| 103 | background-repeat: no-repeat; |
| 104 | background-size: 26px 26px; |
| 105 | border-radius: 6px; |
| 106 | height: 40px; |
| 107 | width: 40px; |
| 108 | margin: 10px 5px; |
| 109 | } |
| 110 | |
| 111 | button#copy:active { |
| 112 | box-shadow: inset 0px 0px 5px #6c6c6c; |
| 113 | } |
| 114 | |
| 115 | textarea.clipboard-temp { |
| 116 | position: fixed; |
| 117 | top: 0; |
| 118 | left: 0; |
| 119 | width: 2em; |
| 120 | height: 2em; |
| 121 | padding: 0; |
| 122 | border: None; |
| 123 | outline: None; |
| 124 | box-shadow: None; |
| 125 | background: transparent; |
| 126 | } |
| 127 | |
| 128 | .left-most-button { |
| 129 | border-right: 0; |
| 130 | border-top-left-radius: 6px; |
| 131 | border-bottom-left-radius: 6px; |
| 132 | } |
| 133 | |
| 134 | .middle-button { |
| 135 | border-right: 0; |
| 136 | } |
| 137 | |
| 138 | .right-most-button { |
| 139 | border-top-right-radius: 6px; |
| 140 | border-bottom-right-radius: 6px; |
| 141 | } |
| 142 | |
| 143 | .button-container { |
| 144 | font-size: 0; |
| 145 | margin: 10px 10px 10px 0px; |
| 146 | } |
| 147 | |
| 148 | .dark .button-container { |
| 149 | filter: invert(1); |
| 150 | } |
| 151 | |
| 152 | .button-container button { |
| 153 | background-size: 32px 32px; |
| 154 | background-position: 5px 5px; |
| 155 | background-repeat: no-repeat; |
| 156 | } |
| 157 | |
| 158 | @media print { |
| 159 | .hideonprint { |
| 160 | display: none; |
| 161 | } |
| 162 | } |
| 163 | |
| 164 | canvas { |
| 165 | cursor: crosshair; |
| 166 | } |
| 167 | |
| 168 | canvas:active { |
| 169 | cursor: grabbing; |
| 170 | } |
| 171 | |
| 172 | .fileinfo { |
| 173 | width: 100%; |
| 174 | max-width: 1000px; |
| 175 | border: none; |
| 176 | padding: 5px; |
| 177 | } |
| 178 | |
| 179 | .fileinfo .title { |
| 180 | font-size: 20pt; |
| 181 | font-weight: bold; |
| 182 | } |
| 183 | |
| 184 | .fileinfo td { |
| 185 | overflow: hidden; |
| 186 | white-space: nowrap; |
| 187 | max-width: 1px; |
| 188 | width: 50%; |
| 189 | text-overflow: ellipsis; |
| 190 | } |
| 191 | |
| 192 | .bom { |
| 193 | border-collapse: collapse; |
| 194 | font-family: Consolas, "DejaVu Sans Mono", Monaco, monospace; |
| 195 | font-size: 10pt; |
| 196 | table-layout: fixed; |
| 197 | width: 100%; |
| 198 | margin-top: 1px; |
| 199 | } |
| 200 | |
| 201 | .bom th, .bom td { |
| 202 | border: 1px solid black; |
| 203 | padding: 5px; |
| 204 | word-wrap: break-word; |
| 205 | text-align: center; |
| 206 | position: relative; |
| 207 | } |
| 208 | |
| 209 | .dark .bom th, .dark .bom td { |
| 210 | border: 1px solid #777; |
| 211 | } |
| 212 | |
| 213 | .bom th { |
| 214 | background-color: #CCCCCC; |
| 215 | background-clip: padding-box; |
| 216 | } |
| 217 | |
| 218 | .dark .bom th { |
| 219 | background-color: #3b4749; |
| 220 | } |
| 221 | |
| 222 | .bom tr.highlighted:nth-child(n) { |
| 223 | background-color: #cfc; |
| 224 | } |
| 225 | |
| 226 | .dark .bom tr.highlighted:nth-child(n) { |
| 227 | background-color: #226022; |
| 228 | } |
| 229 | |
| 230 | .bom tr:nth-child(even) { |
| 231 | background-color: #f2f2f2; |
| 232 | } |
| 233 | |
| 234 | .dark .bom tr:nth-child(even) { |
| 235 | background-color: #313b40; |
| 236 | } |
| 237 | |
| 238 | .bom tr.checked { |
| 239 | color: #aaa; |
| 240 | } |
| 241 | |
| 242 | .dark .bom tr.checked { |
| 243 | color: #666; |
| 244 | } |
| 245 | |
| 246 | .bom tr { |
| 247 | transition: background-color 0.2s; |
| 248 | } |
| 249 | |
| 250 | .bom .numCol { |
| 251 | width: 25px; |
| 252 | } |
| 253 | |
| 254 | .bom .Description { |
| 255 | width: 10%; |
| 256 | } |
| 257 | |
| 258 | .bom .Part { |
| 259 | width: 10%; |
| 260 | } |
| 261 | |
| 262 | .bom .Value { |
| 263 | width: 15%; |
| 264 | } |
| 265 | |
| 266 | .bom .Quantity { |
| 267 | width: 65px; |
| 268 | } |
| 269 | |
| 270 | .bom th .sortmark { |
| 271 | position: absolute; |
| 272 | right: 1px; |
| 273 | top: 1px; |
| 274 | margin-top: -5px; |
| 275 | border-width: 5px; |
| 276 | border-style: solid; |
| 277 | border-color: transparent transparent #221 transparent; |
| 278 | transform-origin: 50% 85%; |
| 279 | transition: opacity 0.2s, transform 0.4s; |
| 280 | } |
| 281 | |
| 282 | .dark .bom th .sortmark { |
| 283 | filter: invert(1); |
| 284 | } |
| 285 | |
| 286 | .bom th .sortmark.none { |
| 287 | opacity: 0; |
| 288 | } |
| 289 | |
| 290 | .bom th .sortmark.desc { |
| 291 | transform: rotate(180deg); |
| 292 | } |
| 293 | |
| 294 | .bom th:hover .sortmark.none { |
| 295 | opacity: 0.5; |
| 296 | } |
| 297 | |
| 298 | .bom .bom-checkbox { |
| 299 | width: 30px; |
| 300 | position: relative; |
| 301 | user-select: none; |
| 302 | -moz-user-select: none; |
| 303 | } |
| 304 | |
| 305 | .bom .bom-checkbox:before { |
| 306 | content: ""; |
| 307 | position: absolute; |
| 308 | border-width: 15px; |
| 309 | border-style: solid; |
| 310 | border-color: #51829f transparent transparent transparent; |
| 311 | visibility: hidden; |
| 312 | top: -15px; |
| 313 | } |
| 314 | |
| 315 | .bom .bom-checkbox:after { |
| 316 | content: "Double click to set/unset all"; |
| 317 | position: absolute; |
| 318 | color: white; |
| 319 | top: -35px; |
| 320 | left: -26px; |
| 321 | background: #51829f; |
| 322 | padding: 5px 15px; |
| 323 | border-radius: 8px; |
| 324 | white-space: nowrap; |
| 325 | visibility: hidden; |
| 326 | } |
| 327 | |
| 328 | .bom .bom-checkbox:hover:before, .bom .bom-checkbox:hover:after { |
| 329 | visibility: visible; |
| 330 | transition: visibility 0.2s linear 1s; |
| 331 | } |
| 332 | |
| 333 | .split { |
| 334 | -webkit-box-sizing: border-box; |
| 335 | -moz-box-sizing: border-box; |
| 336 | box-sizing: border-box; |
| 337 | overflow-y: auto; |
| 338 | overflow-x: hidden; |
| 339 | background-color: inherit; |
| 340 | } |
| 341 | |
| 342 | .split.split-horizontal, .gutter.gutter-horizontal { |
| 343 | height: 100%; |
| 344 | float: left; |
| 345 | } |
| 346 | |
| 347 | .gutter { |
| 348 | background-color: #ddd; |
| 349 | background-repeat: no-repeat; |
| 350 | background-position: 50%; |
| 351 | transition: background-color 0.3s; |
| 352 | } |
| 353 | |
| 354 | .dark .gutter { |
| 355 | background-color: #777; |
| 356 | } |
| 357 | |
| 358 | .gutter.gutter-horizontal { |
| 359 | background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAeCAYAAADkftS9AAAAIklEQVQoU2M4c+bMfxAGAgYYmwGrIIiDjrELjpo5aiZeMwF+yNnOs5KSvgAAAABJRU5ErkJggg=='); |
| 360 | cursor: ew-resize; |
| 361 | width: 5px; |
| 362 | } |
| 363 | |
| 364 | .gutter.gutter-vertical { |
| 365 | background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAFAQMAAABo7865AAAABlBMVEVHcEzMzMzyAv2sAAAAAXRSTlMAQObYZgAAABBJREFUeF5jOAMEEAIEEFwAn3kMwcB6I2AAAAAASUVORK5CYII='); |
| 366 | cursor: ns-resize; |
| 367 | height: 5px; |
| 368 | } |
| 369 | |
| 370 | .searchbox { |
| 371 | float: left; |
| 372 | height: 40px; |
| 373 | margin: 10px 5px; |
| 374 | padding: 12px 32px; |
| 375 | font-family: Consolas, "DejaVu Sans Mono", Monaco, monospace; |
| 376 | font-size: 18px; |
| 377 | box-sizing: border-box; |
| 378 | border: 1px solid #888; |
| 379 | border-radius: 6px; |
| 380 | outline: none; |
| 381 | background-color: #eee; |
| 382 | transition: background-color 0.2s, border 0.2s; |
| 383 | 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=='); |
| 384 | background-position: 10px 10px; |
| 385 | background-repeat: no-repeat; |
| 386 | } |
| 387 | |
| 388 | .dark .searchbox { |
| 389 | background-color: #111; |
| 390 | color: #eee; |
| 391 | } |
| 392 | |
| 393 | .searchbox::placeholder { |
| 394 | color: #ccc; |
| 395 | } |
| 396 | |
| 397 | .dark .searchbox::placeholder { |
| 398 | color: #666; |
| 399 | } |
| 400 | |
| 401 | .filter { |
| 402 | width: calc(60% - 64px); |
| 403 | } |
| 404 | |
| 405 | .reflookup { |
| 406 | width: calc(40% - 10px); |
| 407 | } |
| 408 | |
| 409 | input[type=text]:focus { |
| 410 | background-color: white; |
| 411 | border: 1px solid #333; |
| 412 | } |
| 413 | |
| 414 | .dark input[type=text]:focus { |
| 415 | background-color: #333; |
| 416 | border: 1px solid #ccc; |
| 417 | } |
| 418 | |
| 419 | mark.highlight { |
| 420 | background-color: #5050ff; |
| 421 | color: #fff; |
| 422 | padding: 2px; |
| 423 | border-radius: 6px; |
| 424 | } |
| 425 | |
| 426 | .dark mark.highlight { |
| 427 | background-color: #76a6da; |
| 428 | color: #111; |
| 429 | } |
| 430 | |
| 431 | .menubtn { |
| 432 | background-color: white; |
| 433 | border: none; |
| 434 | 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"); |
| 435 | background-position: center; |
| 436 | background-repeat: no-repeat; |
| 437 | } |
| 438 | |
| 439 | .statsbtn { |
| 440 | background-color: white; |
| 441 | border: none; |
| 442 | 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"); |
| 443 | background-position: center; |
| 444 | background-repeat: no-repeat; |
| 445 | } |
| 446 | |
| 447 | .iobtn { |
| 448 | background-color: white; |
| 449 | border: none; |
| 450 | 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"); |
| 451 | background-position: center; |
| 452 | background-repeat: no-repeat; |
| 453 | } |
| 454 | |
| 455 | .dark .statsbtn, .dark .savebtn, .dark .menubtn, .dark .iobtn { |
| 456 | filter: invert(1); |
| 457 | } |
| 458 | |
| 459 | .flexbox { |
| 460 | display: flex; |
| 461 | align-items: center; |
| 462 | justify-content: space-between; |
| 463 | width: 100%; |
| 464 | } |
| 465 | |
| 466 | .savebtn { |
| 467 | background-color: #d6d6d6; |
| 468 | width: auto; |
| 469 | height: 30px; |
| 470 | flex-grow: 1; |
| 471 | margin: 5px; |
| 472 | border-radius: 4px; |
| 473 | } |
| 474 | |
| 475 | .savebtn:active { |
| 476 | background-color: #0a0; |
| 477 | color: white; |
| 478 | } |
| 479 | |
| 480 | .dark .savebtn:active { |
| 481 | /* This will be inverted */ |
| 482 | background-color: #b3b; |
| 483 | } |
| 484 | |
| 485 | .stats { |
| 486 | border-collapse: collapse; |
| 487 | font-size: 12pt; |
| 488 | table-layout: fixed; |
| 489 | width: 100%; |
| 490 | min-width: 450px; |
| 491 | } |
| 492 | |
| 493 | .dark .stats td { |
| 494 | border: 1px solid #bbb; |
| 495 | } |
| 496 | |
| 497 | .stats td { |
| 498 | border: 1px solid black; |
| 499 | padding: 5px; |
| 500 | word-wrap: break-word; |
| 501 | text-align: center; |
| 502 | position: relative; |
| 503 | } |
| 504 | |
| 505 | #checkbox-stats div { |
| 506 | position: absolute; |
| 507 | left: 0; |
| 508 | top: 0; |
| 509 | height: 100%; |
| 510 | width: 100%; |
| 511 | display: flex; |
| 512 | align-items: center; |
| 513 | justify-content: center; |
| 514 | } |
| 515 | |
| 516 | #checkbox-stats .bar { |
| 517 | background-color: rgba(28, 251, 0, 0.6); |
| 518 | } |
| 519 | |
| 520 | .menu { |
| 521 | position: relative; |
| 522 | display: inline-block; |
| 523 | margin: 10px 10px 10px 0px; |
| 524 | } |
| 525 | |
| 526 | .menu-content { |
| 527 | display: none; |
| 528 | position: absolute; |
| 529 | background-color: white; |
| 530 | right: 0; |
| 531 | min-width: 300px; |
| 532 | box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.2); |
| 533 | z-index: 100; |
| 534 | padding: 8px; |
| 535 | } |
| 536 | |
| 537 | .dark .menu-content { |
| 538 | background-color: #111; |
| 539 | } |
| 540 | |
| 541 | .menu:hover .menu-content { |
| 542 | display: block; |
| 543 | } |
| 544 | |
| 545 | .menu:hover .menubtn, .menu:hover .iobtn, .menu:hover .statsbtn { |
| 546 | background-color: #eee; |
| 547 | } |
| 548 | |
| 549 | .menu-label { |
| 550 | display: inline-block; |
| 551 | padding: 8px; |
| 552 | border: 1px solid #ccc; |
| 553 | border-top: 0; |
| 554 | width: calc(100% - 18px); |
| 555 | } |
| 556 | |
| 557 | .menu-label-top { |
| 558 | border-top: 1px solid #ccc; |
| 559 | } |
| 560 | |
| 561 | .menu-textbox { |
| 562 | float: left; |
| 563 | height: 24px; |
| 564 | margin: 10px 5px; |
| 565 | padding: 5px 5px; |
| 566 | font-family: Consolas, "DejaVu Sans Mono", Monaco, monospace; |
| 567 | font-size: 14px; |
| 568 | box-sizing: border-box; |
| 569 | border: 1px solid #888; |
| 570 | border-radius: 4px; |
| 571 | outline: none; |
| 572 | background-color: #eee; |
| 573 | transition: background-color 0.2s, border 0.2s; |
| 574 | width: calc(100% - 10px); |
| 575 | } |
| 576 | |
| 577 | .menu-textbox.invalid, .dark .menu-textbox.invalid { |
| 578 | color: red; |
| 579 | } |
| 580 | |
| 581 | .dark .menu-textbox { |
| 582 | background-color: #222; |
| 583 | color: #eee; |
| 584 | } |
| 585 | |
| 586 | .radio-container { |
| 587 | margin: 4px; |
| 588 | } |
| 589 | |
| 590 | .topmostdiv { |
| 591 | width: 100%; |
| 592 | height: 100%; |
| 593 | background-color: white; |
| 594 | transition: background-color 0.3s; |
| 595 | } |
| 596 | |
| 597 | #top { |
| 598 | height: 78px; |
| 599 | border-bottom: 2px solid black; |
| 600 | } |
| 601 | |
| 602 | .dark #top { |
| 603 | border-bottom: 2px solid #ccc; |
| 604 | } |
| 605 | |
| 606 | #dbg { |
| 607 | display: block; |
| 608 | } |
| 609 | |
| 610 | ::-webkit-scrollbar { |
| 611 | width: 8px; |
| 612 | } |
| 613 | |
| 614 | ::-webkit-scrollbar-track { |
| 615 | background: #aaa; |
| 616 | } |
| 617 | |
| 618 | ::-webkit-scrollbar-thumb { |
| 619 | background: #666; |
| 620 | border-radius: 3px; |
| 621 | } |
| 622 | |
| 623 | ::-webkit-scrollbar-thumb:hover { |
| 624 | background: #555; |
| 625 | } |
| 626 | |
| 627 | .slider { |
| 628 | -webkit-appearance: none; |
| 629 | width: 100%; |
| 630 | margin: 3px 0; |
| 631 | padding: 0; |
| 632 | outline: none; |
| 633 | opacity: 0.7; |
| 634 | -webkit-transition: .2s; |
| 635 | transition: opacity .2s; |
| 636 | border-radius: 3px; |
| 637 | } |
| 638 | |
| 639 | .slider:hover { |
| 640 | opacity: 1; |
| 641 | } |
| 642 | |
| 643 | .slider:focus { |
| 644 | outline: none; |
| 645 | } |
| 646 | |
| 647 | .slider::-webkit-slider-runnable-track { |
| 648 | -webkit-appearance: none; |
| 649 | width: 100%; |
| 650 | height: 8px; |
| 651 | background: #d3d3d3; |
| 652 | border-radius: 3px; |
| 653 | border: none; |
| 654 | } |
| 655 | |
| 656 | .slider::-webkit-slider-thumb { |
| 657 | -webkit-appearance: none; |
| 658 | width: 15px; |
| 659 | height: 15px; |
| 660 | border-radius: 50%; |
| 661 | background: #0a0; |
| 662 | cursor: pointer; |
| 663 | margin-top: -4px; |
| 664 | } |
| 665 | |
| 666 | .dark .slider::-webkit-slider-thumb { |
| 667 | background: #3d3; |
| 668 | } |
| 669 | |
| 670 | .slider::-moz-range-thumb { |
| 671 | width: 15px; |
| 672 | height: 15px; |
| 673 | border-radius: 50%; |
| 674 | background: #0a0; |
| 675 | cursor: pointer; |
| 676 | } |
| 677 | |
| 678 | .slider::-moz-range-track { |
| 679 | height: 8px; |
| 680 | background: #d3d3d3; |
| 681 | border-radius: 3px; |
| 682 | } |
| 683 | |
| 684 | .dark .slider::-moz-range-thumb { |
| 685 | background: #3d3; |
| 686 | } |
| 687 | |
| 688 | .slider::-ms-track { |
| 689 | width: 100%; |
| 690 | height: 8px; |
| 691 | border-width: 3px 0; |
| 692 | background: transparent; |
| 693 | border-color: transparent; |
| 694 | color: transparent; |
| 695 | transition: opacity .2s; |
| 696 | } |
| 697 | |
| 698 | .slider::-ms-fill-lower { |
| 699 | background: #d3d3d3; |
| 700 | border: none; |
| 701 | border-radius: 3px; |
| 702 | } |
| 703 | |
| 704 | .slider::-ms-fill-upper { |
| 705 | background: #d3d3d3; |
| 706 | border: none; |
| 707 | border-radius: 3px; |
| 708 | } |
| 709 | |
| 710 | .slider::-ms-thumb { |
| 711 | width: 15px; |
| 712 | height: 15px; |
| 713 | border-radius: 50%; |
| 714 | background: #0a0; |
| 715 | cursor: pointer; |
| 716 | margin: 0; |
| 717 | } |
| 718 | |
| 719 | .shameless-plug { |
| 720 | font-size: 0.8em; |
| 721 | text-align: center; |
| 722 | display: block; |
| 723 | } |
| 724 | |
| 725 | a { |
| 726 | color: #0278a4; |
| 727 | } |
| 728 | |
| 729 | .dark a { |
| 730 | color: #00b9fd; |
| 731 | } |
| 732 | |
| 733 | #frontcanvas, #backcanvas { |
| 734 | touch-action: none; |
| 735 | } |
| 736 | |
| 737 | |
| 738 | </style> |
| 739 | <script type="text/javascript" > |
| 740 | /////////////////////////////////////////////// |
| 741 | /* |
| 742 | Split.js - v1.3.5 |
| 743 | MIT License |
| 744 | https://github.com/nathancahill/Split.js |
| 745 | */ |
| 746 | !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}}}); |
| 747 | |
| 748 | /////////////////////////////////////////////// |
| 749 | |
| 750 | /////////////////////////////////////////////// |
| 751 | // Copyright (c) 2013 Pieroxy <pieroxy@pieroxy.net> |
| 752 | // This work is free. You can redistribute it and/or modify it |
| 753 | // under the terms of the WTFPL, Version 2 |
| 754 | // For more information see LICENSE.txt or http://www.wtfpl.net/ |
| 755 | // |
| 756 | // For more information, the home page: |
| 757 | // http://pieroxy.net/blog/pages/lz-string/testing.html |
| 758 | // |
| 759 | // LZ-based compression algorithm, version 1.4.4 |
| 760 | 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}); |
| 761 | /////////////////////////////////////////////// |
| 762 | |
| 763 | /////////////////////////////////////////////// |
| 764 | /*! |
| 765 | * PEP v0.4.3 | https://github.com/jquery/PEP |
| 766 | * Copyright jQuery Foundation and other contributors | http://jquery.org/license |
| 767 | */ |
| 768 | !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); |
| 769 | for(var d,e=2;e<m.length;e++)d=m[e],c[d]=b[d]||n[e];c.buttons=b.buttons||0; |
| 770 | 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}})} |
| 771 | 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++) |
| 772 | b.register.call(b,a)},unregister:function(a){for(var b,c=this.eventSourceList.length,d=0;d<c&&(b=this.eventSourceList[d]);d++) |
| 773 | 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){ |
| 774 | for(var b=a;b.parentNode;)b=b.parentNode; |
| 775 | 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); |
| 776 | 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){ |
| 777 | // |
| 778 | 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))}, |
| 779 | 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){ |
| 780 | var b=x(a,this.findElements,this); |
| 781 | 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){} |
| 782 | 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:[], |
| 783 | 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++){ |
| 784 | 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); |
| 785 | 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]; |
| 786 | c.buttons=b?b.buttons&~d:0,a.buttons=c.buttons}H.set(this.POINTER_ID,a), |
| 787 | 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), |
| 788 | 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), |
| 789 | 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); |
| 790 | 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){ |
| 791 | (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, |
| 792 | c.altKey=b.altKey,c.ctrlKey=b.ctrlKey,c.metaKey=b.metaKey,c.shiftKey=b.shiftKey; |
| 793 | 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))}, |
| 794 | shouldScroll:function(a){if(this.firstXY){var b,c=a.currentTarget._scrollType;if("none"===c) |
| 795 | b=!1;else if("XY"===c) |
| 796 | 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]); |
| 797 | 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}, |
| 798 | vacuumTouches:function(a){var b=a.touches; |
| 799 | if(R.size>=b.length){var c=[];R.forEach(function(a,d){ |
| 800 | 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); |
| 801 | if(c){var d=c.out,e=c.outTarget;u.move(b),d&&e!==b.target&&(d.relatedTarget=b.target,b.relatedTarget=e, |
| 802 | d.target=e,b.target?(u.leaveOut(d),u.enterOver(b)):( |
| 803 | 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)}, |
| 804 | dedupSynthMouse:function(a){var b=N.lastTouches,c=a.changedTouches[0]; |
| 805 | if(this.isPrimaryTouch(c)){ |
| 806 | 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}); |
| 807 | |
| 808 | /////////////////////////////////////////////// |
| 809 | |
| 810 | /////////////////////////////////////////////// |
| 811 | var config = {"dark_mode": true, "show_pads": true, "show_fabrication": true, "show_silkscreen": true, "highlight_pin1": true, "redraw_on_drag": true, "board_rotation": 0, "checkboxes": "Sourced,Placed", "bom_view": "left-right", "layer_view": "F", "extra_fields": []} |
| 812 | /////////////////////////////////////////////// |
| 813 | |
| 814 | /////////////////////////////////////////////// |
| 815 | var pcbdata = JSON.parse(LZString.decompressFromBase64("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")) |
| 816 | /////////////////////////////////////////////// |
| 817 | |
| 818 | /////////////////////////////////////////////// |
| 819 | /* Utility functions */ |
| 820 | |
| 821 | var storagePrefix = 'KiCad_HTML_BOM__' + pcbdata.metadata.title + '__' + |
| 822 | pcbdata.metadata.revision + '__#'; |
| 823 | var storage; |
| 824 | |
| 825 | function initStorage(key) { |
| 826 | try { |
| 827 | window.localStorage.getItem("blank"); |
| 828 | storage = window.localStorage; |
| 829 | } catch (e) { |
| 830 | // localStorage not available |
| 831 | } |
| 832 | if (!storage) { |
| 833 | try { |
| 834 | window.sessionStorage.getItem("blank"); |
| 835 | storage = window.sessionStorage; |
| 836 | } catch (e) { |
| 837 | // sessionStorage also not available |
| 838 | } |
| 839 | } |
| 840 | } |
| 841 | |
| 842 | function readStorage(key) { |
| 843 | if (storage) { |
| 844 | return storage.getItem(storagePrefix + key); |
| 845 | } else { |
| 846 | return null; |
| 847 | } |
| 848 | } |
| 849 | |
| 850 | function writeStorage(key, value) { |
| 851 | if (storage) { |
| 852 | storage.setItem(storagePrefix + key, value); |
| 853 | } |
| 854 | } |
| 855 | |
| 856 | function fancyDblClickHandler(el, onsingle, ondouble) { |
| 857 | return function() { |
| 858 | if (el.getAttribute("data-dblclick") == null) { |
| 859 | el.setAttribute("data-dblclick", 1); |
| 860 | setTimeout(function() { |
| 861 | if (el.getAttribute("data-dblclick") == 1) { |
| 862 | onsingle(); |
| 863 | } |
| 864 | el.removeAttribute("data-dblclick"); |
| 865 | }, 200); |
| 866 | } else { |
| 867 | el.removeAttribute("data-dblclick"); |
| 868 | ondouble(); |
| 869 | } |
| 870 | } |
| 871 | } |
| 872 | |
| 873 | function smoothScrollToRow(rowid) { |
| 874 | document.getElementById(rowid).scrollIntoView({ |
| 875 | behavior: "smooth", |
| 876 | block: "center", |
| 877 | inline: "nearest" |
| 878 | }); |
| 879 | } |
| 880 | |
| 881 | function focusInputField(input) { |
| 882 | input.scrollIntoView(false); |
| 883 | input.focus(); |
| 884 | input.select(); |
| 885 | } |
| 886 | |
| 887 | function copyToClipboard() { |
| 888 | var text = ''; |
| 889 | for (var node of bomhead.childNodes[0].childNodes) { |
| 890 | if (node.firstChild) { |
| 891 | text = text + node.firstChild.nodeValue; |
| 892 | } |
| 893 | if (node != bomhead.childNodes[0].lastChild) { |
| 894 | text += '\t'; |
| 895 | } |
| 896 | } |
| 897 | text += '\n'; |
| 898 | for (var row of bombody.childNodes) { |
| 899 | for (var cell of row.childNodes) { |
| 900 | for (var node of cell.childNodes) { |
| 901 | if (node.nodeName == "INPUT") { |
| 902 | if (node.checked) { |
| 903 | text = text + '✓'; |
| 904 | } |
| 905 | } else if (node.nodeName == "MARK") { |
| 906 | text = text + node.firstChild.nodeValue; |
| 907 | } else { |
| 908 | text = text + node.nodeValue; |
| 909 | } |
| 910 | } |
| 911 | if (cell != row.lastChild) { |
| 912 | text += '\t'; |
| 913 | } |
| 914 | } |
| 915 | text += '\n'; |
| 916 | } |
| 917 | var textArea = document.createElement("textarea"); |
| 918 | textArea.classList.add('clipboard-temp'); |
| 919 | textArea.value = text; |
| 920 | |
| 921 | document.body.appendChild(textArea); |
| 922 | textArea.focus(); |
| 923 | textArea.select(); |
| 924 | |
| 925 | try { |
| 926 | if (document.execCommand('copy')) { |
| 927 | console.log('Bom copied to clipboard.'); |
| 928 | } |
| 929 | } catch (err) { |
| 930 | console.log('Can not copy to clipboard.'); |
| 931 | } |
| 932 | |
| 933 | document.body.removeChild(textArea); |
| 934 | } |
| 935 | |
| 936 | function removeGutterNode(node) { |
| 937 | for (var i = 0; i < node.childNodes.length; i++) { |
| 938 | if (node.childNodes[i].classList && |
| 939 | node.childNodes[i].classList.contains("gutter")) { |
| 940 | node.removeChild(node.childNodes[i]); |
| 941 | break; |
| 942 | } |
| 943 | } |
| 944 | } |
| 945 | |
| 946 | function cleanGutters() { |
| 947 | removeGutterNode(document.getElementById("bot")); |
| 948 | removeGutterNode(document.getElementById("canvasdiv")); |
| 949 | } |
| 950 | |
| 951 | var units = { |
| 952 | prefixes: { |
| 953 | giga: ["G", "g", "giga", "Giga", "GIGA"], |
| 954 | mega: ["M", "mega", "Mega", "MEGA"], |
| 955 | kilo: ["K", "k", "kilo", "Kilo", "KILO"], |
| 956 | milli: ["m", "milli", "Milli", "MILLI"], |
| 957 | micro: ["U", "u", "micro", "Micro", "MICRO", "μ", "µ"], // different utf8 μ |
| 958 | nano: ["N", "n", "nano", "Nano", "NANO"], |
| 959 | pico: ["P", "p", "pico", "Pico", "PICO"], |
| 960 | }, |
| 961 | unitsShort: ["R", "r", "Ω", "F", "f", "H", "h"], |
| 962 | unitsLong: [ |
| 963 | "OHM", "Ohm", "ohm", "ohms", |
| 964 | "FARAD", "Farad", "farad", |
| 965 | "HENRY", "Henry", "henry" |
| 966 | ], |
| 967 | getMultiplier: function(s) { |
| 968 | if (this.prefixes.giga.includes(s)) return 1e9; |
| 969 | if (this.prefixes.mega.includes(s)) return 1e6; |
| 970 | if (this.prefixes.kilo.includes(s)) return 1e3; |
| 971 | if (this.prefixes.milli.includes(s)) return 1e-3; |
| 972 | if (this.prefixes.micro.includes(s)) return 1e-6; |
| 973 | if (this.prefixes.nano.includes(s)) return 1e-9; |
| 974 | if (this.prefixes.pico.includes(s)) return 1e-12; |
| 975 | return 1; |
| 976 | }, |
| 977 | valueRegex: null, |
| 978 | } |
| 979 | |
| 980 | function initUtils() { |
| 981 | var allPrefixes = units.prefixes.giga |
| 982 | .concat(units.prefixes.mega) |
| 983 | .concat(units.prefixes.kilo) |
| 984 | .concat(units.prefixes.milli) |
| 985 | .concat(units.prefixes.micro) |
| 986 | .concat(units.prefixes.nano) |
| 987 | .concat(units.prefixes.pico); |
| 988 | var allUnits = units.unitsShort.concat(units.unitsLong); |
| 989 | units.valueRegex = new RegExp("^([0-9\.]+)" + |
| 990 | "\\s*(" + allPrefixes.join("|") + ")?" + |
| 991 | "(" + allUnits.join("|") + ")?" + |
| 992 | "(\\b.*)?$", ""); |
| 993 | units.valueAltRegex = new RegExp("^([0-9]*)" + |
| 994 | "(" + units.unitsShort.join("|") + ")?" + |
| 995 | "([GgMmKkUuNnPp])?" + |
| 996 | "([0-9]*)" + |
| 997 | "(\\b.*)?$", ""); |
| 998 | for (var bom_type of ["both", "F", "B"]) { |
| 999 | for (var row of pcbdata.bom[bom_type]) { |
| 1000 | row.push(parseValue(row[1], row[3][0][0])); |
| 1001 | } |
| 1002 | } |
| 1003 | } |
| 1004 | |
| 1005 | function parseValue(val, ref) { |
| 1006 | var inferUnit = (unit, ref) => { |
| 1007 | if (unit) { |
| 1008 | unit = unit.toLowerCase(); |
| 1009 | if (unit == 'Ω' || unit == "ohm" || unit == "ohms") { |
| 1010 | unit = 'r'; |
| 1011 | } |
| 1012 | unit = unit[0]; |
| 1013 | } else { |
| 1014 | ref = /^([a-z]+)\d+$/i.exec(ref); |
| 1015 | if (ref) { |
| 1016 | ref = ref[1].toLowerCase(); |
| 1017 | if (ref == "c") unit = 'f'; |
| 1018 | else if (ref == "l") unit = 'h'; |
| 1019 | else if (ref == "r" || ref == "rv") unit = 'r'; |
| 1020 | else unit = null; |
| 1021 | } |
| 1022 | } |
| 1023 | return unit; |
| 1024 | }; |
| 1025 | val = val.replace(/,/g, ""); |
| 1026 | var match = units.valueRegex.exec(val); |
| 1027 | var unit; |
| 1028 | if (match) { |
| 1029 | val = parseFloat(match[1]); |
| 1030 | if (match[2]) { |
| 1031 | val = val * units.getMultiplier(match[2]); |
| 1032 | } |
| 1033 | unit = inferUnit(match[3], ref); |
| 1034 | if (!unit) return null; |
| 1035 | else return { |
| 1036 | val: val, |
| 1037 | unit: unit, |
| 1038 | extra: match[4], |
| 1039 | } |
| 1040 | } |
| 1041 | match = units.valueAltRegex.exec(val); |
| 1042 | if (match && (match[1] || match[4])) { |
| 1043 | val = parseFloat(match[1] + "." + match[4]); |
| 1044 | if (match[3]) { |
| 1045 | val = val * units.getMultiplier(match[3]); |
| 1046 | } |
| 1047 | unit = inferUnit(match[2], ref); |
| 1048 | if (!unit) return null; |
| 1049 | else return { |
| 1050 | val: val, |
| 1051 | unit: unit, |
| 1052 | extra: match[5], |
| 1053 | } |
| 1054 | } |
| 1055 | return null; |
| 1056 | } |
| 1057 | |
| 1058 | function valueCompare(a, b, stra, strb) { |
| 1059 | if (a === null && b === null) { |
| 1060 | // Failed to parse both values, compare them as strings. |
| 1061 | if (stra != strb) return stra > strb ? 1 : -1; |
| 1062 | else return 0; |
| 1063 | } else if (a === null) { |
| 1064 | return 1; |
| 1065 | } else if (b === null) { |
| 1066 | return -1; |
| 1067 | } else { |
| 1068 | if (a.unit != b.unit) return a.unit > b.unit ? 1 : -1; |
| 1069 | else if (a.val != b.val) return a.val > b.val ? 1 : -1; |
| 1070 | else if (a.extra != b.extra) return a.extra > b.extra ? 1 : -1; |
| 1071 | else return 0; |
| 1072 | } |
| 1073 | } |
| 1074 | |
| 1075 | function validateSaveImgDimension(element) { |
| 1076 | var valid = false; |
| 1077 | var intValue = 0; |
| 1078 | if (/^[1-9]\d*$/.test(element.value)) { |
| 1079 | intValue = parseInt(element.value); |
| 1080 | if (intValue <= 16000) { |
| 1081 | valid = true; |
| 1082 | } |
| 1083 | } |
| 1084 | if (valid) { |
| 1085 | element.classList.remove("invalid"); |
| 1086 | } else { |
| 1087 | element.classList.add("invalid"); |
| 1088 | } |
| 1089 | return intValue; |
| 1090 | } |
| 1091 | |
| 1092 | function saveImage(layer) { |
| 1093 | var width = validateSaveImgDimension(document.getElementById("render-save-width")); |
| 1094 | var height = validateSaveImgDimension(document.getElementById("render-save-height")); |
| 1095 | var bgcolor = null; |
| 1096 | if (!document.getElementById("render-save-transparent").checked) { |
| 1097 | var style = getComputedStyle(topmostdiv); |
| 1098 | bgcolor = style.getPropertyValue("background-color"); |
| 1099 | } |
| 1100 | if (!width || !height) return; |
| 1101 | |
| 1102 | // Prepare image |
| 1103 | var canvas = document.createElement("canvas"); |
| 1104 | var layerdict = { |
| 1105 | transform: { |
| 1106 | x: 0, |
| 1107 | y: 0, |
| 1108 | s: 1, |
| 1109 | panx: 0, |
| 1110 | pany: 0, |
| 1111 | zoom: 1, |
| 1112 | }, |
| 1113 | bg: canvas, |
| 1114 | fab: canvas, |
| 1115 | silk: canvas, |
| 1116 | highlight: canvas, |
| 1117 | layer: layer, |
| 1118 | } |
| 1119 | // Do the rendering |
| 1120 | recalcLayerScale(layerdict, width, height); |
| 1121 | prepareLayer(layerdict); |
| 1122 | clearCanvas(canvas, bgcolor); |
| 1123 | drawBackground(layerdict, false); |
| 1124 | drawHighlightsOnLayer(layerdict, false); |
| 1125 | |
| 1126 | // Save image |
| 1127 | var imgdata = canvas.toDataURL("image/png"); |
| 1128 | |
| 1129 | var filename = pcbdata.metadata.title; |
| 1130 | if (pcbdata.metadata.revision) { |
| 1131 | filename += `.${pcbdata.metadata.revision}`; |
| 1132 | } |
| 1133 | filename += `.${layer}.png`; |
| 1134 | saveFile(filename, dataURLtoBlob(imgdata)); |
| 1135 | } |
| 1136 | |
| 1137 | function saveSettings() { |
| 1138 | var data = { |
| 1139 | type: "InteractiveHtmlBom settings", |
| 1140 | version: 1, |
| 1141 | pcbmetadata: pcbdata.metadata, |
| 1142 | settings: settings, |
| 1143 | } |
| 1144 | var blob = new Blob([JSON.stringify(data, null, 4)], {type: "application/json"}); |
| 1145 | saveFile(`${pcbdata.metadata.title}.settings.json`, blob); |
| 1146 | } |
| 1147 | |
| 1148 | function loadSettings() { |
| 1149 | var input = document.createElement("input"); |
| 1150 | input.type = "file"; |
| 1151 | input.accept = ".settings.json"; |
| 1152 | input.onchange = function(e) { |
| 1153 | var file = e.target.files[0]; |
| 1154 | var reader = new FileReader(); |
| 1155 | reader.onload = readerEvent => { |
| 1156 | var content = readerEvent.target.result; |
| 1157 | var newSettings; |
| 1158 | try { |
| 1159 | newSettings = JSON.parse(content); |
| 1160 | } catch(e) { |
| 1161 | alert("Selected file is not InteractiveHtmlBom settings file."); |
| 1162 | return; |
| 1163 | } |
| 1164 | if (newSettings.type != "InteractiveHtmlBom settings") { |
| 1165 | alert("Selected file is not InteractiveHtmlBom settings file."); |
| 1166 | return; |
| 1167 | } |
| 1168 | var metadataMatches = newSettings.hasOwnProperty("pcbmetadata"); |
| 1169 | if (metadataMatches) { |
| 1170 | for (var k in pcbdata.metadata) { |
| 1171 | if (!newSettings.pcbmetadata.hasOwnProperty(k) || newSettings.pcbmetadata[k] != pcbdata.metadata[k]) { |
| 1172 | metadataMatches = false; |
| 1173 | } |
| 1174 | } |
| 1175 | } |
| 1176 | if (!metadataMatches) { |
| 1177 | var currentMetadata = JSON.stringify(pcbdata.metadata, null, 4); |
| 1178 | var fileMetadata = JSON.stringify(newSettings.pcbmetadata, null, 4); |
| 1179 | if (!confirm( |
| 1180 | `Settins file metadata does not match current metadata.\n\n` + |
| 1181 | `Page metadata:\n${currentMetadata}\n\n` + |
| 1182 | `Settings file metadata:\n${fileMetadata}\n\n` + |
| 1183 | `Press OK if you would like to import settings anyway.`)) { |
| 1184 | return; |
| 1185 | } |
| 1186 | } |
| 1187 | overwriteSettings(newSettings.settings); |
| 1188 | } |
| 1189 | reader.readAsText(file, 'UTF-8'); |
| 1190 | } |
| 1191 | input.click(); |
| 1192 | } |
| 1193 | |
| 1194 | function overwriteSettings(newSettings) { |
| 1195 | initDone = false; |
| 1196 | Object.assign(settings, newSettings); |
| 1197 | writeStorage("bomlayout", settings.bomlayout); |
| 1198 | writeStorage("bommode", settings.bommode); |
| 1199 | writeStorage("canvaslayout", settings.canvaslayout); |
| 1200 | writeStorage("bomCheckboxes", settings.checkboxes.join(",")); |
| 1201 | document.getElementById("bomCheckboxes").value = settings.checkboxes.join(","); |
| 1202 | for (var checkbox of settings.checkboxes) { |
| 1203 | writeStorage("checkbox_" + checkbox, settings.checkboxStoredRefs[checkbox]); |
| 1204 | } |
| 1205 | writeStorage("darkenWhenChecked", settings.darkenWhenChecked); |
| 1206 | padsVisible(settings.renderPads); |
| 1207 | document.getElementById("padsCheckbox").checked = settings.renderPads; |
| 1208 | fabricationVisible(settings.renderFabrication); |
| 1209 | document.getElementById("fabricationCheckbox").checked = settings.renderFabrication; |
| 1210 | silkscreenVisible(settings.renderSilkscreen); |
| 1211 | document.getElementById("silkscreenCheckbox").checked = settings.renderSilkscreen; |
| 1212 | referencesVisible(settings.renderReferences); |
| 1213 | document.getElementById("referencesCheckbox").checked = settings.renderReferences; |
| 1214 | valuesVisible(settings.renderValues); |
| 1215 | document.getElementById("valuesCheckbox").checked = settings.renderValues; |
| 1216 | tracksVisible(settings.renderTracks); |
| 1217 | document.getElementById("tracksCheckbox").checked = settings.renderTracks; |
| 1218 | zonesVisible(settings.renderZones); |
| 1219 | document.getElementById("zonesCheckbox").checked = settings.renderZones; |
| 1220 | dnpOutline(settings.renderDnpOutline); |
| 1221 | document.getElementById("dnpOutlineCheckbox").checked = settings.renderDnpOutline; |
| 1222 | setRedrawOnDrag(settings.redrawOnDrag); |
| 1223 | document.getElementById("dragCheckbox").checked = settings.redrawOnDrag; |
| 1224 | setDarkMode(settings.darkMode); |
| 1225 | document.getElementById("darkmodeCheckbox").checked = settings.darkMode; |
| 1226 | setHighlightPin1(settings.highlightpin1); |
| 1227 | document.getElementById("highlightpin1Checkbox").checked = settings.highlightpin1; |
| 1228 | writeStorage("boardRotation", settings.boardRotation); |
| 1229 | document.getElementById("boardRotation").value = settings.boardRotation / 5; |
| 1230 | document.getElementById("rotationDegree").textContent = settings.boardRotation; |
| 1231 | initDone = true; |
| 1232 | prepCheckboxes(); |
| 1233 | changeBomLayout(settings.bomlayout); |
| 1234 | } |
| 1235 | |
| 1236 | function saveFile(filename, blob) { |
| 1237 | var link = document.createElement("a"); |
| 1238 | var objurl = URL.createObjectURL(blob); |
| 1239 | link.download = filename; |
| 1240 | link.href = objurl; |
| 1241 | link.click(); |
| 1242 | } |
| 1243 | |
| 1244 | function dataURLtoBlob(dataurl) { |
| 1245 | var arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1], |
| 1246 | bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n); |
| 1247 | while(n--){ |
| 1248 | u8arr[n] = bstr.charCodeAt(n); |
| 1249 | } |
| 1250 | return new Blob([u8arr], {type:mime}); |
| 1251 | } |
| 1252 | |
| 1253 | var settings = { |
| 1254 | canvaslayout: "default", |
| 1255 | bomlayout: "default", |
| 1256 | bommode: "grouped", |
| 1257 | checkboxes: [], |
| 1258 | checkboxStoredRefs: {}, |
| 1259 | darkMode: false, |
| 1260 | highlightpin1: false, |
| 1261 | redrawOnDrag: true, |
| 1262 | boardRotation: 0, |
| 1263 | renderPads: true, |
| 1264 | renderReferences: true, |
| 1265 | renderValues: true, |
| 1266 | renderSilkscreen: true, |
| 1267 | renderFabrication: true, |
| 1268 | renderDnpOutline: false, |
| 1269 | renderTracks: true, |
| 1270 | renderZones: true, |
| 1271 | } |
| 1272 | |
| 1273 | function initDefaults() { |
| 1274 | settings.bomlayout = readStorage("bomlayout"); |
| 1275 | if (settings.bomlayout === null) { |
| 1276 | settings.bomlayout = config.bom_view; |
| 1277 | } |
| 1278 | if (!['bom-only', 'left-right', 'top-bottom'].includes(settings.bomlayout)) { |
| 1279 | settings.bomlayout = config.bom_view; |
| 1280 | } |
| 1281 | settings.bommode = readStorage("bommode"); |
| 1282 | if (settings.bommode === null) { |
| 1283 | settings.bommode = "grouped"; |
| 1284 | } |
| 1285 | if (!["grouped", "ungrouped", "netlist"].includes(settings.bommode)) { |
| 1286 | settings.bommode = "grouped"; |
| 1287 | } |
| 1288 | settings.canvaslayout = readStorage("canvaslayout"); |
| 1289 | if (settings.canvaslayout === null) { |
| 1290 | settings.canvaslayout = config.layer_view; |
| 1291 | } |
| 1292 | var bomCheckboxes = readStorage("bomCheckboxes"); |
| 1293 | if (bomCheckboxes === null) { |
| 1294 | bomCheckboxes = config.checkboxes; |
| 1295 | } |
| 1296 | settings.checkboxes = bomCheckboxes.split(",").filter((e) => e); |
| 1297 | document.getElementById("bomCheckboxes").value = bomCheckboxes; |
| 1298 | |
| 1299 | settings.darkenWhenChecked = readStorage("darkenWhenChecked") || ""; |
| 1300 | populateDarkenWhenCheckedOptions(); |
| 1301 | |
| 1302 | function initBooleanSetting(storageString, def, elementId, func) { |
| 1303 | var b = readStorage(storageString); |
| 1304 | if (b === null) { |
| 1305 | b = def; |
| 1306 | } else { |
| 1307 | b = (b == "true"); |
| 1308 | } |
| 1309 | document.getElementById(elementId).checked = b; |
| 1310 | func(b); |
| 1311 | } |
| 1312 | |
| 1313 | initBooleanSetting("padsVisible", config.show_pads, "padsCheckbox", padsVisible); |
| 1314 | initBooleanSetting("fabricationVisible", config.show_fabrication, "fabricationCheckbox", fabricationVisible); |
| 1315 | initBooleanSetting("silkscreenVisible", config.show_silkscreen, "silkscreenCheckbox", silkscreenVisible); |
| 1316 | initBooleanSetting("referencesVisible", true, "referencesCheckbox", referencesVisible); |
| 1317 | initBooleanSetting("valuesVisible", true, "valuesCheckbox", valuesVisible); |
| 1318 | if ("tracks" in pcbdata) { |
| 1319 | initBooleanSetting("tracksVisible", true, "tracksCheckbox", tracksVisible); |
| 1320 | initBooleanSetting("zonesVisible", true, "zonesCheckbox", zonesVisible); |
| 1321 | } else { |
| 1322 | document.getElementById("tracksAndZonesCheckboxes").style.display = "none"; |
| 1323 | tracksVisible(false); |
| 1324 | zonesVisible(false); |
| 1325 | } |
| 1326 | initBooleanSetting("dnpOutline", false, "dnpOutlineCheckbox", dnpOutline); |
| 1327 | initBooleanSetting("redrawOnDrag", config.redraw_on_drag, "dragCheckbox", setRedrawOnDrag); |
| 1328 | initBooleanSetting("darkmode", config.dark_mode, "darkmodeCheckbox", setDarkMode); |
| 1329 | initBooleanSetting("highlightpin1", config.highlight_pin1, "highlightpin1Checkbox", setHighlightPin1); |
| 1330 | settings.boardRotation = readStorage("boardRotation"); |
| 1331 | if (settings.boardRotation === null) { |
| 1332 | settings.boardRotation = config.board_rotation * 5; |
| 1333 | } else { |
| 1334 | settings.boardRotation = parseInt(settings.boardRotation); |
| 1335 | } |
| 1336 | document.getElementById("boardRotation").value = settings.boardRotation / 5; |
| 1337 | document.getElementById("rotationDegree").textContent = settings.boardRotation; |
| 1338 | } |
| 1339 | |
| 1340 | // Helper classes for user js callbacks. |
| 1341 | |
| 1342 | const IBOM_EVENT_TYPES = { |
| 1343 | ALL: "all", |
| 1344 | HIGHLIGHT_EVENT: "highlightEvent", |
| 1345 | CHECKBOX_CHANGE_EVENT: "checkboxChangeEvent", |
| 1346 | BOM_BODY_CHANGE_EVENT: "bomBodyChangeEvent", |
| 1347 | } |
| 1348 | |
| 1349 | const EventHandler = { |
| 1350 | callbacks: {}, |
| 1351 | init: function() { |
| 1352 | for (eventType of Object.values(IBOM_EVENT_TYPES)) |
| 1353 | this.callbacks[eventType] = []; |
| 1354 | }, |
| 1355 | registerCallback: function(eventType, callback) { |
| 1356 | this.callbacks[eventType].push(callback); |
| 1357 | }, |
| 1358 | emitEvent: function(eventType, eventArgs) { |
| 1359 | event = { |
| 1360 | eventType: eventType, |
| 1361 | args: eventArgs, |
| 1362 | } |
| 1363 | var callback; |
| 1364 | for(callback of this.callbacks[eventType]) |
| 1365 | callback(event); |
| 1366 | for(callback of this.callbacks[IBOM_EVENT_TYPES.ALL]) |
| 1367 | callback(event); |
| 1368 | } |
| 1369 | } |
| 1370 | EventHandler.init(); |
| 1371 | |
| 1372 | /////////////////////////////////////////////// |
| 1373 | |
| 1374 | /////////////////////////////////////////////// |
| 1375 | /* PCB rendering code */ |
| 1376 | |
| 1377 | var emptyContext2d = document.createElement("canvas").getContext("2d"); |
| 1378 | |
| 1379 | function deg2rad(deg) { |
| 1380 | return deg * Math.PI / 180; |
| 1381 | } |
| 1382 | |
| 1383 | function calcFontPoint(linepoint, text, offsetx, offsety, tilt) { |
| 1384 | var point = [ |
| 1385 | linepoint[0] * text.width + offsetx, |
| 1386 | linepoint[1] * text.height + offsety |
| 1387 | ]; |
| 1388 | // This approximates pcbnew behavior with how text tilts depending on horizontal justification |
| 1389 | point[0] -= (linepoint[1] + 0.5 * (1 + text.horiz_justify)) * text.height * tilt; |
| 1390 | return point; |
| 1391 | } |
| 1392 | |
| 1393 | function drawtext(ctx, text, color, flip) { |
| 1394 | if ("ref" in text && !settings.renderReferences) return; |
| 1395 | if ("val" in text && !settings.renderValues) return; |
| 1396 | ctx.save(); |
| 1397 | ctx.fillStyle = color; |
| 1398 | ctx.strokeStyle = color; |
| 1399 | ctx.lineCap = "round"; |
| 1400 | ctx.lineJoin = "round"; |
| 1401 | ctx.lineWidth = text.thickness; |
| 1402 | if (text.svgpath) { |
| 1403 | ctx.stroke(new Path2D(text.svgpath)); |
| 1404 | ctx.restore(); |
| 1405 | return; |
| 1406 | } |
| 1407 | ctx.translate(...text.pos); |
| 1408 | ctx.translate(text.thickness * 0.5, 0); |
| 1409 | var angle = -text.angle; |
| 1410 | if (text.attr.includes("mirrored")) { |
| 1411 | ctx.scale(-1, 1); |
| 1412 | angle = -angle; |
| 1413 | } |
| 1414 | var tilt = 0; |
| 1415 | if (text.attr.includes("italic")) { |
| 1416 | tilt = 0.125; |
| 1417 | } |
| 1418 | var interline = (text.height * 1.5 + text.thickness) / 2; |
| 1419 | var txt = text.text.split("\n"); |
| 1420 | // KiCad ignores last empty line. |
| 1421 | if (txt[txt.length - 1] == '') txt.pop(); |
| 1422 | ctx.rotate(deg2rad(angle)); |
| 1423 | for (var i in txt) { |
| 1424 | var offsety = (-(txt.length - 1) + i * 2) * interline + text.height / 2; |
| 1425 | var lineWidth = text.thickness + interline * tilt; |
| 1426 | for (var j = 0; j < txt[i].length; j++) { |
| 1427 | if (txt[i][j] == '\t') { |
| 1428 | var fourSpaces = 4 * pcbdata.font_data[' '].w * text.width; |
| 1429 | lineWidth += fourSpaces - lineWidth % fourSpaces; |
| 1430 | } else { |
| 1431 | if (txt[i][j] == '~') { |
| 1432 | j++; |
| 1433 | if (j == txt[i].length) |
| 1434 | break; |
| 1435 | } |
| 1436 | lineWidth += pcbdata.font_data[txt[i][j]].w * text.width; |
| 1437 | } |
| 1438 | } |
| 1439 | var offsetx = 0; |
| 1440 | switch (text.horiz_justify) { |
| 1441 | case -1: |
| 1442 | // Justify left, do nothing |
| 1443 | break; |
| 1444 | case 0: |
| 1445 | // Justify center |
| 1446 | offsetx -= lineWidth / 2; |
| 1447 | break; |
| 1448 | case 1: |
| 1449 | // Justify right |
| 1450 | offsetx -= lineWidth; |
| 1451 | break; |
| 1452 | } |
| 1453 | var inOverbar = false; |
| 1454 | for (var j = 0; j < txt[i].length; j++) { |
| 1455 | if (txt[i][j] == '\t') { |
| 1456 | var fourSpaces = 4 * pcbdata.font_data[' '].w * text.width; |
| 1457 | offsetx += fourSpaces - offsetx % fourSpaces; |
| 1458 | continue; |
| 1459 | } else if (txt[i][j] == '~') { |
| 1460 | j++; |
| 1461 | if (j == txt[i].length) |
| 1462 | break; |
| 1463 | if (txt[i][j] != '~') { |
| 1464 | inOverbar = !inOverbar; |
| 1465 | } |
| 1466 | } |
| 1467 | var glyph = pcbdata.font_data[txt[i][j]]; |
| 1468 | if (inOverbar) { |
| 1469 | var overbarStart = [offsetx, -text.height * 1.4 + offsety]; |
| 1470 | var overbarEnd = [offsetx + text.width * glyph.w, overbarStart[1]]; |
| 1471 | |
| 1472 | if (!lastHadOverbar) { |
| 1473 | overbarStart[0] += text.height * 1.4 * tilt; |
| 1474 | lastHadOverbar = true; |
| 1475 | } |
| 1476 | ctx.beginPath(); |
| 1477 | ctx.moveTo(...overbarStart); |
| 1478 | ctx.lineTo(...overbarEnd); |
| 1479 | ctx.stroke(); |
| 1480 | } else { |
| 1481 | lastHadOverbar = false; |
| 1482 | } |
| 1483 | for (var line of glyph.l) { |
| 1484 | ctx.beginPath(); |
| 1485 | ctx.moveTo(...calcFontPoint(line[0], text, offsetx, offsety, tilt)); |
| 1486 | for (var k = 1; k < line.length; k++) { |
| 1487 | ctx.lineTo(...calcFontPoint(line[k], text, offsetx, offsety, tilt)); |
| 1488 | } |
| 1489 | ctx.stroke(); |
| 1490 | } |
| 1491 | offsetx += glyph.w * text.width; |
| 1492 | } |
| 1493 | } |
| 1494 | ctx.restore(); |
| 1495 | } |
| 1496 | |
| 1497 | function drawedge(ctx, scalefactor, edge, color) { |
| 1498 | ctx.strokeStyle = color; |
| 1499 | ctx.lineWidth = Math.max(1 / scalefactor, edge.width); |
| 1500 | ctx.lineCap = "round"; |
| 1501 | if (edge.svgpath) { |
| 1502 | ctx.stroke(new Path2D(edge.svgpath)); |
| 1503 | } else { |
| 1504 | ctx.beginPath(); |
| 1505 | if (edge.type == "segment") { |
| 1506 | ctx.moveTo(...edge.start); |
| 1507 | ctx.lineTo(...edge.end); |
| 1508 | } |
| 1509 | if (edge.type == "arc") { |
| 1510 | ctx.arc( |
| 1511 | ...edge.start, |
| 1512 | edge.radius, |
| 1513 | deg2rad(edge.startangle), |
| 1514 | deg2rad(edge.endangle)); |
| 1515 | } |
| 1516 | if (edge.type == "circle") { |
| 1517 | ctx.arc( |
| 1518 | ...edge.start, |
| 1519 | edge.radius, |
| 1520 | 0, 2 * Math.PI); |
| 1521 | ctx.closePath(); |
| 1522 | } |
| 1523 | if (edge.type == "curve") { |
| 1524 | ctx.moveTo(...edge.start); |
| 1525 | ctx.bezierCurveTo(...edge.cpa, ...edge.cpb, ...edge.end); |
| 1526 | } |
| 1527 | ctx.stroke(); |
| 1528 | } |
| 1529 | } |
| 1530 | |
| 1531 | function getChamferedRectPath(size, radius, chamfpos, chamfratio) { |
| 1532 | // chamfpos is a bitmask, left = 1, right = 2, bottom left = 4, bottom right = 8 |
| 1533 | var path = new Path2D(); |
| 1534 | var width = size[0]; |
| 1535 | var height = size[1]; |
| 1536 | var x = width * -0.5; |
| 1537 | var y = height * -0.5; |
| 1538 | var chamfOffset = Math.min(width, height) * chamfratio; |
| 1539 | path.moveTo(x, 0); |
| 1540 | if (chamfpos & 4) { |
| 1541 | path.lineTo(x, y + height - chamfOffset); |
| 1542 | path.lineTo(x + chamfOffset, y + height); |
| 1543 | path.lineTo(0, y + height); |
| 1544 | } else { |
| 1545 | path.arcTo(x, y + height, x + width, y + height, radius); |
| 1546 | } |
| 1547 | if (chamfpos & 8) { |
| 1548 | path.lineTo(x + width - chamfOffset, y + height); |
| 1549 | path.lineTo(x + width, y + height - chamfOffset); |
| 1550 | path.lineTo(x + width, 0); |
| 1551 | } else { |
| 1552 | path.arcTo(x + width, y + height, x + width, y, radius); |
| 1553 | } |
| 1554 | if (chamfpos & 2) { |
| 1555 | path.lineTo(x + width, y + chamfOffset); |
| 1556 | path.lineTo(x + width - chamfOffset, y); |
| 1557 | path.lineTo(0, y); |
| 1558 | } else { |
| 1559 | path.arcTo(x + width, y, x, y, radius); |
| 1560 | } |
| 1561 | if (chamfpos & 1) { |
| 1562 | path.lineTo(x + chamfOffset, y); |
| 1563 | path.lineTo(x, y + chamfOffset); |
| 1564 | path.lineTo(x, 0); |
| 1565 | } else { |
| 1566 | path.arcTo(x, y, x, y + height, radius); |
| 1567 | } |
| 1568 | path.closePath(); |
| 1569 | return path; |
| 1570 | } |
| 1571 | |
| 1572 | function getOblongPath(size) { |
| 1573 | return getChamferedRectPath(size, Math.min(size[0], size[1]) / 2, 0, 0); |
| 1574 | } |
| 1575 | |
| 1576 | function getPolygonsPath(shape) { |
| 1577 | if (shape.path2d) { |
| 1578 | return shape.path2d; |
| 1579 | } |
| 1580 | if (shape.svgpath) { |
| 1581 | shape.path2d = new Path2D(shape.svgpath); |
| 1582 | } else { |
| 1583 | var path = new Path2D(); |
| 1584 | for (var polygon of shape.polygons) { |
| 1585 | path.moveTo(...polygon[0]); |
| 1586 | for (var i = 1; i < polygon.length; i++) { |
| 1587 | path.lineTo(...polygon[i]); |
| 1588 | } |
| 1589 | path.closePath(); |
| 1590 | } |
| 1591 | shape.path2d = path; |
| 1592 | } |
| 1593 | return shape.path2d; |
| 1594 | } |
| 1595 | |
| 1596 | function drawPolygonShape(ctx, shape, color) { |
| 1597 | ctx.save(); |
| 1598 | ctx.fillStyle = color; |
| 1599 | if (!shape.svgpath) { |
| 1600 | ctx.translate(...shape.pos); |
| 1601 | ctx.rotate(deg2rad(-shape.angle)); |
| 1602 | } |
| 1603 | ctx.fill(getPolygonsPath(shape)); |
| 1604 | ctx.restore(); |
| 1605 | } |
| 1606 | |
| 1607 | function drawDrawing(ctx, layer, scalefactor, drawing, color) { |
| 1608 | if (["segment", "arc", "circle", "curve"].includes(drawing.type)) { |
| 1609 | drawedge(ctx, scalefactor, drawing, color); |
| 1610 | } else if (drawing.type == "polygon") { |
| 1611 | drawPolygonShape(ctx, drawing, color); |
| 1612 | } else { |
| 1613 | drawtext(ctx, drawing, color, layer == "B"); |
| 1614 | } |
| 1615 | } |
| 1616 | |
| 1617 | function getCirclePath(radius) { |
| 1618 | var path = new Path2D(); |
| 1619 | path.arc(0, 0, radius, 0, 2 * Math.PI); |
| 1620 | path.closePath(); |
| 1621 | return path; |
| 1622 | } |
| 1623 | |
| 1624 | function getCachedPadPath(pad) { |
| 1625 | if (!pad.path2d) { |
| 1626 | // if path2d is not set, build one and cache it on pad object |
| 1627 | if (pad.shape == "rect") { |
| 1628 | pad.path2d = new Path2D(); |
| 1629 | pad.path2d.rect(...pad.size.map(c => -c * 0.5), ...pad.size); |
| 1630 | } else if (pad.shape == "oval") { |
| 1631 | pad.path2d = getOblongPath(pad.size); |
| 1632 | } else if (pad.shape == "circle") { |
| 1633 | pad.path2d = getCirclePath(pad.size[0] / 2); |
| 1634 | } else if (pad.shape == "roundrect") { |
| 1635 | pad.path2d = getChamferedRectPath(pad.size, pad.radius, 0, 0); |
| 1636 | } else if (pad.shape == "chamfrect") { |
| 1637 | pad.path2d = getChamferedRectPath(pad.size, pad.radius, pad.chamfpos, pad.chamfratio) |
| 1638 | } else if (pad.shape == "custom") { |
| 1639 | pad.path2d = getPolygonsPath(pad); |
| 1640 | } |
| 1641 | } |
| 1642 | return pad.path2d; |
| 1643 | } |
| 1644 | |
| 1645 | function drawPad(ctx, pad, color, outline, hole) { |
| 1646 | ctx.save(); |
| 1647 | ctx.translate(...pad.pos); |
| 1648 | ctx.rotate(deg2rad(pad.angle)); |
| 1649 | if (pad.offset) { |
| 1650 | ctx.translate(...pad.offset); |
| 1651 | } |
| 1652 | ctx.fillStyle = color; |
| 1653 | ctx.strokeStyle = color; |
| 1654 | var path = getCachedPadPath(pad); |
| 1655 | if (outline) { |
| 1656 | ctx.stroke(path); |
| 1657 | } else { |
| 1658 | ctx.fill(path); |
| 1659 | } |
| 1660 | if (pad.type == "th" && hole) { |
| 1661 | if (pad.offset) { |
| 1662 | ctx.translate(-pad.offset[0], -pad.offset[1]); |
| 1663 | } |
| 1664 | ctx.fillStyle = "#CCCCCC"; |
| 1665 | if (pad.drillshape == "oblong") { |
| 1666 | ctx.fill(getOblongPath(pad.drillsize)); |
| 1667 | } else { |
| 1668 | ctx.fill(getCirclePath(pad.drillsize[0] / 2)); |
| 1669 | } |
| 1670 | } |
| 1671 | ctx.restore(); |
| 1672 | } |
| 1673 | |
| 1674 | function drawModule(ctx, layer, scalefactor, module, padcolor, outlinecolor, highlight, outline) { |
| 1675 | if (highlight) { |
| 1676 | // draw bounding box |
| 1677 | if (module.layer == layer) { |
| 1678 | ctx.save(); |
| 1679 | ctx.globalAlpha = 0.2; |
| 1680 | ctx.translate(...module.bbox.pos); |
| 1681 | ctx.rotate(deg2rad(-module.bbox.angle)); |
| 1682 | ctx.translate(...module.bbox.relpos); |
| 1683 | ctx.fillStyle = padcolor; |
| 1684 | ctx.fillRect(0, 0, ...module.bbox.size); |
| 1685 | ctx.globalAlpha = 1; |
| 1686 | ctx.strokeStyle = padcolor; |
| 1687 | ctx.strokeRect(0, 0, ...module.bbox.size); |
| 1688 | ctx.restore(); |
| 1689 | } |
| 1690 | } |
| 1691 | // draw drawings |
| 1692 | for (var drawing of module.drawings) { |
| 1693 | if (drawing.layer == layer) { |
| 1694 | drawDrawing(ctx, layer, scalefactor, drawing.drawing, padcolor); |
| 1695 | } |
| 1696 | } |
| 1697 | // draw pads |
| 1698 | if (settings.renderPads) { |
| 1699 | for (var pad of module.pads) { |
| 1700 | if (pad.layers.includes(layer)) { |
| 1701 | drawPad(ctx, pad, padcolor, outline, true); |
| 1702 | if (pad.pin1 && settings.highlightpin1) { |
| 1703 | drawPad(ctx, pad, outlinecolor, true, false); |
| 1704 | } |
| 1705 | } |
| 1706 | } |
| 1707 | } |
| 1708 | } |
| 1709 | |
| 1710 | function drawEdgeCuts(canvas, scalefactor) { |
| 1711 | var ctx = canvas.getContext("2d"); |
| 1712 | var edgecolor = getComputedStyle(topmostdiv).getPropertyValue('--pcb-edge-color'); |
| 1713 | for (var edge of pcbdata.edges) { |
| 1714 | drawedge(ctx, scalefactor, edge, edgecolor); |
| 1715 | } |
| 1716 | } |
| 1717 | |
| 1718 | function drawModules(canvas, layer, scalefactor, highlight) { |
| 1719 | var ctx = canvas.getContext("2d"); |
| 1720 | ctx.lineWidth = 3 / scalefactor; |
| 1721 | var style = getComputedStyle(topmostdiv); |
| 1722 | var padcolor = style.getPropertyValue('--pad-color'); |
| 1723 | var outlinecolor = style.getPropertyValue('--pin1-outline-color'); |
| 1724 | if (highlight) { |
| 1725 | padcolor = style.getPropertyValue('--pad-color-highlight'); |
| 1726 | outlinecolor = style.getPropertyValue('--pin1-outline-color-highlight'); |
| 1727 | } |
| 1728 | for (var i = 0; i < pcbdata.modules.length; i++) { |
| 1729 | var mod = pcbdata.modules[i]; |
| 1730 | var outline = settings.renderDnpOutline && pcbdata.bom.skipped.includes(i); |
| 1731 | if (!highlight || highlightedModules.includes(i)) { |
| 1732 | drawModule(ctx, layer, scalefactor, mod, padcolor, outlinecolor, highlight, outline); |
| 1733 | } |
| 1734 | } |
| 1735 | } |
| 1736 | |
| 1737 | function drawBgLayer(layername, canvas, layer, scalefactor, edgeColor, polygonColor, textColor) { |
| 1738 | var ctx = canvas.getContext("2d"); |
| 1739 | for (var d of pcbdata[layername][layer]) { |
| 1740 | if (["segment", "arc", "circle", "curve"].includes(d.type)) { |
| 1741 | drawedge(ctx, scalefactor, d, edgeColor); |
| 1742 | } else if (d.type == "polygon") { |
| 1743 | drawPolygonShape(ctx, d, polygonColor); |
| 1744 | } else { |
| 1745 | drawtext(ctx, d, textColor, layer == "B"); |
| 1746 | } |
| 1747 | } |
| 1748 | } |
| 1749 | |
| 1750 | function drawTracks(canvas, layer, color, highlight) { |
| 1751 | ctx = canvas.getContext("2d"); |
| 1752 | ctx.strokeStyle = color; |
| 1753 | ctx.lineCap = "round"; |
| 1754 | for(var track of pcbdata.tracks[layer]) { |
| 1755 | if (highlight && highlightedNet != track.net) continue; |
| 1756 | ctx.lineWidth = track.width; |
| 1757 | ctx.beginPath(); |
| 1758 | ctx.moveTo(...track.start); |
| 1759 | ctx.lineTo(...track.end); |
| 1760 | ctx.stroke(); |
| 1761 | } |
| 1762 | } |
| 1763 | |
| 1764 | function drawZones(canvas, layer, color, highlight) { |
| 1765 | ctx = canvas.getContext("2d"); |
| 1766 | ctx.strokeStyle = color; |
| 1767 | ctx.fillStyle = color; |
| 1768 | ctx.lineJoin = "round"; |
| 1769 | for(var zone of pcbdata.zones[layer]) { |
| 1770 | if (!zone.path2d) { |
| 1771 | zone.path2d = getPolygonsPath(zone); |
| 1772 | } |
| 1773 | if (highlight && highlightedNet != zone.net) continue; |
| 1774 | ctx.lineWidth = zone.width ? zone.width : 0; |
| 1775 | ctx.fill(zone.path2d); |
| 1776 | ctx.stroke(zone.path2d); |
| 1777 | } |
| 1778 | } |
| 1779 | |
| 1780 | function clearCanvas(canvas, color = null) { |
| 1781 | var ctx = canvas.getContext("2d"); |
| 1782 | ctx.save(); |
| 1783 | ctx.setTransform(1, 0, 0, 1, 0, 0); |
| 1784 | if (color) { |
| 1785 | ctx.fillStyle = color; |
| 1786 | ctx.fillRect(0, 0, canvas.width, canvas.height); |
| 1787 | } else { |
| 1788 | ctx.clearRect(0, 0, canvas.width, canvas.height); |
| 1789 | } |
| 1790 | ctx.restore(); |
| 1791 | } |
| 1792 | |
| 1793 | function drawNets(canvas, layer, highlight) { |
| 1794 | var style = getComputedStyle(topmostdiv); |
| 1795 | if (settings.renderTracks) { |
| 1796 | var trackColor = style.getPropertyValue(highlight ? '--track-color-highlight' : '--track-color'); |
| 1797 | drawTracks(canvas, layer, trackColor, highlight); |
| 1798 | } |
| 1799 | if (settings.renderZones) { |
| 1800 | var zoneColor = style.getPropertyValue(highlight ? '--zone-color-highlight' : '--zone-color'); |
| 1801 | drawZones(canvas, layer, zoneColor, highlight); |
| 1802 | } |
| 1803 | if (highlight && settings.renderPads) { |
| 1804 | var padColor = style.getPropertyValue('--pad-color-highlight'); |
| 1805 | var ctx = canvas.getContext("2d"); |
| 1806 | for (var mod of pcbdata.modules) { |
| 1807 | // draw pads |
| 1808 | for (var pad of mod.pads) { |
| 1809 | if (highlightedNet != pad.net) continue; |
| 1810 | if (pad.layers.includes(layer)) { |
| 1811 | drawPad(ctx, pad, padColor, false, true); |
| 1812 | } |
| 1813 | } |
| 1814 | } |
| 1815 | } |
| 1816 | } |
| 1817 | |
| 1818 | function drawHighlightsOnLayer(canvasdict, clear = true) { |
| 1819 | if (clear) { |
| 1820 | clearCanvas(canvasdict.highlight); |
| 1821 | } |
| 1822 | if (highlightedModules.length > 0) { |
| 1823 | drawModules(canvasdict.highlight, canvasdict.layer, |
| 1824 | canvasdict.transform.s * canvasdict.transform.zoom, true); |
| 1825 | } |
| 1826 | if (highlightedNet !== null) { |
| 1827 | drawNets(canvasdict.highlight, canvasdict.layer, true); |
| 1828 | } |
| 1829 | } |
| 1830 | |
| 1831 | function drawHighlights() { |
| 1832 | drawHighlightsOnLayer(allcanvas.front); |
| 1833 | drawHighlightsOnLayer(allcanvas.back); |
| 1834 | } |
| 1835 | |
| 1836 | function drawBackground(canvasdict, clear = true) { |
| 1837 | if (clear) { |
| 1838 | clearCanvas(canvasdict.bg); |
| 1839 | clearCanvas(canvasdict.fab); |
| 1840 | clearCanvas(canvasdict.silk); |
| 1841 | } |
| 1842 | |
| 1843 | drawNets(canvasdict.bg, canvasdict.layer, false); |
| 1844 | drawModules(canvasdict.bg, canvasdict.layer, |
| 1845 | canvasdict.transform.s * canvasdict.transform.zoom, false); |
| 1846 | |
| 1847 | drawEdgeCuts(canvasdict.bg, canvasdict.transform.s); |
| 1848 | |
| 1849 | var style = getComputedStyle(topmostdiv); |
| 1850 | var edgeColor = style.getPropertyValue('--silkscreen-edge-color'); |
| 1851 | var polygonColor = style.getPropertyValue('--silkscreen-polygon-color'); |
| 1852 | var textColor = style.getPropertyValue('--silkscreen-text-color'); |
| 1853 | if (settings.renderSilkscreen) { |
| 1854 | drawBgLayer( |
| 1855 | "silkscreen", canvasdict.silk, canvasdict.layer, |
| 1856 | canvasdict.transform.s * canvasdict.transform.zoom, |
| 1857 | edgeColor, polygonColor, textColor); |
| 1858 | } |
| 1859 | edgeColor = style.getPropertyValue('--fabrication-edge-color'); |
| 1860 | polygonColor = style.getPropertyValue('--fabrication-polygon-color'); |
| 1861 | textColor = style.getPropertyValue('--fabrication-text-color'); |
| 1862 | if (settings.renderFabrication) { |
| 1863 | drawBgLayer( |
| 1864 | "fabrication", canvasdict.fab, canvasdict.layer, |
| 1865 | canvasdict.transform.s * canvasdict.transform.zoom, |
| 1866 | edgeColor, polygonColor, textColor); |
| 1867 | } |
| 1868 | } |
| 1869 | |
| 1870 | function prepareCanvas(canvas, flip, transform) { |
| 1871 | var ctx = canvas.getContext("2d"); |
| 1872 | ctx.setTransform(1, 0, 0, 1, 0, 0); |
| 1873 | var fontsize = 1.55; |
| 1874 | ctx.scale(transform.zoom, transform.zoom); |
| 1875 | ctx.translate(transform.panx, transform.pany); |
| 1876 | if (flip) { |
| 1877 | ctx.scale(-1, 1); |
| 1878 | } |
| 1879 | ctx.translate(transform.x, transform.y); |
| 1880 | ctx.rotate(deg2rad(settings.boardRotation)); |
| 1881 | ctx.scale(transform.s, transform.s); |
| 1882 | } |
| 1883 | |
| 1884 | function prepareLayer(canvasdict) { |
| 1885 | var flip = (canvasdict.layer == "B"); |
| 1886 | for (var c of ["bg", "fab", "silk", "highlight"]) { |
| 1887 | prepareCanvas(canvasdict[c], flip, canvasdict.transform); |
| 1888 | } |
| 1889 | } |
| 1890 | |
| 1891 | function rotateVector(v, angle) { |
| 1892 | angle = deg2rad(angle); |
| 1893 | return [ |
| 1894 | v[0] * Math.cos(angle) - v[1] * Math.sin(angle), |
| 1895 | v[0] * Math.sin(angle) + v[1] * Math.cos(angle) |
| 1896 | ]; |
| 1897 | } |
| 1898 | |
| 1899 | function applyRotation(bbox) { |
| 1900 | var corners = [ |
| 1901 | [bbox.minx, bbox.miny], |
| 1902 | [bbox.minx, bbox.maxy], |
| 1903 | [bbox.maxx, bbox.miny], |
| 1904 | [bbox.maxx, bbox.maxy], |
| 1905 | ]; |
| 1906 | corners = corners.map((v) => rotateVector(v, settings.boardRotation)); |
| 1907 | return { |
| 1908 | minx: corners.reduce((a, v) => Math.min(a, v[0]), Infinity), |
| 1909 | miny: corners.reduce((a, v) => Math.min(a, v[1]), Infinity), |
| 1910 | maxx: corners.reduce((a, v) => Math.max(a, v[0]), -Infinity), |
| 1911 | maxy: corners.reduce((a, v) => Math.max(a, v[1]), -Infinity), |
| 1912 | } |
| 1913 | } |
| 1914 | |
| 1915 | function recalcLayerScale(layerdict, width, height) { |
| 1916 | var bbox = applyRotation(pcbdata.edges_bbox); |
| 1917 | var scalefactor = 0.98 * Math.min( |
| 1918 | width / (bbox.maxx - bbox.minx), |
| 1919 | height / (bbox.maxy - bbox.miny) |
| 1920 | ); |
| 1921 | if (scalefactor < 0.1) { |
| 1922 | scalefactor = 1; |
| 1923 | } |
| 1924 | layerdict.transform.s = scalefactor; |
| 1925 | var flip = (layerdict.layer == "B"); |
| 1926 | if (flip) { |
| 1927 | layerdict.transform.x = -((bbox.maxx + bbox.minx) * scalefactor + width) * 0.5; |
| 1928 | } else { |
| 1929 | layerdict.transform.x = -((bbox.maxx + bbox.minx) * scalefactor - width) * 0.5; |
| 1930 | } |
| 1931 | layerdict.transform.y = -((bbox.maxy + bbox.miny) * scalefactor - height) * 0.5; |
| 1932 | for (var c of ["bg", "fab", "silk", "highlight"]) { |
| 1933 | canvas = layerdict[c]; |
| 1934 | canvas.width = width; |
| 1935 | canvas.height = height; |
| 1936 | canvas.style.width = (width / devicePixelRatio) + "px"; |
| 1937 | canvas.style.height = (height / devicePixelRatio) + "px"; |
| 1938 | } |
| 1939 | } |
| 1940 | |
| 1941 | function redrawCanvas(layerdict) { |
| 1942 | prepareLayer(layerdict); |
| 1943 | drawBackground(layerdict); |
| 1944 | drawHighlightsOnLayer(layerdict); |
| 1945 | } |
| 1946 | |
| 1947 | function resizeCanvas(layerdict) { |
| 1948 | var canvasdivid = { |
| 1949 | "F": "frontcanvas", |
| 1950 | "B": "backcanvas" |
| 1951 | } [layerdict.layer]; |
| 1952 | var width = document.getElementById(canvasdivid).clientWidth * devicePixelRatio; |
| 1953 | var height = document.getElementById(canvasdivid).clientHeight * devicePixelRatio; |
| 1954 | recalcLayerScale(layerdict, width, height); |
| 1955 | redrawCanvas(layerdict); |
| 1956 | } |
| 1957 | |
| 1958 | function resizeAll() { |
| 1959 | resizeCanvas(allcanvas.front); |
| 1960 | resizeCanvas(allcanvas.back); |
| 1961 | } |
| 1962 | |
| 1963 | function pointWithinDistanceToSegment(x, y, x1, y1, x2, y2, d) { |
| 1964 | var A = x - x1; |
| 1965 | var B = y - y1; |
| 1966 | var C = x2 - x1; |
| 1967 | var D = y2 - y1; |
| 1968 | |
| 1969 | var dot = A * C + B * D; |
| 1970 | var len_sq = C * C + D * D; |
| 1971 | var dx, dy; |
| 1972 | if (len_sq == 0) { |
| 1973 | // start and end of the segment coincide |
| 1974 | dx = x - x1; |
| 1975 | dy = y - y1; |
| 1976 | } else { |
| 1977 | var param = dot / len_sq; |
| 1978 | var xx, yy; |
| 1979 | if (param < 0) { |
| 1980 | xx = x1; |
| 1981 | yy = y1; |
| 1982 | } else if (param > 1) { |
| 1983 | xx = x2; |
| 1984 | yy = y2; |
| 1985 | } else { |
| 1986 | xx = x1 + param * C; |
| 1987 | yy = y1 + param * D; |
| 1988 | } |
| 1989 | dx = x - xx; |
| 1990 | dy = y - yy; |
| 1991 | } |
| 1992 | return dx * dx + dy * dy <= d * d; |
| 1993 | } |
| 1994 | |
| 1995 | function pointWithinPad(x, y, pad) { |
| 1996 | var v = [x - pad.pos[0], y - pad.pos[1]]; |
| 1997 | v = rotateVector(v, -pad.angle); |
| 1998 | if (pad.offset) { |
| 1999 | v[0] -= pad.offset[0]; |
| 2000 | v[1] -= pad.offset[1]; |
| 2001 | } |
| 2002 | return emptyContext2d.isPointInPath(getCachedPadPath(pad), ...v); |
| 2003 | } |
| 2004 | |
| 2005 | function netHitScan(layer, x, y) { |
| 2006 | // Check track segments |
| 2007 | if (settings.renderTracks && pcbdata.tracks) { |
| 2008 | for(var track of pcbdata.tracks[layer]) { |
| 2009 | if (pointWithinDistanceToSegment(x, y, ...track.start, ...track.end, track.width / 2)) { |
| 2010 | return track.net; |
| 2011 | } |
| 2012 | } |
| 2013 | } |
| 2014 | // Check pads |
| 2015 | if (settings.renderPads) { |
| 2016 | for (var mod of pcbdata.modules) { |
| 2017 | for(var pad of mod.pads) { |
| 2018 | if (pad.layers.includes(layer) && pointWithinPad(x, y, pad)) { |
| 2019 | return pad.net; |
| 2020 | } |
| 2021 | } |
| 2022 | } |
| 2023 | } |
| 2024 | return null; |
| 2025 | } |
| 2026 | |
| 2027 | function pointWithinModuleBbox(x, y, bbox) { |
| 2028 | var v = [x - bbox.pos[0], y - bbox.pos[1]]; |
| 2029 | v = rotateVector(v, bbox.angle); |
| 2030 | return bbox.relpos[0] <= v[0] && v[0] <= bbox.relpos[0] + bbox.size[0] && |
| 2031 | bbox.relpos[1] <= v[1] && v[1] <= bbox.relpos[1] + bbox.size[1]; |
| 2032 | } |
| 2033 | |
| 2034 | function bboxHitScan(layer, x, y) { |
| 2035 | var result = []; |
| 2036 | for (var i = 0; i < pcbdata.modules.length; i++) { |
| 2037 | var module = pcbdata.modules[i]; |
| 2038 | if (module.layer == layer) { |
| 2039 | if (pointWithinModuleBbox(x, y, module.bbox)) { |
| 2040 | result.push(i); |
| 2041 | } |
| 2042 | } |
| 2043 | } |
| 2044 | return result; |
| 2045 | } |
| 2046 | |
| 2047 | function handlePointerDown(e, layerdict) { |
| 2048 | if (e.button != 0 && e.button != 1) { |
| 2049 | return; |
| 2050 | } |
| 2051 | e.preventDefault(); |
| 2052 | e.stopPropagation(); |
| 2053 | |
| 2054 | if (!e.hasOwnProperty("offsetX")) { |
| 2055 | // The polyfill doesn't set this properly |
| 2056 | e.offsetX = e.pageX - e.currentTarget.offsetLeft; |
| 2057 | e.offsetY = e.pageY - e.currentTarget.offsetTop; |
| 2058 | } |
| 2059 | |
| 2060 | layerdict.pointerStates[e.pointerId] = { |
| 2061 | distanceTravelled: 0, |
| 2062 | lastX: e.offsetX, |
| 2063 | lastY: e.offsetY, |
| 2064 | downTime: Date.now(), |
| 2065 | }; |
| 2066 | } |
| 2067 | |
| 2068 | function handleMouseClick(e, layerdict) { |
| 2069 | if (!e.hasOwnProperty("offsetX")) { |
| 2070 | // The polyfill doesn't set this properly |
| 2071 | e.offsetX = e.pageX - e.currentTarget.offsetLeft; |
| 2072 | e.offsetY = e.pageY - e.currentTarget.offsetTop; |
| 2073 | } |
| 2074 | |
| 2075 | var x = e.offsetX; |
| 2076 | var y = e.offsetY; |
| 2077 | var t = layerdict.transform; |
| 2078 | if (layerdict.layer == "B") { |
| 2079 | x = (devicePixelRatio * x / t.zoom - t.panx + t.x) / -t.s; |
| 2080 | } else { |
| 2081 | x = (devicePixelRatio * x / t.zoom - t.panx - t.x) / t.s; |
| 2082 | } |
| 2083 | y = (devicePixelRatio * y / t.zoom - t.y - t.pany) / t.s; |
| 2084 | var v = rotateVector([x, y], -settings.boardRotation); |
| 2085 | if ("nets" in pcbdata) { |
| 2086 | var net = netHitScan(layerdict.layer, ...v); |
| 2087 | if (net !== highlightedNet) { |
| 2088 | netClicked(net); |
| 2089 | } |
| 2090 | } |
| 2091 | if (highlightedNet === null) { |
| 2092 | var modules = bboxHitScan(layerdict.layer, ...v); |
| 2093 | if (modules.length > 0) { |
| 2094 | modulesClicked(modules); |
| 2095 | } |
| 2096 | } |
| 2097 | } |
| 2098 | |
| 2099 | function handlePointerLeave(e, layerdict) { |
| 2100 | e.preventDefault(); |
| 2101 | e.stopPropagation(); |
| 2102 | |
| 2103 | if (!settings.redrawOnDrag) { |
| 2104 | redrawCanvas(layerdict); |
| 2105 | } |
| 2106 | |
| 2107 | delete layerdict.pointerStates[e.pointerId]; |
| 2108 | } |
| 2109 | |
| 2110 | function resetTransform(layerdict) { |
| 2111 | layerdict.transform.panx = 0; |
| 2112 | layerdict.transform.pany = 0; |
| 2113 | layerdict.transform.zoom = 1; |
| 2114 | redrawCanvas(layerdict); |
| 2115 | } |
| 2116 | |
| 2117 | function handlePointerUp(e, layerdict) { |
| 2118 | if (!e.hasOwnProperty("offsetX")) { |
| 2119 | // The polyfill doesn't set this properly |
| 2120 | e.offsetX = e.pageX - e.currentTarget.offsetLeft; |
| 2121 | e.offsetY = e.pageY - e.currentTarget.offsetTop; |
| 2122 | } |
| 2123 | |
| 2124 | e.preventDefault(); |
| 2125 | e.stopPropagation(); |
| 2126 | |
| 2127 | if (e.button == 2) { |
| 2128 | // Reset pan and zoom on right click. |
| 2129 | resetTransform(layerdict); |
| 2130 | layerdict.anotherPointerTapped = false; |
| 2131 | return; |
| 2132 | } |
| 2133 | |
| 2134 | // We haven't necessarily had a pointermove event since the interaction started, so make sure we update this now |
| 2135 | var ptr = layerdict.pointerStates[e.pointerId]; |
| 2136 | ptr.distanceTravelled += Math.abs(e.offsetX - ptr.lastX) + Math.abs(e.offsetY - ptr.lastY); |
| 2137 | |
| 2138 | if (e.button == 0 && ptr.distanceTravelled < 10 && Date.now() - ptr.downTime <= 500) { |
| 2139 | if (Object.keys(layerdict.pointerStates).length == 1) { |
| 2140 | if (layerdict.anotherPointerTapped) { |
| 2141 | // This is the second pointer coming off of a two-finger tap |
| 2142 | resetTransform(layerdict); |
| 2143 | } else { |
| 2144 | // This is just a regular tap |
| 2145 | handleMouseClick(e, layerdict); |
| 2146 | } |
| 2147 | layerdict.anotherPointerTapped = false; |
| 2148 | } else { |
| 2149 | // This is the first finger coming off of what could become a two-finger tap |
| 2150 | layerdict.anotherPointerTapped = true; |
| 2151 | } |
| 2152 | } else { |
| 2153 | if (!settings.redrawOnDrag) { |
| 2154 | redrawCanvas(layerdict); |
| 2155 | } |
| 2156 | layerdict.anotherPointerTapped = false; |
| 2157 | } |
| 2158 | |
| 2159 | delete layerdict.pointerStates[e.pointerId]; |
| 2160 | } |
| 2161 | |
| 2162 | function handlePointerMove(e, layerdict) { |
| 2163 | if (!layerdict.pointerStates.hasOwnProperty(e.pointerId)) { |
| 2164 | return; |
| 2165 | } |
| 2166 | e.preventDefault(); |
| 2167 | e.stopPropagation(); |
| 2168 | |
| 2169 | if (!e.hasOwnProperty("offsetX")) { |
| 2170 | // The polyfill doesn't set this properly |
| 2171 | e.offsetX = e.pageX - e.currentTarget.offsetLeft; |
| 2172 | e.offsetY = e.pageY - e.currentTarget.offsetTop; |
| 2173 | } |
| 2174 | |
| 2175 | var thisPtr = layerdict.pointerStates[e.pointerId]; |
| 2176 | |
| 2177 | var dx = e.offsetX - thisPtr.lastX; |
| 2178 | var dy = e.offsetY - thisPtr.lastY; |
| 2179 | |
| 2180 | // If this number is low on pointer up, we count the action as a click |
| 2181 | thisPtr.distanceTravelled += Math.abs(dx) + Math.abs(dy); |
| 2182 | |
| 2183 | if (Object.keys(layerdict.pointerStates).length == 1) { |
| 2184 | // This is a simple drag |
| 2185 | layerdict.transform.panx += devicePixelRatio * dx / layerdict.transform.zoom; |
| 2186 | layerdict.transform.pany += devicePixelRatio * dy / layerdict.transform.zoom; |
| 2187 | } else if (Object.keys(layerdict.pointerStates).length == 2) { |
| 2188 | var otherPtr = Object.values(layerdict.pointerStates).filter((ptr) => ptr != thisPtr)[0]; |
| 2189 | |
| 2190 | var oldDist = Math.sqrt(Math.pow(thisPtr.lastX - otherPtr.lastX, 2) + Math.pow(thisPtr.lastY - otherPtr.lastY, 2)); |
| 2191 | var newDist = Math.sqrt(Math.pow(e.offsetX - otherPtr.lastX, 2) + Math.pow(e.offsetY - otherPtr.lastY, 2)); |
| 2192 | |
| 2193 | var scaleFactor = newDist/oldDist; |
| 2194 | |
| 2195 | if (scaleFactor != NaN) { |
| 2196 | layerdict.transform.zoom *= scaleFactor; |
| 2197 | |
| 2198 | var zoomd = (1 - scaleFactor) / layerdict.transform.zoom; |
| 2199 | layerdict.transform.panx += devicePixelRatio * otherPtr.lastX * zoomd; |
| 2200 | layerdict.transform.pany += devicePixelRatio * otherPtr.lastY * zoomd; |
| 2201 | } |
| 2202 | } |
| 2203 | |
| 2204 | thisPtr.lastX = e.offsetX; |
| 2205 | thisPtr.lastY = e.offsetY; |
| 2206 | |
| 2207 | if (settings.redrawOnDrag) { |
| 2208 | redrawCanvas(layerdict); |
| 2209 | } |
| 2210 | } |
| 2211 | |
| 2212 | function handleMouseWheel(e, layerdict) { |
| 2213 | e.preventDefault(); |
| 2214 | e.stopPropagation(); |
| 2215 | var t = layerdict.transform; |
| 2216 | var wheeldelta = e.deltaY; |
| 2217 | if (e.deltaMode == 1) { |
| 2218 | // FF only, scroll by lines |
| 2219 | wheeldelta *= 30; |
| 2220 | } else if (e.deltaMode == 2) { |
| 2221 | wheeldelta *= 300; |
| 2222 | } |
| 2223 | var m = Math.pow(1.1, -wheeldelta / 40); |
| 2224 | // Limit amount of zoom per tick. |
| 2225 | if (m > 2) { |
| 2226 | m = 2; |
| 2227 | } else if (m < 0.5) { |
| 2228 | m = 0.5; |
| 2229 | } |
| 2230 | t.zoom *= m; |
| 2231 | var zoomd = (1 - m) / t.zoom; |
| 2232 | t.panx += devicePixelRatio * e.offsetX * zoomd; |
| 2233 | t.pany += devicePixelRatio * e.offsetY * zoomd; |
| 2234 | redrawCanvas(layerdict); |
| 2235 | } |
| 2236 | |
| 2237 | function addMouseHandlers(div, layerdict) { |
| 2238 | div.addEventListener("pointerdown", function(e) { |
| 2239 | handlePointerDown(e, layerdict); |
| 2240 | }); |
| 2241 | div.addEventListener("pointermove", function(e) { |
| 2242 | handlePointerMove(e, layerdict); |
| 2243 | }); |
| 2244 | div.addEventListener("pointerup", function(e) { |
| 2245 | handlePointerUp(e, layerdict); |
| 2246 | }); |
| 2247 | var pointerleave = function(e) { |
| 2248 | handlePointerLeave(e, layerdict); |
| 2249 | } |
| 2250 | div.addEventListener("pointercancel", pointerleave); |
| 2251 | div.addEventListener("pointerleave", pointerleave); |
| 2252 | div.addEventListener("pointerout", pointerleave); |
| 2253 | |
| 2254 | div.onwheel = function(e) { |
| 2255 | handleMouseWheel(e, layerdict); |
| 2256 | } |
| 2257 | for (var element of [div, layerdict.bg, layerdict.fab, layerdict.silk, layerdict.highlight]) { |
| 2258 | element.addEventListener("contextmenu", function(e) { |
| 2259 | e.preventDefault(); |
| 2260 | }, false); |
| 2261 | } |
| 2262 | } |
| 2263 | |
| 2264 | function setRedrawOnDrag(value) { |
| 2265 | settings.redrawOnDrag = value; |
| 2266 | writeStorage("redrawOnDrag", value); |
| 2267 | } |
| 2268 | |
| 2269 | function setBoardRotation(value) { |
| 2270 | settings.boardRotation = value * 5; |
| 2271 | writeStorage("boardRotation", settings.boardRotation); |
| 2272 | document.getElementById("rotationDegree").textContent = settings.boardRotation; |
| 2273 | resizeAll(); |
| 2274 | } |
| 2275 | |
| 2276 | function initRender() { |
| 2277 | allcanvas = { |
| 2278 | front: { |
| 2279 | transform: { |
| 2280 | x: 0, |
| 2281 | y: 0, |
| 2282 | s: 1, |
| 2283 | panx: 0, |
| 2284 | pany: 0, |
| 2285 | zoom: 1, |
| 2286 | }, |
| 2287 | pointerStates: {}, |
| 2288 | anotherPointerTapped: false, |
| 2289 | bg: document.getElementById("F_bg"), |
| 2290 | fab: document.getElementById("F_fab"), |
| 2291 | silk: document.getElementById("F_slk"), |
| 2292 | highlight: document.getElementById("F_hl"), |
| 2293 | layer: "F", |
| 2294 | }, |
| 2295 | back: { |
| 2296 | transform: { |
| 2297 | x: 0, |
| 2298 | y: 0, |
| 2299 | s: 1, |
| 2300 | panx: 0, |
| 2301 | pany: 0, |
| 2302 | zoom: 1, |
| 2303 | }, |
| 2304 | pointerStates: {}, |
| 2305 | anotherPointerTapped: false, |
| 2306 | bg: document.getElementById("B_bg"), |
| 2307 | fab: document.getElementById("B_fab"), |
| 2308 | silk: document.getElementById("B_slk"), |
| 2309 | highlight: document.getElementById("B_hl"), |
| 2310 | layer: "B", |
| 2311 | } |
| 2312 | }; |
| 2313 | addMouseHandlers(document.getElementById("frontcanvas"), allcanvas.front); |
| 2314 | addMouseHandlers(document.getElementById("backcanvas"), allcanvas.back); |
| 2315 | } |
| 2316 | |
| 2317 | /////////////////////////////////////////////// |
| 2318 | |
| 2319 | /////////////////////////////////////////////// |
| 2320 | /* DOM manipulation and misc code */ |
| 2321 | |
| 2322 | var bomsplit; |
| 2323 | var canvassplit; |
| 2324 | var initDone = false; |
| 2325 | var bomSortFunction = null; |
| 2326 | var currentSortColumn = null; |
| 2327 | var currentSortOrder = null; |
| 2328 | var currentHighlightedRowId; |
| 2329 | var highlightHandlers = []; |
| 2330 | var moduleIndexToHandler = {}; |
| 2331 | var netsToHandler = {}; |
| 2332 | var highlightedModules = []; |
| 2333 | var highlightedNet = null; |
| 2334 | var lastClicked; |
| 2335 | |
| 2336 | function dbg(html) { |
| 2337 | dbgdiv.innerHTML = html; |
| 2338 | } |
| 2339 | |
| 2340 | function redrawIfInitDone() { |
| 2341 | if (initDone) { |
| 2342 | redrawCanvas(allcanvas.front); |
| 2343 | redrawCanvas(allcanvas.back); |
| 2344 | } |
| 2345 | } |
| 2346 | |
| 2347 | function padsVisible(value) { |
| 2348 | writeStorage("padsVisible", value); |
| 2349 | settings.renderPads = value; |
| 2350 | redrawIfInitDone(); |
| 2351 | } |
| 2352 | |
| 2353 | function referencesVisible(value) { |
| 2354 | writeStorage("referencesVisible", value); |
| 2355 | settings.renderReferences = value; |
| 2356 | redrawIfInitDone(); |
| 2357 | } |
| 2358 | |
| 2359 | function valuesVisible(value) { |
| 2360 | writeStorage("valuesVisible", value); |
| 2361 | settings.renderValues = value; |
| 2362 | redrawIfInitDone(); |
| 2363 | } |
| 2364 | |
| 2365 | function tracksVisible(value) { |
| 2366 | writeStorage("tracksVisible", value); |
| 2367 | settings.renderTracks = value; |
| 2368 | redrawIfInitDone(); |
| 2369 | } |
| 2370 | |
| 2371 | function zonesVisible(value) { |
| 2372 | writeStorage("zonesVisible", value); |
| 2373 | settings.renderZones = value; |
| 2374 | redrawIfInitDone(); |
| 2375 | } |
| 2376 | |
| 2377 | function dnpOutline(value) { |
| 2378 | writeStorage("dnpOutline", value); |
| 2379 | settings.renderDnpOutline = value; |
| 2380 | redrawIfInitDone(); |
| 2381 | } |
| 2382 | |
| 2383 | function setDarkMode(value) { |
| 2384 | if (value) { |
| 2385 | topmostdiv.classList.add("dark"); |
| 2386 | } else { |
| 2387 | topmostdiv.classList.remove("dark"); |
| 2388 | } |
| 2389 | writeStorage("darkmode", value); |
| 2390 | settings.darkMode = value; |
| 2391 | redrawIfInitDone(); |
| 2392 | } |
| 2393 | |
| 2394 | function setFullscreen(value) { |
| 2395 | if (value) { |
| 2396 | document.documentElement.requestFullscreen(); |
| 2397 | } else { |
| 2398 | document.exitFullscreen(); |
| 2399 | } |
| 2400 | } |
| 2401 | |
| 2402 | function fabricationVisible(value) { |
| 2403 | writeStorage("fabricationVisible", value); |
| 2404 | settings.renderFabrication = value; |
| 2405 | redrawIfInitDone(); |
| 2406 | } |
| 2407 | |
| 2408 | function silkscreenVisible(value) { |
| 2409 | writeStorage("silkscreenVisible", value); |
| 2410 | settings.renderSilkscreen = value; |
| 2411 | redrawIfInitDone(); |
| 2412 | } |
| 2413 | |
| 2414 | function setHighlightPin1(value) { |
| 2415 | writeStorage("highlightpin1", value); |
| 2416 | settings.highlightpin1 = value; |
| 2417 | redrawIfInitDone(); |
| 2418 | } |
| 2419 | |
| 2420 | function getStoredCheckboxRefs(checkbox) { |
| 2421 | function convert(ref) { |
| 2422 | var intref = parseInt(ref); |
| 2423 | if (isNaN(intref)) { |
| 2424 | for (var i = 0; i < pcbdata.modules.length; i++) { |
| 2425 | if (pcbdata.modules[i].ref == ref) { |
| 2426 | return i; |
| 2427 | } |
| 2428 | } |
| 2429 | return -1; |
| 2430 | } else { |
| 2431 | return intref; |
| 2432 | } |
| 2433 | } |
| 2434 | if (!(checkbox in settings.checkboxStoredRefs)) { |
| 2435 | var val = readStorage("checkbox_" + checkbox); |
| 2436 | settings.checkboxStoredRefs[checkbox] = val ? val : ""; |
| 2437 | } |
| 2438 | if (!settings.checkboxStoredRefs[checkbox]) { |
| 2439 | return new Set(); |
| 2440 | } else { |
| 2441 | return new Set(settings.checkboxStoredRefs[checkbox].split(",").map(r => convert(r)).filter(a => a >= 0)); |
| 2442 | } |
| 2443 | } |
| 2444 | |
| 2445 | function getCheckboxState(checkbox, references) { |
| 2446 | var storedRefsSet = getStoredCheckboxRefs(checkbox); |
| 2447 | var currentRefsSet = new Set(references.map(r => r[1])); |
| 2448 | // Get difference of current - stored |
| 2449 | var difference = new Set(currentRefsSet); |
| 2450 | for (ref of storedRefsSet) { |
| 2451 | difference.delete(ref); |
| 2452 | } |
| 2453 | if (difference.size == 0) { |
| 2454 | // All the current refs are stored |
| 2455 | return "checked"; |
| 2456 | } else if (difference.size == currentRefsSet.size) { |
| 2457 | // None of the current refs are stored |
| 2458 | return "unchecked"; |
| 2459 | } else { |
| 2460 | // Some of the refs are stored |
| 2461 | return "indeterminate"; |
| 2462 | } |
| 2463 | } |
| 2464 | |
| 2465 | function setBomCheckboxState(checkbox, element, references) { |
| 2466 | var state = getCheckboxState(checkbox, references); |
| 2467 | element.checked = (state == "checked"); |
| 2468 | element.indeterminate = (state == "indeterminate"); |
| 2469 | } |
| 2470 | |
| 2471 | function createCheckboxChangeHandler(checkbox, references, row) { |
| 2472 | return function() { |
| 2473 | refsSet = getStoredCheckboxRefs(checkbox); |
| 2474 | var darkenWhenChecked = settings.darkenWhenChecked == checkbox; |
| 2475 | eventArgs = { |
| 2476 | checkbox: checkbox, |
| 2477 | refs: references, |
| 2478 | } |
| 2479 | if (this.checked) { |
| 2480 | // checkbox ticked |
| 2481 | for (var ref of references) { |
| 2482 | refsSet.add(ref[1]); |
| 2483 | } |
| 2484 | if (darkenWhenChecked) { |
| 2485 | row.classList.add("checked"); |
| 2486 | } |
| 2487 | eventArgs.state = 'checked'; |
| 2488 | } else { |
| 2489 | // checkbox unticked |
| 2490 | for (var ref of references) { |
| 2491 | refsSet.delete(ref[1]); |
| 2492 | } |
| 2493 | if (darkenWhenChecked) { |
| 2494 | row.classList.remove("checked"); |
| 2495 | } |
| 2496 | eventArgs.state = 'unchecked'; |
| 2497 | } |
| 2498 | settings.checkboxStoredRefs[checkbox] = [...refsSet].join(","); |
| 2499 | writeStorage("checkbox_" + checkbox, settings.checkboxStoredRefs[checkbox]); |
| 2500 | updateCheckboxStats(checkbox); |
| 2501 | EventHandler.emitEvent(IBOM_EVENT_TYPES.CHECKBOX_CHANGE_EVENT, eventArgs); |
| 2502 | } |
| 2503 | } |
| 2504 | |
| 2505 | function clearHighlightedModules() { |
| 2506 | if (currentHighlightedRowId) { |
| 2507 | document.getElementById(currentHighlightedRowId).classList.remove("highlighted"); |
| 2508 | currentHighlightedRowId = null; |
| 2509 | highlightedModules = []; |
| 2510 | highlightedNet = null; |
| 2511 | } |
| 2512 | } |
| 2513 | |
| 2514 | function createRowHighlightHandler(rowid, refs, net) { |
| 2515 | return function() { |
| 2516 | if (currentHighlightedRowId) { |
| 2517 | if (currentHighlightedRowId == rowid) { |
| 2518 | return; |
| 2519 | } |
| 2520 | document.getElementById(currentHighlightedRowId).classList.remove("highlighted"); |
| 2521 | } |
| 2522 | document.getElementById(rowid).classList.add("highlighted"); |
| 2523 | currentHighlightedRowId = rowid; |
| 2524 | highlightedModules = refs ? refs.map(r => r[1]) : []; |
| 2525 | highlightedNet = net; |
| 2526 | drawHighlights(); |
| 2527 | EventHandler.emitEvent( |
| 2528 | IBOM_EVENT_TYPES.HIGHLIGHT_EVENT, |
| 2529 | { |
| 2530 | rowid: rowid, |
| 2531 | refs: refs, |
| 2532 | net: net |
| 2533 | }); |
| 2534 | } |
| 2535 | } |
| 2536 | |
| 2537 | function entryMatches(entry) { |
| 2538 | if (settings.bommode == "netlist") { |
| 2539 | // entry is just a net name |
| 2540 | return entry.toLowerCase().indexOf(filter) >= 0; |
| 2541 | } |
| 2542 | // check refs |
| 2543 | for (var ref of entry[3]) { |
| 2544 | if (ref[0].toLowerCase().indexOf(filter) >= 0) { |
| 2545 | return true; |
| 2546 | } |
| 2547 | } |
| 2548 | // check extra fields |
| 2549 | for (var i in config.extra_fields) { |
| 2550 | if (entry[4][i].toLowerCase().indexOf(filter) >= 0) { |
| 2551 | return true; |
| 2552 | } |
| 2553 | } |
| 2554 | // check value |
| 2555 | if (entry[1].toLowerCase().indexOf(filter) >= 0) { |
| 2556 | return true; |
| 2557 | } |
| 2558 | // check footprint |
| 2559 | if (entry[2].toLowerCase().indexOf(filter) >= 0) { |
| 2560 | return true; |
| 2561 | } |
| 2562 | return false; |
| 2563 | } |
| 2564 | |
| 2565 | function findRefInEntry(entry) { |
| 2566 | return entry[3].filter(r => r[0].toLowerCase() == reflookup); |
| 2567 | } |
| 2568 | |
| 2569 | function highlightFilter(s) { |
| 2570 | if (!filter) { |
| 2571 | return s; |
| 2572 | } |
| 2573 | var parts = s.toLowerCase().split(filter); |
| 2574 | if (parts.length == 1) { |
| 2575 | return s; |
| 2576 | } |
| 2577 | var r = ""; |
| 2578 | var pos = 0; |
| 2579 | for (var i in parts) { |
| 2580 | if (i > 0) { |
| 2581 | r += '<mark class="highlight">' + |
| 2582 | s.substring(pos, pos + filter.length) + |
| 2583 | '</mark>'; |
| 2584 | pos += filter.length; |
| 2585 | } |
| 2586 | r += s.substring(pos, pos + parts[i].length); |
| 2587 | pos += parts[i].length; |
| 2588 | } |
| 2589 | return r; |
| 2590 | } |
| 2591 | |
| 2592 | function checkboxSetUnsetAllHandler(checkboxname) { |
| 2593 | return function() { |
| 2594 | var checkboxnum = 0; |
| 2595 | while (checkboxnum < settings.checkboxes.length && |
| 2596 | settings.checkboxes[checkboxnum].toLowerCase() != checkboxname.toLowerCase()) { |
| 2597 | checkboxnum++; |
| 2598 | } |
| 2599 | if (checkboxnum >= settings.checkboxes.length) { |
| 2600 | return; |
| 2601 | } |
| 2602 | var allset = true; |
| 2603 | var checkbox; |
| 2604 | var row; |
| 2605 | for (row of bombody.childNodes) { |
| 2606 | checkbox = row.childNodes[checkboxnum + 1].childNodes[0]; |
| 2607 | if (!checkbox.checked || checkbox.indeterminate) { |
| 2608 | allset = false; |
| 2609 | break; |
| 2610 | } |
| 2611 | } |
| 2612 | for (row of bombody.childNodes) { |
| 2613 | checkbox = row.childNodes[checkboxnum + 1].childNodes[0]; |
| 2614 | checkbox.checked = !allset; |
| 2615 | checkbox.indeterminate = false; |
| 2616 | checkbox.onchange(); |
| 2617 | } |
| 2618 | } |
| 2619 | } |
| 2620 | |
| 2621 | function createColumnHeader(name, cls, comparator) { |
| 2622 | var th = document.createElement("TH"); |
| 2623 | th.innerHTML = name; |
| 2624 | th.classList.add(cls); |
| 2625 | th.style.cursor = "pointer"; |
| 2626 | var span = document.createElement("SPAN"); |
| 2627 | span.classList.add("sortmark"); |
| 2628 | span.classList.add("none"); |
| 2629 | th.appendChild(span); |
| 2630 | th.onclick = function() { |
| 2631 | if (currentSortColumn && this !== currentSortColumn) { |
| 2632 | // Currently sorted by another column |
| 2633 | currentSortColumn.childNodes[1].classList.remove(currentSortOrder); |
| 2634 | currentSortColumn.childNodes[1].classList.add("none"); |
| 2635 | currentSortColumn = null; |
| 2636 | currentSortOrder = null; |
| 2637 | } |
| 2638 | if (currentSortColumn && this === currentSortColumn) { |
| 2639 | // Already sorted by this column |
| 2640 | if (currentSortOrder == "asc") { |
| 2641 | // Sort by this column, descending order |
| 2642 | bomSortFunction = function(a, b) { |
| 2643 | return -comparator(a, b); |
| 2644 | } |
| 2645 | currentSortColumn.childNodes[1].classList.remove("asc"); |
| 2646 | currentSortColumn.childNodes[1].classList.add("desc"); |
| 2647 | currentSortOrder = "desc"; |
| 2648 | } else { |
| 2649 | // Unsort |
| 2650 | bomSortFunction = null; |
| 2651 | currentSortColumn.childNodes[1].classList.remove("desc"); |
| 2652 | currentSortColumn.childNodes[1].classList.add("none"); |
| 2653 | currentSortColumn = null; |
| 2654 | currentSortOrder = null; |
| 2655 | } |
| 2656 | } else { |
| 2657 | // Sort by this column, ascending order |
| 2658 | bomSortFunction = comparator; |
| 2659 | currentSortColumn = this; |
| 2660 | currentSortColumn.childNodes[1].classList.remove("none"); |
| 2661 | currentSortColumn.childNodes[1].classList.add("asc"); |
| 2662 | currentSortOrder = "asc"; |
| 2663 | } |
| 2664 | populateBomBody(); |
| 2665 | } |
| 2666 | return th; |
| 2667 | } |
| 2668 | |
| 2669 | function populateBomHeader() { |
| 2670 | while (bomhead.firstChild) { |
| 2671 | bomhead.removeChild(bomhead.firstChild); |
| 2672 | } |
| 2673 | var tr = document.createElement("TR"); |
| 2674 | var th = document.createElement("TH"); |
| 2675 | th.classList.add("numCol"); |
| 2676 | tr.appendChild(th); |
| 2677 | var checkboxCompareClosure = function(checkbox) { |
| 2678 | return (a, b) => { |
| 2679 | var stateA = getCheckboxState(checkbox, a[3]); |
| 2680 | var stateB = getCheckboxState(checkbox, b[3]); |
| 2681 | if (stateA > stateB) return -1; |
| 2682 | if (stateA < stateB) return 1; |
| 2683 | return 0; |
| 2684 | } |
| 2685 | } |
| 2686 | if (settings.bommode == "netlist") { |
| 2687 | th = createColumnHeader("Net name", "bom-netname", (a, b) => { |
| 2688 | if (a > b) return -1; |
| 2689 | if (a < b) return 1; |
| 2690 | return 0; |
| 2691 | }); |
| 2692 | tr.appendChild(th); |
| 2693 | } else { |
| 2694 | for (var checkbox of settings.checkboxes) { |
| 2695 | th = createColumnHeader( |
| 2696 | checkbox, "bom-checkbox", checkboxCompareClosure(checkbox)); |
| 2697 | th.onclick = fancyDblClickHandler( |
| 2698 | th, th.onclick.bind(th), checkboxSetUnsetAllHandler(checkbox)); |
| 2699 | tr.appendChild(th); |
| 2700 | } |
| 2701 | tr.appendChild(createColumnHeader("References", "References", (a, b) => { |
| 2702 | var i = 0; |
| 2703 | while (i < a[3].length && i < b[3].length) { |
| 2704 | if (a[3][i] != b[3][i]) return a[3][i] > b[3][i] ? 1 : -1; |
| 2705 | i++; |
| 2706 | } |
| 2707 | return a[3].length - b[3].length; |
| 2708 | })); |
| 2709 | // Extra fields |
| 2710 | if (config.extra_fields.length > 0) { |
| 2711 | var extraFieldCompareClosure = function(fieldIndex) { |
| 2712 | return (a, b) => { |
| 2713 | var fa = a[4][fieldIndex]; |
| 2714 | var fb = b[4][fieldIndex]; |
| 2715 | if (fa != fb) return fa > fb ? 1 : -1; |
| 2716 | else return 0; |
| 2717 | } |
| 2718 | } |
| 2719 | for (var i in config.extra_fields) { |
| 2720 | tr.appendChild(createColumnHeader( |
| 2721 | config.extra_fields[i], "extra", extraFieldCompareClosure(i))); |
| 2722 | } |
| 2723 | } |
| 2724 | tr.appendChild(createColumnHeader("Value", "Value", (a, b) => { |
| 2725 | return valueCompare(a[5], b[5], a[1], b[1]); |
| 2726 | })); |
| 2727 | tr.appendChild(createColumnHeader("Footprint", "Footprint", (a, b) => { |
| 2728 | if (a[2] != b[2]) return a[2] > b[2] ? 1 : -1; |
| 2729 | else return 0; |
| 2730 | })); |
| 2731 | if (settings.bommode == "grouped") { |
| 2732 | tr.appendChild(createColumnHeader("Quantity", "Quantity", (a, b) => { |
| 2733 | return a[3].length - b[3].length; |
| 2734 | })); |
| 2735 | } |
| 2736 | } |
| 2737 | bomhead.appendChild(tr); |
| 2738 | } |
| 2739 | |
| 2740 | function populateBomBody() { |
| 2741 | while (bom.firstChild) { |
| 2742 | bom.removeChild(bom.firstChild); |
| 2743 | } |
| 2744 | highlightHandlers = []; |
| 2745 | moduleIndexToHandler = {}; |
| 2746 | netsToHandler = {}; |
| 2747 | currentHighlightedRowId = null; |
| 2748 | var first = true; |
| 2749 | if (settings.bommode == "netlist") { |
| 2750 | bomtable = pcbdata.nets.slice(); |
| 2751 | } else { |
| 2752 | switch (settings.canvaslayout) { |
| 2753 | case 'F': |
| 2754 | bomtable = pcbdata.bom.F.slice(); |
| 2755 | break; |
| 2756 | case 'FB': |
| 2757 | bomtable = pcbdata.bom.both.slice(); |
| 2758 | break; |
| 2759 | case 'B': |
| 2760 | bomtable = pcbdata.bom.B.slice(); |
| 2761 | break; |
| 2762 | } |
| 2763 | if (settings.bommode == "ungrouped") { |
| 2764 | // expand bom table |
| 2765 | expandedTable = [] |
| 2766 | for (var bomentry of bomtable) { |
| 2767 | for (var ref of bomentry[3]) { |
| 2768 | expandedTable.push([1, bomentry[1], bomentry[2], [ref], bomentry[4], bomentry[5]]); |
| 2769 | } |
| 2770 | } |
| 2771 | bomtable = expandedTable; |
| 2772 | } |
| 2773 | } |
| 2774 | if (bomSortFunction) { |
| 2775 | bomtable = bomtable.sort(bomSortFunction); |
| 2776 | } |
| 2777 | for (var i in bomtable) { |
| 2778 | var bomentry = bomtable[i]; |
| 2779 | if (filter && !entryMatches(bomentry)) { |
| 2780 | continue; |
| 2781 | } |
| 2782 | var references = null; |
| 2783 | var netname = null; |
| 2784 | var tr = document.createElement("TR"); |
| 2785 | var td = document.createElement("TD"); |
| 2786 | var rownum = +i + 1; |
| 2787 | tr.id = "bomrow" + rownum; |
| 2788 | td.textContent = rownum; |
| 2789 | tr.appendChild(td); |
| 2790 | if (settings.bommode == "netlist") { |
| 2791 | netname = bomentry; |
| 2792 | td = document.createElement("TD"); |
| 2793 | td.innerHTML = highlightFilter(netname ? netname : "<no net>"); |
| 2794 | tr.appendChild(td); |
| 2795 | } else { |
| 2796 | if (reflookup) { |
| 2797 | references = findRefInEntry(bomentry); |
| 2798 | if (references.length == 0) { |
| 2799 | continue; |
| 2800 | } |
| 2801 | } else { |
| 2802 | references = bomentry[3]; |
| 2803 | } |
| 2804 | // Checkboxes |
| 2805 | for (var checkbox of settings.checkboxes) { |
| 2806 | if (checkbox) { |
| 2807 | td = document.createElement("TD"); |
| 2808 | var input = document.createElement("input"); |
| 2809 | input.type = "checkbox"; |
| 2810 | input.onchange = createCheckboxChangeHandler(checkbox, references, tr); |
| 2811 | setBomCheckboxState(checkbox, input, references); |
| 2812 | if (input.checked && settings.darkenWhenChecked == checkbox) { |
| 2813 | tr.classList.add("checked"); |
| 2814 | } |
| 2815 | td.appendChild(input); |
| 2816 | tr.appendChild(td); |
| 2817 | } |
| 2818 | } |
| 2819 | // References |
| 2820 | td = document.createElement("TD"); |
| 2821 | td.innerHTML = highlightFilter(references.map(r => r[0]).join(", ")); |
| 2822 | tr.appendChild(td); |
| 2823 | // Extra fields |
| 2824 | for (var i in config.extra_fields) { |
| 2825 | td = document.createElement("TD"); |
| 2826 | td.innerHTML = highlightFilter(bomentry[4][i]); |
| 2827 | tr.appendChild(td); |
| 2828 | } |
| 2829 | // Value |
| 2830 | td = document.createElement("TD"); |
| 2831 | td.innerHTML = highlightFilter(bomentry[1]); |
| 2832 | tr.appendChild(td); |
| 2833 | // Footprint |
| 2834 | td = document.createElement("TD"); |
| 2835 | td.innerHTML = highlightFilter(bomentry[2]); |
| 2836 | tr.appendChild(td); |
| 2837 | if (settings.bommode == "grouped") { |
| 2838 | // Quantity |
| 2839 | td = document.createElement("TD"); |
| 2840 | td.textContent = bomentry[3].length; |
| 2841 | tr.appendChild(td); |
| 2842 | } |
| 2843 | } |
| 2844 | bom.appendChild(tr); |
| 2845 | var handler = createRowHighlightHandler(tr.id, references, netname); |
| 2846 | tr.onmousemove = handler; |
| 2847 | highlightHandlers.push({ |
| 2848 | id: tr.id, |
| 2849 | handler: handler, |
| 2850 | }); |
| 2851 | if (references !== null) { |
| 2852 | for (var refIndex of references.map(r => r[1])) { |
| 2853 | moduleIndexToHandler[refIndex] = handler; |
| 2854 | } |
| 2855 | } |
| 2856 | if (netname !== null) { |
| 2857 | netsToHandler[netname] = handler; |
| 2858 | } |
| 2859 | if ((filter || reflookup) && first) { |
| 2860 | handler(); |
| 2861 | first = false; |
| 2862 | } |
| 2863 | } |
| 2864 | EventHandler.emitEvent( |
| 2865 | IBOM_EVENT_TYPES.BOM_BODY_CHANGE_EVENT, |
| 2866 | { |
| 2867 | filter: filter, |
| 2868 | reflookup: reflookup, |
| 2869 | checkboxes: settings.checkboxes, |
| 2870 | bommode: settings.bommode, |
| 2871 | }); |
| 2872 | } |
| 2873 | |
| 2874 | function highlightPreviousRow() { |
| 2875 | if (!currentHighlightedRowId) { |
| 2876 | highlightHandlers[highlightHandlers.length - 1].handler(); |
| 2877 | } else { |
| 2878 | if (highlightHandlers.length > 1 && |
| 2879 | highlightHandlers[0].id == currentHighlightedRowId) { |
| 2880 | highlightHandlers[highlightHandlers.length - 1].handler(); |
| 2881 | } else { |
| 2882 | for (var i = 0; i < highlightHandlers.length - 1; i++) { |
| 2883 | if (highlightHandlers[i + 1].id == currentHighlightedRowId) { |
| 2884 | highlightHandlers[i].handler(); |
| 2885 | break; |
| 2886 | } |
| 2887 | } |
| 2888 | } |
| 2889 | } |
| 2890 | smoothScrollToRow(currentHighlightedRowId); |
| 2891 | } |
| 2892 | |
| 2893 | function highlightNextRow() { |
| 2894 | if (!currentHighlightedRowId) { |
| 2895 | highlightHandlers[0].handler(); |
| 2896 | } else { |
| 2897 | if (highlightHandlers.length > 1 && |
| 2898 | highlightHandlers[highlightHandlers.length - 1].id == currentHighlightedRowId) { |
| 2899 | highlightHandlers[0].handler(); |
| 2900 | } else { |
| 2901 | for (var i = 1; i < highlightHandlers.length; i++) { |
| 2902 | if (highlightHandlers[i - 1].id == currentHighlightedRowId) { |
| 2903 | highlightHandlers[i].handler(); |
| 2904 | break; |
| 2905 | } |
| 2906 | } |
| 2907 | } |
| 2908 | } |
| 2909 | smoothScrollToRow(currentHighlightedRowId); |
| 2910 | } |
| 2911 | |
| 2912 | function populateBomTable() { |
| 2913 | populateBomHeader(); |
| 2914 | populateBomBody(); |
| 2915 | } |
| 2916 | |
| 2917 | function modulesClicked(moduleIndexes) { |
| 2918 | var lastClickedIndex = moduleIndexes.indexOf(lastClicked); |
| 2919 | for (var i = 1; i <= moduleIndexes.length; i++) { |
| 2920 | var refIndex = moduleIndexes[(lastClickedIndex + i) % moduleIndexes.length]; |
| 2921 | if (refIndex in moduleIndexToHandler) { |
| 2922 | lastClicked = refIndex; |
| 2923 | moduleIndexToHandler[refIndex](); |
| 2924 | smoothScrollToRow(currentHighlightedRowId); |
| 2925 | break; |
| 2926 | } |
| 2927 | } |
| 2928 | } |
| 2929 | |
| 2930 | function netClicked(net) { |
| 2931 | if (net in netsToHandler) { |
| 2932 | netsToHandler[net](); |
| 2933 | smoothScrollToRow(currentHighlightedRowId); |
| 2934 | } else { |
| 2935 | clearHighlightedModules(); |
| 2936 | highlightedNet = net; |
| 2937 | drawHighlights(); |
| 2938 | } |
| 2939 | } |
| 2940 | |
| 2941 | function updateFilter(input) { |
| 2942 | filter = input.toLowerCase(); |
| 2943 | populateBomTable(); |
| 2944 | } |
| 2945 | |
| 2946 | function updateRefLookup(input) { |
| 2947 | reflookup = input.toLowerCase(); |
| 2948 | populateBomTable(); |
| 2949 | } |
| 2950 | |
| 2951 | function changeCanvasLayout(layout) { |
| 2952 | document.getElementById("fl-btn").classList.remove("depressed"); |
| 2953 | document.getElementById("fb-btn").classList.remove("depressed"); |
| 2954 | document.getElementById("bl-btn").classList.remove("depressed"); |
| 2955 | switch (layout) { |
| 2956 | case 'F': |
| 2957 | document.getElementById("fl-btn").classList.add("depressed"); |
| 2958 | if (settings.bomlayout != "bom-only") { |
| 2959 | canvassplit.collapse(1); |
| 2960 | } |
| 2961 | break; |
| 2962 | case 'B': |
| 2963 | document.getElementById("bl-btn").classList.add("depressed"); |
| 2964 | if (settings.bomlayout != "bom-only") { |
| 2965 | canvassplit.collapse(0); |
| 2966 | } |
| 2967 | break; |
| 2968 | default: |
| 2969 | document.getElementById("fb-btn").classList.add("depressed"); |
| 2970 | if (settings.bomlayout != "bom-only") { |
| 2971 | canvassplit.setSizes([50, 50]); |
| 2972 | } |
| 2973 | } |
| 2974 | settings.canvaslayout = layout; |
| 2975 | writeStorage("canvaslayout", layout); |
| 2976 | resizeAll(); |
| 2977 | changeBomMode(settings.bommode); |
| 2978 | } |
| 2979 | |
| 2980 | function populateMetadata() { |
| 2981 | document.getElementById("title").innerHTML = pcbdata.metadata.title; |
| 2982 | document.getElementById("revision").innerHTML = "Rev: " + pcbdata.metadata.revision; |
| 2983 | document.getElementById("company").innerHTML = pcbdata.metadata.company; |
| 2984 | document.getElementById("filedate").innerHTML = pcbdata.metadata.date; |
| 2985 | if (pcbdata.metadata.title != "") { |
| 2986 | document.title = pcbdata.metadata.title + " BOM"; |
| 2987 | } |
| 2988 | // Calculate board stats |
| 2989 | var fp_f = 0, fp_b = 0, pads_f = 0, pads_b = 0, pads_th = 0; |
| 2990 | for (var i = 0; i < pcbdata.modules.length; i++) { |
| 2991 | if (pcbdata.bom.skipped.includes(i)) continue; |
| 2992 | var mod = pcbdata.modules[i]; |
| 2993 | if (mod.layer == "F") { |
| 2994 | fp_f++; |
| 2995 | } else { |
| 2996 | fp_b++; |
| 2997 | } |
| 2998 | for (var pad of mod.pads) { |
| 2999 | if (pad.type == "th") { |
| 3000 | pads_th++; |
| 3001 | } else { |
| 3002 | if (pad.layers.includes("F")) { |
| 3003 | pads_f++; |
| 3004 | } |
| 3005 | if (pad.layers.includes("B")) { |
| 3006 | pads_b++; |
| 3007 | } |
| 3008 | } |
| 3009 | } |
| 3010 | } |
| 3011 | document.getElementById("stats-components-front").innerHTML = fp_f; |
| 3012 | document.getElementById("stats-components-back").innerHTML = fp_b; |
| 3013 | document.getElementById("stats-components-total").innerHTML = fp_f + fp_b; |
| 3014 | document.getElementById("stats-groups-front").innerHTML = pcbdata.bom.F.length; |
| 3015 | document.getElementById("stats-groups-back").innerHTML = pcbdata.bom.B.length; |
| 3016 | document.getElementById("stats-groups-total").innerHTML = pcbdata.bom.both.length; |
| 3017 | document.getElementById("stats-smd-pads-front").innerHTML = pads_f; |
| 3018 | document.getElementById("stats-smd-pads-back").innerHTML = pads_b; |
| 3019 | document.getElementById("stats-smd-pads-total").innerHTML = pads_f + pads_b; |
| 3020 | document.getElementById("stats-th-pads").innerHTML = pads_th; |
| 3021 | // Update version string |
| 3022 | document.getElementById("github-link").innerHTML = "InteractiveHtmlBom " + |
| 3023 | /^v\d+\.\d+/.exec(pcbdata.ibom_version)[0]; |
| 3024 | } |
| 3025 | |
| 3026 | function changeBomLayout(layout) { |
| 3027 | document.getElementById("bom-btn").classList.remove("depressed"); |
| 3028 | document.getElementById("lr-btn").classList.remove("depressed"); |
| 3029 | document.getElementById("tb-btn").classList.remove("depressed"); |
| 3030 | switch (layout) { |
| 3031 | case 'bom-only': |
| 3032 | document.getElementById("bom-btn").classList.add("depressed"); |
| 3033 | if (bomsplit) { |
| 3034 | bomsplit.destroy(); |
| 3035 | bomsplit = null; |
| 3036 | canvassplit.destroy(); |
| 3037 | canvassplit = null; |
| 3038 | } |
| 3039 | document.getElementById("frontcanvas").style.display = "none"; |
| 3040 | document.getElementById("backcanvas").style.display = "none"; |
| 3041 | document.getElementById("bot").style.height = ""; |
| 3042 | break; |
| 3043 | case 'top-bottom': |
| 3044 | document.getElementById("tb-btn").classList.add("depressed"); |
| 3045 | document.getElementById("frontcanvas").style.display = ""; |
| 3046 | document.getElementById("backcanvas").style.display = ""; |
| 3047 | document.getElementById("bot").style.height = "calc(100% - 80px)"; |
| 3048 | document.getElementById("bomdiv").classList.remove("split-horizontal"); |
| 3049 | document.getElementById("canvasdiv").classList.remove("split-horizontal"); |
| 3050 | document.getElementById("frontcanvas").classList.add("split-horizontal"); |
| 3051 | document.getElementById("backcanvas").classList.add("split-horizontal"); |
| 3052 | if (bomsplit) { |
| 3053 | bomsplit.destroy(); |
| 3054 | bomsplit = null; |
| 3055 | canvassplit.destroy(); |
| 3056 | canvassplit = null; |
| 3057 | } |
| 3058 | bomsplit = Split(['#bomdiv', '#canvasdiv'], { |
| 3059 | sizes: [50, 50], |
| 3060 | onDragEnd: resizeAll, |
| 3061 | direction: "vertical", |
| 3062 | gutterSize: 5 |
| 3063 | }); |
| 3064 | canvassplit = Split(['#frontcanvas', '#backcanvas'], { |
| 3065 | sizes: [50, 50], |
| 3066 | gutterSize: 5, |
| 3067 | onDragEnd: resizeAll |
| 3068 | }); |
| 3069 | break; |
| 3070 | case 'left-right': |
| 3071 | document.getElementById("lr-btn").classList.add("depressed"); |
| 3072 | document.getElementById("frontcanvas").style.display = ""; |
| 3073 | document.getElementById("backcanvas").style.display = ""; |
| 3074 | document.getElementById("bot").style.height = "calc(100% - 80px)"; |
| 3075 | document.getElementById("bomdiv").classList.add("split-horizontal"); |
| 3076 | document.getElementById("canvasdiv").classList.add("split-horizontal"); |
| 3077 | document.getElementById("frontcanvas").classList.remove("split-horizontal"); |
| 3078 | document.getElementById("backcanvas").classList.remove("split-horizontal"); |
| 3079 | if (bomsplit) { |
| 3080 | bomsplit.destroy(); |
| 3081 | bomsplit = null; |
| 3082 | canvassplit.destroy(); |
| 3083 | canvassplit = null; |
| 3084 | } |
| 3085 | bomsplit = Split(['#bomdiv', '#canvasdiv'], { |
| 3086 | sizes: [50, 50], |
| 3087 | onDragEnd: resizeAll, |
| 3088 | gutterSize: 5 |
| 3089 | }); |
| 3090 | canvassplit = Split(['#frontcanvas', '#backcanvas'], { |
| 3091 | sizes: [50, 50], |
| 3092 | gutterSize: 5, |
| 3093 | direction: "vertical", |
| 3094 | onDragEnd: resizeAll |
| 3095 | }); |
| 3096 | } |
| 3097 | settings.bomlayout = layout; |
| 3098 | writeStorage("bomlayout", layout); |
| 3099 | changeCanvasLayout(settings.canvaslayout); |
| 3100 | } |
| 3101 | |
| 3102 | function changeBomMode(mode) { |
| 3103 | document.getElementById("bom-grouped-btn").classList.remove("depressed"); |
| 3104 | document.getElementById("bom-ungrouped-btn").classList.remove("depressed"); |
| 3105 | document.getElementById("bom-netlist-btn").classList.remove("depressed"); |
| 3106 | switch (mode) { |
| 3107 | case 'grouped': |
| 3108 | document.getElementById("bom-grouped-btn").classList.add("depressed"); |
| 3109 | break; |
| 3110 | case 'ungrouped': |
| 3111 | document.getElementById("bom-ungrouped-btn").classList.add("depressed"); |
| 3112 | break; |
| 3113 | case 'netlist': |
| 3114 | document.getElementById("bom-netlist-btn").classList.add("depressed"); |
| 3115 | } |
| 3116 | writeStorage("bommode", mode); |
| 3117 | if (mode != settings.bommode) { |
| 3118 | settings.bommode = mode; |
| 3119 | bomSortFunction = null; |
| 3120 | currentSortColumn = null; |
| 3121 | currentSortOrder = null; |
| 3122 | clearHighlightedModules(); |
| 3123 | } |
| 3124 | populateBomTable(); |
| 3125 | } |
| 3126 | |
| 3127 | function focusFilterField() { |
| 3128 | focusInputField(document.getElementById("filter")); |
| 3129 | } |
| 3130 | |
| 3131 | function focusRefLookupField() { |
| 3132 | focusInputField(document.getElementById("reflookup")); |
| 3133 | } |
| 3134 | |
| 3135 | function toggleBomCheckbox(bomrowid, checkboxnum) { |
| 3136 | if (!bomrowid || checkboxnum > settings.checkboxes.length) { |
| 3137 | return; |
| 3138 | } |
| 3139 | var bomrow = document.getElementById(bomrowid); |
| 3140 | var checkbox = bomrow.childNodes[checkboxnum].childNodes[0]; |
| 3141 | checkbox.checked = !checkbox.checked; |
| 3142 | checkbox.indeterminate = false; |
| 3143 | checkbox.onchange(); |
| 3144 | } |
| 3145 | |
| 3146 | function checkBomCheckbox(bomrowid, checkboxname) { |
| 3147 | var checkboxnum = 0; |
| 3148 | while (checkboxnum < settings.checkboxes.length && |
| 3149 | settings.checkboxes[checkboxnum].toLowerCase() != checkboxname.toLowerCase()) { |
| 3150 | checkboxnum++; |
| 3151 | } |
| 3152 | if (!bomrowid || checkboxnum >= settings.checkboxes.length) { |
| 3153 | return; |
| 3154 | } |
| 3155 | var bomrow = document.getElementById(bomrowid); |
| 3156 | var checkbox = bomrow.childNodes[checkboxnum + 1].childNodes[0]; |
| 3157 | checkbox.checked = true; |
| 3158 | checkbox.indeterminate = false; |
| 3159 | checkbox.onchange(); |
| 3160 | } |
| 3161 | |
| 3162 | function setBomCheckboxes(value) { |
| 3163 | writeStorage("bomCheckboxes", value); |
| 3164 | settings.checkboxes = value.split(",").filter((e) => e); |
| 3165 | prepCheckboxes(); |
| 3166 | populateBomTable(); |
| 3167 | populateDarkenWhenCheckedOptions(); |
| 3168 | } |
| 3169 | |
| 3170 | function setDarkenWhenChecked(value) { |
| 3171 | writeStorage("darkenWhenChecked", value); |
| 3172 | settings.darkenWhenChecked = value; |
| 3173 | populateBomTable(); |
| 3174 | } |
| 3175 | |
| 3176 | function prepCheckboxes() { |
| 3177 | var table = document.getElementById("checkbox-stats"); |
| 3178 | while (table.childElementCount > 1) { |
| 3179 | table.removeChild(table.lastChild); |
| 3180 | } |
| 3181 | if (settings.checkboxes.length) { |
| 3182 | table.style.display = ""; |
| 3183 | } else { |
| 3184 | table.style.display = "none"; |
| 3185 | } |
| 3186 | for (var checkbox of settings.checkboxes) { |
| 3187 | var tr = document.createElement("TR"); |
| 3188 | var td = document.createElement("TD"); |
| 3189 | td.innerHTML = checkbox; |
| 3190 | tr.appendChild(td); |
| 3191 | td = document.createElement("TD"); |
| 3192 | td.id = "checkbox-stats-" + checkbox; |
| 3193 | var progressbar = document.createElement("div"); |
| 3194 | progressbar.classList.add("bar"); |
| 3195 | td.appendChild(progressbar); |
| 3196 | var text = document.createElement("div"); |
| 3197 | text.classList.add("text"); |
| 3198 | td.appendChild(text); |
| 3199 | tr.appendChild(td); |
| 3200 | table.appendChild(tr); |
| 3201 | updateCheckboxStats(checkbox); |
| 3202 | } |
| 3203 | } |
| 3204 | |
| 3205 | function populateDarkenWhenCheckedOptions() { |
| 3206 | var container = document.getElementById("darkenWhenCheckedContainer"); |
| 3207 | |
| 3208 | if (settings.checkboxes.length == 0) { |
| 3209 | container.parentElement.style.display = "none"; |
| 3210 | return; |
| 3211 | } |
| 3212 | |
| 3213 | container.innerHTML = ''; |
| 3214 | container.parentElement.style.display = "inline-block"; |
| 3215 | |
| 3216 | function createOption(name, displayName) { |
| 3217 | var id = "darkenWhenChecked-" + name; |
| 3218 | |
| 3219 | var div = document.createElement("div"); |
| 3220 | div.classList.add("radio-container"); |
| 3221 | |
| 3222 | var input = document.createElement("input"); |
| 3223 | input.type = "radio"; |
| 3224 | input.name = "darkenWhenChecked"; |
| 3225 | input.value = name; |
| 3226 | input.id = id; |
| 3227 | input.onchange = () => setDarkenWhenChecked(name); |
| 3228 | div.appendChild(input); |
| 3229 | |
| 3230 | // Preserve the selected element when the checkboxes change |
| 3231 | if (name == settings.darkenWhenChecked) { |
| 3232 | input.checked = true; |
| 3233 | } |
| 3234 | |
| 3235 | var label = document.createElement("label"); |
| 3236 | label.innerHTML = displayName; |
| 3237 | label.htmlFor = id; |
| 3238 | div.appendChild(label); |
| 3239 | |
| 3240 | container.appendChild(div); |
| 3241 | } |
| 3242 | createOption("", "None"); |
| 3243 | for (var checkbox of settings.checkboxes) { |
| 3244 | createOption(checkbox, checkbox); |
| 3245 | } |
| 3246 | } |
| 3247 | |
| 3248 | function updateCheckboxStats(checkbox) { |
| 3249 | var checked = getStoredCheckboxRefs(checkbox).size; |
| 3250 | var total = pcbdata.modules.length - pcbdata.bom.skipped.length; |
| 3251 | var percent = checked * 100.0 / total; |
| 3252 | var td = document.getElementById("checkbox-stats-" + checkbox); |
| 3253 | td.firstChild.style.width = percent + "%"; |
| 3254 | td.lastChild.innerHTML = checked + "/" + total + " (" + Math.round(percent) + "%)"; |
| 3255 | } |
| 3256 | |
| 3257 | document.onkeydown = function(e) { |
| 3258 | switch (e.key) { |
| 3259 | case "n": |
| 3260 | if (document.activeElement.type == "text") { |
| 3261 | return; |
| 3262 | } |
| 3263 | if (currentHighlightedRowId !== null) { |
| 3264 | checkBomCheckbox(currentHighlightedRowId, "placed"); |
| 3265 | highlightNextRow(); |
| 3266 | e.preventDefault(); |
| 3267 | } |
| 3268 | break; |
| 3269 | case "ArrowUp": |
| 3270 | highlightPreviousRow(); |
| 3271 | e.preventDefault(); |
| 3272 | break; |
| 3273 | case "ArrowDown": |
| 3274 | highlightNextRow(); |
| 3275 | e.preventDefault(); |
| 3276 | break; |
| 3277 | default: |
| 3278 | break; |
| 3279 | } |
| 3280 | if (e.altKey) { |
| 3281 | switch (e.key) { |
| 3282 | case "f": |
| 3283 | focusFilterField(); |
| 3284 | e.preventDefault(); |
| 3285 | break; |
| 3286 | case "r": |
| 3287 | focusRefLookupField(); |
| 3288 | e.preventDefault(); |
| 3289 | break; |
| 3290 | case "z": |
| 3291 | changeBomLayout("bom-only"); |
| 3292 | e.preventDefault(); |
| 3293 | break; |
| 3294 | case "x": |
| 3295 | changeBomLayout("left-right"); |
| 3296 | e.preventDefault(); |
| 3297 | break; |
| 3298 | case "c": |
| 3299 | changeBomLayout("top-bottom"); |
| 3300 | e.preventDefault(); |
| 3301 | break; |
| 3302 | case "v": |
| 3303 | changeCanvasLayout("F"); |
| 3304 | e.preventDefault(); |
| 3305 | break; |
| 3306 | case "b": |
| 3307 | changeCanvasLayout("FB"); |
| 3308 | e.preventDefault(); |
| 3309 | break; |
| 3310 | case "n": |
| 3311 | changeCanvasLayout("B"); |
| 3312 | e.preventDefault(); |
| 3313 | break; |
| 3314 | default: |
| 3315 | break; |
| 3316 | } |
| 3317 | if (e.key >= '1' && e.key <= '9') { |
| 3318 | toggleBomCheckbox(currentHighlightedRowId, parseInt(e.key)); |
| 3319 | } |
| 3320 | } |
| 3321 | } |
| 3322 | |
| 3323 | function hideNetlistButton() { |
| 3324 | document.getElementById("bom-ungrouped-btn").classList.remove("middle-button"); |
| 3325 | document.getElementById("bom-ungrouped-btn").classList.add("right-most-button"); |
| 3326 | document.getElementById("bom-netlist-btn").style.display = "none"; |
| 3327 | } |
| 3328 | |
| 3329 | window.onload = function(e) { |
| 3330 | initUtils(); |
| 3331 | initRender(); |
| 3332 | initStorage(); |
| 3333 | initDefaults(); |
| 3334 | cleanGutters(); |
| 3335 | populateMetadata(); |
| 3336 | dbgdiv = document.getElementById("dbg"); |
| 3337 | bom = document.getElementById("bombody"); |
| 3338 | bomhead = document.getElementById("bomhead"); |
| 3339 | filter = ""; |
| 3340 | reflookup = ""; |
| 3341 | if (!("nets" in pcbdata)) { |
| 3342 | hideNetlistButton(); |
| 3343 | } |
| 3344 | initDone = true; |
| 3345 | prepCheckboxes(); |
| 3346 | // Triggers render |
| 3347 | changeBomLayout(settings.bomlayout); |
| 3348 | |
| 3349 | // Users may leave fullscreen without touching the checkbox. Uncheck. |
| 3350 | document.addEventListener('fullscreenchange', () => { |
| 3351 | if (!document.fullscreenElement) |
| 3352 | document.getElementById('fullscreenCheckbox').checked = false; |
| 3353 | }); |
| 3354 | } |
| 3355 | |
| 3356 | window.onresize = resizeAll; |
| 3357 | window.matchMedia("print").addListener(resizeAll); |
| 3358 | |
| 3359 | /////////////////////////////////////////////// |
| 3360 | |
| 3361 | /////////////////////////////////////////////// |
| 3362 | |
| 3363 | /////////////////////////////////////////////// |
| 3364 | </script> |
| 3365 | </head> |
| 3366 | |
| 3367 | <body> |
| 3368 | |
| 3369 | <div id="topmostdiv" class="topmostdiv"> |
| 3370 | <div id="top"> |
| 3371 | <div style="float: right; height: 100%;"> |
| 3372 | <div class="hideonprint menu" style="float: right; top: 8px;"> |
| 3373 | <button class="menubtn"></button> |
| 3374 | <div class="menu-content"> |
| 3375 | <label class="menu-label menu-label-top" style="width: calc(50% - 18px)"> |
| 3376 | <input id="darkmodeCheckbox" type="checkbox" onchange="setDarkMode(this.checked)"> |
| 3377 | Dark mode |
| 3378 | </label><!-- This comment eats space! All of it! |
| 3379 | --><label class="menu-label menu-label-top" style="width: calc(50% - 17px); border-left: 0;"> |
| 3380 | <input id="fullscreenCheckbox" type="checkbox" onchange="setFullscreen(this.checked)"> |
| 3381 | Full Screen |
| 3382 | </label> |
| 3383 | <label class="menu-label" style="width: calc(50% - 18px)"> |
| 3384 | <input id="fabricationCheckbox" type="checkbox" checked onchange="fabricationVisible(this.checked)"> |
| 3385 | Fab layer |
| 3386 | </label><!-- This comment eats space! All of it! |
| 3387 | --><label class="menu-label" style="width: calc(50% - 17px); border-left: 0;"> |
| 3388 | <input id="silkscreenCheckbox" type="checkbox" checked onchange="silkscreenVisible(this.checked)"> |
| 3389 | Silkscreen |
| 3390 | </label> |
| 3391 | <label class="menu-label" style="width: calc(50% - 18px)"> |
| 3392 | <input id="referencesCheckbox" type="checkbox" checked onchange="referencesVisible(this.checked)"> |
| 3393 | References |
| 3394 | </label><!-- This comment eats space! All of it! |
| 3395 | --><label class="menu-label" style="width: calc(50% - 17px); border-left: 0;"> |
| 3396 | <input id="valuesCheckbox" type="checkbox" checked onchange="valuesVisible(this.checked)"> |
| 3397 | Values |
| 3398 | </label> |
| 3399 | <div id="tracksAndZonesCheckboxes"> |
| 3400 | <label class="menu-label" style="width: calc(50% - 18px)"> |
| 3401 | <input id="tracksCheckbox" type="checkbox" checked onchange="tracksVisible(this.checked)"> |
| 3402 | Tracks |
| 3403 | </label><!-- This comment eats space! All of it! |
| 3404 | --><label class="menu-label" style="width: calc(50% - 17px); border-left: 0;"> |
| 3405 | <input id="zonesCheckbox" type="checkbox" checked onchange="zonesVisible(this.checked)"> |
| 3406 | Zones |
| 3407 | </label> |
| 3408 | </div> |
| 3409 | <label class="menu-label" style="width: calc(50% - 18px)"> |
| 3410 | <input id="padsCheckbox" type="checkbox" checked onchange="padsVisible(this.checked)"> |
| 3411 | Pads |
| 3412 | </label><!-- This comment eats space! All of it! |
| 3413 | --><label class="menu-label" style="width: calc(50% - 17px); border-left: 0;"> |
| 3414 | <input id="dnpOutlineCheckbox" type="checkbox" checked onchange="dnpOutline(this.checked)"> |
| 3415 | DNP outlined |
| 3416 | </label> |
| 3417 | <label class="menu-label"> |
| 3418 | <input id="highlightpin1Checkbox" type="checkbox" onchange="setHighlightPin1(this.checked)"> |
| 3419 | Highlight first pin |
| 3420 | </label> |
| 3421 | <label class="menu-label"> |
| 3422 | <input id="dragCheckbox" type="checkbox" checked onchange="setRedrawOnDrag(this.checked)"> |
| 3423 | Continuous redraw on drag |
| 3424 | </label> |
| 3425 | <label class="menu-label"> |
| 3426 | <span>Board rotation</span> |
| 3427 | <span style="float: right"><span id="rotationDegree">0</span>°</span> |
| 3428 | <input id="boardRotation" type="range" min="-36" max="36" value="0" class="slider" oninput="setBoardRotation(this.value)"> |
| 3429 | </label> |
| 3430 | <label class="menu-label"> |
| 3431 | <div style="margin-left: 5px">Bom checkboxes</div> |
| 3432 | <input id="bomCheckboxes" class="menu-textbox" type=text |
| 3433 | oninput="setBomCheckboxes(this.value)"> |
| 3434 | </label> |
| 3435 | <label class="menu-label"> |
| 3436 | <div style="margin-left: 5px">Darken when checked</div> |
| 3437 | <div id="darkenWhenCheckedContainer"></div> |
| 3438 | </label> |
| 3439 | <label class="menu-label"> |
| 3440 | <span class="shameless-plug"> |
| 3441 | <span>Created using</span> |
| 3442 | <a id="github-link" target="blank" href="https://github.com/openscopeproject/InteractiveHtmlBom">InteractiveHtmlBom</a> |
| 3443 | </span> |
| 3444 | </label> |
| 3445 | </div> |
| 3446 | </div> |
| 3447 | <div class="button-container hideonprint" |
| 3448 | style="float: right; position: relative; top: 8px"> |
| 3449 | <button id="fl-btn" class="left-most-button" onclick="changeCanvasLayout('F')" |
| 3450 | title="Front only">F |
| 3451 | </button> |
| 3452 | <button id="fb-btn" class="middle-button" onclick="changeCanvasLayout('FB')" |
| 3453 | title="Front and Back">FB |
| 3454 | </button> |
| 3455 | <button id="bl-btn" class="right-most-button" onclick="changeCanvasLayout('B')" |
| 3456 | title="Back only">B |
| 3457 | </button> |
| 3458 | </div> |
| 3459 | <div class="button-container hideonprint" |
| 3460 | style="float: right; position: relative; top: 8px"> |
| 3461 | <button id="bom-btn" class="left-most-button" onclick="changeBomLayout('bom-only')" |
| 3462 | title="BOM only"></button> |
| 3463 | <button id="lr-btn" class="middle-button" onclick="changeBomLayout('left-right')" |
| 3464 | title="BOM left, drawings right"></button> |
| 3465 | <button id="tb-btn" class="right-most-button" onclick="changeBomLayout('top-bottom')" |
| 3466 | title="BOM top, drawings bot"></button> |
| 3467 | </div> |
| 3468 | <div class="button-container hideonprint" |
| 3469 | style="float: right; position: relative; top: 8px"> |
| 3470 | <button id="bom-grouped-btn" class="left-most-button" onclick="changeBomMode('grouped')" |
| 3471 | title="Grouped BOM"></button> |
| 3472 | <button id="bom-ungrouped-btn" class="middle-button" onclick="changeBomMode('ungrouped')" |
| 3473 | title="Ungrouped BOM"></button> |
| 3474 | <button id="bom-netlist-btn" class="right-most-button" onclick="changeBomMode('netlist')" |
| 3475 | title="Netlist"></button> |
| 3476 | </div> |
| 3477 | <div class="hideonprint menu" style="float: right; top: 8px;"> |
| 3478 | <button class="statsbtn"></button> |
| 3479 | <div class="menu-content"> |
| 3480 | <table class="stats"> |
| 3481 | <tbody> |
| 3482 | <tr> |
| 3483 | <td width="40%">Board stats</td> |
| 3484 | <td>Front</td> |
| 3485 | <td>Back</td> |
| 3486 | <td>Total</td> |
| 3487 | </tr> |
| 3488 | <tr> |
| 3489 | <td>Components</td> |
| 3490 | <td id="stats-components-front">~</td> |
| 3491 | <td id="stats-components-back">~</td> |
| 3492 | <td id="stats-components-total">~</td> |
| 3493 | </tr> |
| 3494 | <tr> |
| 3495 | <td>Groups</td> |
| 3496 | <td id="stats-groups-front">~</td> |
| 3497 | <td id="stats-groups-back">~</td> |
| 3498 | <td id="stats-groups-total">~</td> |
| 3499 | </tr> |
| 3500 | <tr> |
| 3501 | <td>SMD pads</td> |
| 3502 | <td id="stats-smd-pads-front">~</td> |
| 3503 | <td id="stats-smd-pads-back">~</td> |
| 3504 | <td id="stats-smd-pads-total">~</td> |
| 3505 | </tr> |
| 3506 | <tr> |
| 3507 | <td>TH pads</td> |
| 3508 | <td colspan=3 id="stats-th-pads">~</td> |
| 3509 | </tr> |
| 3510 | </tbody> |
| 3511 | </table> |
| 3512 | <table class="stats"> |
| 3513 | <col width="40%"/><col /> |
| 3514 | <tbody id="checkbox-stats"> |
| 3515 | <tr> |
| 3516 | <td colspan=2 style="border-top: 0">Checkboxes</td> |
| 3517 | </tr> |
| 3518 | </tbody> |
| 3519 | </table> |
| 3520 | </div> |
| 3521 | </div> |
| 3522 | <div class="hideonprint menu" style="float: right; top: 8px;"> |
| 3523 | <button class="iobtn"></button> |
| 3524 | <div class="menu-content"> |
| 3525 | <div class="menu-label menu-label-top"> |
| 3526 | <div style="margin-left: 5px;">Save board image</div> |
| 3527 | <div class="flexbox"> |
| 3528 | <input id="render-save-width" class="menu-textbox" type="text" value="1000" placeholder="Width" |
| 3529 | style="flex-grow: 1; width: 50px;" oninput="validateSaveImgDimension(this)"> |
| 3530 | <span>X</span> |
| 3531 | <input id="render-save-height" class="menu-textbox" type="text" value="1000" placeholder="Height" |
| 3532 | style="flex-grow: 1; width: 50px;" oninput="validateSaveImgDimension(this)"> |
| 3533 | </div> |
| 3534 | <label> |
| 3535 | <input id="render-save-transparent" type="checkbox"> |
| 3536 | Transparent background |
| 3537 | </label> |
| 3538 | <div class="flexbox"> |
| 3539 | <button class="savebtn" onclick="saveImage('F')">Front</button> |
| 3540 | <button class="savebtn" onclick="saveImage('B')">Back</button> |
| 3541 | </div> |
| 3542 | </div> |
| 3543 | <div class="menu-label"> |
| 3544 | <span style="margin-left: 5px;">Config and checkbox state</span> |
| 3545 | <div class="flexbox"> |
| 3546 | <button class="savebtn" onclick="saveSettings()">Export</button> |
| 3547 | <button class="savebtn" onclick="loadSettings()">Import</button> |
| 3548 | </div> |
| 3549 | </div> |
| 3550 | </div> |
| 3551 | </div> |
| 3552 | </div> |
| 3553 | <div id="fileinfodiv" style="overflow: auto;"> |
| 3554 | <table class="fileinfo"> |
| 3555 | <tbody> |
| 3556 | <tr> |
| 3557 | <td id="title" class="title" style="width: 70%"> |
| 3558 | Title |
| 3559 | </td> |
| 3560 | <td id="revision" class="title" style="width: 30%"> |
| 3561 | Revision |
| 3562 | </td> |
| 3563 | </tr> |
| 3564 | <tr> |
| 3565 | <td id="company"> |
| 3566 | Company |
| 3567 | </td> |
| 3568 | <td id="filedate"> |
| 3569 | Date |
| 3570 | </td> |
| 3571 | </tr> |
| 3572 | </tbody> |
| 3573 | </table> |
| 3574 | </div> |
| 3575 | </div> |
| 3576 | <div id="bot" class="split" style="height: calc(100% - 80px)"> |
| 3577 | <div id="bomdiv" class="split split-horizontal"> |
| 3578 | <div style="width: 100%"> |
| 3579 | <input id="reflookup" class="textbox searchbox reflookup hideonprint" type="text" placeholder="Ref lookup" |
| 3580 | oninput="updateRefLookup(this.value)"> |
| 3581 | <input id="filter" class="textbox searchbox filter hideonprint" type="text" placeholder="Filter" |
| 3582 | oninput="updateFilter(this.value)"> |
| 3583 | <div class="button-container hideonprint" style="float: left; margin: 0;"> |
| 3584 | <button id="copy" title="Copy bom table to clipboard" |
| 3585 | onclick="copyToClipboard()"></button> |
| 3586 | </div> |
| 3587 | </div> |
| 3588 | <div id="dbg"></div> |
| 3589 | <table class="bom"> |
| 3590 | <thead id="bomhead"> |
| 3591 | </thead> |
| 3592 | <tbody id="bombody"> |
| 3593 | </tbody> |
| 3594 | </table> |
| 3595 | </div> |
| 3596 | <div id="canvasdiv" class="split split-horizontal"> |
| 3597 | <div id="frontcanvas" class="split" touch-action="none" style="overflow: hidden"> |
| 3598 | <div style="position: relative; width: 100%; height: 100%;"> |
| 3599 | <canvas id="F_bg" style="position: absolute; left: 0; top: 0; z-index: 0;"></canvas> |
| 3600 | <canvas id="F_fab" style="position: absolute; left: 0; top: 0; z-index: 1;"></canvas> |
| 3601 | <canvas id="F_slk" style="position: absolute; left: 0; top: 0; z-index: 2;"></canvas> |
| 3602 | <canvas id="F_hl" style="position: absolute; left: 0; top: 0; z-index: 3;"></canvas> |
| 3603 | </div> |
| 3604 | </div> |
| 3605 | <div id="backcanvas" class="split" touch-action="none" style="overflow: hidden"> |
| 3606 | <div style="position: relative; width: 100%; height: 100%;"> |
| 3607 | <canvas id="B_bg" style="position: absolute; left: 0; top: 0; z-index: 0;"></canvas> |
| 3608 | <canvas id="B_fab" style="position: absolute; left: 0; top: 0; z-index: 1;"></canvas> |
| 3609 | <canvas id="B_slk" style="position: absolute; left: 0; top: 0; z-index: 2;"></canvas> |
| 3610 | <canvas id="B_hl" style="position: absolute; left: 0; top: 0; z-index: 3;"></canvas> |
| 3611 | </div> |
| 3612 | </div> |
| 3613 | </div> |
| 3614 | </div> |
| 3615 | </div> |
| 3616 | |
| 3617 | </body> |
| 3618 | |
| 3619 | </html> |