ibom.html 309 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6. <title>Interactive BOM for KiCAD</title>
  7. <style type="text/css">
  8. :root {
  9. --pcb-edge-color: black;
  10. --pad-color: #878787;
  11. --pad-hole-color: #CCCCCC;
  12. --pad-color-highlight: #D04040;
  13. --pad-color-highlight-both: #D0D040;
  14. --pad-color-highlight-marked: #44a344;
  15. --pin1-outline-color: #ffb629;
  16. --pin1-outline-color-highlight: #ffb629;
  17. --pin1-outline-color-highlight-both: #fcbb39;
  18. --pin1-outline-color-highlight-marked: #fdbe41;
  19. --silkscreen-edge-color: #aa4;
  20. --silkscreen-polygon-color: #4aa;
  21. --silkscreen-text-color: #4aa;
  22. --fabrication-edge-color: #907651;
  23. --fabrication-polygon-color: #907651;
  24. --fabrication-text-color: #a27c24;
  25. --track-color: #def5f1;
  26. --track-color-highlight: #D04040;
  27. --zone-color: #def5f1;
  28. --zone-color-highlight: #d0404080;
  29. }
  30. html,
  31. body {
  32. margin: 0px;
  33. height: 100%;
  34. font-family: Verdana, sans-serif;
  35. }
  36. .dark.topmostdiv {
  37. --pcb-edge-color: #eee;
  38. --pad-color: #808080;
  39. --pin1-outline-color: #ffa800;
  40. --pin1-outline-color-highlight: #ccff00;
  41. --track-color: #42524f;
  42. --zone-color: #42524f;
  43. background-color: #252c30;
  44. color: #eee;
  45. }
  46. button {
  47. background-color: #eee;
  48. border: 1px solid #888;
  49. color: black;
  50. height: 44px;
  51. width: 44px;
  52. text-align: center;
  53. text-decoration: none;
  54. display: inline-block;
  55. font-size: 14px;
  56. font-weight: bolder;
  57. }
  58. .dark button {
  59. /* This will be inverted */
  60. background-color: #c3b7b5;
  61. }
  62. button.depressed {
  63. background-color: #0a0;
  64. color: white;
  65. }
  66. .dark button.depressed {
  67. /* This will be inverted */
  68. background-color: #b3b;
  69. }
  70. button:focus {
  71. outline: 0;
  72. }
  73. button#tb-btn {
  74. 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");
  75. }
  76. button#lr-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.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");
  78. }
  79. button#bom-btn {
  80. 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");
  81. }
  82. button#bom-grouped-btn {
  83. 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");
  84. }
  85. button#bom-ungrouped-btn {
  86. 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");
  87. }
  88. button#bom-netlist-btn {
  89. 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");
  90. }
  91. button#copy {
  92. 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");
  93. background-position: 6px 6px;
  94. background-repeat: no-repeat;
  95. background-size: 26px 26px;
  96. border-radius: 6px;
  97. height: 40px;
  98. width: 40px;
  99. margin: 10px 5px;
  100. }
  101. button#copy:active {
  102. box-shadow: inset 0px 0px 5px #6c6c6c;
  103. }
  104. textarea.clipboard-temp {
  105. position: fixed;
  106. top: 0;
  107. left: 0;
  108. width: 2em;
  109. height: 2em;
  110. padding: 0;
  111. border: None;
  112. outline: None;
  113. box-shadow: None;
  114. background: transparent;
  115. }
  116. .left-most-button {
  117. border-right: 0;
  118. border-top-left-radius: 6px;
  119. border-bottom-left-radius: 6px;
  120. }
  121. .middle-button {
  122. border-right: 0;
  123. }
  124. .right-most-button {
  125. border-top-right-radius: 6px;
  126. border-bottom-right-radius: 6px;
  127. }
  128. .button-container {
  129. font-size: 0;
  130. margin: 0.4rem 0.4rem 0.4rem 0;
  131. }
  132. .dark .button-container {
  133. filter: invert(1);
  134. }
  135. .button-container button {
  136. background-size: 32px 32px;
  137. background-position: 5px 5px;
  138. background-repeat: no-repeat;
  139. }
  140. @media print {
  141. .hideonprint {
  142. display: none;
  143. }
  144. }
  145. canvas {
  146. cursor: crosshair;
  147. }
  148. canvas:active {
  149. cursor: grabbing;
  150. }
  151. .fileinfo {
  152. width: 100%;
  153. max-width: 1000px;
  154. border: none;
  155. padding: 3px;
  156. }
  157. .fileinfo .title {
  158. font-size: 20pt;
  159. font-weight: bold;
  160. }
  161. .fileinfo td {
  162. overflow: hidden;
  163. white-space: nowrap;
  164. max-width: 1px;
  165. width: 50%;
  166. text-overflow: ellipsis;
  167. }
  168. .bom {
  169. border-collapse: collapse;
  170. font-family: Consolas, "DejaVu Sans Mono", Monaco, monospace;
  171. font-size: 10pt;
  172. table-layout: fixed;
  173. width: 100%;
  174. margin-top: 1px;
  175. position: relative;
  176. }
  177. .bom th,
  178. .bom td {
  179. border: 1px solid black;
  180. padding: 5px;
  181. word-wrap: break-word;
  182. text-align: center;
  183. position: relative;
  184. }
  185. .dark .bom th,
  186. .dark .bom td {
  187. border: 1px solid #777;
  188. }
  189. .bom th {
  190. background-color: #CCCCCC;
  191. background-clip: padding-box;
  192. }
  193. .dark .bom th {
  194. background-color: #3b4749;
  195. }
  196. .bom tr.highlighted:nth-child(n) {
  197. background-color: #cfc;
  198. }
  199. .dark .bom tr.highlighted:nth-child(n) {
  200. background-color: #226022;
  201. }
  202. .bom tr:nth-child(even) {
  203. background-color: #f2f2f2;
  204. }
  205. .dark .bom tr:nth-child(even) {
  206. background-color: #313b40;
  207. }
  208. .bom tr.checked {
  209. color: #1cb53d;
  210. }
  211. .dark .bom tr.checked {
  212. color: #2cce54;
  213. }
  214. .bom tr {
  215. transition: background-color 0.2s;
  216. }
  217. .bom .numCol {
  218. width: 30px;
  219. }
  220. .bom .value {
  221. width: 15%;
  222. }
  223. .bom .quantity {
  224. width: 65px;
  225. }
  226. .bom th .sortmark {
  227. position: absolute;
  228. right: 1px;
  229. top: 1px;
  230. margin-top: -5px;
  231. border-width: 5px;
  232. border-style: solid;
  233. border-color: transparent transparent #221 transparent;
  234. transform-origin: 50% 85%;
  235. transition: opacity 0.2s, transform 0.4s;
  236. }
  237. .dark .bom th .sortmark {
  238. filter: invert(1);
  239. }
  240. .bom th .sortmark.none {
  241. opacity: 0;
  242. }
  243. .bom th .sortmark.desc {
  244. transform: rotate(180deg);
  245. }
  246. .bom th:hover .sortmark.none {
  247. opacity: 0.5;
  248. }
  249. .bom .bom-checkbox {
  250. width: 30px;
  251. position: relative;
  252. user-select: none;
  253. -moz-user-select: none;
  254. }
  255. .bom .bom-checkbox:before {
  256. content: "";
  257. position: absolute;
  258. border-width: 15px;
  259. border-style: solid;
  260. border-color: #51829f transparent transparent transparent;
  261. visibility: hidden;
  262. top: -15px;
  263. }
  264. .bom .bom-checkbox:after {
  265. content: "Double click to set/unset all";
  266. position: absolute;
  267. color: white;
  268. top: -35px;
  269. left: -26px;
  270. background: #51829f;
  271. padding: 5px 15px;
  272. border-radius: 8px;
  273. white-space: nowrap;
  274. visibility: hidden;
  275. }
  276. .bom .bom-checkbox:hover:before,
  277. .bom .bom-checkbox:hover:after {
  278. visibility: visible;
  279. transition: visibility 0.2s linear 1s;
  280. }
  281. .split {
  282. -webkit-box-sizing: border-box;
  283. -moz-box-sizing: border-box;
  284. box-sizing: border-box;
  285. overflow-y: auto;
  286. overflow-x: hidden;
  287. background-color: inherit;
  288. }
  289. .split.split-horizontal,
  290. .gutter.gutter-horizontal {
  291. height: 100%;
  292. float: left;
  293. }
  294. .gutter {
  295. background-color: #ddd;
  296. background-repeat: no-repeat;
  297. background-position: 50%;
  298. transition: background-color 0.3s;
  299. }
  300. .dark .gutter {
  301. background-color: #777;
  302. }
  303. .gutter.gutter-horizontal {
  304. background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAeCAYAAADkftS9AAAAIklEQVQoU2M4c+bMfxAGAgYYmwGrIIiDjrELjpo5aiZeMwF+yNnOs5KSvgAAAABJRU5ErkJggg==');
  305. cursor: ew-resize;
  306. width: 5px;
  307. }
  308. .gutter.gutter-vertical {
  309. background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAFAQMAAABo7865AAAABlBMVEVHcEzMzMzyAv2sAAAAAXRSTlMAQObYZgAAABBJREFUeF5jOAMEEAIEEFwAn3kMwcB6I2AAAAAASUVORK5CYII=');
  310. cursor: ns-resize;
  311. height: 5px;
  312. }
  313. .searchbox {
  314. float: left;
  315. height: 40px;
  316. margin: 10px 5px;
  317. padding: 12px 32px;
  318. font-family: Consolas, "DejaVu Sans Mono", Monaco, monospace;
  319. font-size: 18px;
  320. box-sizing: border-box;
  321. border: 1px solid #888;
  322. border-radius: 6px;
  323. outline: none;
  324. background-color: #eee;
  325. transition: background-color 0.2s, border 0.2s;
  326. 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==');
  327. background-position: 10px 10px;
  328. background-repeat: no-repeat;
  329. }
  330. .dark .searchbox {
  331. background-color: #111;
  332. color: #eee;
  333. }
  334. .searchbox::placeholder {
  335. color: #ccc;
  336. }
  337. .dark .searchbox::placeholder {
  338. color: #666;
  339. }
  340. .filter {
  341. width: calc(60% - 64px);
  342. }
  343. .reflookup {
  344. width: calc(40% - 10px);
  345. }
  346. input[type=text]:focus {
  347. background-color: white;
  348. border: 1px solid #333;
  349. }
  350. .dark input[type=text]:focus {
  351. background-color: #333;
  352. border: 1px solid #ccc;
  353. }
  354. mark.highlight {
  355. background-color: #5050ff;
  356. color: #fff;
  357. padding: 2px;
  358. border-radius: 6px;
  359. }
  360. .dark mark.highlight {
  361. background-color: #76a6da;
  362. color: #111;
  363. }
  364. .menubtn {
  365. background-color: white;
  366. border: none;
  367. 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");
  368. background-position: center;
  369. background-repeat: no-repeat;
  370. }
  371. .statsbtn {
  372. background-color: white;
  373. border: none;
  374. 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");
  375. background-position: center;
  376. background-repeat: no-repeat;
  377. }
  378. .iobtn {
  379. background-color: white;
  380. border: none;
  381. 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");
  382. background-position: center;
  383. background-repeat: no-repeat;
  384. }
  385. .visbtn {
  386. background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24'%3E%3Cpath fill='none' stroke='%23333' d='M2.5 4.5h5v15h-5zM9.5 4.5h5v15h-5zM16.5 4.5h5v15h-5z'/%3E%3C/svg%3E");
  387. background-position: center;
  388. background-repeat: no-repeat;
  389. padding: 15px;
  390. }
  391. #vismenu-content {
  392. left: 0px;
  393. font-family: Verdana, sans-serif;
  394. }
  395. .dark .statsbtn,
  396. .dark .savebtn,
  397. .dark .menubtn,
  398. .dark .iobtn,
  399. .dark .visbtn {
  400. filter: invert(1);
  401. }
  402. .flexbox {
  403. display: flex;
  404. align-items: center;
  405. justify-content: space-between;
  406. width: 100%;
  407. }
  408. .savebtn {
  409. background-color: #d6d6d6;
  410. width: auto;
  411. height: 30px;
  412. flex-grow: 1;
  413. margin: 5px;
  414. border-radius: 4px;
  415. }
  416. .savebtn:active {
  417. background-color: #0a0;
  418. color: white;
  419. }
  420. .dark .savebtn:active {
  421. /* This will be inverted */
  422. background-color: #b3b;
  423. }
  424. .stats {
  425. border-collapse: collapse;
  426. font-size: 12pt;
  427. table-layout: fixed;
  428. width: 100%;
  429. min-width: 450px;
  430. }
  431. .dark .stats td {
  432. border: 1px solid #bbb;
  433. }
  434. .stats td {
  435. border: 1px solid black;
  436. padding: 5px;
  437. word-wrap: break-word;
  438. text-align: center;
  439. position: relative;
  440. }
  441. #checkbox-stats div {
  442. position: absolute;
  443. left: 0;
  444. top: 0;
  445. height: 100%;
  446. width: 100%;
  447. display: flex;
  448. align-items: center;
  449. justify-content: center;
  450. }
  451. #checkbox-stats .bar {
  452. background-color: rgba(28, 251, 0, 0.6);
  453. }
  454. .menu {
  455. position: relative;
  456. display: inline-block;
  457. margin: 0.4rem 0.4rem 0.4rem 0;
  458. }
  459. .menu-content {
  460. font-size: 12pt !important;
  461. text-align: left !important;
  462. font-weight: normal !important;
  463. display: none;
  464. position: absolute;
  465. background-color: white;
  466. right: 0;
  467. min-width: 300px;
  468. box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.2);
  469. z-index: 100;
  470. padding: 8px;
  471. }
  472. .dark .menu-content {
  473. background-color: #111;
  474. }
  475. .menu:hover .menu-content {
  476. display: block;
  477. }
  478. .menu:hover .menubtn,
  479. .menu:hover .iobtn,
  480. .menu:hover .statsbtn {
  481. background-color: #eee;
  482. }
  483. .menu-label {
  484. display: inline-block;
  485. padding: 8px;
  486. border: 1px solid #ccc;
  487. border-top: 0;
  488. width: calc(100% - 18px);
  489. }
  490. .menu-label-top {
  491. border-top: 1px solid #ccc;
  492. }
  493. .menu-textbox {
  494. float: left;
  495. height: 24px;
  496. margin: 10px 5px;
  497. padding: 5px 5px;
  498. font-family: Consolas, "DejaVu Sans Mono", Monaco, monospace;
  499. font-size: 14px;
  500. box-sizing: border-box;
  501. border: 1px solid #888;
  502. border-radius: 4px;
  503. outline: none;
  504. background-color: #eee;
  505. transition: background-color 0.2s, border 0.2s;
  506. width: calc(100% - 10px);
  507. }
  508. .menu-textbox.invalid,
  509. .dark .menu-textbox.invalid {
  510. color: red;
  511. }
  512. .dark .menu-textbox {
  513. background-color: #222;
  514. color: #eee;
  515. }
  516. .radio-container {
  517. margin: 4px;
  518. }
  519. .topmostdiv {
  520. display: flex;
  521. flex-direction: column;
  522. width: 100%;
  523. background-color: white;
  524. transition: background-color 0.3s;
  525. min-height: 100%;
  526. }
  527. #top {
  528. display: flex;
  529. flex-wrap: wrap;
  530. justify-content: flex-end;
  531. align-items: center;
  532. }
  533. #topdivider {
  534. border-bottom: 2px solid black;
  535. display: flex;
  536. justify-content: center;
  537. align-items: center;
  538. }
  539. .dark #topdivider {
  540. border-bottom: 2px solid #ccc;
  541. }
  542. #topdivider>div {
  543. position: relative;
  544. }
  545. #toptoggle {
  546. cursor: pointer;
  547. user-select: none;
  548. position: absolute;
  549. padding: 0.1rem 0.3rem;
  550. top: -0.4rem;
  551. left: -1rem;
  552. font-size: 1.4rem;
  553. line-height: 60%;
  554. border: 1px solid black;
  555. border-radius: 1rem;
  556. background-color: #fff;
  557. z-index: 100;
  558. }
  559. .flipped {
  560. transform: rotate(0.5turn);
  561. }
  562. .dark #toptoggle {
  563. border: 1px solid #fff;
  564. background-color: #222;
  565. }
  566. #fileinfodiv {
  567. flex: 20rem 1 0;
  568. overflow: auto;
  569. }
  570. #bomcontrols {
  571. display: flex;
  572. flex-direction: row-reverse;
  573. }
  574. #bomcontrols>* {
  575. flex-shrink: 0;
  576. }
  577. #dbg {
  578. display: block;
  579. }
  580. ::-webkit-scrollbar {
  581. width: 8px;
  582. }
  583. ::-webkit-scrollbar-track {
  584. background: #aaa;
  585. }
  586. ::-webkit-scrollbar-thumb {
  587. background: #666;
  588. border-radius: 3px;
  589. }
  590. ::-webkit-scrollbar-thumb:hover {
  591. background: #555;
  592. }
  593. .slider {
  594. -webkit-appearance: none;
  595. width: 100%;
  596. margin: 3px 0;
  597. padding: 0;
  598. outline: none;
  599. opacity: 0.7;
  600. -webkit-transition: .2s;
  601. transition: opacity .2s;
  602. border-radius: 3px;
  603. }
  604. .slider:hover {
  605. opacity: 1;
  606. }
  607. .slider:focus {
  608. outline: none;
  609. }
  610. .slider::-webkit-slider-runnable-track {
  611. -webkit-appearance: none;
  612. width: 100%;
  613. height: 8px;
  614. background: #d3d3d3;
  615. border-radius: 3px;
  616. border: none;
  617. }
  618. .slider::-webkit-slider-thumb {
  619. -webkit-appearance: none;
  620. width: 15px;
  621. height: 15px;
  622. border-radius: 50%;
  623. background: #0a0;
  624. cursor: pointer;
  625. margin-top: -4px;
  626. }
  627. .dark .slider::-webkit-slider-thumb {
  628. background: #3d3;
  629. }
  630. .slider::-moz-range-thumb {
  631. width: 15px;
  632. height: 15px;
  633. border-radius: 50%;
  634. background: #0a0;
  635. cursor: pointer;
  636. }
  637. .slider::-moz-range-track {
  638. height: 8px;
  639. background: #d3d3d3;
  640. border-radius: 3px;
  641. }
  642. .dark .slider::-moz-range-thumb {
  643. background: #3d3;
  644. }
  645. .slider::-ms-track {
  646. width: 100%;
  647. height: 8px;
  648. border-width: 3px 0;
  649. background: transparent;
  650. border-color: transparent;
  651. color: transparent;
  652. transition: opacity .2s;
  653. }
  654. .slider::-ms-fill-lower {
  655. background: #d3d3d3;
  656. border: none;
  657. border-radius: 3px;
  658. }
  659. .slider::-ms-fill-upper {
  660. background: #d3d3d3;
  661. border: none;
  662. border-radius: 3px;
  663. }
  664. .slider::-ms-thumb {
  665. width: 15px;
  666. height: 15px;
  667. border-radius: 50%;
  668. background: #0a0;
  669. cursor: pointer;
  670. margin: 0;
  671. }
  672. .shameless-plug {
  673. font-size: 0.8em;
  674. text-align: center;
  675. display: block;
  676. }
  677. a {
  678. color: #0278a4;
  679. }
  680. .dark a {
  681. color: #00b9fd;
  682. }
  683. #frontcanvas,
  684. #backcanvas {
  685. touch-action: none;
  686. }
  687. .placeholder {
  688. border: 1px dashed #9f9fda !important;
  689. background-color: #edf2f7 !important;
  690. }
  691. .dragging {
  692. z-index: 999;
  693. }
  694. .dark .dragging>table>tbody>tr {
  695. background-color: #252c30;
  696. }
  697. .dark .placeholder {
  698. filter: invert(1);
  699. }
  700. .column-spacer {
  701. top: 0;
  702. left: 0;
  703. width: calc(100% - 4px);
  704. position: absolute;
  705. cursor: pointer;
  706. user-select: none;
  707. height: 100%;
  708. }
  709. .column-width-handle {
  710. top: 0;
  711. right: 0;
  712. width: 4px;
  713. position: absolute;
  714. cursor: col-resize;
  715. user-select: none;
  716. height: 100%;
  717. }
  718. .column-width-handle:hover {
  719. background-color: #4f99bd;
  720. }
  721. .help-link {
  722. border: 1px solid #0278a4;
  723. padding-inline: 0.3rem;
  724. border-radius: 3px;
  725. cursor: pointer;
  726. }
  727. .dark .help-link {
  728. border: 1px solid #00b9fd;
  729. }
  730. .bom-color {
  731. width: 20%;
  732. }
  733. .color-column input {
  734. width: 1.6rem;
  735. height: 1rem;
  736. border: 1px solid black;
  737. cursor: pointer;
  738. padding: 0;
  739. }
  740. /* removes default styling from input color element */
  741. ::-webkit-color-swatch {
  742. border: none;
  743. }
  744. ::-webkit-color-swatch-wrapper {
  745. padding: 0;
  746. }
  747. ::-moz-color-swatch,
  748. ::-moz-focus-inner {
  749. border: none;
  750. }
  751. ::-moz-focus-inner {
  752. padding: 0;
  753. }
  754. /* #bomhead {
  755. position: sticky;
  756. top: 0px;
  757. z-index: 1;
  758. } */
  759. </style>
  760. <script type="text/javascript" >
  761. ///////////////////////////////////////////////
  762. /*
  763. Split.js - v1.3.5
  764. MIT License
  765. https://github.com/nathancahill/Split.js
  766. */
  767. !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}}});
  768. ///////////////////////////////////////////////
  769. ///////////////////////////////////////////////
  770. // Copyright (c) 2013 Pieroxy <pieroxy@pieroxy.net>
  771. // This work is free. You can redistribute it and/or modify it
  772. // under the terms of the WTFPL, Version 2
  773. // For more information see LICENSE.txt or http://www.wtfpl.net/
  774. //
  775. // For more information, the home page:
  776. // http://pieroxy.net/blog/pages/lz-string/testing.html
  777. //
  778. // LZ-based compression algorithm, version 1.4.4
  779. 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});
  780. ///////////////////////////////////////////////
  781. ///////////////////////////////////////////////
  782. /*!
  783. * PEP v0.4.3 | https://github.com/jquery/PEP
  784. * Copyright jQuery Foundation and other contributors | http://jquery.org/license
  785. */
  786. !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);
  787. for(var d,e=2;e<m.length;e++)d=m[e],c[d]=b[d]||n[e];c.buttons=b.buttons||0;
  788. 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}})}
  789. 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++)
  790. b.register.call(b,a)},unregister:function(a){for(var b,c=this.eventSourceList.length,d=0;d<c&&(b=this.eventSourceList[d]);d++)
  791. 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){
  792. for(var b=a;b.parentNode;)b=b.parentNode;
  793. 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);
  794. 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){
  795. //
  796. 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))},
  797. 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){
  798. var b=x(a,this.findElements,this);
  799. 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){}
  800. 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:[],
  801. 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++){
  802. 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);
  803. 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];
  804. c.buttons=b?b.buttons&~d:0,a.buttons=c.buttons}H.set(this.POINTER_ID,a),
  805. 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),
  806. 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),
  807. 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);
  808. 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){
  809. (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,
  810. c.altKey=b.altKey,c.ctrlKey=b.ctrlKey,c.metaKey=b.metaKey,c.shiftKey=b.shiftKey;
  811. 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))},
  812. shouldScroll:function(a){if(this.firstXY){var b,c=a.currentTarget._scrollType;if("none"===c)
  813. b=!1;else if("XY"===c)
  814. 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]);
  815. 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},
  816. vacuumTouches:function(a){var b=a.touches;
  817. if(R.size>=b.length){var c=[];R.forEach(function(a,d){
  818. 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);
  819. if(c){var d=c.out,e=c.outTarget;u.move(b),d&&e!==b.target&&(d.relatedTarget=b.target,b.relatedTarget=e,
  820. d.target=e,b.target?(u.leaveOut(d),u.enterOver(b)):(
  821. 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)},
  822. dedupSynthMouse:function(a){var b=N.lastTouches,c=a.changedTouches[0];
  823. if(this.isPrimaryTouch(c)){
  824. 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});
  825. ///////////////////////////////////////////////
  826. ///////////////////////////////////////////////
  827. var config = {"dark_mode": false, "show_pads": true, "show_fabrication": false, "show_silkscreen": true, "highlight_pin1": "none", "redraw_on_drag": true, "board_rotation": 0, "checkboxes": "Sourced,Placed", "bom_view": "left-right", "layer_view": "FB", "offset_back_rotation": false, "kicad_text_formatting": true, "fields": ["Value", "Footprint"]}
  828. ///////////////////////////////////////////////
  829. ///////////////////////////////////////////////
  830. var pcbdata = JSON.parse(LZString.decompressFromBase64("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1cLx7N8C5WAEou1K9JLmSuWSyxLKEM9xlqi37RGC+srFAtcixpLIQv8S2RLkEvCS1RLvAvTwMcrSitSixrL74toS0HLP3Pe8H0ru0B48+qLOItzKxTLqgt9868rBktbKwZLMItmiycr6St1K/8ryQvZK5crl7ysqRN4YKs/CxyLmyvvK9sr+ouCi5pLbkswS1sLFIvIq+rLJYt0iwCrVkv9Sw3GOKtwyxqLkKtRywSLsKseS7srXksiS/eLFKviiz8rpksMy+crKIvfyxpAorMyC6CrzKsQq+3L+Qvwq+5LxIuEqwirYotIqwKrIsu2yyKrwitpxCCrvrBSq/irrKudy+cLbkscqwqreys8qz5LfnOUq6qrw8twKxqr+csItFPGtys1CyyrMqsuS6SrnAvGqwaLpqsfK8qrdQvWy8orOMtMS3SrmKsz6FrwICbOy1kLOwsuq08rQwtaS4wLxKueS26rZqsHKxar/Kt+q78rNKuyS0GrzMsr0DzYDqu4q+yLkavzyyoArqvPK7GrGgtUS3Kr5KspqyqraauCq38rgavoS90rK4h58nmruquFqyBL0isxq0ar2kvxq1yriaveq3yrNatqyzbLNqvMS40rTou2KwOLrSuZy7Qr47NSADnLXSvfy/isK6aA2AHwgyteAIuL2BA7s2FkfiuEMNEL0gBBKwsrj0v+aur0xrgeZn4r0WM5NgSr4Cuxy7DQouxEK+YrZyv1K6PLdgssSx2mqmDzpqurw0vjiFer+qtxK13LsiuJK/nzO8zVK2kr1KuMS4kLZCsyc+FL+8vvc/YrGnOY/ftLJUvTlnBId7Drq/EAUk23bDuzYkJ4S0GAIOQPwDXLR6t1y/1LTeQThO6k4ctGS0WrHcv/q9HLXsv4KzTLVsvDq/6rScsYq9mrLGJr+WRrd7DvS5RrkcsGq+UrECsMa4ortatqq6QrmKu6Y5xrhSuGyzxr7st8azHL9Gv/Sy+gNSsoq0+ruMtNqzu4cmgSaxRrcsufS1HL/Gu3qwprRcBKa+BrKitm85ir+Biz4MjWkmtbCz+rbstSK1CrBiuAa39LIYEPq6crZkvPq2JrTkir4JZrWmtkyzJrNGt6a/JrzmuMazArKmuma2xr+UqH5N5rMsvNQb5rdmu6a3JrcisCyy5rymtua6proqsDS15r2NBWa0Vz0mtxa7JrdGuJaz7LimtgayOr5ytQa6nLzStwa9OrR8u0K8fLBEALqy4rz/OpFNq6WoDsKxurOTbbq88tT8tnsx1YkfP3S0RrQisec81rYZYA81ErqQCYK7zzoCtlKwlrQGsHWlAryWvGawGrkGusa2prLVB2tn1a+asmE9ErKFDp89GrtGuGK05rySumKyVrzGvby+Or60tVa1tLMUuzq+92SGvP83ZM+SuqUMtw6Gubs6XLQfNwy1XLVNCBc/1rH8uLK82ESWRQSTjyUSsSK99rnav7a45rK8t9y9ArxCuoq6WLCCuvq2xryWyPa+8oOiujS7zze2sBa4Vrg/PHa37Li2tJyzvL1iswa5Vrm3Pwa8OLAAAiVZx3a09Lw2vVMAoNa6ueK37zETida3zgeEtrhPurvWuuSm/LwSuiq2tr/ra3oMNL0EFRiwHwu2tg65jrs2vwYIUOhCvBazDroWvLa/Dr48twrqHoJrbjGALr9Rm/q+3LU2tNizNrTmsOoPUZ0OuPq6lrpmvna7BrJOvVaw4rs6tvQA1recv1y5PLOPZKUG1rGGtva2GL4auns1GLEfMNi9zriYsNyxj2G8Co6xmL7cuLy7grCSuHaworxWu466Vrz6sra+lrtushqAbLYkuty5IredSB6w5rweuQ6/mLC2sR6zLzxuvE64vzZutO8xq2VOv3DqFKXvPPawzrHCtO69lL0Wufa9GL7ctc6wNrISvBy8Xr4NKJ887Ls8uJ6y7AmutmywVr4uvY6/rrrmtCq5Hr8utIKxegiVyQjmdmfuvVSxrr2CvTa93rIeuga+Hrp2uia9nrk6tUK1drNCs2AOOziGvny6trlYu+NJqGDuuvaxvND8vlywBL1evu63Zrnusec7vrSM4Yhq3rI0v+61RryevxK1TLlSvp69LrBusD66orQ+vqK36LiFDATBPrc8u8a/5r2utp66Hrhmsna+mrEGtPC+VrNitGAHYreeuxSxvz3ovb6zzr4onDGGwroCi+8+XrR+s+K87rEyu8K3lLAiv166gbxiCYri3r+But8yDrOmv5awdroBvz61arGSuD67YAEMs5K9TrpBtrTNorACsJ63orM+u0G6/rYBvWIEZrmetG67vLROsr6y0ra+ttKxvr+oPIG4urU4sj5BFuKuAH65wrnWuV6y7rZ+uEa79rx6tbEZ/G6W6fAAAb7esLyxjrIBv8G/QbwmvWq2VrUevyG7obgZipi0Ur9+uT64/rxhuz63QbOOsMG7DrkGsE6ynLsBvwG5IbM6sb63QAVutMK7PDjJOpYJ5AyhsV6yfrNQsaG+jr8ytaG8RrKSDgZmEboIAGG6Dr9mvP6xUrSSsCG3NLC+uQGyZrcuvMG4grP+uuHr1wyRsdWMDruiuxG+kbAGup66YbbhvmG4wbWeuiG00r4huXazhz6+soQJOzTiub8ygbwiv0qP5UgYtl6+1rOBvcKx9rfCtfa0Qb8RuDaz9z/V5QPimLqRvUG8AbLht1G33rKWuf63DrhRsI62prsxtVi3YbD4vcG4sbvBsQ6ysbGeuL62VrXhvkK2IbcBtTq34bNWs2AMfLmaPOK9brWPMqxDgUhrSl61gbwxsb2A/LFUvRa6WKL8u883XrUxsN6z9zrxuxOEig6CvjazErk2vT61rryxtJK/Nr7+v96/WrBRv4c0UbrBuClJXMKD65QJCbJSswm84bfBsIm1LrQmtMa3kbS2vQGxcb0GstG9cbq+vtG1IbKEDqczIbhetQo6vDdiVnAQNMnxsYawTk2GvRtnhLRdBVUL2gaRuX6/XLmIzGuNNYGQtiS+ogBFlpG/Fr8Jv582YYxJth6+4bsuvQG1YbJUvdJWnsqos1iz5gB8AymzQbxxu9ywqbZhukm3WrGavdS5irVkRR7Fqb9hs6m8qAeptLG4Sb8ptW9MabIWuG654b4Wu7vpqbEpvwRLab/VA4JtUb4Ou1G4abzpv1GyabImvnG+FrL1xWm96b1ly+m/abRxtBm06b96tIm2sbKJsUm5GbwCxem8NLcZtVG7KbjptTwEaboZuum+sb7ptqaw7wQPWMCOybFBsHwP0gbKxUawSbBptJm4qb4Bu5G6abUBvmm2xr5ZuJ7ORwAuu1m8Lr+lqi6yYbwZvJmySbxZtpmx2bZZt5+nvDIXC9m7DQ/Zt2soObcpsFmyGbqxt469vLnZtTm/PDPZsAK1Kbgpu5m/qbiZvLmyObSpsNGx4b6ZuTm7u0SUkzmzubfZvxm3Cb+ZuwQIWbq5vCG6Wb6Wuim1eb25t367ubdZv+m3mbjZtHm82bghsQG22b+Rvnm6KrXZsfm1WbNYvfm/Ob5ZKLmw+bBkorm6cbZJv46xubl5u+uOKbs5vSm/ubDpv/m4+bSFspm2ubomsZm3doe7gm0Nmbrst+mwObAZti605rT5vIWyBb5JsTm9HrrJs8ghRb/SBUWwubNFtDm02bLpsy626bYFte656bebjkWwArOZvtyw2bh5v4W8ebLZvKmwJbzFtCW6xbhNDsW+NgnFtwW9xbS5vSW4BbORtyWyWbglvqm5mbIlvWmw+L4lv1m/BbeFuIWzJbQFutm+Gb7mvha5fgOwFsW2JblFt3m13rCFtXUARbo5v8W3pbClslSzcBZFvGW2JLplu/mwebL+vDm9pb68s2WxYbdltqa8JExrinSjGbSAuwoCgL08sSW6Lrl4sMW7ZbaWte6++bO41XATebc5uuWzergWv0W4RbL5v6WyKbxPrTm5+b1ZvKgLebOFsJm2FbvFtFm95b45tfc+FruVtXHVBb9hswW0VbQetNWwBbfFsf621bWss5W1VbvrhF0IlbpfO9Ww1b95sWWx5bVls6W6ebKpu+W5VbanETW9ebX5v1W2lbGlvuW21ki1uRW7pbI1uAq/1L/lvP+JdgzlscW31bKesDW1pbQ1vIm2ab7VuxWw5b0ZsqW7qbs1tuW/Nb+1sRW6krUVuNGyIbhOvUm74bdJv+GyhADxtBG02rhtWP1Yx8ERveK1lLvxsu6/8bgStVG8KbEyB6JNdk9gpx61RzUJs7a9Rbf5tSWwQr91upm49bWSvf6xib/nhooH+0vutcGzjbwCvqW/jbt1uE2y1bw1sk2w0rzRsTqzSbEhsg23cbnRs+QBDb4FvLuD+cOeUOK5yb5nN9OJZzKT58m9ZK/AsI21RrQJu2APGL0xtLK8u4RiCOq9cLvmgoC3TbHeuwm59bBNtzm0TbRFuWG2TblysXcS9LUOZwyxrb/Ata23RzkluM2/rbzNsPW+2bViveG1cbwNvbSzzbLAAAABJ7S70bG7M2nOkgZnEEQMobXBQ8mw5QUttrYHIumhsK25/LIJto2wpcvJSxbFLbEWOni4cbcqseqySrpatkq6JLl/NfKwILy1vyW7aLdKsYq8vrnNttG+7b5usb6z7bchslS4lchuG84MobkFYS23Vll0siFAtg3MBCm8QbXuvIOHXb7IBwy7MLytNmW7tbX1s1zQ7bxNtO26TbmxsK6/HAqsw921HEAEv927Bb91DmW3rbBFkG2+Vb5psl227b12sb62OLPRvV26sLCht76/bWL2sqG8frfiu5S27rUdu3s39rOhsPxKDOt+u1WwcbAeu225kb8itr22cbTBtom1sb38sjblecAZBM/Y/bVBvP28vbdtsmK8+bH9tNG4DbHNtb2x0bLACji1vr+9tPS3vsEdTKG1hrlnM4a5dLeGsCm8Lb5Muo27/rJESi+D5rtmtJ6y/bAmsGa9ZbR1us2y+rU9thip/kq0SEO38buWskOyA7r9tJa2VbEDtha6trf3IEO4HU3Gvaa8A7Q9sr20FrXlss2+PbJ1spICK0PDt7G9ZrTDsmy6Q7+mvCOyebYZvRW9lb2XOSO5lrDDuI27I7RhssO2Q7ijuyW/nbPltPWzzr3DsaO7w7HMvaO9zLgjugO/o7FDuGO8db9KuHoHQ700qaOxQbhVCWO9RrjVusO0VrBjvKO/9br5sHS9frLjvmO1Jr/DtOG7o7CjvSjJlbKjsA2y7bQNs3G9zbFdsoQJ7bSBvMm7nwkUPpYPiMNrIn2yHb6DtcgH4rci4Cm7Lb/pt4O/XwGTvWELTrNrJGCz/gApvW2wZKbKsvKz2rFauKq5yrRgtHK3nbfjtnmyFLH4vG25vbCTvl2xpzu1pPG8EbFvBRSCg7mBtH82g7mUsYO87LWDsZIARrkxvR2zfb6US3qGRrITsyO2E7QBteO3o7UTvsOyhbI8tqm0CrWHRSO0Q7nIs6O9Y73jtxy3s7jFuoW2WbqeEnO4w7mzt+a9s7kTs/W0IbHDsBO8Rz3/17RLtA0js5a087eWu4W0I7uzsiO47boFurW0srmMhmO387J3MeO0/rNRs2OyC7Sjtjm1Q7Jtv3O9C7pzs8G3NbwLtvO8BbWVucO+BbxzsYu487sWvMOxc7Ozu4u39bXTvGO17rMesbYOs7/zuku3I7ETuBa0i7vjsou2I7MBuu2/0729soQKvzVduNay8bgsy7UKUck0lDGxhrSfUfC6MriqZ28M7LXwTXAM6UNaDjK7g7ndvEc+RJZbgTSXhL9yt6WoC7+wuNO3GrzTteq8aLnyvdYB07HLvgu4Xbjauiq+q7rmB/IHPbLfPau1i7LTvp2wmrmdv7K207udtThOa7TFuWu+I79fDCuzbEKsUAS86r4Ts0WxlbTTtvK0a7SquDq76rnTsrW7671DvD67nwAbsvkJ1ZbavEO8y7AZvsqxG7cKstO1Wrw3OWq/Y7rNu2q6CbKbtTcfa71wshu1s7ads5u607lavZ2wW7qatxuwXbqEtWu4mLkMylitzmhknRa1W7zzs1uwa7kbvcqwOr1auxu967gcslu0K7J/KZa0yA6btnO1Y7DTtlq0cLhrtDu8a7Pqu3C2C7Prutu367ufBISa9ArtTBu9KrobsLu92rA7u5u1G7rTuIq6O7rVvFu3JLams2u83rMLvdC4e71bvOu7W7Jqsru9G7I7vru2PbFrtbu4479fC7u4zUj7sns727urv9u+Wrg7v9q6u7Mbvfu4bb9SsTu4KUSEleUPReB7t6qwI7x7vuq2+7nqsfuxe7a7vmixu747u3u9a7SHuwtMB7EasZu+c7GHsjC1h7Gdtdq+67l7uwe+vbCbuXK/e7WwnbRD27z7t9u6+7p7t1u3m7DbvA84W7zbtGO3+7LHspuw+SCEmoe+2rXHvnuy67fatuu0mr89tNu2O76qtEe+27SHtTamR72wsUe/O7BqvZuzx777tQe5+7jbtDq8p7o6tZq3e7SEmTENWLTquce2B73HsQe2e7OHv5uwJ7SnvXu2I7CHsAewl8oDq4qRx7aHtHu7p7+rsOe7x757vOe8YLrnuiO7+7Fytsa/e7zXH6G757Unt2ezJ7NHuuu3R7CnsMe/h7P7ubu1F7Fntee6+E8tSSe9p7njvge0u7kHvye8O7xntXuxF7WXseezu7uXsDVXPLBXtzu0V79nsle457hnu4ezB7GXtwe2ir27sxxGJ7noazu067SXv6e9h77Xuhe6aLlXsEeyp75nvWu2J7IEQVu+Crfnsvu8N7QXsGe2V70Htfu117THsie9F7Kbuq24SAg3up2y17eovLu2N7/HtheyZ7bnuRezV7fXtTu2tMgkCHe+h7AXuLuyd7pXupe+V7LnuXe1V7hHsze+27e3uszI97/ns0a3p7q3uje+t7Rnufe5N7mXs/e227art7e7Z4C3t4qwl7ZLtUe8CLyXtye+97G3sVe4x7HzuZq7D7pbt3e6YQvdvxe4V78LuGq5h7I3u0e+T7aXt4e1Sr23sXK307tJsDO7FL9WvDO9sbbuCw0iuzEzteKwHzuBtqG247ruv8K7XrsYtLO9obbIy/4d9yhzkVG2jrU+vyO6y72RuHW0W7nLuHO6zzHPvA0t1b+xtAO1RrnevFW1jrM0vgO/s7S+vs2xdrpuu3G0k7LADHyy7zvtv1y0LZ3nh6CrDb3xt8+7Lb70sBK/8Ar8si+9fbYvt+RPLGX5mI+y3LtNtYK3L7evvapO/bhvtG25PbSbve+z3Gr7jpxDTbeJuy+yy7wftVK6Pb3XuxO5cb8TtM+7y7LABzq6k71vtPS1VaJ2mk4PTrotubq40KoYuXyKzr3MD7q3g+Havvy6L7CRvvLgWcW2lF+9+rZ7OL285LQfs963erlLuUO8r7xtvZqyxsuFpzaS37ACs2a8U7REud+zrrB1u/W737kXtcuxn7XNvM+7Qro4tW+4g7j5CF4I2cgOQi26dL/pjLi+bbl0v2cy+QjnOLO577Dfs0nPTgMMv5c+9LrstNe2T7tFtp6z37Svtz+yr76/uiYJf7m2suy3C7k/sP+6H7Nzvrm7FbM17v++HLN/tDe/1blzuCa8i7V3tZe/+7bcDmckAHfxsgB0d7uvtd++Q7S1tCew47ZmvY0FLL0KDAB1/7ifsoB7Y7aAemexGbAAfVcNgHo2scy4gHT3tAu4i7j/voB6i74WtXFOQHH/uyy0y7lHuhW+AHqAeK+/QHnLuYq+dIzAe4BwC7KPscBxS7v/v4u54bjPuL+1n7I4ur+4K7CktQxP2I/3CoO5jMeTt++4Vg4XBhwJQNh6vAmz/bqVRP5PoYeEtVQPur16tgB3o7nRkp+/T7ibvFG4vcegeKB2rbx7NGB9kL7fvFq9/7lSvmBwb7f/vEW02rUAjHhEoHl0uOB4HgJgc3W5wHsgBiBzE7nzurC7YHFYSN0h/7jge5AEEHGRtmB3rr0Tv+OxSbkgdl29IHc6sIO3IH9fBhgLE4bBAO+1wr72tV6+MbNety2x77itux2wqUL/UKukRNd+tP29r7OtvIB3PrFge4+91LL/u5BzUHBjDUKdL7D+si6+S7kTsK+zP7T/vQB5SbFWutG6b7iTtjs8fLuftr+2UgcHLTlEeADvtSu74r3WtRixzr9lzy26f7StspIAsHl/TUrXH7o3N1O+kArgdEm2EHqQftB/372xt7B655QZS4m0cHgfv4B4driJugu9D7Z2vG+ybruetm+/nrlOt5+zFUS7N26zDkJ9uRG+fbgvsTGwI7pTuPsz7rWNsty1r7y3umB4MH5wfUuxPbX9s0OyvQpGv1STCHW2twh9J7CIfy+0iH8bvT8x8HOeubS1MHw4uji0ybfwfzB2JA4zscm5M7u/vTO9/CuGvXS/M7ODse66q7Mxv9G2s7mns2a7f7pwd5i3QHxAef2ywblyts4jgUhogMu7C7QgeZuwzbIQdsu3Y7PAdz+6KHlynch5i7SAd4h0n78odEB1AHtzuiq+7Uw9iqhyS7pPv8h2w7rwep+xEHrPMeqRZrvztqh9QHLzusu4KHOof/+3qHKocVhPS7PId4BwMHDocEhy27vXsQJPpgxLtaO9KH7Ac0B3KHjoffe86HfRtxINaHrjt8O2wHOnuhh6IHrQdh++5r6QeTB0v7ldsCu88bKSBch/QYzsR0hzz7RQd4G6frpQfn62S7kIcRNNGHysUXqw4bgBu4h8EHOztDB+87KYdf6xH71geVh846/MXlG/YbDQfwhw2HiIfJh54H5xtph18HZIe0KwAAygAA6r8HcweFYEmMrjilSgfzJfvtuHk794A5SzHKCrsiWs4HV1AVh2UIarSOMJJKRguOB1VA11vg+/KrYPuY+xD7J7MnIKiAdPttB8x72at7h2mlwCSGBwhEJ4cfWyt7rXvBe05753uogNELXrtOh2Z7+Ptoi/OHnnnERK+HEQDvhztbqPtEq6d7Z4fje9PAt4ez+9V7qnupCwRl7aXgR/4Hb4cPK4+bMEfoyzsrervgSwhHN4dmu4BHwquoR28LoEdiulWlAvvFYL9Qp4eXh+eHVPsEi6F7l6v2gHeHLYcNq/ArbYfk24VgBIOqujRHAEt0RyeADEfU+2j7lPspe2JHWPsmE2P7HEdDh/B7FEdoi0K0C4eRpdFrwkdlh0vbWbuBe1+Ha3uMR6xHMWvsR8hHMPu9e8vwfLSW0lNbv1DRCxpHuEfPeye7oPvMR/xL+keyR0ZH03vAR/5q/EeVO3GlLuvqR6JHIPs6RxeHUkdXh2xHHVhChz17MAfJBMpHWTteR7RHVke+R9pHr3tte/BH53vBR3JH4gd4+2zbUDsm+6OHGYe82/zbXutnWzH7xftH86UUzOuhth67oMiLDlfblQfpawVHspSt+0LroAf9h4FrIGuDh2lHlwc8R8Grhlu7JFiHpfNj+9uHd/s8W8cg0/vNh/JHkDtxO9A7PLuwO3QrlIezh0lgYISTUEdZwdvi25lLktuXSwQIKAvj+5sHFQcx20ur80e2WvYHfnOW2/2Ajwdeh0n7w0d4u+EHqptXB7tH1wQwy2VHNQtHRynbCfunRwQH50dUu4SHGUfjR1lHpIc5R17bnSs5B+k7psSZO8Am6VLLlAWHfvO5O4yHYdtrRyNzkdso2xyHLxvlOygmQqBgxxQbNTvzO8cHe2t+RwlH34dne7yrOdumuwBHEYdAR9xHqIdboCOHP0eZB8CAeUd+2xMCP9UFB9z7d8u8+6MbJQeEGztbFYd6JPUZhrRTW23rokf3+ycb1zttR2DLHUfZqw+Ss5zcxwsb0EciBwOHHgdCx0SHmUefB5THU0fqc+OHRDwzhwDHksZEQFk7qUQn29VMlnN/4ufbANrFMFyAHds6BwdL1qCqupKHJhPXZEtkcUcvew1zvauER1nb+MfWXDbH2XCpR5dH3Tu/e9lzQJSWx8B7S2Qfs9uHWMfxRw7HcEd6R8lH2XCBxx7HFwcPh6trDlvXy8LbhktAS0HH6Vswq4LHnsfCx2TH7YfongnHNYduCwPbIVv+a+G7ZoeWB5crH8jatNDHd+v5xynHYbtpxyXH94ejW/XzbxtPqjWHmyAIY3zHxceQB8THJAd6hz8kucfDS23HYkAdx3XHXcdTe14HvcdoYP3HACuDxwXHeNt8a53H7LtkRzFbeocjllPHd+szxzXHumsLxwqHoUcEu8IriMRrx7Vb1cfDx++gKQfIh36HHuIVx4nH9hsbxyfH4kejx28H48fCK3JQh8c1i7fHH4fQq6fH6ccxx43Hz/NavK/HN8fRC7PHXFtbxyPHi8fdx8vHB0tXGAAnD4vvx1LHRcdgJzvHS8eqOxWLnmyquu640WuQR95AokcoAGy6sEdve09ziAD2AC4AUAAfe6XzbgtRxLvHtKtuRxLLckTqtMT7LuuzC017e2u4J29y+CeJRwlzRCckJ2QnnFD/h9HH58c3e0cy2roYJ4wnbds1+3PHNGusJ89S7Ce4xyhAKABcJ8EAPCdae5QnyCdcR+FHQidRtgwnAvtMJzgneCf4R47HbAvyJ8QniifSR+QnfCcuRyTH8/sTR5n7U0er8+rH2YdOYBcNPYxLh5M7qsyn82MrsrsUG/K71/ORyLMrwvs/a/X7OwdOYMJN6jpauwhEGyv4m2Dr2MehxwQnLEfne+07RMdjx+RH3sdmc3T4s2YbW2RNzsuOu5EnWkf2x73wYceBRx17BMcoC4knj8fJJzQn7ZJ3ks4ngPv9B6AnX8cSRxj7hScIR4J7VCfpR1YHvEfv9E4nqbubWwL7oHt51Dr7OHuye07H9Hu0+xYn5Se9exYhf9vEuTUnA0lNB4Mn6PvDJzT7nXv8Jx9HN3uTJxOYyuQWR1p7TXsDJ+17Qyf1uy7HkPs4+5xH1CcTJ10ni3lbJ30n2tvBx3knBEcHJ+ar2Ptbew3H2Xvfy2knM4uhpDMnICtzJ3snCyf3J8mrjycrJ76HaycYTV5yD0CfJ/0n3ydnh/snfHuHJxd7UPvmh20nLEtvJ84gPmjdh5W7tnsQpzcndkf+Rw5HREe/hzcLTycnJ4inoscYTV5QiuDgp9cnUSchx/knsSeOR/inLSeqJ6cn4UfIp1LLAUAUpzbbVKe3JwYnMKcPJ0cnhKejR2onSKekpwV2aKeLe8j7lKe5J9inOMe6R00n9Kfhe0knCkcpJ2jbXSfGkp2NjXsnR3hHTEeSR3EnsKcTe8cnAqdMp0KnjFhKS6Zp7Kc4ALsnUKe/Jzyn/yd8p4CnwnsvJ+7zLKdBajRAZqcnB5ynUqcxJxwnsqe6pwSndqfHW8CnxqfCxSInvScYpxKnmqfQpyF7cqdfewqnYUdGp+knzXEhHiGnS3uzJ1inFPv2R9qndKc+pwynECexpySngadthOLMrqcWp4xHEac/h1mn8qdlJ4qnFSfv9BhNT4hA6EWnkKclp1ankaflp9Gnlae5p5DbKqeVMJcnoaccp5Knaac4pxmneKetp/Cn9PtrJyqn3xA9p8mnXyepp9R7DSeLJ2Qneqf8p3LHDqd+210nizKBW0j7hXvFp4Unpad4x7yncKf6pyun46dVJ2tMOHANp7On98eDp40nOqcHp0unfqc3u0qnFnjrp+QwU6fip32n4afNp2Wnd6e+p2MnVadnJ6en0onRR+qnOSefp/OnfyeKe22nCKdex9Wn6yccGDdwF6fupwOn0qcBR7enNqeHp8unGcciexTHrovfB1nLsgcOJ3QWEQBpHBD6wIcjG8UH6hulh1VHO0de64UAZBvZa7CHlRt2h9i7iLtNhxdHP8ekxyKH9lsIRPWwOJtcGziHiXsahwQHb+v1x0SnG9vEhxMH2UeZB90bshsax8xlsdjCreDHQysMh5urXWXOy63bPADt2yf71UdTiyJiXK2UmX3bQCf9RyaH8GDhhzGnGxtZxx0n8mdMrbfAhmfJx41HiQcKO29Hf6djR+n71idSB1NHc6uqADTHqwt6Z6+EUW1KZxurjdsrR83b6mcsh/q07vsBJ9sHVQdtC4jasW12WpgnRmcap9LHzUdmZ+2nFmdcZ02r1mcUFKpciWf2Z6BnKWdnR2ln0GfO225n30e4Z2OHNgDqc/9HhGeax3s8PKx1myfbZuQ7s4VQYSfxNAqI24dbBzpnvXPRtoqszShwyxlgHjs7p/zHSSvFZ5YHHQcGc+k8fWd9ZQBLg2fBh+anjaeBm7QHPof2p+onGKC4XSAQoIdzZ/GHbqcvR4drY2fPJ2tnwvKYXT8AA2e2mzsni2cjZwKHK2cYB2xrPvX1GRZ+LAeUDUNnl2eDRz47SCc5p3vHPWd5LI9nZ2dUB40HJmdXO6JnBqdpBxJnpdvph9IHo4veZ2z7P9vWpCTkeiVzi+K7h+vqIKMrGqwyy25M9QCBbdoHgScxZy8RLw6dwAjnoIcKu4V7sqvfS9vHnqeyJ+HHsKcpRy5naicTZ4UIi9phwITnrqek55+HKGe4p87HB6c05yMHxkfhRxTpgI7QeCznJatNp+Bn1qc1i85HPOeuR717/OfZzaCHVycd+0hnc6fppzenmadc5wZHIUeMp8SnWWdw51VQiVycS+in06f/C5enMicyp2hn4udnsw+n7nuKR+5HjOcZIHrncue9py4HiudXp+znQ6ec5+hn3OeKhyhHT6dgPVIYsudC58bn+icFJ2bn9hsS517nvOdjBz4bk0f0m9n7Qzt72xrH5iWsK6RnSOen23z7URvXCzEbEIcIx2NQ6FtrMOQbvQeOG32Hjmf4h61HWGecZ+ibZce++M+wnBv1BwJnwgeJhzLHZ8cfR1Yn5Wek67Vr9icjO1DRoRtgSR4rJfsdaz8boIdI2277kKsVhxLD1WA95wxnW2sB+3+r9oeahy8HD8clZyiHmWcTx5YogOuT563z0+dRq08Haevz5+An5mcSB2DnMDsx5yAAntsd55Db8duuYByxS0f3OFDH18f484U78zubR+WH2edOYBfnJWBX5zDHydvHB2T70Sc0p16nIef48wknlufXez07HUc4Z23nKnNn53qHLCs3+LsEyhvvak3b1aBhJz1QE9iRZ3EbOOfQF5or88Prw9FrPmBmQclnDeepZzdnVDv050/Dl8Pbw7gXxOdshzOn2+eVK85nkudG+wrHJIcVZ79HE7MFAD5n/Uvq0Jz7vefBi+RnxYfRG1RngJvbR8s7fkQJyM3r6+e8xwVnhBeah2xn70e+h+0nFpvIHsDSTfOAO0xnAOe0F1kbxBe8B+AXCBs3a9Dn8ee1Zz/jIORe6B8bvBfMxxRnAvuZ56G7o+cxZPRnksdA+7PnwmeyF7TnqJvL517rAcccG3xntedqF0XnCLtyh84XDBfDh4fn0eeg23A7MmdpOzEgXYib+0CHKednS9K790f484f7SEzUZyIXeCR+XANzCAeeh7KHSYeyx2XnChd3Zxdl8AeI2/9nvhdLZ2GHWhdKh3dnIWhFFwL7Ecv1h8XnmocHZ2JnNLvZc1hGNRfX+1kXhWfCZ00XIOcQuykgbReOyzgHmRfzZ817zQc/+6XnHGfqJxL8/3SK88UXnRfSF90XFRejBwUXqlACB8MXO2cDR5pbQOcL56XHd2f2DGsXcxcjF5sXe1uEB9wHrSfiZ0wXkmdKx8fno4scF+uo6DPHS4zHHCtxFxdLzstJF8f7WedmxyVLq2DpFywMggcbF4DnEAd75+lnrhcV5xmbp/DXnETLtRclF/UXfhc5F03n8hcm28Hwvxewy+sXxocaF9dnExfnx+on/zj8wGzL/xfol3tn4xe5F5MXaLsGVlLLN5xol3yHGJemhzsXh2dIl0LWFJf5ltCX8xeOF/tnSxe6h7S7rB5Mlz1HrAeEl9kXrzscl5GH3xdKjDyXBJfUl0SXr+s9FyunLeeKxywXmQfCQHcXYD250FtpoTUN21ur5fsJF4crVftOB+InfQtRZ91nbwvxjKqXDtN3631HCQdwl05n9Bfh5wc710dSCzYmCxA43DWH5pcz5yxnIQctRySX2JeR59y7Nic3F3zbMOcHS2gbetTKBwhdjId59MyH5Tysh8Zn6BfRZ7DnuhsShx6HRxeAl1wHwwc2l6QrpBc3pKUQpUqJlwCXNJfvZ9qHn2cWh0XrK2CGh0GHuZeSl6NnQpdPx64rwJCll7UXrJdul/CX38del4jrO2aBh/WXSZd5l9sXwJeL536HzAbYS8E7OZf8l10X7JdYl83nZcdGxBOY7oe2hw4XjZeCl2OXiJcD+4fbboc2h0aHEpcCl96HC5erZ96XC/sZB14bHsB+wBAATwAiAG7zpgAEAKYAedQji6rHUk3jh5hzBABsJwNMtwAEAIsAOZIsABSQ3sCrACgAeACPABwANgDjhy0AYAAAAAqAcwAAVmELTwBtIOswAgBbs3wAUk1CgIuy3otfl27zqADzwJMgE7MErWu4E7Mb8xQ+xQATs/qDKW5iC+OzcefuXBOzTdxvQAsgE7MVpoREdCsBLHQAFFdzqwBdW9CEV22zCE30V/QrWaX0V5br9QDfUGwXASwHB5Xzk7MAXcrThFePGxkgnFcb8zxXXRvWwDJAnFf6g1UAIldx523LIldN3CkbuFeTsxWmx8NqV/BXtkv0V4EbC2BrIOhXAF3iQLpXBK1shgsgIlfWwEKA9FfdG+ybzFf6F8Mo5ld0KwStLevMVxvzo2COV3Or+oOpLMxXcefGeR5XfFdmxP5X3RvCQJ5aCQAgAHVr1sBROGIL4NuG8BRXx8vBVwk40VeiV7qsxQDRVwStjVjRVxvzVESOV5b7lleBV6lX4Ves+5IAmWCOVxTr1sACxY5Xtxf7sBRX6nMAXYHEYguac+VXNVfdG/+QDVfsV+64lVdx56uMlfPqcypXmFcUh9bAnrRtV4pX9VcjiyxXCEqhVw1XBK3QgJNXI4v4V5JIBVfqcxWmAMCzV1DnkVf5V0XUY1cBLCVXBVe7AAEsiICzV1OHfFcLV5tXp+fWwKLAFFfe29JXGVcn5xhXN1cpO5ZXHlqLV6rH21f9MI5XdieRV3f471eMVztXm1cdK+VXX1cFV+vzlldeE7AASwAEABYAVgDuIM0AgwBrs5/LoADeZ59zFQBEAKhL47PwALvo3ADwAODNLwBCcxmSikrNALXzYgsvAAAAggAAGt+ou4nCAOOHAADyAACS47NSTd8A8AC4iGgALTB4AHgA8ACAVx207NfcR++kSNfqACjX3sBo1xjXWNcNQDjXpgB419xH9kSfc2TrRDx8APAAuwAAAKIk12CAitfewGTr44fqc0Q8Mk3wAOOHKAAnAEJz8ACe2ygAGZIHsy4AfsD2AJzXYYxoALC47NfwAIrX0ABAV8QA1Ndj87IedtfG19pKkADwAC8A4XNnl8EAxtehALAALtdI827XeADcRxf2/NeqAILXwgDC17igotdaAOLXktfNANu5n3OAV8rXitfcAFJN0FcU65nXZOtC1y4AtwCYc6YAmHPwAGTr47Nl1/AA47Pqc7TX8AC01wAAcmjXadcvABnXUk3iAFJNZOtt13nXzQC5KJHX0dfZ++jXcdfY17jXxwDcR7tan3Mk1+TXE9AyGzTX9NeM18zX9oCs1/aAdtdc1wDgPNfNALPQvdeo1wPXnwDx13fMw9f418IAOQifcwIASwBVnMfL29eY10PXEtcj1wTXiNeV88jXW9ci11fXSdfCAM40n3PaSMfL3sDn10/XYtf719xH9Wsy13LX3tfE16rX6tea19rX8teAV8QACADG16bX5tdPUlbXiZA216pQdtcO1zAAUDdEAMHXSHOh10bXQHPFwBAA3te+19bzAddwAFg3QnOh1//X0teV8+DYmkq7AAAA9EWAAABqQtfo18/MWNd0eInXN9ev1xHXlfPjh3XXXDwyZzTXc9eqsGgAOdDL19zXYdcE1ynXlfPcAEsAMtPf14PXv9fX1wfXLABFgJ1zD9csNz/XCdd/1wTXY9eV86rXZOvYAEQ8YIDqc2rXwgAGN6w3G8DsN+8mOjev1xvX99cC14/XijfaN8o3/9dH1w43UddONzvXz9dcNywAluub15o3zjd71643zQDjgOo3jjeBN943Sjcv1343fNceN33XE7MX17vXnDcqNyAAmaMBNzHXSTc+N6k32csZN/3XWjfBNzE3aTfSN2ILH9df11k30Te+N2k3Pdc9V6rHldeAV5wwmdcAAOIvAMfLUk1NNwAAirsAddcatl03dddWc98Ai4uK14BX8AACAGgAAgDL1+AgqDeAV5TYaACU2GvXwgDsF+/XQoCf18IACjdRNy43RTcgQEjXCTdo12oQmNfoXCk3nNf2ShYYczcKQO7XQQAQAHrX9gAQAPbzoTfuN0TXRDf+1w4Afgs+18BzftdQACQ389fcAHbXLwDUAMc3owDNAPBX/Ne0N5o3KGjwAONUMMS2NywAgRt5N4k3BTcpN1LXcTdiC3w3AjfewEI3TNciN2I3HNcr1wUACzcwt1Q3jzfvN8Q3LzfewG83ZcAkt6EA3ze/N/83gFf2SlLXPDcot/w3YJ3ot9TXwjc0AKI3RoDiN6vXkjfCABiAnXOy11cA3tdPUn4LGtda11ZzAgCc19A3uDdwN2XACDcNN0g3ttcc12g3TteYN67XDxDu13g3Xtfktx83JDdB1+q3IiD4tyAAtQDhN543kTeX15U3qTet2Z9z9ABLAHHn4VcVN5s3VTen0UjXtDd0N1cAtwCaN2w3hIhOgNC3xrcPN6hAZNcU19PXdNcM10zXLNds1zi3Ejfh13fXYgtggOf8aQBk6wAAKlnXmgCstym3oLBwV/AASbdpkhg376TNAMvApre7N463hTdVNwyAnXMn12fXJbeItwW3hLcgABo3mTcIt363mYCdc6i3LLdU12y3mLcct9i3nNfRtwW3JTf1txE3jbdBNzW3wgC7iZ9zU4el14BXybfwADbX6LeTh/bXN5dtAKYAqwCdAPbXTTf6clO3M7fE18hEgLdjt3o3Ygu0AKC3jbfetxw3zbf2N4e3xbf7N/AAhzf71wC3pzeSFBc3LcDXN7c3ynMFtwG3OreUt683TzefNy831Lcc1383ALfcR+JARbdeNxa3TrepN7AWn3Oe28fLbLdJtwAAmmnXUk0M13QAUk0vAIuLMtMqx0Q8ldfwAMfLbHNgABYAfsC+C0bXsHfZt4h3itfId3BXtABodxh3wHfItyAAgreSt0rXKtdmNywAYrfa10K3etcG16YAMrcUc/A3ltcKtwqAyDdMYKg3jtcYN2Q3pgA4Nx7X+DeEN8S3zzeB1xJ3FDfJ13W3Dbf5NyO3frd5AOE3x7f5N+C3kLejtywAaSBad4/XundGbPp3IABi1J9zWHdggOOzZABWc+OHNnfpt1Zz1ABSTbkoydcHtyAASbdk6w8bGHfoQJOHtNf510QAhdcBwCXXZdcV10m3x8vE1+Oz1NfZt153mdfiAOIAfnfAdxe3g7dmt8O3Gzelt5B3AbdlN2s31bd+t6LAnXOft/J337dyd7+3VLeVgDS3QHfd14TXIACAVx0g/QCe15IAY/DE197AuwCe11jXyJDM17vAZncCgKB35rfJN3l3KndDt2p36Xfdd4y3gbeT1wzgrLez1+G3C9eRt723PLfcR9KABXdBt1PXU3dht/PXfACL13wA3Ld4t7y3LACpEK639Dcet163Vjc+t9137ndtt9WgrLfst9QAnLc/N1G3C3fdczhzqBToV4NX9FfYV4lXeFfSV9RXRFeRV5JXZFfyV5RX0ldsV7RXn3cMV5ZXsFDMV03c/jjMVxWmagCcV/oXnMYiV3xXBleCV4NXcF1sF85X4lfWwJJXVwDSV5hXk7NyV5xXilc/dzCGqlcCV2EmQki6V/oX0rpaVwEshOSGV5FXgPfjswfKZlcFV5OzllfM9zZXBPdqAJFXv1dhV3OrzleQ93QrblcJYP5XXleSV/6XPABi9+z3AVezV3OrwVdPV5tXEVcK3HFXAF0FAHFXCVdq9wStKVfK9+lXcVdZV4DXyvcVpgd7OVdFV/+kpVcBLBVXi1f7Vxj3tVfWwKNXjVf1AM1X51f9V+1X5TCdV5ZX/Vd9VzVXajfX4L73I1e+903cDYSVV9NXJ1dhV4yb0lfh9w1Xy1f+AJVXvPcUGKtXu9v897KL+1dvVwVXR1eDV9H3J+f7V4D3V1cLYPdXd1eXV25XSvcR9y9XkVfp939X21dG92FX/LuWVyn3IAD/V/UANfdiC8DXrmBeE52ztis9s/0A5tfwAEeXfsBzsz2zBACoABzXQXcvl9sAxrLEOGm32gBAAAAA="))
  831. ///////////////////////////////////////////////
  832. ///////////////////////////////////////////////
  833. /* Utility functions */
  834. var storagePrefix = 'KiCad_HTML_BOM__' + pcbdata.metadata.title + '__' +
  835. pcbdata.metadata.revision + '__#';
  836. var storage;
  837. function initStorage(key) {
  838. try {
  839. window.localStorage.getItem("blank");
  840. storage = window.localStorage;
  841. } catch (e) {
  842. // localStorage not available
  843. }
  844. if (!storage) {
  845. try {
  846. window.sessionStorage.getItem("blank");
  847. storage = window.sessionStorage;
  848. } catch (e) {
  849. // sessionStorage also not available
  850. }
  851. }
  852. }
  853. function readStorage(key) {
  854. if (storage) {
  855. return storage.getItem(storagePrefix + key);
  856. } else {
  857. return null;
  858. }
  859. }
  860. function writeStorage(key, value) {
  861. if (storage) {
  862. storage.setItem(storagePrefix + key, value);
  863. }
  864. }
  865. function fancyDblClickHandler(el, onsingle, ondouble) {
  866. return function () {
  867. if (el.getAttribute("data-dblclick") == null) {
  868. el.setAttribute("data-dblclick", 1);
  869. setTimeout(function () {
  870. if (el.getAttribute("data-dblclick") == 1) {
  871. onsingle();
  872. }
  873. el.removeAttribute("data-dblclick");
  874. }, 200);
  875. } else {
  876. el.removeAttribute("data-dblclick");
  877. ondouble();
  878. }
  879. }
  880. }
  881. function smoothScrollToRow(rowid) {
  882. document.getElementById(rowid).scrollIntoView({
  883. behavior: "smooth",
  884. block: "center",
  885. inline: "nearest"
  886. });
  887. }
  888. function focusInputField(input) {
  889. input.scrollIntoView(false);
  890. input.focus();
  891. input.select();
  892. }
  893. function saveBomTable(output) {
  894. var text = '';
  895. for (var node of bomhead.childNodes[0].childNodes) {
  896. if (node.firstChild) {
  897. var name = node.firstChild.nodeValue ?? "";
  898. text += (output == 'csv' ? `"${name}"` : name);
  899. }
  900. if (node != bomhead.childNodes[0].lastChild) {
  901. text += (output == 'csv' ? ',' : '\t');
  902. }
  903. }
  904. text += '\n';
  905. for (var row of bombody.childNodes) {
  906. for (var cell of row.childNodes) {
  907. let val = '';
  908. for (var node of cell.childNodes) {
  909. if (node.nodeName == "INPUT") {
  910. if (node.checked) {
  911. val += '✓';
  912. }
  913. } else if ((node.nodeName == "MARK") || (node.nodeName == "A")) {
  914. val += node.firstChild.nodeValue;
  915. } else {
  916. val += node.nodeValue;
  917. }
  918. }
  919. if (output == 'csv') {
  920. val = val.replace(/\"/g, '\"\"'); // pair of double-quote characters
  921. if (isNumeric(val)) {
  922. val = +val; // use number
  923. } else {
  924. val = `"${val}"`; // enclosed within double-quote
  925. }
  926. }
  927. text += val;
  928. if (cell != row.lastChild) {
  929. text += (output == 'csv' ? ',' : '\t');
  930. }
  931. }
  932. text += '\n';
  933. }
  934. if (output != 'clipboard') {
  935. // To file: csv or txt
  936. var blob = new Blob([text], {
  937. type: `text/${output}`
  938. });
  939. saveFile(`${pcbdata.metadata.title}.${output}`, blob);
  940. } else {
  941. // To clipboard
  942. var textArea = document.createElement("textarea");
  943. textArea.classList.add('clipboard-temp');
  944. textArea.value = text;
  945. document.body.appendChild(textArea);
  946. textArea.focus();
  947. textArea.select();
  948. try {
  949. if (document.execCommand('copy')) {
  950. console.log('Bom copied to clipboard.');
  951. }
  952. } catch (err) {
  953. console.log('Can not copy to clipboard.');
  954. }
  955. document.body.removeChild(textArea);
  956. }
  957. }
  958. function isNumeric(str) {
  959. /* https://stackoverflow.com/a/175787 */
  960. return (typeof str != "string" ? false : !isNaN(str) && !isNaN(parseFloat(str)));
  961. }
  962. function removeGutterNode(node) {
  963. for (var i = 0; i < node.childNodes.length; i++) {
  964. if (node.childNodes[i].classList &&
  965. node.childNodes[i].classList.contains("gutter")) {
  966. node.removeChild(node.childNodes[i]);
  967. break;
  968. }
  969. }
  970. }
  971. function cleanGutters() {
  972. removeGutterNode(document.getElementById("bot"));
  973. removeGutterNode(document.getElementById("canvasdiv"));
  974. }
  975. var units = {
  976. prefixes: {
  977. giga: ["G", "g", "giga", "Giga", "GIGA"],
  978. mega: ["M", "mega", "Mega", "MEGA"],
  979. kilo: ["K", "k", "kilo", "Kilo", "KILO"],
  980. milli: ["m", "milli", "Milli", "MILLI"],
  981. micro: ["U", "u", "micro", "Micro", "MICRO", "μ", "µ"], // different utf8 μ
  982. nano: ["N", "n", "nano", "Nano", "NANO"],
  983. pico: ["P", "p", "pico", "Pico", "PICO"],
  984. },
  985. unitsShort: ["R", "r", "Ω", "F", "f", "H", "h"],
  986. unitsLong: [
  987. "OHM", "Ohm", "ohm", "ohms",
  988. "FARAD", "Farad", "farad",
  989. "HENRY", "Henry", "henry"
  990. ],
  991. getMultiplier: function (s) {
  992. if (this.prefixes.giga.includes(s)) return 1e9;
  993. if (this.prefixes.mega.includes(s)) return 1e6;
  994. if (this.prefixes.kilo.includes(s)) return 1e3;
  995. if (this.prefixes.milli.includes(s)) return 1e-3;
  996. if (this.prefixes.micro.includes(s)) return 1e-6;
  997. if (this.prefixes.nano.includes(s)) return 1e-9;
  998. if (this.prefixes.pico.includes(s)) return 1e-12;
  999. return 1;
  1000. },
  1001. valueRegex: null,
  1002. valueAltRegex: null,
  1003. }
  1004. function initUtils() {
  1005. var allPrefixes = units.prefixes.giga
  1006. .concat(units.prefixes.mega)
  1007. .concat(units.prefixes.kilo)
  1008. .concat(units.prefixes.milli)
  1009. .concat(units.prefixes.micro)
  1010. .concat(units.prefixes.nano)
  1011. .concat(units.prefixes.pico);
  1012. var allUnits = units.unitsShort.concat(units.unitsLong);
  1013. units.valueRegex = new RegExp("^([0-9\.]+)" +
  1014. "\\s*(" + allPrefixes.join("|") + ")?" +
  1015. "(" + allUnits.join("|") + ")?" +
  1016. "(\\b.*)?$", "");
  1017. units.valueAltRegex = new RegExp("^([0-9]*)" +
  1018. "(" + units.unitsShort.join("|") + ")?" +
  1019. "([GgMmKkUuNnPp])?" +
  1020. "([0-9]*)" +
  1021. "(\\b.*)?$", "");
  1022. if (config.fields.includes("Value")) {
  1023. var index = config.fields.indexOf("Value");
  1024. pcbdata.bom["parsedValues"] = {};
  1025. var allList = getBomListByLayer('FB').flat();
  1026. for (var id in pcbdata.bom.fields) {
  1027. var ref_key = allList.find(item => item[1] == Number(id)) || [];
  1028. pcbdata.bom.parsedValues[id] = parseValue(pcbdata.bom.fields[id][index], ref_key[0] || '');
  1029. }
  1030. }
  1031. }
  1032. function parseValue(val, ref) {
  1033. var inferUnit = (unit, ref) => {
  1034. if (unit) {
  1035. unit = unit.toLowerCase();
  1036. if (unit == 'Ω' || unit == "ohm" || unit == "ohms") {
  1037. unit = 'r';
  1038. }
  1039. return unit[0];
  1040. }
  1041. var resarr = /^([a-z]+)\d+$/i.exec(ref);
  1042. switch (Array.isArray(resarr) && resarr[1].toLowerCase()) {
  1043. case "c": return 'f';
  1044. case "l": return 'h';
  1045. case "r":
  1046. case "rv": return 'r';
  1047. }
  1048. return null;
  1049. };
  1050. val = val.replace(/,/g, "");
  1051. var match = units.valueRegex.exec(val);
  1052. if (Array.isArray(match)) {
  1053. var unit = inferUnit(match[3], ref);
  1054. var val_i = parseFloat(match[1]);
  1055. if (!unit) return null;
  1056. if (match[2]) {
  1057. val_i = val_i * units.getMultiplier(match[2]);
  1058. }
  1059. return {
  1060. val: val_i,
  1061. unit: unit,
  1062. extra: match[4],
  1063. }
  1064. }
  1065. match = units.valueAltRegex.exec(val);
  1066. if (Array.isArray(match) && (match[1] || match[4])) {
  1067. var unit = inferUnit(match[2], ref);
  1068. var val_i = parseFloat(match[1] + "." + match[4]);
  1069. if (!unit) return null;
  1070. if (match[3]) {
  1071. val_i = val_i * units.getMultiplier(match[3]);
  1072. }
  1073. return {
  1074. val: val_i,
  1075. unit: unit,
  1076. extra: match[5],
  1077. }
  1078. }
  1079. return null;
  1080. }
  1081. function valueCompare(a, b, stra, strb) {
  1082. if (a === null && b === null) {
  1083. // Failed to parse both values, compare them as strings.
  1084. if (stra != strb) return stra > strb ? 1 : -1;
  1085. else return 0;
  1086. } else if (a === null) {
  1087. return 1;
  1088. } else if (b === null) {
  1089. return -1;
  1090. } else {
  1091. if (a.unit != b.unit) return a.unit > b.unit ? 1 : -1;
  1092. else if (a.val != b.val) return a.val > b.val ? 1 : -1;
  1093. else if (a.extra != b.extra) return a.extra > b.extra ? 1 : -1;
  1094. else return 0;
  1095. }
  1096. }
  1097. function validateSaveImgDimension(element) {
  1098. var valid = false;
  1099. var intValue = 0;
  1100. if (/^[1-9]\d*$/.test(element.value)) {
  1101. intValue = parseInt(element.value);
  1102. if (intValue <= 16000) {
  1103. valid = true;
  1104. }
  1105. }
  1106. if (valid) {
  1107. element.classList.remove("invalid");
  1108. } else {
  1109. element.classList.add("invalid");
  1110. }
  1111. return intValue;
  1112. }
  1113. function saveImage(layer) {
  1114. var width = validateSaveImgDimension(document.getElementById("render-save-width"));
  1115. var height = validateSaveImgDimension(document.getElementById("render-save-height"));
  1116. var bgcolor = null;
  1117. if (!document.getElementById("render-save-transparent").checked) {
  1118. var style = getComputedStyle(topmostdiv);
  1119. bgcolor = style.getPropertyValue("background-color");
  1120. }
  1121. if (!width || !height) return;
  1122. // Prepare image
  1123. var canvas = document.createElement("canvas");
  1124. var layerdict = {
  1125. transform: {
  1126. x: 0,
  1127. y: 0,
  1128. s: 1,
  1129. panx: 0,
  1130. pany: 0,
  1131. zoom: 1,
  1132. },
  1133. bg: canvas,
  1134. fab: canvas,
  1135. silk: canvas,
  1136. highlight: canvas,
  1137. layer: layer,
  1138. }
  1139. // Do the rendering
  1140. recalcLayerScale(layerdict, width, height);
  1141. prepareLayer(layerdict);
  1142. clearCanvas(canvas, bgcolor);
  1143. drawBackground(layerdict, false);
  1144. drawHighlightsOnLayer(layerdict, false);
  1145. // Save image
  1146. var imgdata = canvas.toDataURL("image/png");
  1147. var filename = pcbdata.metadata.title;
  1148. if (pcbdata.metadata.revision) {
  1149. filename += `.${pcbdata.metadata.revision}`;
  1150. }
  1151. filename += `.${layer}.png`;
  1152. saveFile(filename, dataURLtoBlob(imgdata));
  1153. }
  1154. function saveSettings() {
  1155. var data = {
  1156. type: "InteractiveHtmlBom settings",
  1157. version: 1,
  1158. pcbmetadata: pcbdata.metadata,
  1159. settings: settings,
  1160. }
  1161. var blob = new Blob([JSON.stringify(data, null, 4)], {
  1162. type: "application/json"
  1163. });
  1164. saveFile(`${pcbdata.metadata.title}.settings.json`, blob);
  1165. }
  1166. function loadSettings() {
  1167. var input = document.createElement("input");
  1168. input.type = "file";
  1169. input.accept = ".settings.json";
  1170. input.onchange = function (e) {
  1171. var file = e.target.files[0];
  1172. var reader = new FileReader();
  1173. reader.onload = readerEvent => {
  1174. var content = readerEvent.target.result;
  1175. var newSettings;
  1176. try {
  1177. newSettings = JSON.parse(content);
  1178. } catch (e) {
  1179. alert("Selected file is not InteractiveHtmlBom settings file.");
  1180. return;
  1181. }
  1182. if (newSettings.type != "InteractiveHtmlBom settings") {
  1183. alert("Selected file is not InteractiveHtmlBom settings file.");
  1184. return;
  1185. }
  1186. var metadataMatches = newSettings.hasOwnProperty("pcbmetadata");
  1187. if (metadataMatches) {
  1188. for (var k in pcbdata.metadata) {
  1189. if (!newSettings.pcbmetadata.hasOwnProperty(k) || newSettings.pcbmetadata[k] != pcbdata.metadata[k]) {
  1190. metadataMatches = false;
  1191. }
  1192. }
  1193. }
  1194. if (!metadataMatches) {
  1195. var currentMetadata = JSON.stringify(pcbdata.metadata, null, 4);
  1196. var fileMetadata = JSON.stringify(newSettings.pcbmetadata, null, 4);
  1197. if (!confirm(
  1198. `Settins file metadata does not match current metadata.\n\n` +
  1199. `Page metadata:\n${currentMetadata}\n\n` +
  1200. `Settings file metadata:\n${fileMetadata}\n\n` +
  1201. `Press OK if you would like to import settings anyway.`)) {
  1202. return;
  1203. }
  1204. }
  1205. overwriteSettings(newSettings.settings);
  1206. }
  1207. reader.readAsText(file, 'UTF-8');
  1208. }
  1209. input.click();
  1210. }
  1211. function resetSettings() {
  1212. if (!confirm(
  1213. `This will reset all checkbox states and other settings.\n\n` +
  1214. `Press OK if you want to continue.`)) {
  1215. return;
  1216. }
  1217. if (storage) {
  1218. var keys = [];
  1219. for (var i = 0; i < storage.length; i++) {
  1220. var key = storage.key(i);
  1221. if (key.startsWith(storagePrefix)) keys.push(key);
  1222. }
  1223. for (var key of keys) storage.removeItem(key);
  1224. }
  1225. location.reload();
  1226. }
  1227. function overwriteSettings(newSettings) {
  1228. initDone = false;
  1229. Object.assign(settings, newSettings);
  1230. writeStorage("bomlayout", settings.bomlayout);
  1231. writeStorage("bommode", settings.bommode);
  1232. writeStorage("canvaslayout", settings.canvaslayout);
  1233. writeStorage("bomCheckboxes", settings.checkboxes.join(","));
  1234. document.getElementById("bomCheckboxes").value = settings.checkboxes.join(",");
  1235. for (var checkbox of settings.checkboxes) {
  1236. writeStorage("checkbox_" + checkbox, settings.checkboxStoredRefs[checkbox]);
  1237. }
  1238. writeStorage("markWhenChecked", settings.markWhenChecked);
  1239. padsVisible(settings.renderPads);
  1240. document.getElementById("padsCheckbox").checked = settings.renderPads;
  1241. fabricationVisible(settings.renderFabrication);
  1242. document.getElementById("fabricationCheckbox").checked = settings.renderFabrication;
  1243. silkscreenVisible(settings.renderSilkscreen);
  1244. document.getElementById("silkscreenCheckbox").checked = settings.renderSilkscreen;
  1245. referencesVisible(settings.renderReferences);
  1246. document.getElementById("referencesCheckbox").checked = settings.renderReferences;
  1247. valuesVisible(settings.renderValues);
  1248. document.getElementById("valuesCheckbox").checked = settings.renderValues;
  1249. tracksVisible(settings.renderTracks);
  1250. document.getElementById("tracksCheckbox").checked = settings.renderTracks;
  1251. zonesVisible(settings.renderZones);
  1252. document.getElementById("zonesCheckbox").checked = settings.renderZones;
  1253. dnpOutline(settings.renderDnpOutline);
  1254. document.getElementById("dnpOutlineCheckbox").checked = settings.renderDnpOutline;
  1255. setRedrawOnDrag(settings.redrawOnDrag);
  1256. document.getElementById("dragCheckbox").checked = settings.redrawOnDrag;
  1257. setHighlightRowOnClick(settings.highlightRowOnClick);
  1258. document.getElementById("highlightRowOnClickCheckbox").checked = settings.highlightRowOnClick;
  1259. setDarkMode(settings.darkMode);
  1260. document.getElementById("darkmodeCheckbox").checked = settings.darkMode;
  1261. setHighlightPin1(settings.highlightpin1);
  1262. document.forms.highlightpin1.highlightpin1.value = settings.highlightpin1;
  1263. writeStorage("boardRotation", settings.boardRotation);
  1264. document.getElementById("boardRotation").value = settings.boardRotation / 5;
  1265. document.getElementById("rotationDegree").textContent = settings.boardRotation;
  1266. setOffsetBackRotation(settings.offsetBackRotation);
  1267. document.getElementById("offsetBackRotationCheckbox").checked = settings.offsetBackRotation;
  1268. initDone = true;
  1269. prepCheckboxes();
  1270. changeBomLayout(settings.bomlayout);
  1271. }
  1272. function saveFile(filename, blob) {
  1273. var link = document.createElement("a");
  1274. var objurl = URL.createObjectURL(blob);
  1275. link.download = filename;
  1276. link.href = objurl;
  1277. link.click();
  1278. }
  1279. function dataURLtoBlob(dataurl) {
  1280. var arr = dataurl.split(','),
  1281. mime = arr[0].match(/:(.*?);/)[1],
  1282. bstr = atob(arr[1]),
  1283. n = bstr.length,
  1284. u8arr = new Uint8Array(n);
  1285. while (n--) {
  1286. u8arr[n] = bstr.charCodeAt(n);
  1287. }
  1288. return new Blob([u8arr], {
  1289. type: mime
  1290. });
  1291. }
  1292. var settings = {
  1293. canvaslayout: "FB",
  1294. bomlayout: "left-right",
  1295. bommode: "grouped",
  1296. checkboxes: [],
  1297. checkboxStoredRefs: {},
  1298. darkMode: false,
  1299. highlightpin1: "none",
  1300. redrawOnDrag: true,
  1301. boardRotation: 0,
  1302. offsetBackRotation: false,
  1303. renderPads: true,
  1304. renderReferences: true,
  1305. renderValues: true,
  1306. renderSilkscreen: true,
  1307. renderFabrication: true,
  1308. renderDnpOutline: false,
  1309. renderTracks: true,
  1310. renderZones: true,
  1311. columnOrder: [],
  1312. hiddenColumns: [],
  1313. netColors: {},
  1314. }
  1315. function initDefaults() {
  1316. settings.bomlayout = readStorage("bomlayout");
  1317. if (settings.bomlayout === null) {
  1318. settings.bomlayout = config.bom_view;
  1319. }
  1320. if (!['bom-only', 'left-right', 'top-bottom'].includes(settings.bomlayout)) {
  1321. settings.bomlayout = config.bom_view;
  1322. }
  1323. settings.bommode = readStorage("bommode");
  1324. if (settings.bommode === null) {
  1325. settings.bommode = "grouped";
  1326. }
  1327. if (settings.bommode == "netlist" && !pcbdata.nets) {
  1328. settings.bommode = "grouped";
  1329. }
  1330. if (!["grouped", "ungrouped", "netlist"].includes(settings.bommode)) {
  1331. settings.bommode = "grouped";
  1332. }
  1333. settings.canvaslayout = readStorage("canvaslayout");
  1334. if (settings.canvaslayout === null) {
  1335. settings.canvaslayout = config.layer_view;
  1336. }
  1337. var bomCheckboxes = readStorage("bomCheckboxes");
  1338. if (bomCheckboxes === null) {
  1339. bomCheckboxes = config.checkboxes;
  1340. }
  1341. settings.checkboxes = bomCheckboxes.split(",").filter((e) => e);
  1342. document.getElementById("bomCheckboxes").value = bomCheckboxes;
  1343. var highlightpin1 = readStorage("highlightpin1") || config.highlight_pin1;
  1344. if (highlightpin1 === "false") highlightpin1 = "none";
  1345. if (highlightpin1 === "true") highlightpin1 = "all";
  1346. setHighlightPin1(highlightpin1);
  1347. document.forms.highlightpin1.highlightpin1.value = highlightpin1;
  1348. settings.markWhenChecked = readStorage("markWhenChecked") || "";
  1349. populateMarkWhenCheckedOptions();
  1350. function initBooleanSetting(storageString, def, elementId, func) {
  1351. var b = readStorage(storageString);
  1352. if (b === null) {
  1353. b = def;
  1354. } else {
  1355. b = (b == "true");
  1356. }
  1357. document.getElementById(elementId).checked = b;
  1358. func(b);
  1359. }
  1360. initBooleanSetting("padsVisible", config.show_pads, "padsCheckbox", padsVisible);
  1361. initBooleanSetting("fabricationVisible", config.show_fabrication, "fabricationCheckbox", fabricationVisible);
  1362. initBooleanSetting("silkscreenVisible", config.show_silkscreen, "silkscreenCheckbox", silkscreenVisible);
  1363. initBooleanSetting("referencesVisible", true, "referencesCheckbox", referencesVisible);
  1364. initBooleanSetting("valuesVisible", true, "valuesCheckbox", valuesVisible);
  1365. if ("tracks" in pcbdata) {
  1366. initBooleanSetting("tracksVisible", true, "tracksCheckbox", tracksVisible);
  1367. initBooleanSetting("zonesVisible", true, "zonesCheckbox", zonesVisible);
  1368. } else {
  1369. document.getElementById("tracksAndZonesCheckboxes").style.display = "none";
  1370. tracksVisible(false);
  1371. zonesVisible(false);
  1372. }
  1373. initBooleanSetting("dnpOutline", false, "dnpOutlineCheckbox", dnpOutline);
  1374. initBooleanSetting("redrawOnDrag", config.redraw_on_drag, "dragCheckbox", setRedrawOnDrag);
  1375. initBooleanSetting("highlightRowOnClick", false, "highlightRowOnClickCheckbox", setHighlightRowOnClick);
  1376. initBooleanSetting("darkmode", config.dark_mode, "darkmodeCheckbox", setDarkMode);
  1377. var fields = ["checkboxes", "References"].concat(config.fields).concat(["Quantity"]);
  1378. var hcols = JSON.parse(readStorage("hiddenColumns"));
  1379. if (hcols === null) {
  1380. hcols = [];
  1381. }
  1382. settings.hiddenColumns = hcols.filter(e => fields.includes(e));
  1383. var cord = JSON.parse(readStorage("columnOrder"));
  1384. if (cord === null) {
  1385. cord = fields;
  1386. } else {
  1387. cord = cord.filter(e => fields.includes(e));
  1388. if (cord.length != fields.length)
  1389. cord = fields;
  1390. }
  1391. settings.columnOrder = cord;
  1392. settings.boardRotation = readStorage("boardRotation");
  1393. if (settings.boardRotation === null) {
  1394. settings.boardRotation = config.board_rotation * 5;
  1395. } else {
  1396. settings.boardRotation = parseInt(settings.boardRotation);
  1397. }
  1398. document.getElementById("boardRotation").value = settings.boardRotation / 5;
  1399. document.getElementById("rotationDegree").textContent = settings.boardRotation;
  1400. initBooleanSetting("offsetBackRotation", config.offset_back_rotation, "offsetBackRotationCheckbox", setOffsetBackRotation);
  1401. settings.netColors = JSON.parse(readStorage("netColors")) || {};
  1402. }
  1403. // Helper classes for user js callbacks.
  1404. const IBOM_EVENT_TYPES = {
  1405. ALL: "all",
  1406. HIGHLIGHT_EVENT: "highlightEvent",
  1407. CHECKBOX_CHANGE_EVENT: "checkboxChangeEvent",
  1408. BOM_BODY_CHANGE_EVENT: "bomBodyChangeEvent",
  1409. }
  1410. const EventHandler = {
  1411. callbacks: {},
  1412. init: function () {
  1413. for (eventType of Object.values(IBOM_EVENT_TYPES))
  1414. this.callbacks[eventType] = [];
  1415. },
  1416. registerCallback: function (eventType, callback) {
  1417. this.callbacks[eventType].push(callback);
  1418. },
  1419. emitEvent: function (eventType, eventArgs) {
  1420. event = {
  1421. eventType: eventType,
  1422. args: eventArgs,
  1423. }
  1424. var callback;
  1425. for (callback of this.callbacks[eventType])
  1426. callback(event);
  1427. for (callback of this.callbacks[IBOM_EVENT_TYPES.ALL])
  1428. callback(event);
  1429. }
  1430. }
  1431. EventHandler.init();
  1432. ///////////////////////////////////////////////
  1433. ///////////////////////////////////////////////
  1434. /* PCB rendering code */
  1435. var emptyContext2d = document.createElement("canvas").getContext("2d");
  1436. function deg2rad(deg) {
  1437. return deg * Math.PI / 180;
  1438. }
  1439. function calcFontPoint(linepoint, text, offsetx, offsety, tilt) {
  1440. var point = [
  1441. linepoint[0] * text.width + offsetx,
  1442. linepoint[1] * text.height + offsety
  1443. ];
  1444. // This approximates pcbnew behavior with how text tilts depending on horizontal justification
  1445. point[0] -= (linepoint[1] + 0.5 * (1 + text.justify[0])) * text.height * tilt;
  1446. return point;
  1447. }
  1448. function drawText(ctx, text, color) {
  1449. if ("ref" in text && !settings.renderReferences) return;
  1450. if ("val" in text && !settings.renderValues) return;
  1451. ctx.save();
  1452. ctx.fillStyle = color;
  1453. ctx.strokeStyle = color;
  1454. ctx.lineCap = "round";
  1455. ctx.lineJoin = "round";
  1456. ctx.lineWidth = text.thickness;
  1457. if ("svgpath" in text) {
  1458. ctx.stroke(new Path2D(text.svgpath));
  1459. ctx.restore();
  1460. return;
  1461. }
  1462. if ("polygons" in text) {
  1463. ctx.fill(getPolygonsPath(text));
  1464. ctx.restore();
  1465. return;
  1466. }
  1467. ctx.translate(...text.pos);
  1468. ctx.translate(text.thickness * 0.5, 0);
  1469. var angle = -text.angle;
  1470. if (text.attr.includes("mirrored")) {
  1471. ctx.scale(-1, 1);
  1472. angle = -angle;
  1473. }
  1474. var tilt = 0;
  1475. if (text.attr.includes("italic")) {
  1476. tilt = 0.125;
  1477. }
  1478. var interline = text.height * 1.5 + text.thickness;
  1479. var txt = text.text.split("\n");
  1480. // KiCad ignores last empty line.
  1481. if (txt[txt.length - 1] == '') txt.pop();
  1482. ctx.rotate(deg2rad(angle));
  1483. var offsety = (1 - text.justify[1]) / 2 * text.height; // One line offset
  1484. offsety -= (txt.length - 1) * (text.justify[1] + 1) / 2 * interline; // Multiline offset
  1485. for (var i in txt) {
  1486. var lineWidth = text.thickness + interline / 2 * tilt;
  1487. for (var j = 0; j < txt[i].length; j++) {
  1488. if (txt[i][j] == '\t') {
  1489. var fourSpaces = 4 * pcbdata.font_data[' '].w * text.width;
  1490. lineWidth += fourSpaces - lineWidth % fourSpaces;
  1491. } else {
  1492. if (txt[i][j] == '~') {
  1493. j++;
  1494. if (j == txt[i].length)
  1495. break;
  1496. }
  1497. lineWidth += pcbdata.font_data[txt[i][j]].w * text.width;
  1498. }
  1499. }
  1500. var offsetx = -lineWidth * (text.justify[0] + 1) / 2;
  1501. var inOverbar = false;
  1502. for (var j = 0; j < txt[i].length; j++) {
  1503. if (config.kicad_text_formatting) {
  1504. if (txt[i][j] == '\t') {
  1505. var fourSpaces = 4 * pcbdata.font_data[' '].w * text.width;
  1506. offsetx += fourSpaces - offsetx % fourSpaces;
  1507. continue;
  1508. } else if (txt[i][j] == '~') {
  1509. j++;
  1510. if (j == txt[i].length)
  1511. break;
  1512. if (txt[i][j] != '~') {
  1513. inOverbar = !inOverbar;
  1514. }
  1515. }
  1516. }
  1517. var glyph = pcbdata.font_data[txt[i][j]];
  1518. if (inOverbar) {
  1519. var overbarStart = [offsetx, -text.height * 1.4 + offsety];
  1520. var overbarEnd = [offsetx + text.width * glyph.w, overbarStart[1]];
  1521. if (!lastHadOverbar) {
  1522. overbarStart[0] += text.height * 1.4 * tilt;
  1523. lastHadOverbar = true;
  1524. }
  1525. ctx.beginPath();
  1526. ctx.moveTo(...overbarStart);
  1527. ctx.lineTo(...overbarEnd);
  1528. ctx.stroke();
  1529. } else {
  1530. lastHadOverbar = false;
  1531. }
  1532. for (var line of glyph.l) {
  1533. ctx.beginPath();
  1534. ctx.moveTo(...calcFontPoint(line[0], text, offsetx, offsety, tilt));
  1535. for (var k = 1; k < line.length; k++) {
  1536. ctx.lineTo(...calcFontPoint(line[k], text, offsetx, offsety, tilt));
  1537. }
  1538. ctx.stroke();
  1539. }
  1540. offsetx += glyph.w * text.width;
  1541. }
  1542. offsety += interline;
  1543. }
  1544. ctx.restore();
  1545. }
  1546. function drawedge(ctx, scalefactor, edge, color) {
  1547. ctx.strokeStyle = color;
  1548. ctx.fillStyle = color;
  1549. ctx.lineWidth = Math.max(1 / scalefactor, edge.width);
  1550. ctx.lineCap = "round";
  1551. ctx.lineJoin = "round";
  1552. if ("svgpath" in edge) {
  1553. ctx.stroke(new Path2D(edge.svgpath));
  1554. } else {
  1555. ctx.beginPath();
  1556. if (edge.type == "segment") {
  1557. ctx.moveTo(...edge.start);
  1558. ctx.lineTo(...edge.end);
  1559. }
  1560. if (edge.type == "rect") {
  1561. ctx.moveTo(...edge.start);
  1562. ctx.lineTo(edge.start[0], edge.end[1]);
  1563. ctx.lineTo(...edge.end);
  1564. ctx.lineTo(edge.end[0], edge.start[1]);
  1565. ctx.lineTo(...edge.start);
  1566. }
  1567. if (edge.type == "arc") {
  1568. ctx.arc(
  1569. ...edge.start,
  1570. edge.radius,
  1571. deg2rad(edge.startangle),
  1572. deg2rad(edge.endangle));
  1573. }
  1574. if (edge.type == "circle") {
  1575. ctx.arc(
  1576. ...edge.start,
  1577. edge.radius,
  1578. 0, 2 * Math.PI);
  1579. ctx.closePath();
  1580. }
  1581. if (edge.type == "curve") {
  1582. ctx.moveTo(...edge.start);
  1583. ctx.bezierCurveTo(...edge.cpa, ...edge.cpb, ...edge.end);
  1584. }
  1585. if("filled" in edge && edge.filled)
  1586. ctx.fill();
  1587. else
  1588. ctx.stroke();
  1589. }
  1590. }
  1591. function getChamferedRectPath(size, radius, chamfpos, chamfratio) {
  1592. // chamfpos is a bitmask, left = 1, right = 2, bottom left = 4, bottom right = 8
  1593. var path = new Path2D();
  1594. var width = size[0];
  1595. var height = size[1];
  1596. var x = width * -0.5;
  1597. var y = height * -0.5;
  1598. var chamfOffset = Math.min(width, height) * chamfratio;
  1599. path.moveTo(x, 0);
  1600. if (chamfpos & 4) {
  1601. path.lineTo(x, y + height - chamfOffset);
  1602. path.lineTo(x + chamfOffset, y + height);
  1603. path.lineTo(0, y + height);
  1604. } else {
  1605. path.arcTo(x, y + height, x + width, y + height, radius);
  1606. }
  1607. if (chamfpos & 8) {
  1608. path.lineTo(x + width - chamfOffset, y + height);
  1609. path.lineTo(x + width, y + height - chamfOffset);
  1610. path.lineTo(x + width, 0);
  1611. } else {
  1612. path.arcTo(x + width, y + height, x + width, y, radius);
  1613. }
  1614. if (chamfpos & 2) {
  1615. path.lineTo(x + width, y + chamfOffset);
  1616. path.lineTo(x + width - chamfOffset, y);
  1617. path.lineTo(0, y);
  1618. } else {
  1619. path.arcTo(x + width, y, x, y, radius);
  1620. }
  1621. if (chamfpos & 1) {
  1622. path.lineTo(x + chamfOffset, y);
  1623. path.lineTo(x, y + chamfOffset);
  1624. path.lineTo(x, 0);
  1625. } else {
  1626. path.arcTo(x, y, x, y + height, radius);
  1627. }
  1628. path.closePath();
  1629. return path;
  1630. }
  1631. function getOblongPath(size) {
  1632. return getChamferedRectPath(size, Math.min(size[0], size[1]) / 2, 0, 0);
  1633. }
  1634. function getPolygonsPath(shape) {
  1635. if (shape.path2d) {
  1636. return shape.path2d;
  1637. }
  1638. if ("svgpath" in shape) {
  1639. shape.path2d = new Path2D(shape.svgpath);
  1640. } else {
  1641. var path = new Path2D();
  1642. for (var polygon of shape.polygons) {
  1643. path.moveTo(...polygon[0]);
  1644. for (var i = 1; i < polygon.length; i++) {
  1645. path.lineTo(...polygon[i]);
  1646. }
  1647. path.closePath();
  1648. }
  1649. shape.path2d = path;
  1650. }
  1651. return shape.path2d;
  1652. }
  1653. function drawPolygonShape(ctx, scalefactor, shape, color) {
  1654. ctx.save();
  1655. if (!("svgpath" in shape)) {
  1656. ctx.translate(...shape.pos);
  1657. ctx.rotate(deg2rad(-shape.angle));
  1658. }
  1659. if("filled" in shape && !shape.filled) {
  1660. ctx.strokeStyle = color;
  1661. ctx.lineWidth = Math.max(1 / scalefactor, shape.width);
  1662. ctx.lineCap = "round";
  1663. ctx.lineJoin = "round";
  1664. ctx.stroke(getPolygonsPath(shape));
  1665. } else {
  1666. ctx.fillStyle = color;
  1667. ctx.fill(getPolygonsPath(shape));
  1668. }
  1669. ctx.restore();
  1670. }
  1671. function drawDrawing(ctx, scalefactor, drawing, color) {
  1672. if (["segment", "arc", "circle", "curve", "rect"].includes(drawing.type)) {
  1673. drawedge(ctx, scalefactor, drawing, color);
  1674. } else if (drawing.type == "polygon") {
  1675. drawPolygonShape(ctx, scalefactor, drawing, color);
  1676. } else {
  1677. drawText(ctx, drawing, color);
  1678. }
  1679. }
  1680. function getCirclePath(radius) {
  1681. var path = new Path2D();
  1682. path.arc(0, 0, radius, 0, 2 * Math.PI);
  1683. path.closePath();
  1684. return path;
  1685. }
  1686. function getCachedPadPath(pad) {
  1687. if (!pad.path2d) {
  1688. // if path2d is not set, build one and cache it on pad object
  1689. if (pad.shape == "rect") {
  1690. pad.path2d = new Path2D();
  1691. pad.path2d.rect(...pad.size.map(c => -c * 0.5), ...pad.size);
  1692. } else if (pad.shape == "oval") {
  1693. pad.path2d = getOblongPath(pad.size);
  1694. } else if (pad.shape == "circle") {
  1695. pad.path2d = getCirclePath(pad.size[0] / 2);
  1696. } else if (pad.shape == "roundrect") {
  1697. pad.path2d = getChamferedRectPath(pad.size, pad.radius, 0, 0);
  1698. } else if (pad.shape == "chamfrect") {
  1699. pad.path2d = getChamferedRectPath(pad.size, pad.radius, pad.chamfpos, pad.chamfratio)
  1700. } else if (pad.shape == "custom") {
  1701. pad.path2d = getPolygonsPath(pad);
  1702. }
  1703. }
  1704. return pad.path2d;
  1705. }
  1706. function drawPad(ctx, pad, color, outline) {
  1707. ctx.save();
  1708. ctx.translate(...pad.pos);
  1709. ctx.rotate(-deg2rad(pad.angle));
  1710. if (pad.offset) {
  1711. ctx.translate(...pad.offset);
  1712. }
  1713. ctx.fillStyle = color;
  1714. ctx.strokeStyle = color;
  1715. var path = getCachedPadPath(pad);
  1716. if (outline) {
  1717. ctx.stroke(path);
  1718. } else {
  1719. ctx.fill(path);
  1720. }
  1721. ctx.restore();
  1722. }
  1723. function drawPadHole(ctx, pad, padHoleColor) {
  1724. if (pad.type != "th") return;
  1725. ctx.save();
  1726. ctx.translate(...pad.pos);
  1727. ctx.rotate(-deg2rad(pad.angle));
  1728. ctx.fillStyle = padHoleColor;
  1729. if (pad.drillshape == "oblong") {
  1730. ctx.fill(getOblongPath(pad.drillsize));
  1731. } else if (pad.drillshape == "rect") {
  1732. ctx.fill(getChamferedRectPath(pad.drillsize, 0, 0, 0));
  1733. } else {
  1734. ctx.fill(getCirclePath(pad.drillsize[0] / 2));
  1735. }
  1736. ctx.restore();
  1737. }
  1738. function drawFootprint(ctx, layer, scalefactor, footprint, colors, highlight, outline) {
  1739. if (highlight) {
  1740. // draw bounding box
  1741. if (footprint.layer == layer) {
  1742. ctx.save();
  1743. ctx.globalAlpha = 0.2;
  1744. ctx.translate(...footprint.bbox.pos);
  1745. ctx.rotate(deg2rad(-footprint.bbox.angle));
  1746. ctx.translate(...footprint.bbox.relpos);
  1747. ctx.fillStyle = colors.pad;
  1748. ctx.fillRect(0, 0, ...footprint.bbox.size);
  1749. ctx.globalAlpha = 1;
  1750. ctx.strokeStyle = colors.pad;
  1751. ctx.lineWidth = 3 / scalefactor;
  1752. ctx.strokeRect(0, 0, ...footprint.bbox.size);
  1753. ctx.restore();
  1754. }
  1755. }
  1756. // draw drawings
  1757. for (var drawing of footprint.drawings) {
  1758. if (drawing.layer == layer) {
  1759. drawDrawing(ctx, scalefactor, drawing.drawing, colors.pad);
  1760. }
  1761. }
  1762. ctx.lineWidth = 3 / scalefactor;
  1763. // draw pads
  1764. if (settings.renderPads) {
  1765. for (var pad of footprint.pads) {
  1766. if (pad.layers.includes(layer)) {
  1767. drawPad(ctx, pad, colors.pad, outline);
  1768. if (pad.pin1 &&
  1769. (settings.highlightpin1 == "all" ||
  1770. settings.highlightpin1 == "selected" && highlight)) {
  1771. drawPad(ctx, pad, colors.outline, true);
  1772. }
  1773. }
  1774. }
  1775. for (var pad of footprint.pads) {
  1776. drawPadHole(ctx, pad, colors.padHole);
  1777. }
  1778. }
  1779. }
  1780. function drawEdgeCuts(canvas, scalefactor) {
  1781. var ctx = canvas.getContext("2d");
  1782. var edgecolor = getComputedStyle(topmostdiv).getPropertyValue('--pcb-edge-color');
  1783. for (var edge of pcbdata.edges) {
  1784. drawDrawing(ctx, scalefactor, edge, edgecolor);
  1785. }
  1786. }
  1787. function drawFootprints(canvas, layer, scalefactor, highlight) {
  1788. var ctx = canvas.getContext("2d");
  1789. ctx.lineWidth = 3 / scalefactor;
  1790. var style = getComputedStyle(topmostdiv);
  1791. var colors = {
  1792. pad: style.getPropertyValue('--pad-color'),
  1793. padHole: style.getPropertyValue('--pad-hole-color'),
  1794. outline: style.getPropertyValue('--pin1-outline-color'),
  1795. }
  1796. for (var i = 0; i < pcbdata.footprints.length; i++) {
  1797. var mod = pcbdata.footprints[i];
  1798. var outline = settings.renderDnpOutline && pcbdata.bom.skipped.includes(i);
  1799. var h = highlightedFootprints.includes(i);
  1800. var d = markedFootprints.has(i);
  1801. if (highlight) {
  1802. if(h && d) {
  1803. colors.pad = style.getPropertyValue('--pad-color-highlight-both');
  1804. colors.outline = style.getPropertyValue('--pin1-outline-color-highlight-both');
  1805. } else if (h) {
  1806. colors.pad = style.getPropertyValue('--pad-color-highlight');
  1807. colors.outline = style.getPropertyValue('--pin1-outline-color-highlight');
  1808. } else if (d) {
  1809. colors.pad = style.getPropertyValue('--pad-color-highlight-marked');
  1810. colors.outline = style.getPropertyValue('--pin1-outline-color-highlight-marked');
  1811. }
  1812. }
  1813. if( h || d || !highlight) {
  1814. drawFootprint(ctx, layer, scalefactor, mod, colors, highlight, outline);
  1815. }
  1816. }
  1817. }
  1818. function drawBgLayer(layername, canvas, layer, scalefactor, edgeColor, polygonColor, textColor) {
  1819. var ctx = canvas.getContext("2d");
  1820. for (var d of pcbdata.drawings[layername][layer]) {
  1821. if (["segment", "arc", "circle", "curve", "rect"].includes(d.type)) {
  1822. drawedge(ctx, scalefactor, d, edgeColor);
  1823. } else if (d.type == "polygon") {
  1824. drawPolygonShape(ctx, scalefactor, d, polygonColor);
  1825. } else {
  1826. drawText(ctx, d, textColor);
  1827. }
  1828. }
  1829. }
  1830. function drawTracks(canvas, layer, defaultColor, highlight) {
  1831. ctx = canvas.getContext("2d");
  1832. ctx.lineCap = "round";
  1833. var hasHole = (track) => (
  1834. 'drillsize' in track &&
  1835. track.start[0] == track.end[0] &&
  1836. track.start[1] == track.end[1]);
  1837. // First draw tracks and tented vias
  1838. for (var track of pcbdata.tracks[layer]) {
  1839. if (highlight && highlightedNet != track.net) continue;
  1840. if (!hasHole(track)) {
  1841. ctx.strokeStyle = highlight ? defaultColor : settings.netColors[track.net] || defaultColor;
  1842. ctx.lineWidth = track.width;
  1843. ctx.beginPath();
  1844. if ('radius' in track) {
  1845. ctx.arc(
  1846. ...track.center,
  1847. track.radius,
  1848. deg2rad(track.startangle),
  1849. deg2rad(track.endangle));
  1850. } else {
  1851. ctx.moveTo(...track.start);
  1852. ctx.lineTo(...track.end);
  1853. }
  1854. ctx.stroke();
  1855. }
  1856. }
  1857. // Second pass to draw untented vias
  1858. var style = getComputedStyle(topmostdiv);
  1859. var holeColor = style.getPropertyValue('--pad-hole-color')
  1860. for (var track of pcbdata.tracks[layer]) {
  1861. if (highlight && highlightedNet != track.net) continue;
  1862. if (hasHole(track)) {
  1863. ctx.strokeStyle = highlight ? defaultColor : settings.netColors[track.net] || defaultColor;
  1864. ctx.lineWidth = track.width;
  1865. ctx.beginPath();
  1866. ctx.moveTo(...track.start);
  1867. ctx.lineTo(...track.end);
  1868. ctx.stroke();
  1869. ctx.strokeStyle = holeColor;
  1870. ctx.lineWidth = track.drillsize;
  1871. ctx.lineTo(...track.end);
  1872. ctx.stroke();
  1873. }
  1874. }
  1875. }
  1876. function drawZones(canvas, layer, defaultColor, highlight) {
  1877. ctx = canvas.getContext("2d");
  1878. ctx.lineJoin = "round";
  1879. for (var zone of pcbdata.zones[layer]) {
  1880. if (highlight && highlightedNet != zone.net) continue;
  1881. ctx.strokeStyle = highlight ? defaultColor : settings.netColors[zone.net] || defaultColor;
  1882. ctx.fillStyle = highlight ? defaultColor : settings.netColors[zone.net] || defaultColor;
  1883. if (!zone.path2d) {
  1884. zone.path2d = getPolygonsPath(zone);
  1885. }
  1886. ctx.fill(zone.path2d, zone.fillrule || "nonzero");
  1887. if (zone.width > 0) {
  1888. ctx.lineWidth = zone.width;
  1889. ctx.stroke(zone.path2d);
  1890. }
  1891. }
  1892. }
  1893. function clearCanvas(canvas, color = null) {
  1894. var ctx = canvas.getContext("2d");
  1895. ctx.save();
  1896. ctx.setTransform(1, 0, 0, 1, 0, 0);
  1897. if (color) {
  1898. ctx.fillStyle = color;
  1899. ctx.fillRect(0, 0, canvas.width, canvas.height);
  1900. } else {
  1901. if (!window.matchMedia("print").matches)
  1902. ctx.clearRect(0, 0, canvas.width, canvas.height);
  1903. }
  1904. ctx.restore();
  1905. }
  1906. function drawNets(canvas, layer, highlight) {
  1907. var style = getComputedStyle(topmostdiv);
  1908. if (settings.renderZones) {
  1909. var zoneColor = style.getPropertyValue(highlight ? '--zone-color-highlight' : '--zone-color');
  1910. drawZones(canvas, layer, zoneColor, highlight);
  1911. }
  1912. if (settings.renderTracks) {
  1913. var trackColor = style.getPropertyValue(highlight ? '--track-color-highlight' : '--track-color');
  1914. drawTracks(canvas, layer, trackColor, highlight);
  1915. }
  1916. if (highlight && settings.renderPads) {
  1917. var padColor = style.getPropertyValue('--pad-color-highlight');
  1918. var padHoleColor = style.getPropertyValue('--pad-hole-color');
  1919. var ctx = canvas.getContext("2d");
  1920. for (var footprint of pcbdata.footprints) {
  1921. // draw pads
  1922. var padDrawn = false;
  1923. for (var pad of footprint.pads) {
  1924. if (highlightedNet != pad.net) continue;
  1925. if (pad.layers.includes(layer)) {
  1926. drawPad(ctx, pad, padColor, false);
  1927. padDrawn = true;
  1928. }
  1929. }
  1930. if (padDrawn) {
  1931. // redraw all pad holes because some pads may overlap
  1932. for (var pad of footprint.pads) {
  1933. drawPadHole(ctx, pad, padHoleColor);
  1934. }
  1935. }
  1936. }
  1937. }
  1938. }
  1939. function drawHighlightsOnLayer(canvasdict, clear = true) {
  1940. if (clear) {
  1941. clearCanvas(canvasdict.highlight);
  1942. }
  1943. if (markedFootprints.size > 0 || highlightedFootprints.length > 0) {
  1944. drawFootprints(canvasdict.highlight, canvasdict.layer,
  1945. canvasdict.transform.s * canvasdict.transform.zoom, true);
  1946. }
  1947. if (highlightedNet !== null) {
  1948. drawNets(canvasdict.highlight, canvasdict.layer, true);
  1949. }
  1950. }
  1951. function drawHighlights() {
  1952. drawHighlightsOnLayer(allcanvas.front);
  1953. drawHighlightsOnLayer(allcanvas.back);
  1954. }
  1955. function drawBackground(canvasdict, clear = true) {
  1956. if (clear) {
  1957. clearCanvas(canvasdict.bg);
  1958. clearCanvas(canvasdict.fab);
  1959. clearCanvas(canvasdict.silk);
  1960. }
  1961. drawNets(canvasdict.bg, canvasdict.layer, false);
  1962. drawFootprints(canvasdict.bg, canvasdict.layer,
  1963. canvasdict.transform.s * canvasdict.transform.zoom, false);
  1964. drawEdgeCuts(canvasdict.bg, canvasdict.transform.s * canvasdict.transform.zoom);
  1965. var style = getComputedStyle(topmostdiv);
  1966. var edgeColor = style.getPropertyValue('--silkscreen-edge-color');
  1967. var polygonColor = style.getPropertyValue('--silkscreen-polygon-color');
  1968. var textColor = style.getPropertyValue('--silkscreen-text-color');
  1969. if (settings.renderSilkscreen) {
  1970. drawBgLayer(
  1971. "silkscreen", canvasdict.silk, canvasdict.layer,
  1972. canvasdict.transform.s * canvasdict.transform.zoom,
  1973. edgeColor, polygonColor, textColor);
  1974. }
  1975. edgeColor = style.getPropertyValue('--fabrication-edge-color');
  1976. polygonColor = style.getPropertyValue('--fabrication-polygon-color');
  1977. textColor = style.getPropertyValue('--fabrication-text-color');
  1978. if (settings.renderFabrication) {
  1979. drawBgLayer(
  1980. "fabrication", canvasdict.fab, canvasdict.layer,
  1981. canvasdict.transform.s * canvasdict.transform.zoom,
  1982. edgeColor, polygonColor, textColor);
  1983. }
  1984. }
  1985. function prepareCanvas(canvas, flip, transform) {
  1986. var ctx = canvas.getContext("2d");
  1987. ctx.setTransform(1, 0, 0, 1, 0, 0);
  1988. ctx.scale(transform.zoom, transform.zoom);
  1989. ctx.translate(transform.panx, transform.pany);
  1990. if (flip) {
  1991. ctx.scale(-1, 1);
  1992. }
  1993. ctx.translate(transform.x, transform.y);
  1994. ctx.rotate(deg2rad(settings.boardRotation + (flip && settings.offsetBackRotation ? - 180 : 0)));
  1995. ctx.scale(transform.s, transform.s);
  1996. }
  1997. function prepareLayer(canvasdict) {
  1998. var flip = (canvasdict.layer === "B");
  1999. for (var c of ["bg", "fab", "silk", "highlight"]) {
  2000. prepareCanvas(canvasdict[c], flip, canvasdict.transform);
  2001. }
  2002. }
  2003. function rotateVector(v, angle) {
  2004. angle = deg2rad(angle);
  2005. return [
  2006. v[0] * Math.cos(angle) - v[1] * Math.sin(angle),
  2007. v[0] * Math.sin(angle) + v[1] * Math.cos(angle)
  2008. ];
  2009. }
  2010. function applyRotation(bbox, flip) {
  2011. var corners = [
  2012. [bbox.minx, bbox.miny],
  2013. [bbox.minx, bbox.maxy],
  2014. [bbox.maxx, bbox.miny],
  2015. [bbox.maxx, bbox.maxy],
  2016. ];
  2017. corners = corners.map((v) => rotateVector(v, settings.boardRotation + (flip && settings.offsetBackRotation ? - 180 : 0)));
  2018. return {
  2019. minx: corners.reduce((a, v) => Math.min(a, v[0]), Infinity),
  2020. miny: corners.reduce((a, v) => Math.min(a, v[1]), Infinity),
  2021. maxx: corners.reduce((a, v) => Math.max(a, v[0]), -Infinity),
  2022. maxy: corners.reduce((a, v) => Math.max(a, v[1]), -Infinity),
  2023. }
  2024. }
  2025. function recalcLayerScale(layerdict, width, height) {
  2026. var flip = (layerdict.layer === "B");
  2027. var bbox = applyRotation(pcbdata.edges_bbox, flip);
  2028. var scalefactor = 0.98 * Math.min(
  2029. width / (bbox.maxx - bbox.minx),
  2030. height / (bbox.maxy - bbox.miny)
  2031. );
  2032. if (scalefactor < 0.1) {
  2033. scalefactor = 1;
  2034. }
  2035. layerdict.transform.s = scalefactor;
  2036. if (flip) {
  2037. layerdict.transform.x = -((bbox.maxx + bbox.minx) * scalefactor + width) * 0.5;
  2038. } else {
  2039. layerdict.transform.x = -((bbox.maxx + bbox.minx) * scalefactor - width) * 0.5;
  2040. }
  2041. layerdict.transform.y = -((bbox.maxy + bbox.miny) * scalefactor - height) * 0.5;
  2042. for (var c of ["bg", "fab", "silk", "highlight"]) {
  2043. canvas = layerdict[c];
  2044. canvas.width = width;
  2045. canvas.height = height;
  2046. canvas.style.width = (width / devicePixelRatio) + "px";
  2047. canvas.style.height = (height / devicePixelRatio) + "px";
  2048. }
  2049. }
  2050. function redrawCanvas(layerdict) {
  2051. prepareLayer(layerdict);
  2052. drawBackground(layerdict);
  2053. drawHighlightsOnLayer(layerdict);
  2054. }
  2055. function resizeCanvas(layerdict) {
  2056. var canvasdivid = {
  2057. "F": "frontcanvas",
  2058. "B": "backcanvas"
  2059. } [layerdict.layer];
  2060. var width = document.getElementById(canvasdivid).clientWidth * devicePixelRatio;
  2061. var height = document.getElementById(canvasdivid).clientHeight * devicePixelRatio;
  2062. recalcLayerScale(layerdict, width, height);
  2063. redrawCanvas(layerdict);
  2064. }
  2065. function resizeAll() {
  2066. resizeCanvas(allcanvas.front);
  2067. resizeCanvas(allcanvas.back);
  2068. }
  2069. function pointWithinDistanceToSegment(x, y, x1, y1, x2, y2, d) {
  2070. var A = x - x1;
  2071. var B = y - y1;
  2072. var C = x2 - x1;
  2073. var D = y2 - y1;
  2074. var dot = A * C + B * D;
  2075. var len_sq = C * C + D * D;
  2076. var dx, dy;
  2077. if (len_sq == 0) {
  2078. // start and end of the segment coincide
  2079. dx = x - x1;
  2080. dy = y - y1;
  2081. } else {
  2082. var param = dot / len_sq;
  2083. var xx, yy;
  2084. if (param < 0) {
  2085. xx = x1;
  2086. yy = y1;
  2087. } else if (param > 1) {
  2088. xx = x2;
  2089. yy = y2;
  2090. } else {
  2091. xx = x1 + param * C;
  2092. yy = y1 + param * D;
  2093. }
  2094. dx = x - xx;
  2095. dy = y - yy;
  2096. }
  2097. return dx * dx + dy * dy <= d * d;
  2098. }
  2099. function modulo(n, mod) {
  2100. return ((n % mod) + mod) % mod;
  2101. }
  2102. function pointWithinDistanceToArc(x, y, xc, yc, radius, startangle, endangle, d) {
  2103. var dx = x - xc;
  2104. var dy = y - yc;
  2105. var r_sq = dx * dx + dy * dy;
  2106. var rmin = Math.max(0, radius - d);
  2107. var rmax = radius + d;
  2108. if (r_sq < rmin * rmin || r_sq > rmax * rmax)
  2109. return false;
  2110. var angle1 = modulo(deg2rad(startangle), 2 * Math.PI);
  2111. var dx1 = xc + radius * Math.cos(angle1) - x;
  2112. var dy1 = yc + radius * Math.sin(angle1) - y;
  2113. if (dx1 * dx1 + dy1 * dy1 <= d * d)
  2114. return true;
  2115. var angle2 = modulo(deg2rad(endangle), 2 * Math.PI);
  2116. var dx2 = xc + radius * Math.cos(angle2) - x;
  2117. var dy2 = yc + radius * Math.sin(angle2) - y;
  2118. if (dx2 * dx2 + dy2 * dy2 <= d * d)
  2119. return true;
  2120. var angle = modulo(Math.atan2(dy, dx), 2 * Math.PI);
  2121. if (angle1 > angle2)
  2122. return (angle >= angle2 || angle <= angle1);
  2123. else
  2124. return (angle >= angle1 && angle <= angle2);
  2125. }
  2126. function pointWithinPad(x, y, pad) {
  2127. var v = [x - pad.pos[0], y - pad.pos[1]];
  2128. v = rotateVector(v, pad.angle);
  2129. if (pad.offset) {
  2130. v[0] -= pad.offset[0];
  2131. v[1] -= pad.offset[1];
  2132. }
  2133. return emptyContext2d.isPointInPath(getCachedPadPath(pad), ...v);
  2134. }
  2135. function netHitScan(layer, x, y) {
  2136. // Check track segments
  2137. if (settings.renderTracks && pcbdata.tracks) {
  2138. for (var track of pcbdata.tracks[layer]) {
  2139. if ('radius' in track) {
  2140. if (pointWithinDistanceToArc(x, y, ...track.center, track.radius, track.startangle, track.endangle, track.width / 2)) {
  2141. return track.net;
  2142. }
  2143. } else {
  2144. if (pointWithinDistanceToSegment(x, y, ...track.start, ...track.end, track.width / 2)) {
  2145. return track.net;
  2146. }
  2147. }
  2148. }
  2149. }
  2150. // Check pads
  2151. if (settings.renderPads) {
  2152. for (var footprint of pcbdata.footprints) {
  2153. for (var pad of footprint.pads) {
  2154. if (pad.layers.includes(layer) && pointWithinPad(x, y, pad)) {
  2155. return pad.net;
  2156. }
  2157. }
  2158. }
  2159. }
  2160. return null;
  2161. }
  2162. function pointWithinFootprintBbox(x, y, bbox) {
  2163. var v = [x - bbox.pos[0], y - bbox.pos[1]];
  2164. v = rotateVector(v, bbox.angle);
  2165. return bbox.relpos[0] <= v[0] && v[0] <= bbox.relpos[0] + bbox.size[0] &&
  2166. bbox.relpos[1] <= v[1] && v[1] <= bbox.relpos[1] + bbox.size[1];
  2167. }
  2168. function bboxHitScan(layer, x, y) {
  2169. var result = [];
  2170. for (var i = 0; i < pcbdata.footprints.length; i++) {
  2171. var footprint = pcbdata.footprints[i];
  2172. if (footprint.layer == layer) {
  2173. if (pointWithinFootprintBbox(x, y, footprint.bbox)) {
  2174. result.push(i);
  2175. }
  2176. }
  2177. }
  2178. return result;
  2179. }
  2180. function handlePointerDown(e, layerdict) {
  2181. if (e.button != 0 && e.button != 1) {
  2182. return;
  2183. }
  2184. e.preventDefault();
  2185. e.stopPropagation();
  2186. if (!e.hasOwnProperty("offsetX")) {
  2187. // The polyfill doesn't set this properly
  2188. e.offsetX = e.pageX - e.currentTarget.offsetLeft;
  2189. e.offsetY = e.pageY - e.currentTarget.offsetTop;
  2190. }
  2191. layerdict.pointerStates[e.pointerId] = {
  2192. distanceTravelled: 0,
  2193. lastX: e.offsetX,
  2194. lastY: e.offsetY,
  2195. downTime: Date.now(),
  2196. };
  2197. }
  2198. function handleMouseClick(e, layerdict) {
  2199. if (!e.hasOwnProperty("offsetX")) {
  2200. // The polyfill doesn't set this properly
  2201. e.offsetX = e.pageX - e.currentTarget.offsetLeft;
  2202. e.offsetY = e.pageY - e.currentTarget.offsetTop;
  2203. }
  2204. var x = e.offsetX;
  2205. var y = e.offsetY;
  2206. var t = layerdict.transform;
  2207. var flip = layerdict.layer === "B";
  2208. if (flip) {
  2209. x = (devicePixelRatio * x / t.zoom - t.panx + t.x) / -t.s;
  2210. } else {
  2211. x = (devicePixelRatio * x / t.zoom - t.panx - t.x) / t.s;
  2212. }
  2213. y = (devicePixelRatio * y / t.zoom - t.y - t.pany) / t.s;
  2214. var v = rotateVector([x, y], -settings.boardRotation + (flip && settings.offsetBackRotation ? - 180 : 0));
  2215. if ("nets" in pcbdata) {
  2216. var net = netHitScan(layerdict.layer, ...v);
  2217. if (net !== highlightedNet) {
  2218. netClicked(net);
  2219. }
  2220. }
  2221. if (highlightedNet === null) {
  2222. var footprints = bboxHitScan(layerdict.layer, ...v);
  2223. if (footprints.length > 0) {
  2224. footprintsClicked(footprints);
  2225. }
  2226. }
  2227. }
  2228. function handlePointerLeave(e, layerdict) {
  2229. e.preventDefault();
  2230. e.stopPropagation();
  2231. if (!settings.redrawOnDrag) {
  2232. redrawCanvas(layerdict);
  2233. }
  2234. delete layerdict.pointerStates[e.pointerId];
  2235. }
  2236. function resetTransform(layerdict) {
  2237. layerdict.transform.panx = 0;
  2238. layerdict.transform.pany = 0;
  2239. layerdict.transform.zoom = 1;
  2240. redrawCanvas(layerdict);
  2241. }
  2242. function handlePointerUp(e, layerdict) {
  2243. if (!e.hasOwnProperty("offsetX")) {
  2244. // The polyfill doesn't set this properly
  2245. e.offsetX = e.pageX - e.currentTarget.offsetLeft;
  2246. e.offsetY = e.pageY - e.currentTarget.offsetTop;
  2247. }
  2248. e.preventDefault();
  2249. e.stopPropagation();
  2250. if (e.button == 2) {
  2251. // Reset pan and zoom on right click.
  2252. resetTransform(layerdict);
  2253. layerdict.anotherPointerTapped = false;
  2254. return;
  2255. }
  2256. // We haven't necessarily had a pointermove event since the interaction started, so make sure we update this now
  2257. var ptr = layerdict.pointerStates[e.pointerId];
  2258. ptr.distanceTravelled += Math.abs(e.offsetX - ptr.lastX) + Math.abs(e.offsetY - ptr.lastY);
  2259. if (e.button == 0 && ptr.distanceTravelled < 10 && Date.now() - ptr.downTime <= 500) {
  2260. if (Object.keys(layerdict.pointerStates).length == 1) {
  2261. if (layerdict.anotherPointerTapped) {
  2262. // This is the second pointer coming off of a two-finger tap
  2263. resetTransform(layerdict);
  2264. } else {
  2265. // This is just a regular tap
  2266. handleMouseClick(e, layerdict);
  2267. }
  2268. layerdict.anotherPointerTapped = false;
  2269. } else {
  2270. // This is the first finger coming off of what could become a two-finger tap
  2271. layerdict.anotherPointerTapped = true;
  2272. }
  2273. } else {
  2274. if (!settings.redrawOnDrag) {
  2275. redrawCanvas(layerdict);
  2276. }
  2277. layerdict.anotherPointerTapped = false;
  2278. }
  2279. delete layerdict.pointerStates[e.pointerId];
  2280. }
  2281. function handlePointerMove(e, layerdict) {
  2282. if (!layerdict.pointerStates.hasOwnProperty(e.pointerId)) {
  2283. return;
  2284. }
  2285. e.preventDefault();
  2286. e.stopPropagation();
  2287. if (!e.hasOwnProperty("offsetX")) {
  2288. // The polyfill doesn't set this properly
  2289. e.offsetX = e.pageX - e.currentTarget.offsetLeft;
  2290. e.offsetY = e.pageY - e.currentTarget.offsetTop;
  2291. }
  2292. var thisPtr = layerdict.pointerStates[e.pointerId];
  2293. var dx = e.offsetX - thisPtr.lastX;
  2294. var dy = e.offsetY - thisPtr.lastY;
  2295. // If this number is low on pointer up, we count the action as a click
  2296. thisPtr.distanceTravelled += Math.abs(dx) + Math.abs(dy);
  2297. if (Object.keys(layerdict.pointerStates).length == 1) {
  2298. // This is a simple drag
  2299. layerdict.transform.panx += devicePixelRatio * dx / layerdict.transform.zoom;
  2300. layerdict.transform.pany += devicePixelRatio * dy / layerdict.transform.zoom;
  2301. } else if (Object.keys(layerdict.pointerStates).length == 2) {
  2302. var otherPtr = Object.values(layerdict.pointerStates).filter((ptr) => ptr != thisPtr)[0];
  2303. var oldDist = Math.sqrt(Math.pow(thisPtr.lastX - otherPtr.lastX, 2) + Math.pow(thisPtr.lastY - otherPtr.lastY, 2));
  2304. var newDist = Math.sqrt(Math.pow(e.offsetX - otherPtr.lastX, 2) + Math.pow(e.offsetY - otherPtr.lastY, 2));
  2305. var scaleFactor = newDist / oldDist;
  2306. if (scaleFactor != NaN) {
  2307. layerdict.transform.zoom *= scaleFactor;
  2308. var zoomd = (1 - scaleFactor) / layerdict.transform.zoom;
  2309. layerdict.transform.panx += devicePixelRatio * otherPtr.lastX * zoomd;
  2310. layerdict.transform.pany += devicePixelRatio * otherPtr.lastY * zoomd;
  2311. }
  2312. }
  2313. thisPtr.lastX = e.offsetX;
  2314. thisPtr.lastY = e.offsetY;
  2315. if (settings.redrawOnDrag) {
  2316. redrawCanvas(layerdict);
  2317. }
  2318. }
  2319. function handleMouseWheel(e, layerdict) {
  2320. e.preventDefault();
  2321. e.stopPropagation();
  2322. var t = layerdict.transform;
  2323. var wheeldelta = e.deltaY;
  2324. if (e.deltaMode == 1) {
  2325. // FF only, scroll by lines
  2326. wheeldelta *= 30;
  2327. } else if (e.deltaMode == 2) {
  2328. wheeldelta *= 300;
  2329. }
  2330. var m = Math.pow(1.1, -wheeldelta / 40);
  2331. // Limit amount of zoom per tick.
  2332. if (m > 2) {
  2333. m = 2;
  2334. } else if (m < 0.5) {
  2335. m = 0.5;
  2336. }
  2337. t.zoom *= m;
  2338. var zoomd = (1 - m) / t.zoom;
  2339. t.panx += devicePixelRatio * e.offsetX * zoomd;
  2340. t.pany += devicePixelRatio * e.offsetY * zoomd;
  2341. redrawCanvas(layerdict);
  2342. }
  2343. function addMouseHandlers(div, layerdict) {
  2344. div.addEventListener("pointerdown", function(e) {
  2345. handlePointerDown(e, layerdict);
  2346. });
  2347. div.addEventListener("pointermove", function(e) {
  2348. handlePointerMove(e, layerdict);
  2349. });
  2350. div.addEventListener("pointerup", function(e) {
  2351. handlePointerUp(e, layerdict);
  2352. });
  2353. var pointerleave = function(e) {
  2354. handlePointerLeave(e, layerdict);
  2355. }
  2356. div.addEventListener("pointercancel", pointerleave);
  2357. div.addEventListener("pointerleave", pointerleave);
  2358. div.addEventListener("pointerout", pointerleave);
  2359. div.onwheel = function(e) {
  2360. handleMouseWheel(e, layerdict);
  2361. }
  2362. for (var element of [div, layerdict.bg, layerdict.fab, layerdict.silk, layerdict.highlight]) {
  2363. element.addEventListener("contextmenu", function(e) {
  2364. e.preventDefault();
  2365. }, false);
  2366. }
  2367. }
  2368. function setRedrawOnDrag(value) {
  2369. settings.redrawOnDrag = value;
  2370. writeStorage("redrawOnDrag", value);
  2371. }
  2372. function setBoardRotation(value) {
  2373. settings.boardRotation = value * 5;
  2374. writeStorage("boardRotation", settings.boardRotation);
  2375. document.getElementById("rotationDegree").textContent = settings.boardRotation;
  2376. resizeAll();
  2377. }
  2378. function setOffsetBackRotation(value) {
  2379. settings.offsetBackRotation = value;
  2380. writeStorage("offsetBackRotation", value);
  2381. resizeAll();
  2382. }
  2383. function initRender() {
  2384. allcanvas = {
  2385. front: {
  2386. transform: {
  2387. x: 0,
  2388. y: 0,
  2389. s: 1,
  2390. panx: 0,
  2391. pany: 0,
  2392. zoom: 1,
  2393. },
  2394. pointerStates: {},
  2395. anotherPointerTapped: false,
  2396. bg: document.getElementById("F_bg"),
  2397. fab: document.getElementById("F_fab"),
  2398. silk: document.getElementById("F_slk"),
  2399. highlight: document.getElementById("F_hl"),
  2400. layer: "F",
  2401. },
  2402. back: {
  2403. transform: {
  2404. x: 0,
  2405. y: 0,
  2406. s: 1,
  2407. panx: 0,
  2408. pany: 0,
  2409. zoom: 1,
  2410. },
  2411. pointerStates: {},
  2412. anotherPointerTapped: false,
  2413. bg: document.getElementById("B_bg"),
  2414. fab: document.getElementById("B_fab"),
  2415. silk: document.getElementById("B_slk"),
  2416. highlight: document.getElementById("B_hl"),
  2417. layer: "B",
  2418. }
  2419. };
  2420. addMouseHandlers(document.getElementById("frontcanvas"), allcanvas.front);
  2421. addMouseHandlers(document.getElementById("backcanvas"), allcanvas.back);
  2422. }
  2423. ///////////////////////////////////////////////
  2424. ///////////////////////////////////////////////
  2425. /*
  2426. * Table reordering via Drag'n'Drop
  2427. * Inspired by: https://htmldom.dev/drag-and-drop-table-column
  2428. */
  2429. function setBomHandlers() {
  2430. const bom = document.getElementById('bomtable');
  2431. let dragName;
  2432. let placeHolderElements;
  2433. let draggingElement;
  2434. let forcePopulation;
  2435. let xOffset;
  2436. let yOffset;
  2437. let wasDragged;
  2438. const mouseUpHandler = function(e) {
  2439. // Delete dragging element
  2440. draggingElement.remove();
  2441. // Make BOM selectable again
  2442. bom.style.removeProperty("userSelect");
  2443. // Remove listeners
  2444. document.removeEventListener('mousemove', mouseMoveHandler);
  2445. document.removeEventListener('mouseup', mouseUpHandler);
  2446. if (wasDragged) {
  2447. // Redraw whole BOM
  2448. populateBomTable();
  2449. }
  2450. }
  2451. const mouseMoveHandler = function(e) {
  2452. // Notice the dragging
  2453. wasDragged = true;
  2454. // Make the dragged element visible
  2455. draggingElement.style.removeProperty("display");
  2456. // Set elements position to mouse position
  2457. draggingElement.style.left = `${e.screenX - xOffset}px`;
  2458. draggingElement.style.top = `${e.screenY - yOffset}px`;
  2459. // Forced redrawing of BOM table
  2460. if (forcePopulation) {
  2461. forcePopulation = false;
  2462. // Copy array
  2463. phe = Array.from(placeHolderElements);
  2464. // populate BOM table again
  2465. populateBomHeader(dragName, phe);
  2466. populateBomBody(dragName, phe);
  2467. }
  2468. // Set up array of hidden columns
  2469. var hiddenColumns = Array.from(settings.hiddenColumns);
  2470. // In the ungrouped mode, quantity don't exist
  2471. if (settings.bommode === "ungrouped")
  2472. hiddenColumns.push("Quantity");
  2473. // If no checkbox fields can be found, we consider them hidden
  2474. if (settings.checkboxes.length == 0)
  2475. hiddenColumns.push("checkboxes");
  2476. // Get table headers and group them into checkboxes, extrafields and normal headers
  2477. const bh = document.getElementById("bomhead");
  2478. headers = Array.from(bh.querySelectorAll("th"))
  2479. headers.shift() // numCol is not part of the columnOrder
  2480. headerGroups = []
  2481. lastCompoundClass = null;
  2482. for (i = 0; i < settings.columnOrder.length; i++) {
  2483. cElem = settings.columnOrder[i];
  2484. if (hiddenColumns.includes(cElem)) {
  2485. // Hidden columns appear as a dummy element
  2486. headerGroups.push([]);
  2487. continue;
  2488. }
  2489. elem = headers.filter(e => getColumnOrderName(e) === cElem)[0];
  2490. if (elem.classList.contains("bom-checkbox")) {
  2491. if (lastCompoundClass === "bom-checkbox") {
  2492. cbGroup = headerGroups.pop();
  2493. cbGroup.push(elem);
  2494. headerGroups.push(cbGroup);
  2495. } else {
  2496. lastCompoundClass = "bom-checkbox";
  2497. headerGroups.push([elem])
  2498. }
  2499. } else {
  2500. headerGroups.push([elem])
  2501. }
  2502. }
  2503. // Copy settings.columnOrder
  2504. var columns = Array.from(settings.columnOrder)
  2505. // Set up array with indices of hidden columns
  2506. var hiddenIndices = hiddenColumns.map(e => settings.columnOrder.indexOf(e));
  2507. var dragIndex = columns.indexOf(dragName);
  2508. var swapIndex = dragIndex;
  2509. var swapDone = false;
  2510. // Check if the current dragged element is swapable with the left or right element
  2511. if (dragIndex > 0) {
  2512. // Get left headers boundingbox
  2513. swapIndex = dragIndex - 1;
  2514. while (hiddenIndices.includes(swapIndex) && swapIndex > 0)
  2515. swapIndex--;
  2516. if (!hiddenIndices.includes(swapIndex)) {
  2517. box = getBoundingClientRectFromMultiple(headerGroups[swapIndex]);
  2518. if (e.clientX < box.left + window.scrollX + (box.width / 2)) {
  2519. swapElement = columns[dragIndex];
  2520. columns.splice(dragIndex, 1);
  2521. columns.splice(swapIndex, 0, swapElement);
  2522. forcePopulation = true;
  2523. swapDone = true;
  2524. }
  2525. }
  2526. }
  2527. if ((!swapDone) && dragIndex < headerGroups.length - 1) {
  2528. // Get right headers boundingbox
  2529. swapIndex = dragIndex + 1;
  2530. while (hiddenIndices.includes(swapIndex))
  2531. swapIndex++;
  2532. if (swapIndex < headerGroups.length) {
  2533. box = getBoundingClientRectFromMultiple(headerGroups[swapIndex]);
  2534. if (e.clientX > box.left + window.scrollX + (box.width / 2)) {
  2535. swapElement = columns[dragIndex];
  2536. columns.splice(dragIndex, 1);
  2537. columns.splice(swapIndex, 0, swapElement);
  2538. forcePopulation = true;
  2539. swapDone = true;
  2540. }
  2541. }
  2542. }
  2543. // Write back change to storage
  2544. if (swapDone) {
  2545. settings.columnOrder = columns
  2546. writeStorage("columnOrder", JSON.stringify(columns));
  2547. }
  2548. }
  2549. const mouseDownHandler = function(e) {
  2550. var target = e.target;
  2551. if (target.tagName.toLowerCase() != "td")
  2552. target = target.parentElement;
  2553. // Used to check if a dragging has ever happened
  2554. wasDragged = false;
  2555. // Create new element which will be displayed as the dragged column
  2556. draggingElement = document.createElement("div")
  2557. draggingElement.classList.add("dragging");
  2558. draggingElement.style.display = "none";
  2559. draggingElement.style.position = "absolute";
  2560. draggingElement.style.overflow = "hidden";
  2561. // Get bomhead and bombody elements
  2562. const bh = document.getElementById("bomhead");
  2563. const bb = document.getElementById("bombody");
  2564. // Get all compound headers for the current column
  2565. var compoundHeaders;
  2566. if (target.classList.contains("bom-checkbox")) {
  2567. compoundHeaders = Array.from(bh.querySelectorAll("th.bom-checkbox"));
  2568. } else {
  2569. compoundHeaders = [target];
  2570. }
  2571. // Create new table which will display the column
  2572. var newTable = document.createElement("table");
  2573. newTable.classList.add("bom");
  2574. newTable.style.background = "white";
  2575. draggingElement.append(newTable);
  2576. // Create new header element
  2577. var newHeader = document.createElement("thead");
  2578. newTable.append(newHeader);
  2579. // Set up array for storing all placeholder elements
  2580. placeHolderElements = [];
  2581. // Add all compound headers to the new thead element and placeholders
  2582. compoundHeaders.forEach(function(h) {
  2583. clone = cloneElementWithDimensions(h);
  2584. newHeader.append(clone);
  2585. placeHolderElements.push(clone);
  2586. });
  2587. // Create new body element
  2588. var newBody = document.createElement("tbody");
  2589. newTable.append(newBody);
  2590. // Get indices for compound headers
  2591. var idxs = compoundHeaders.map(e => getBomTableHeaderIndex(e));
  2592. // For each row in the BOM body...
  2593. var rows = bb.querySelectorAll("tr");
  2594. rows.forEach(function(row) {
  2595. // ..get the cells for the compound column
  2596. const tds = row.querySelectorAll("td");
  2597. var copytds = idxs.map(i => tds[i]);
  2598. // Add them to the new element and the placeholders
  2599. var newRow = document.createElement("tr");
  2600. copytds.forEach(function(td) {
  2601. clone = cloneElementWithDimensions(td);
  2602. newRow.append(clone);
  2603. placeHolderElements.push(clone);
  2604. });
  2605. newBody.append(newRow);
  2606. });
  2607. // Compute width for compound header
  2608. var width = compoundHeaders.reduce((acc, x) => acc + x.clientWidth, 0);
  2609. draggingElement.style.width = `${width}px`;
  2610. // Insert the new dragging element and disable selection on BOM
  2611. bom.insertBefore(draggingElement, null);
  2612. bom.style.userSelect = "none";
  2613. // Determine the mouse position offset
  2614. xOffset = e.screenX - compoundHeaders.reduce((acc, x) => Math.min(acc, x.offsetLeft), compoundHeaders[0].offsetLeft);
  2615. yOffset = e.screenY - compoundHeaders[0].offsetTop;
  2616. // Get name for the column in settings.columnOrder
  2617. dragName = getColumnOrderName(target);
  2618. // Change text and class for placeholder elements
  2619. placeHolderElements = placeHolderElements.map(function(e) {
  2620. newElem = cloneElementWithDimensions(e);
  2621. newElem.textContent = "";
  2622. newElem.classList.add("placeholder");
  2623. return newElem;
  2624. });
  2625. // On next mouse move, the whole BOM needs to be redrawn to show the placeholders
  2626. forcePopulation = true;
  2627. // Add listeners for move and up on mouse
  2628. document.addEventListener('mousemove', mouseMoveHandler);
  2629. document.addEventListener('mouseup', mouseUpHandler);
  2630. }
  2631. // In netlist mode, there is nothing to reorder
  2632. if (settings.bommode === "netlist")
  2633. return;
  2634. // Add mouseDownHandler to every column except the numCol
  2635. bom.querySelectorAll("th")
  2636. .forEach(function(head) {
  2637. if (!head.classList.contains("numCol")) {
  2638. head.onmousedown = mouseDownHandler;
  2639. }
  2640. });
  2641. }
  2642. function getBoundingClientRectFromMultiple(elements) {
  2643. var elems = Array.from(elements);
  2644. if (elems.length == 0)
  2645. return null;
  2646. var box = elems.shift()
  2647. .getBoundingClientRect();
  2648. elems.forEach(function(elem) {
  2649. var elembox = elem.getBoundingClientRect();
  2650. box.left = Math.min(elembox.left, box.left);
  2651. box.top = Math.min(elembox.top, box.top);
  2652. box.width += elembox.width;
  2653. box.height = Math.max(elembox.height, box.height);
  2654. });
  2655. return box;
  2656. }
  2657. function cloneElementWithDimensions(elem) {
  2658. var newElem = elem.cloneNode(true);
  2659. newElem.style.height = window.getComputedStyle(elem).height;
  2660. newElem.style.width = window.getComputedStyle(elem).width;
  2661. return newElem;
  2662. }
  2663. function getBomTableHeaderIndex(elem) {
  2664. const bh = document.getElementById('bomhead');
  2665. const ths = Array.from(bh.querySelectorAll("th"));
  2666. return ths.indexOf(elem);
  2667. }
  2668. function getColumnOrderName(elem) {
  2669. var cname = elem.getAttribute("col_name");
  2670. if (cname === "bom-checkbox")
  2671. return "checkboxes";
  2672. else
  2673. return cname;
  2674. }
  2675. function resizableGrid(tablehead) {
  2676. var cols = tablehead.firstElementChild.children;
  2677. var rowWidth = tablehead.offsetWidth;
  2678. for (var i = 1; i < cols.length; i++) {
  2679. if (cols[i].classList.contains("bom-checkbox"))
  2680. continue;
  2681. cols[i].style.width = ((cols[i].clientWidth - paddingDiff(cols[i])) * 100 / rowWidth) + '%';
  2682. }
  2683. for (var i = 1; i < cols.length - 1; i++) {
  2684. var div = document.createElement('div');
  2685. div.className = "column-width-handle";
  2686. cols[i].appendChild(div);
  2687. setListeners(div);
  2688. }
  2689. function setListeners(div) {
  2690. var startX, curCol, nxtCol, curColWidth, nxtColWidth, rowWidth;
  2691. div.addEventListener('mousedown', function(e) {
  2692. e.preventDefault();
  2693. e.stopPropagation();
  2694. curCol = e.target.parentElement;
  2695. nxtCol = curCol.nextElementSibling;
  2696. startX = e.pageX;
  2697. var padding = paddingDiff(curCol);
  2698. rowWidth = curCol.parentElement.offsetWidth;
  2699. curColWidth = curCol.clientWidth - padding;
  2700. nxtColWidth = nxtCol.clientWidth - padding;
  2701. });
  2702. document.addEventListener('mousemove', function(e) {
  2703. if (startX) {
  2704. var diffX = e.pageX - startX;
  2705. diffX = -Math.min(-diffX, curColWidth - 20);
  2706. diffX = Math.min(diffX, nxtColWidth - 20);
  2707. curCol.style.width = ((curColWidth + diffX) * 100 / rowWidth) + '%';
  2708. nxtCol.style.width = ((nxtColWidth - diffX) * 100 / rowWidth) + '%';
  2709. console.log(`${curColWidth + nxtColWidth} ${(curColWidth + diffX) * 100 / rowWidth + (nxtColWidth - diffX) * 100 / rowWidth}`);
  2710. }
  2711. });
  2712. document.addEventListener('mouseup', function(e) {
  2713. curCol = undefined;
  2714. nxtCol = undefined;
  2715. startX = undefined;
  2716. nxtColWidth = undefined;
  2717. curColWidth = undefined
  2718. });
  2719. }
  2720. function paddingDiff(col) {
  2721. if (getStyleVal(col, 'box-sizing') == 'border-box') {
  2722. return 0;
  2723. }
  2724. var padLeft = getStyleVal(col, 'padding-left');
  2725. var padRight = getStyleVal(col, 'padding-right');
  2726. return (parseInt(padLeft) + parseInt(padRight));
  2727. }
  2728. function getStyleVal(elm, css) {
  2729. return (window.getComputedStyle(elm, null).getPropertyValue(css))
  2730. }
  2731. }
  2732. ///////////////////////////////////////////////
  2733. ///////////////////////////////////////////////
  2734. /* DOM manipulation and misc code */
  2735. var bomsplit;
  2736. var canvassplit;
  2737. var initDone = false;
  2738. var bomSortFunction = null;
  2739. var currentSortColumn = null;
  2740. var currentSortOrder = null;
  2741. var currentHighlightedRowId;
  2742. var highlightHandlers = [];
  2743. var footprintIndexToHandler = {};
  2744. var netsToHandler = {};
  2745. var markedFootprints = new Set();
  2746. var highlightedFootprints = [];
  2747. var highlightedNet = null;
  2748. var lastClicked;
  2749. function dbg(html) {
  2750. dbgdiv.innerHTML = html;
  2751. }
  2752. function redrawIfInitDone() {
  2753. if (initDone) {
  2754. redrawCanvas(allcanvas.front);
  2755. redrawCanvas(allcanvas.back);
  2756. }
  2757. }
  2758. function padsVisible(value) {
  2759. writeStorage("padsVisible", value);
  2760. settings.renderPads = value;
  2761. redrawIfInitDone();
  2762. }
  2763. function referencesVisible(value) {
  2764. writeStorage("referencesVisible", value);
  2765. settings.renderReferences = value;
  2766. redrawIfInitDone();
  2767. }
  2768. function valuesVisible(value) {
  2769. writeStorage("valuesVisible", value);
  2770. settings.renderValues = value;
  2771. redrawIfInitDone();
  2772. }
  2773. function tracksVisible(value) {
  2774. writeStorage("tracksVisible", value);
  2775. settings.renderTracks = value;
  2776. redrawIfInitDone();
  2777. }
  2778. function zonesVisible(value) {
  2779. writeStorage("zonesVisible", value);
  2780. settings.renderZones = value;
  2781. redrawIfInitDone();
  2782. }
  2783. function dnpOutline(value) {
  2784. writeStorage("dnpOutline", value);
  2785. settings.renderDnpOutline = value;
  2786. redrawIfInitDone();
  2787. }
  2788. function setDarkMode(value) {
  2789. if (value) {
  2790. topmostdiv.classList.add("dark");
  2791. } else {
  2792. topmostdiv.classList.remove("dark");
  2793. }
  2794. writeStorage("darkmode", value);
  2795. settings.darkMode = value;
  2796. redrawIfInitDone();
  2797. if (initDone) {
  2798. populateBomTable();
  2799. }
  2800. }
  2801. function setShowBOMColumn(field, value) {
  2802. if (field === "references") {
  2803. var rl = document.getElementById("reflookup");
  2804. rl.disabled = !value;
  2805. if (!value) {
  2806. rl.value = "";
  2807. updateRefLookup("");
  2808. }
  2809. }
  2810. var n = settings.hiddenColumns.indexOf(field);
  2811. if (value) {
  2812. if (n != -1) {
  2813. settings.hiddenColumns.splice(n, 1);
  2814. }
  2815. } else {
  2816. if (n == -1) {
  2817. settings.hiddenColumns.push(field);
  2818. }
  2819. }
  2820. writeStorage("hiddenColumns", JSON.stringify(settings.hiddenColumns));
  2821. if (initDone) {
  2822. populateBomTable();
  2823. }
  2824. redrawIfInitDone();
  2825. }
  2826. function setFullscreen(value) {
  2827. if (value) {
  2828. document.documentElement.requestFullscreen();
  2829. } else {
  2830. document.exitFullscreen();
  2831. }
  2832. }
  2833. function fabricationVisible(value) {
  2834. writeStorage("fabricationVisible", value);
  2835. settings.renderFabrication = value;
  2836. redrawIfInitDone();
  2837. }
  2838. function silkscreenVisible(value) {
  2839. writeStorage("silkscreenVisible", value);
  2840. settings.renderSilkscreen = value;
  2841. redrawIfInitDone();
  2842. }
  2843. function setHighlightPin1(value) {
  2844. writeStorage("highlightpin1", value);
  2845. settings.highlightpin1 = value;
  2846. redrawIfInitDone();
  2847. }
  2848. function setHighlightRowOnClick(value) {
  2849. settings.highlightRowOnClick = value;
  2850. writeStorage("highlightRowOnClick", value);
  2851. if (initDone) {
  2852. populateBomTable();
  2853. }
  2854. }
  2855. function getStoredCheckboxRefs(checkbox) {
  2856. function convert(ref) {
  2857. var intref = parseInt(ref);
  2858. if (isNaN(intref)) {
  2859. for (var i = 0; i < pcbdata.footprints.length; i++) {
  2860. if (pcbdata.footprints[i].ref == ref) {
  2861. return i;
  2862. }
  2863. }
  2864. return -1;
  2865. } else {
  2866. return intref;
  2867. }
  2868. }
  2869. if (!(checkbox in settings.checkboxStoredRefs)) {
  2870. var val = readStorage("checkbox_" + checkbox);
  2871. settings.checkboxStoredRefs[checkbox] = val ? val : "";
  2872. }
  2873. if (!settings.checkboxStoredRefs[checkbox]) {
  2874. return new Set();
  2875. } else {
  2876. return new Set(settings.checkboxStoredRefs[checkbox].split(",").map(r => convert(r)).filter(a => a >= 0));
  2877. }
  2878. }
  2879. function getCheckboxState(checkbox, references) {
  2880. var storedRefsSet = getStoredCheckboxRefs(checkbox);
  2881. var currentRefsSet = new Set(references.map(r => r[1]));
  2882. // Get difference of current - stored
  2883. var difference = new Set(currentRefsSet);
  2884. for (ref of storedRefsSet) {
  2885. difference.delete(ref);
  2886. }
  2887. if (difference.size == 0) {
  2888. // All the current refs are stored
  2889. return "checked";
  2890. } else if (difference.size == currentRefsSet.size) {
  2891. // None of the current refs are stored
  2892. return "unchecked";
  2893. } else {
  2894. // Some of the refs are stored
  2895. return "indeterminate";
  2896. }
  2897. }
  2898. function setBomCheckboxState(checkbox, element, references) {
  2899. var state = getCheckboxState(checkbox, references);
  2900. element.checked = (state == "checked");
  2901. element.indeterminate = (state == "indeterminate");
  2902. }
  2903. function createCheckboxHandlers(input, checkbox, references, row) {
  2904. var clickHandler = () => {
  2905. refsSet = getStoredCheckboxRefs(checkbox);
  2906. var markWhenChecked = settings.markWhenChecked == checkbox;
  2907. eventArgs = {
  2908. checkbox: checkbox,
  2909. refs: references,
  2910. }
  2911. if (input.checked) {
  2912. // checkbox ticked
  2913. for (var ref of references) {
  2914. refsSet.add(ref[1]);
  2915. }
  2916. if (markWhenChecked) {
  2917. row.classList.add("checked");
  2918. for (var ref of references) {
  2919. markedFootprints.add(ref[1]);
  2920. }
  2921. drawHighlights();
  2922. }
  2923. eventArgs.state = 'checked';
  2924. } else {
  2925. // checkbox unticked
  2926. for (var ref of references) {
  2927. refsSet.delete(ref[1]);
  2928. }
  2929. if (markWhenChecked) {
  2930. row.classList.remove("checked");
  2931. for (var ref of references) {
  2932. markedFootprints.delete(ref[1]);
  2933. }
  2934. drawHighlights();
  2935. }
  2936. eventArgs.state = 'unchecked';
  2937. }
  2938. settings.checkboxStoredRefs[checkbox] = [...refsSet].join(",");
  2939. writeStorage("checkbox_" + checkbox, settings.checkboxStoredRefs[checkbox]);
  2940. updateCheckboxStats(checkbox);
  2941. EventHandler.emitEvent(IBOM_EVENT_TYPES.CHECKBOX_CHANGE_EVENT, eventArgs);
  2942. }
  2943. return [
  2944. (e) => {
  2945. clickHandler();
  2946. },
  2947. (e) => {
  2948. e.preventDefault();
  2949. if (row.onmousemove) row.onmousemove();
  2950. },
  2951. (e) => {
  2952. e.preventDefault();
  2953. input.checked = !input.checked;
  2954. input.indeterminate = false;
  2955. clickHandler();
  2956. }
  2957. ];
  2958. }
  2959. function clearHighlightedFootprints() {
  2960. if (currentHighlightedRowId) {
  2961. document.getElementById(currentHighlightedRowId).classList.remove("highlighted");
  2962. currentHighlightedRowId = null;
  2963. highlightedFootprints = [];
  2964. highlightedNet = null;
  2965. }
  2966. }
  2967. function createRowHighlightHandler(rowid, refs, net) {
  2968. return function () {
  2969. if (currentHighlightedRowId) {
  2970. if (currentHighlightedRowId == rowid) {
  2971. return;
  2972. }
  2973. document.getElementById(currentHighlightedRowId).classList.remove("highlighted");
  2974. }
  2975. document.getElementById(rowid).classList.add("highlighted");
  2976. currentHighlightedRowId = rowid;
  2977. highlightedFootprints = refs ? refs.map(r => r[1]) : [];
  2978. highlightedNet = net;
  2979. drawHighlights();
  2980. EventHandler.emitEvent(
  2981. IBOM_EVENT_TYPES.HIGHLIGHT_EVENT, {
  2982. rowid: rowid,
  2983. refs: refs,
  2984. net: net
  2985. });
  2986. }
  2987. }
  2988. function updateNetColors() {
  2989. writeStorage("netColors", JSON.stringify(settings.netColors));
  2990. redrawIfInitDone();
  2991. }
  2992. function netColorChangeHandler(net) {
  2993. return (event) => {
  2994. settings.netColors[net] = event.target.value;
  2995. updateNetColors();
  2996. }
  2997. }
  2998. function netColorRightClick(net) {
  2999. return (event) => {
  3000. if (event.button == 2) {
  3001. event.preventDefault();
  3002. event.stopPropagation();
  3003. var style = getComputedStyle(topmostdiv);
  3004. var defaultNetColor = style.getPropertyValue('--track-color').trim();
  3005. event.target.value = defaultNetColor;
  3006. delete settings.netColors[net];
  3007. updateNetColors();
  3008. }
  3009. }
  3010. }
  3011. function entryMatches(entry) {
  3012. if (settings.bommode == "netlist") {
  3013. // entry is just a net name
  3014. return entry.toLowerCase().indexOf(filter) >= 0;
  3015. }
  3016. // check refs
  3017. if (!settings.hiddenColumns.includes("References")) {
  3018. for (var ref of entry) {
  3019. if (ref[0].toLowerCase().indexOf(filter) >= 0) {
  3020. return true;
  3021. }
  3022. }
  3023. }
  3024. // check fields
  3025. for (var i in config.fields) {
  3026. var f = config.fields[i];
  3027. if (!settings.hiddenColumns.includes(f)) {
  3028. for (var ref of entry) {
  3029. if (String(pcbdata.bom.fields[ref[1]][i]).toLowerCase().indexOf(filter) >= 0) {
  3030. return true;
  3031. }
  3032. }
  3033. }
  3034. }
  3035. return false;
  3036. }
  3037. function findRefInEntry(entry) {
  3038. return entry.filter(r => r[0].toLowerCase() == reflookup);
  3039. }
  3040. function highlightFilter(s) {
  3041. if (!filter) {
  3042. return s;
  3043. }
  3044. var parts = s.toLowerCase().split(filter);
  3045. if (parts.length == 1) {
  3046. return s;
  3047. }
  3048. var r = "";
  3049. var pos = 0;
  3050. for (var i in parts) {
  3051. if (i > 0) {
  3052. r += '<mark class="highlight">' +
  3053. s.substring(pos, pos + filter.length) +
  3054. '</mark>';
  3055. pos += filter.length;
  3056. }
  3057. r += s.substring(pos, pos + parts[i].length);
  3058. pos += parts[i].length;
  3059. }
  3060. return r;
  3061. }
  3062. function getBomListByLayer(layer) {
  3063. switch (layer) {
  3064. case 'F': return pcbdata.bom.F.slice();
  3065. case 'B': return pcbdata.bom.B.slice();
  3066. case 'FB': return pcbdata.bom.both.slice();
  3067. }
  3068. return [];
  3069. }
  3070. function getSelectedBomList() {
  3071. if (settings.bommode == "netlist") {
  3072. return pcbdata.nets.slice();
  3073. }
  3074. var out = getBomListByLayer(settings.canvaslayout);
  3075. if (settings.bommode == "ungrouped") {
  3076. // expand bom table
  3077. var expandedTable = [];
  3078. for (var bomentry of out) {
  3079. for (var ref of bomentry) {
  3080. expandedTable.push([ref]);
  3081. }
  3082. }
  3083. return expandedTable;
  3084. }
  3085. return out;
  3086. }
  3087. function checkboxSetUnsetAllHandler(checkboxname) {
  3088. return function () {
  3089. var checkboxnum = 0;
  3090. while (checkboxnum < settings.checkboxes.length &&
  3091. settings.checkboxes[checkboxnum].toLowerCase() != checkboxname.toLowerCase()) {
  3092. checkboxnum++;
  3093. }
  3094. if (checkboxnum >= settings.checkboxes.length) {
  3095. return;
  3096. }
  3097. var allset = true;
  3098. var checkbox;
  3099. var row;
  3100. for (row of bombody.childNodes) {
  3101. checkbox = row.childNodes[checkboxnum + 1].childNodes[0];
  3102. if (!checkbox.checked || checkbox.indeterminate) {
  3103. allset = false;
  3104. break;
  3105. }
  3106. }
  3107. for (row of bombody.childNodes) {
  3108. checkbox = row.childNodes[checkboxnum + 1].childNodes[0];
  3109. checkbox.checked = !allset;
  3110. checkbox.indeterminate = false;
  3111. checkbox.onchange();
  3112. }
  3113. }
  3114. }
  3115. function createColumnHeader(name, cls, comparator, is_checkbox = false) {
  3116. var th = document.createElement("TH");
  3117. th.innerHTML = name;
  3118. th.classList.add(cls);
  3119. if (is_checkbox)
  3120. th.setAttribute("col_name", "bom-checkbox");
  3121. else
  3122. th.setAttribute("col_name", name);
  3123. var span = document.createElement("SPAN");
  3124. span.classList.add("sortmark");
  3125. span.classList.add("none");
  3126. th.appendChild(span);
  3127. var spacer = document.createElement("div");
  3128. spacer.className = "column-spacer";
  3129. th.appendChild(spacer);
  3130. spacer.onclick = function () {
  3131. if (currentSortColumn && th !== currentSortColumn) {
  3132. // Currently sorted by another column
  3133. currentSortColumn.childNodes[1].classList.remove(currentSortOrder);
  3134. currentSortColumn.childNodes[1].classList.add("none");
  3135. currentSortColumn = null;
  3136. currentSortOrder = null;
  3137. }
  3138. if (currentSortColumn && th === currentSortColumn) {
  3139. // Already sorted by this column
  3140. if (currentSortOrder == "asc") {
  3141. // Sort by this column, descending order
  3142. bomSortFunction = function (a, b) {
  3143. return -comparator(a, b);
  3144. }
  3145. currentSortColumn.childNodes[1].classList.remove("asc");
  3146. currentSortColumn.childNodes[1].classList.add("desc");
  3147. currentSortOrder = "desc";
  3148. } else {
  3149. // Unsort
  3150. bomSortFunction = null;
  3151. currentSortColumn.childNodes[1].classList.remove("desc");
  3152. currentSortColumn.childNodes[1].classList.add("none");
  3153. currentSortColumn = null;
  3154. currentSortOrder = null;
  3155. }
  3156. } else {
  3157. // Sort by this column, ascending order
  3158. bomSortFunction = comparator;
  3159. currentSortColumn = th;
  3160. currentSortColumn.childNodes[1].classList.remove("none");
  3161. currentSortColumn.childNodes[1].classList.add("asc");
  3162. currentSortOrder = "asc";
  3163. }
  3164. populateBomBody();
  3165. }
  3166. if (is_checkbox) {
  3167. spacer.onclick = fancyDblClickHandler(
  3168. spacer, spacer.onclick, checkboxSetUnsetAllHandler(name));
  3169. }
  3170. return th;
  3171. }
  3172. function populateBomHeader(placeHolderColumn = null, placeHolderElements = null) {
  3173. while (bomhead.firstChild) {
  3174. bomhead.removeChild(bomhead.firstChild);
  3175. }
  3176. var tr = document.createElement("TR");
  3177. var th = document.createElement("TH");
  3178. th.classList.add("numCol");
  3179. var vismenu = document.createElement("div");
  3180. vismenu.id = "vismenu";
  3181. vismenu.classList.add("menu");
  3182. var visbutton = document.createElement("div");
  3183. visbutton.classList.add("visbtn");
  3184. visbutton.classList.add("hideonprint");
  3185. var viscontent = document.createElement("div");
  3186. viscontent.classList.add("menu-content");
  3187. viscontent.id = "vismenu-content";
  3188. settings.columnOrder.forEach(column => {
  3189. if (typeof column !== "string")
  3190. return;
  3191. // Skip empty columns
  3192. if (column === "checkboxes" && settings.checkboxes.length == 0)
  3193. return;
  3194. else if (column === "Quantity" && settings.bommode == "ungrouped")
  3195. return;
  3196. var label = document.createElement("label");
  3197. label.classList.add("menu-label");
  3198. var input = document.createElement("input");
  3199. input.classList.add("visibility_checkbox");
  3200. input.type = "checkbox";
  3201. input.onchange = function (e) {
  3202. setShowBOMColumn(column, e.target.checked)
  3203. };
  3204. input.checked = !(settings.hiddenColumns.includes(column));
  3205. label.appendChild(input);
  3206. if (column.length > 0)
  3207. label.append(column[0].toUpperCase() + column.slice(1));
  3208. viscontent.appendChild(label);
  3209. });
  3210. viscontent.childNodes[0].classList.add("menu-label-top");
  3211. vismenu.appendChild(visbutton);
  3212. if (settings.bommode != "netlist") {
  3213. vismenu.appendChild(viscontent);
  3214. th.appendChild(vismenu);
  3215. }
  3216. tr.appendChild(th);
  3217. var checkboxCompareClosure = function (checkbox) {
  3218. return (a, b) => {
  3219. var stateA = getCheckboxState(checkbox, a);
  3220. var stateB = getCheckboxState(checkbox, b);
  3221. if (stateA > stateB) return -1;
  3222. if (stateA < stateB) return 1;
  3223. return 0;
  3224. }
  3225. }
  3226. var stringFieldCompareClosure = function (fieldIndex) {
  3227. return (a, b) => {
  3228. var fa = pcbdata.bom.fields[a[0][1]][fieldIndex];
  3229. var fb = pcbdata.bom.fields[b[0][1]][fieldIndex];
  3230. if (fa != fb) return fa > fb ? 1 : -1;
  3231. else return 0;
  3232. }
  3233. }
  3234. var referenceRegex = /(?<prefix>[^0-9]+)(?<number>[0-9]+)/;
  3235. var compareRefs = (a, b) => {
  3236. var ra = referenceRegex.exec(a);
  3237. var rb = referenceRegex.exec(b);
  3238. if (ra === null || rb === null) {
  3239. if (a != b) return a > b ? 1 : -1;
  3240. return 0;
  3241. } else {
  3242. if (ra.groups.prefix != rb.groups.prefix) {
  3243. return ra.groups.prefix > rb.groups.prefix ? 1 : -1;
  3244. }
  3245. if (ra.groups.number != rb.groups.number) {
  3246. return parseInt(ra.groups.number) > parseInt(rb.groups.number) ? 1 : -1;
  3247. }
  3248. return 0;
  3249. }
  3250. }
  3251. if (settings.bommode == "netlist") {
  3252. tr.appendChild(createColumnHeader("Net name", "bom-netname", (a, b) => {
  3253. if (a > b) return -1;
  3254. if (a < b) return 1;
  3255. return 0;
  3256. }));
  3257. tr.appendChild(createColumnHeader("Color", "bom-color", (a, b) => {
  3258. return 0;
  3259. }));
  3260. } else {
  3261. // Filter hidden columns
  3262. var columns = settings.columnOrder.filter(e => !settings.hiddenColumns.includes(e));
  3263. var valueIndex = config.fields.indexOf("Value");
  3264. var footprintIndex = config.fields.indexOf("Footprint");
  3265. columns.forEach((column) => {
  3266. if (column === placeHolderColumn) {
  3267. var n = 1;
  3268. if (column === "checkboxes")
  3269. n = settings.checkboxes.length;
  3270. for (i = 0; i < n; i++) {
  3271. td = placeHolderElements.shift();
  3272. tr.appendChild(td);
  3273. }
  3274. return;
  3275. } else if (column === "checkboxes") {
  3276. for (var checkbox of settings.checkboxes) {
  3277. th = createColumnHeader(
  3278. checkbox, "bom-checkbox", checkboxCompareClosure(checkbox), true);
  3279. tr.appendChild(th);
  3280. }
  3281. } else if (column === "References") {
  3282. tr.appendChild(createColumnHeader("References", "references", (a, b) => {
  3283. var i = 0;
  3284. while (i < a.length && i < b.length) {
  3285. if (a[i][0] != b[i][0]) return compareRefs(a[i][0], b[i][0]);
  3286. i++;
  3287. }
  3288. return a.length - b.length;
  3289. }));
  3290. } else if (column === "Value") {
  3291. tr.appendChild(createColumnHeader("Value", "value", (a, b) => {
  3292. var ra = a[0][1], rb = b[0][1];
  3293. return valueCompare(
  3294. pcbdata.bom.parsedValues[ra], pcbdata.bom.parsedValues[rb],
  3295. pcbdata.bom.fields[ra][valueIndex], pcbdata.bom.fields[rb][valueIndex]);
  3296. }));
  3297. return;
  3298. } else if (column === "Footprint") {
  3299. tr.appendChild(createColumnHeader(
  3300. "Footprint", "footprint", stringFieldCompareClosure(footprintIndex)));
  3301. } else if (column === "Quantity" && settings.bommode == "grouped") {
  3302. tr.appendChild(createColumnHeader("Quantity", "quantity", (a, b) => {
  3303. return a.length - b.length;
  3304. }));
  3305. } else {
  3306. // Other fields
  3307. var i = config.fields.indexOf(column);
  3308. if (i < 0)
  3309. return;
  3310. tr.appendChild(createColumnHeader(
  3311. column, `field${i + 1}`, stringFieldCompareClosure(i)));
  3312. }
  3313. });
  3314. }
  3315. bomhead.appendChild(tr);
  3316. }
  3317. function populateBomBody(placeholderColumn = null, placeHolderElements = null) {
  3318. const urlRegex = /^(https?:\/\/[^\s\/$.?#][^\s]*|file:\/\/([a-zA-Z]:|\/)[^\x00]+)$/;
  3319. while (bom.firstChild) {
  3320. bom.removeChild(bom.firstChild);
  3321. }
  3322. highlightHandlers = [];
  3323. footprintIndexToHandler = {};
  3324. netsToHandler = {};
  3325. currentHighlightedRowId = null;
  3326. var first = true;
  3327. var style = getComputedStyle(topmostdiv);
  3328. var defaultNetColor = style.getPropertyValue('--track-color').trim();
  3329. bomtable = getSelectedBomList();
  3330. if (bomSortFunction) {
  3331. bomtable = bomtable.sort(bomSortFunction);
  3332. }
  3333. for (var i in bomtable) {
  3334. var bomentry = bomtable[i];
  3335. if (filter && !entryMatches(bomentry)) {
  3336. continue;
  3337. }
  3338. var references = null;
  3339. var netname = null;
  3340. var tr = document.createElement("TR");
  3341. var td = document.createElement("TD");
  3342. var rownum = +i + 1;
  3343. tr.id = "bomrow" + rownum;
  3344. td.textContent = rownum;
  3345. tr.appendChild(td);
  3346. if (settings.bommode == "netlist") {
  3347. netname = bomentry;
  3348. td = document.createElement("TD");
  3349. td.innerHTML = highlightFilter(netname ? netname : "&lt;no net&gt;");
  3350. tr.appendChild(td);
  3351. var color = settings.netColors[netname] || defaultNetColor;
  3352. td = document.createElement("TD");
  3353. var colorBox = document.createElement("INPUT");
  3354. colorBox.type = "color";
  3355. colorBox.value = color;
  3356. colorBox.onchange = netColorChangeHandler(netname);
  3357. colorBox.onmouseup = netColorRightClick(netname);
  3358. colorBox.oncontextmenu = (e) => e.preventDefault();
  3359. td.appendChild(colorBox);
  3360. td.classList.add("color-column");
  3361. tr.appendChild(td);
  3362. } else {
  3363. if (reflookup) {
  3364. references = findRefInEntry(bomentry);
  3365. if (references.length == 0) {
  3366. continue;
  3367. }
  3368. } else {
  3369. references = bomentry;
  3370. }
  3371. // Filter hidden columns
  3372. var columns = settings.columnOrder.filter(e => !settings.hiddenColumns.includes(e));
  3373. columns.forEach((column) => {
  3374. if (column === placeholderColumn) {
  3375. var n = 1;
  3376. if (column === "checkboxes")
  3377. n = settings.checkboxes.length;
  3378. for (i = 0; i < n; i++) {
  3379. td = placeHolderElements.shift();
  3380. tr.appendChild(td);
  3381. }
  3382. return;
  3383. } else if (column === "checkboxes") {
  3384. for (var checkbox of settings.checkboxes) {
  3385. if (checkbox) {
  3386. td = document.createElement("TD");
  3387. var input = document.createElement("input");
  3388. input.type = "checkbox";
  3389. [input.onchange, td.ontouchstart, td.ontouchend] = createCheckboxHandlers(input, checkbox, references, tr);
  3390. setBomCheckboxState(checkbox, input, references);
  3391. if (input.checked && settings.markWhenChecked == checkbox) {
  3392. tr.classList.add("checked");
  3393. }
  3394. td.appendChild(input);
  3395. tr.appendChild(td);
  3396. }
  3397. }
  3398. } else if (column === "References") {
  3399. td = document.createElement("TD");
  3400. td.innerHTML = highlightFilter(references.map(r => r[0]).join(", "));
  3401. tr.appendChild(td);
  3402. } else if (column === "Quantity" && settings.bommode == "grouped") {
  3403. // Quantity
  3404. td = document.createElement("TD");
  3405. td.textContent = references.length;
  3406. tr.appendChild(td);
  3407. } else {
  3408. // All the other fields
  3409. var field_index = config.fields.indexOf(column)
  3410. if (field_index < 0)
  3411. return;
  3412. var valueSet = new Set();
  3413. references.map(r => r[1]).forEach((id) => valueSet.add(pcbdata.bom.fields[id][field_index]));
  3414. td = document.createElement("TD");
  3415. var output = new Array();
  3416. for (let item of valueSet) {
  3417. const visible = highlightFilter(String(item));
  3418. if (typeof item === 'string' && item.match(urlRegex)) {
  3419. output.push(`<a href="${item}" target="_blank">${visible}</a>`);
  3420. } else {
  3421. output.push(visible);
  3422. }
  3423. }
  3424. td.innerHTML = output.join(", ");
  3425. tr.appendChild(td);
  3426. }
  3427. });
  3428. }
  3429. bom.appendChild(tr);
  3430. var handler = createRowHighlightHandler(tr.id, references, netname);
  3431. if (settings.highlightRowOnClick) {
  3432. tr.onmousedown = handler;
  3433. } else {
  3434. tr.onmousemove = handler;
  3435. }
  3436. highlightHandlers.push({
  3437. id: tr.id,
  3438. handler: handler,
  3439. });
  3440. if (references !== null) {
  3441. for (var refIndex of references.map(r => r[1])) {
  3442. footprintIndexToHandler[refIndex] = handler;
  3443. }
  3444. }
  3445. if (netname !== null) {
  3446. netsToHandler[netname] = handler;
  3447. }
  3448. if ((filter || reflookup) && first) {
  3449. handler();
  3450. first = false;
  3451. }
  3452. }
  3453. EventHandler.emitEvent(
  3454. IBOM_EVENT_TYPES.BOM_BODY_CHANGE_EVENT, {
  3455. filter: filter,
  3456. reflookup: reflookup,
  3457. checkboxes: settings.checkboxes,
  3458. bommode: settings.bommode,
  3459. });
  3460. }
  3461. function highlightPreviousRow() {
  3462. if (!currentHighlightedRowId) {
  3463. highlightHandlers[highlightHandlers.length - 1].handler();
  3464. } else {
  3465. if (highlightHandlers.length > 1 &&
  3466. highlightHandlers[0].id == currentHighlightedRowId) {
  3467. highlightHandlers[highlightHandlers.length - 1].handler();
  3468. } else {
  3469. for (var i = 0; i < highlightHandlers.length - 1; i++) {
  3470. if (highlightHandlers[i + 1].id == currentHighlightedRowId) {
  3471. highlightHandlers[i].handler();
  3472. break;
  3473. }
  3474. }
  3475. }
  3476. }
  3477. smoothScrollToRow(currentHighlightedRowId);
  3478. }
  3479. function highlightNextRow() {
  3480. if (!currentHighlightedRowId) {
  3481. highlightHandlers[0].handler();
  3482. } else {
  3483. if (highlightHandlers.length > 1 &&
  3484. highlightHandlers[highlightHandlers.length - 1].id == currentHighlightedRowId) {
  3485. highlightHandlers[0].handler();
  3486. } else {
  3487. for (var i = 1; i < highlightHandlers.length; i++) {
  3488. if (highlightHandlers[i - 1].id == currentHighlightedRowId) {
  3489. highlightHandlers[i].handler();
  3490. break;
  3491. }
  3492. }
  3493. }
  3494. }
  3495. smoothScrollToRow(currentHighlightedRowId);
  3496. }
  3497. function populateBomTable() {
  3498. populateBomHeader();
  3499. populateBomBody();
  3500. setBomHandlers();
  3501. resizableGrid(bomhead);
  3502. }
  3503. function footprintsClicked(footprintIndexes) {
  3504. var lastClickedIndex = footprintIndexes.indexOf(lastClicked);
  3505. for (var i = 1; i <= footprintIndexes.length; i++) {
  3506. var refIndex = footprintIndexes[(lastClickedIndex + i) % footprintIndexes.length];
  3507. if (refIndex in footprintIndexToHandler) {
  3508. lastClicked = refIndex;
  3509. footprintIndexToHandler[refIndex]();
  3510. smoothScrollToRow(currentHighlightedRowId);
  3511. break;
  3512. }
  3513. }
  3514. }
  3515. function netClicked(net) {
  3516. if (net in netsToHandler) {
  3517. netsToHandler[net]();
  3518. smoothScrollToRow(currentHighlightedRowId);
  3519. } else {
  3520. clearHighlightedFootprints();
  3521. highlightedNet = net;
  3522. drawHighlights();
  3523. }
  3524. }
  3525. function updateFilter(input) {
  3526. filter = input.toLowerCase();
  3527. populateBomTable();
  3528. }
  3529. function updateRefLookup(input) {
  3530. reflookup = input.toLowerCase();
  3531. populateBomTable();
  3532. }
  3533. function changeCanvasLayout(layout) {
  3534. document.getElementById("fl-btn").classList.remove("depressed");
  3535. document.getElementById("fb-btn").classList.remove("depressed");
  3536. document.getElementById("bl-btn").classList.remove("depressed");
  3537. switch (layout) {
  3538. case 'F':
  3539. document.getElementById("fl-btn").classList.add("depressed");
  3540. if (settings.bomlayout != "bom-only") {
  3541. canvassplit.collapse(1);
  3542. }
  3543. break;
  3544. case 'B':
  3545. document.getElementById("bl-btn").classList.add("depressed");
  3546. if (settings.bomlayout != "bom-only") {
  3547. canvassplit.collapse(0);
  3548. }
  3549. break;
  3550. default:
  3551. document.getElementById("fb-btn").classList.add("depressed");
  3552. if (settings.bomlayout != "bom-only") {
  3553. canvassplit.setSizes([50, 50]);
  3554. }
  3555. }
  3556. settings.canvaslayout = layout;
  3557. writeStorage("canvaslayout", layout);
  3558. resizeAll();
  3559. changeBomMode(settings.bommode);
  3560. }
  3561. function populateMetadata() {
  3562. document.getElementById("title").innerHTML = pcbdata.metadata.title;
  3563. document.getElementById("revision").innerHTML = "Rev: " + pcbdata.metadata.revision;
  3564. document.getElementById("company").innerHTML = pcbdata.metadata.company;
  3565. document.getElementById("filedate").innerHTML = pcbdata.metadata.date;
  3566. if (pcbdata.metadata.title != "") {
  3567. document.title = pcbdata.metadata.title + " BOM";
  3568. }
  3569. // Calculate board stats
  3570. var fp_f = 0,
  3571. fp_b = 0,
  3572. pads_f = 0,
  3573. pads_b = 0,
  3574. pads_th = 0;
  3575. for (var i = 0; i < pcbdata.footprints.length; i++) {
  3576. if (pcbdata.bom.skipped.includes(i)) continue;
  3577. var mod = pcbdata.footprints[i];
  3578. if (mod.layer == "F") {
  3579. fp_f++;
  3580. } else {
  3581. fp_b++;
  3582. }
  3583. for (var pad of mod.pads) {
  3584. if (pad.type == "th") {
  3585. pads_th++;
  3586. } else {
  3587. if (pad.layers.includes("F")) {
  3588. pads_f++;
  3589. }
  3590. if (pad.layers.includes("B")) {
  3591. pads_b++;
  3592. }
  3593. }
  3594. }
  3595. }
  3596. document.getElementById("stats-components-front").innerHTML = fp_f;
  3597. document.getElementById("stats-components-back").innerHTML = fp_b;
  3598. document.getElementById("stats-components-total").innerHTML = fp_f + fp_b;
  3599. document.getElementById("stats-groups-front").innerHTML = pcbdata.bom.F.length;
  3600. document.getElementById("stats-groups-back").innerHTML = pcbdata.bom.B.length;
  3601. document.getElementById("stats-groups-total").innerHTML = pcbdata.bom.both.length;
  3602. document.getElementById("stats-smd-pads-front").innerHTML = pads_f;
  3603. document.getElementById("stats-smd-pads-back").innerHTML = pads_b;
  3604. document.getElementById("stats-smd-pads-total").innerHTML = pads_f + pads_b;
  3605. document.getElementById("stats-th-pads").innerHTML = pads_th;
  3606. // Update version string
  3607. document.getElementById("github-link").innerHTML = "InteractiveHtmlBom&nbsp;" +
  3608. /^v\d+\.\d+/.exec(pcbdata.ibom_version)[0];
  3609. }
  3610. function changeBomLayout(layout) {
  3611. document.getElementById("bom-btn").classList.remove("depressed");
  3612. document.getElementById("lr-btn").classList.remove("depressed");
  3613. document.getElementById("tb-btn").classList.remove("depressed");
  3614. switch (layout) {
  3615. case 'bom-only':
  3616. document.getElementById("bom-btn").classList.add("depressed");
  3617. if (bomsplit) {
  3618. bomsplit.destroy();
  3619. bomsplit = null;
  3620. canvassplit.destroy();
  3621. canvassplit = null;
  3622. }
  3623. document.getElementById("frontcanvas").style.display = "none";
  3624. document.getElementById("backcanvas").style.display = "none";
  3625. document.getElementById("topmostdiv").style.height = "";
  3626. document.getElementById("topmostdiv").style.display = "block";
  3627. break;
  3628. case 'top-bottom':
  3629. document.getElementById("tb-btn").classList.add("depressed");
  3630. document.getElementById("frontcanvas").style.display = "";
  3631. document.getElementById("backcanvas").style.display = "";
  3632. document.getElementById("topmostdiv").style.height = "100%";
  3633. document.getElementById("topmostdiv").style.display = "flex";
  3634. document.getElementById("bomdiv").classList.remove("split-horizontal");
  3635. document.getElementById("canvasdiv").classList.remove("split-horizontal");
  3636. document.getElementById("frontcanvas").classList.add("split-horizontal");
  3637. document.getElementById("backcanvas").classList.add("split-horizontal");
  3638. if (bomsplit) {
  3639. bomsplit.destroy();
  3640. bomsplit = null;
  3641. canvassplit.destroy();
  3642. canvassplit = null;
  3643. }
  3644. bomsplit = Split(['#bomdiv', '#canvasdiv'], {
  3645. sizes: [50, 50],
  3646. onDragEnd: resizeAll,
  3647. direction: "vertical",
  3648. gutterSize: 5
  3649. });
  3650. canvassplit = Split(['#frontcanvas', '#backcanvas'], {
  3651. sizes: [50, 50],
  3652. gutterSize: 5,
  3653. onDragEnd: resizeAll
  3654. });
  3655. break;
  3656. case 'left-right':
  3657. document.getElementById("lr-btn").classList.add("depressed");
  3658. document.getElementById("frontcanvas").style.display = "";
  3659. document.getElementById("backcanvas").style.display = "";
  3660. document.getElementById("topmostdiv").style.height = "100%";
  3661. document.getElementById("topmostdiv").style.display = "flex";
  3662. document.getElementById("bomdiv").classList.add("split-horizontal");
  3663. document.getElementById("canvasdiv").classList.add("split-horizontal");
  3664. document.getElementById("frontcanvas").classList.remove("split-horizontal");
  3665. document.getElementById("backcanvas").classList.remove("split-horizontal");
  3666. if (bomsplit) {
  3667. bomsplit.destroy();
  3668. bomsplit = null;
  3669. canvassplit.destroy();
  3670. canvassplit = null;
  3671. }
  3672. bomsplit = Split(['#bomdiv', '#canvasdiv'], {
  3673. sizes: [50, 50],
  3674. onDragEnd: resizeAll,
  3675. gutterSize: 5
  3676. });
  3677. canvassplit = Split(['#frontcanvas', '#backcanvas'], {
  3678. sizes: [50, 50],
  3679. gutterSize: 5,
  3680. direction: "vertical",
  3681. onDragEnd: resizeAll
  3682. });
  3683. }
  3684. settings.bomlayout = layout;
  3685. writeStorage("bomlayout", layout);
  3686. changeCanvasLayout(settings.canvaslayout);
  3687. }
  3688. function changeBomMode(mode) {
  3689. document.getElementById("bom-grouped-btn").classList.remove("depressed");
  3690. document.getElementById("bom-ungrouped-btn").classList.remove("depressed");
  3691. document.getElementById("bom-netlist-btn").classList.remove("depressed");
  3692. var chkbxs = document.getElementsByClassName("visibility_checkbox");
  3693. switch (mode) {
  3694. case 'grouped':
  3695. document.getElementById("bom-grouped-btn").classList.add("depressed");
  3696. for (var i = 0; i < chkbxs.length; i++) {
  3697. chkbxs[i].disabled = false;
  3698. }
  3699. break;
  3700. case 'ungrouped':
  3701. document.getElementById("bom-ungrouped-btn").classList.add("depressed");
  3702. for (var i = 0; i < chkbxs.length; i++) {
  3703. chkbxs[i].disabled = false;
  3704. }
  3705. break;
  3706. case 'netlist':
  3707. document.getElementById("bom-netlist-btn").classList.add("depressed");
  3708. for (var i = 0; i < chkbxs.length; i++) {
  3709. chkbxs[i].disabled = true;
  3710. }
  3711. }
  3712. writeStorage("bommode", mode);
  3713. if (mode != settings.bommode) {
  3714. settings.bommode = mode;
  3715. bomSortFunction = null;
  3716. currentSortColumn = null;
  3717. currentSortOrder = null;
  3718. clearHighlightedFootprints();
  3719. }
  3720. populateBomTable();
  3721. }
  3722. function focusFilterField() {
  3723. focusInputField(document.getElementById("filter"));
  3724. }
  3725. function focusRefLookupField() {
  3726. focusInputField(document.getElementById("reflookup"));
  3727. }
  3728. function toggleBomCheckbox(bomrowid, checkboxnum) {
  3729. if (!bomrowid || checkboxnum > settings.checkboxes.length) {
  3730. return;
  3731. }
  3732. var bomrow = document.getElementById(bomrowid);
  3733. var childNum = checkboxnum + settings.columnOrder.indexOf("checkboxes");
  3734. var checkbox = bomrow.childNodes[childNum].childNodes[0];
  3735. checkbox.checked = !checkbox.checked;
  3736. checkbox.indeterminate = false;
  3737. checkbox.onchange();
  3738. }
  3739. function checkBomCheckbox(bomrowid, checkboxname) {
  3740. var checkboxnum = 0;
  3741. while (checkboxnum < settings.checkboxes.length &&
  3742. settings.checkboxes[checkboxnum].toLowerCase() != checkboxname.toLowerCase()) {
  3743. checkboxnum++;
  3744. }
  3745. if (!bomrowid || checkboxnum >= settings.checkboxes.length) {
  3746. return;
  3747. }
  3748. var bomrow = document.getElementById(bomrowid);
  3749. var childNum = checkboxnum + 1 + settings.columnOrder.indexOf("checkboxes");
  3750. var checkbox = bomrow.childNodes[childNum].childNodes[0];
  3751. checkbox.checked = true;
  3752. checkbox.indeterminate = false;
  3753. checkbox.onchange();
  3754. }
  3755. function setBomCheckboxes(value) {
  3756. writeStorage("bomCheckboxes", value);
  3757. settings.checkboxes = value.split(",").map((e) => e.trim()).filter((e) => e);
  3758. prepCheckboxes();
  3759. populateMarkWhenCheckedOptions();
  3760. setMarkWhenChecked(settings.markWhenChecked);
  3761. }
  3762. function setMarkWhenChecked(value) {
  3763. writeStorage("markWhenChecked", value);
  3764. settings.markWhenChecked = value;
  3765. markedFootprints.clear();
  3766. for (var ref of (value ? getStoredCheckboxRefs(value) : [])) {
  3767. markedFootprints.add(ref);
  3768. }
  3769. populateBomTable();
  3770. drawHighlights();
  3771. }
  3772. function prepCheckboxes() {
  3773. var table = document.getElementById("checkbox-stats");
  3774. while (table.childElementCount > 1) {
  3775. table.removeChild(table.lastChild);
  3776. }
  3777. if (settings.checkboxes.length) {
  3778. table.style.display = "";
  3779. } else {
  3780. table.style.display = "none";
  3781. }
  3782. for (var checkbox of settings.checkboxes) {
  3783. var tr = document.createElement("TR");
  3784. var td = document.createElement("TD");
  3785. td.innerHTML = checkbox;
  3786. tr.appendChild(td);
  3787. td = document.createElement("TD");
  3788. td.id = "checkbox-stats-" + checkbox;
  3789. var progressbar = document.createElement("div");
  3790. progressbar.classList.add("bar");
  3791. td.appendChild(progressbar);
  3792. var text = document.createElement("div");
  3793. text.classList.add("text");
  3794. td.appendChild(text);
  3795. tr.appendChild(td);
  3796. table.appendChild(tr);
  3797. updateCheckboxStats(checkbox);
  3798. }
  3799. }
  3800. function populateMarkWhenCheckedOptions() {
  3801. var container = document.getElementById("markWhenCheckedContainer");
  3802. if (settings.checkboxes.length == 0) {
  3803. container.parentElement.style.display = "none";
  3804. return;
  3805. }
  3806. container.innerHTML = '';
  3807. container.parentElement.style.display = "inline-block";
  3808. function createOption(name, displayName) {
  3809. var id = "markWhenChecked-" + name;
  3810. var div = document.createElement("div");
  3811. div.classList.add("radio-container");
  3812. var input = document.createElement("input");
  3813. input.type = "radio";
  3814. input.name = "markWhenChecked";
  3815. input.value = name;
  3816. input.id = id;
  3817. input.onchange = () => setMarkWhenChecked(name);
  3818. div.appendChild(input);
  3819. // Preserve the selected element when the checkboxes change
  3820. if (name == settings.markWhenChecked) {
  3821. input.checked = true;
  3822. }
  3823. var label = document.createElement("label");
  3824. label.innerHTML = displayName;
  3825. label.htmlFor = id;
  3826. div.appendChild(label);
  3827. container.appendChild(div);
  3828. }
  3829. createOption("", "None");
  3830. for (var checkbox of settings.checkboxes) {
  3831. createOption(checkbox, checkbox);
  3832. }
  3833. }
  3834. function updateCheckboxStats(checkbox) {
  3835. var checked = getStoredCheckboxRefs(checkbox).size;
  3836. var total = pcbdata.footprints.length - pcbdata.bom.skipped.length;
  3837. var percent = checked * 100.0 / total;
  3838. var td = document.getElementById("checkbox-stats-" + checkbox);
  3839. td.firstChild.style.width = percent + "%";
  3840. td.lastChild.innerHTML = checked + "/" + total + " (" + Math.round(percent) + "%)";
  3841. }
  3842. function constrain(number, min, max) {
  3843. return Math.min(Math.max(parseInt(number), min), max);
  3844. }
  3845. document.onkeydown = function (e) {
  3846. switch (e.key) {
  3847. case "n":
  3848. if (document.activeElement.type == "text") {
  3849. return;
  3850. }
  3851. if (currentHighlightedRowId !== null) {
  3852. checkBomCheckbox(currentHighlightedRowId, "placed");
  3853. highlightNextRow();
  3854. e.preventDefault();
  3855. }
  3856. break;
  3857. case "ArrowUp":
  3858. highlightPreviousRow();
  3859. e.preventDefault();
  3860. break;
  3861. case "ArrowDown":
  3862. highlightNextRow();
  3863. e.preventDefault();
  3864. break;
  3865. case "ArrowLeft":
  3866. case "ArrowRight":
  3867. if (document.activeElement.type != "text") {
  3868. e.preventDefault();
  3869. let boardRotationElement = document.getElementById("boardRotation")
  3870. settings.boardRotation = parseInt(boardRotationElement.value); // degrees / 5
  3871. if (e.key == "ArrowLeft") {
  3872. settings.boardRotation += 3; // 15 degrees
  3873. }
  3874. else {
  3875. settings.boardRotation -= 3;
  3876. }
  3877. settings.boardRotation = constrain(settings.boardRotation, boardRotationElement.min, boardRotationElement.max);
  3878. boardRotationElement.value = settings.boardRotation
  3879. setBoardRotation(settings.boardRotation);
  3880. }
  3881. break;
  3882. default:
  3883. break;
  3884. }
  3885. if (e.altKey) {
  3886. switch (e.key) {
  3887. case "f":
  3888. focusFilterField();
  3889. e.preventDefault();
  3890. break;
  3891. case "r":
  3892. focusRefLookupField();
  3893. e.preventDefault();
  3894. break;
  3895. case "z":
  3896. changeBomLayout("bom-only");
  3897. e.preventDefault();
  3898. break;
  3899. case "x":
  3900. changeBomLayout("left-right");
  3901. e.preventDefault();
  3902. break;
  3903. case "c":
  3904. changeBomLayout("top-bottom");
  3905. e.preventDefault();
  3906. break;
  3907. case "v":
  3908. changeCanvasLayout("F");
  3909. e.preventDefault();
  3910. break;
  3911. case "b":
  3912. changeCanvasLayout("FB");
  3913. e.preventDefault();
  3914. break;
  3915. case "n":
  3916. changeCanvasLayout("B");
  3917. e.preventDefault();
  3918. break;
  3919. default:
  3920. break;
  3921. }
  3922. if (e.key >= '1' && e.key <= '9') {
  3923. toggleBomCheckbox(currentHighlightedRowId, parseInt(e.key));
  3924. e.preventDefault();
  3925. }
  3926. }
  3927. }
  3928. function hideNetlistButton() {
  3929. document.getElementById("bom-ungrouped-btn").classList.remove("middle-button");
  3930. document.getElementById("bom-ungrouped-btn").classList.add("right-most-button");
  3931. document.getElementById("bom-netlist-btn").style.display = "none";
  3932. }
  3933. function topToggle() {
  3934. var top = document.getElementById("top");
  3935. var toptoggle = document.getElementById("toptoggle");
  3936. if (top.style.display === "none") {
  3937. top.style.display = "flex";
  3938. toptoggle.classList.remove("flipped");
  3939. } else {
  3940. top.style.display = "none";
  3941. toptoggle.classList.add("flipped");
  3942. }
  3943. }
  3944. window.onload = function (e) {
  3945. initRender();
  3946. initStorage();
  3947. initDefaults();
  3948. initUtils();
  3949. cleanGutters();
  3950. populateMetadata();
  3951. dbgdiv = document.getElementById("dbg");
  3952. bom = document.getElementById("bombody");
  3953. bomhead = document.getElementById("bomhead");
  3954. filter = "";
  3955. reflookup = "";
  3956. if (!("nets" in pcbdata)) {
  3957. hideNetlistButton();
  3958. }
  3959. initDone = true;
  3960. setBomCheckboxes(document.getElementById("bomCheckboxes").value);
  3961. // Triggers render
  3962. changeBomLayout(settings.bomlayout);
  3963. // Users may leave fullscreen without touching the checkbox. Uncheck.
  3964. document.addEventListener('fullscreenchange', () => {
  3965. if (!document.fullscreenElement)
  3966. document.getElementById('fullscreenCheckbox').checked = false;
  3967. });
  3968. }
  3969. window.onresize = resizeAll;
  3970. window.matchMedia("print").addListener(resizeAll);
  3971. ///////////////////////////////////////////////
  3972. ///////////////////////////////////////////////
  3973. // EventHandler.registerCallback(IBOM_EVENT_TYPES.BOM_BODY_CHANGE_EVENT, () => {
  3974. // for(var tr of bom.childNodes) {
  3975. // tr.onclick = tr.onmousemove;
  3976. // tr.onmousemove = null;
  3977. // };
  3978. // });
  3979. ///////////////////////////////////////////////
  3980. </script>
  3981. </head>
  3982. <body>
  3983. <div id="topmostdiv" class="topmostdiv">
  3984. <div id="top">
  3985. <div id="fileinfodiv">
  3986. <table class="fileinfo">
  3987. <tbody>
  3988. <tr>
  3989. <td id="title" class="title" style="width: 70%">
  3990. Title
  3991. </td>
  3992. <td id="revision" class="title" style="width: 30%">
  3993. Revision
  3994. </td>
  3995. </tr>
  3996. <tr>
  3997. <td id="company">
  3998. Company
  3999. </td>
  4000. <td id="filedate">
  4001. Date
  4002. </td>
  4003. </tr>
  4004. </tbody>
  4005. </table>
  4006. </div>
  4007. <div id="bomcontrols">
  4008. <div class="hideonprint menu">
  4009. <button class="menubtn"></button>
  4010. <div class="menu-content">
  4011. <label class="menu-label menu-label-top" style="width: calc(50% - 18px)">
  4012. <input id="darkmodeCheckbox" type="checkbox" onchange="setDarkMode(this.checked)">
  4013. Dark mode
  4014. </label><!-- This comment eats space! All of it!
  4015. --><label class="menu-label menu-label-top" style="width: calc(50% - 17px); border-left: 0;">
  4016. <input id="fullscreenCheckbox" type="checkbox" onchange="setFullscreen(this.checked)">
  4017. Full Screen
  4018. </label>
  4019. <label class="menu-label" style="width: calc(50% - 18px)">
  4020. <input id="fabricationCheckbox" type="checkbox" checked onchange="fabricationVisible(this.checked)">
  4021. Fab layer
  4022. </label><!-- This comment eats space! All of it!
  4023. --><label class="menu-label" style="width: calc(50% - 17px); border-left: 0;">
  4024. <input id="silkscreenCheckbox" type="checkbox" checked onchange="silkscreenVisible(this.checked)">
  4025. Silkscreen
  4026. </label>
  4027. <label class="menu-label" style="width: calc(50% - 18px)">
  4028. <input id="referencesCheckbox" type="checkbox" checked onchange="referencesVisible(this.checked)">
  4029. References
  4030. </label><!-- This comment eats space! All of it!
  4031. --><label class="menu-label" style="width: calc(50% - 17px); border-left: 0;">
  4032. <input id="valuesCheckbox" type="checkbox" checked onchange="valuesVisible(this.checked)">
  4033. Values
  4034. </label>
  4035. <div id="tracksAndZonesCheckboxes">
  4036. <label class="menu-label" style="width: calc(50% - 18px)">
  4037. <input id="tracksCheckbox" type="checkbox" checked onchange="tracksVisible(this.checked)">
  4038. Tracks
  4039. </label><!-- This comment eats space! All of it!
  4040. --><label class="menu-label" style="width: calc(50% - 17px); border-left: 0;">
  4041. <input id="zonesCheckbox" type="checkbox" checked onchange="zonesVisible(this.checked)">
  4042. Zones
  4043. </label>
  4044. </div>
  4045. <label class="menu-label" style="width: calc(50% - 18px)">
  4046. <input id="padsCheckbox" type="checkbox" checked onchange="padsVisible(this.checked)">
  4047. Pads
  4048. </label><!-- This comment eats space! All of it!
  4049. --><label class="menu-label" style="width: calc(50% - 17px); border-left: 0;">
  4050. <input id="dnpOutlineCheckbox" type="checkbox" checked onchange="dnpOutline(this.checked)">
  4051. DNP outlined
  4052. </label>
  4053. <label class="menu-label">
  4054. <input id="highlightRowOnClickCheckbox" type="checkbox" checked onchange="setHighlightRowOnClick(this.checked)">
  4055. Highlight row on click
  4056. </label>
  4057. <label class="menu-label">
  4058. <input id="dragCheckbox" type="checkbox" checked onchange="setRedrawOnDrag(this.checked)">
  4059. Continuous redraw on drag
  4060. </label>
  4061. <label class="menu-label">
  4062. Highlight first pin
  4063. <form id="highlightpin1">
  4064. <div class="flexbox">
  4065. <label>
  4066. <input type="radio" name="highlightpin1" value="none" onchange="setHighlightPin1('none')">
  4067. None
  4068. </label>
  4069. <label>
  4070. <input type="radio" name="highlightpin1" value="all" onchange="setHighlightPin1('all')">
  4071. All
  4072. </label>
  4073. <label>
  4074. <input type="radio" name="highlightpin1" value="selected" onchange="setHighlightPin1('selected')">
  4075. Selected
  4076. </label>
  4077. </div>
  4078. </form>
  4079. </label>
  4080. <label class="menu-label">
  4081. <span>Board rotation</span>
  4082. <span style="float: right"><span id="rotationDegree">0</span>&#176;</span>
  4083. <input id="boardRotation" type="range" min="-36" max="36" value="0" class="slider" oninput="setBoardRotation(this.value)">
  4084. </label>
  4085. <label class="menu-label">
  4086. <input id="offsetBackRotationCheckbox" type="checkbox" onchange="setOffsetBackRotation(this.checked)">
  4087. Offset back rotation
  4088. </label>
  4089. <label class="menu-label">
  4090. <div style="margin-left: 5px">Bom checkboxes</div>
  4091. <input id="bomCheckboxes" class="menu-textbox" type=text
  4092. oninput="setBomCheckboxes(this.value)">
  4093. </label>
  4094. <label class="menu-label">
  4095. <div style="margin-left: 5px">Mark when checked</div>
  4096. <div id="markWhenCheckedContainer"></div>
  4097. </label>
  4098. <label class="menu-label">
  4099. <span class="shameless-plug">
  4100. <span>Created using</span>
  4101. <a id="github-link" target="blank" href="https://github.com/openscopeproject/InteractiveHtmlBom">InteractiveHtmlBom</a>
  4102. <a target="blank" title="Mouse and keyboard help" href="https://github.com/openscopeproject/InteractiveHtmlBom/wiki/Usage#bom-page-mouse-actions" style="text-decoration: none;"><label class="help-link">?</label></a>
  4103. </span>
  4104. </label>
  4105. </div>
  4106. </div>
  4107. <div class="button-container hideonprint">
  4108. <button id="fl-btn" class="left-most-button" onclick="changeCanvasLayout('F')"
  4109. title="Front only">F
  4110. </button>
  4111. <button id="fb-btn" class="middle-button" onclick="changeCanvasLayout('FB')"
  4112. title="Front and Back">FB
  4113. </button>
  4114. <button id="bl-btn" class="right-most-button" onclick="changeCanvasLayout('B')"
  4115. title="Back only">B
  4116. </button>
  4117. </div>
  4118. <div class="button-container hideonprint">
  4119. <button id="bom-btn" class="left-most-button" onclick="changeBomLayout('bom-only')"
  4120. title="BOM only"></button>
  4121. <button id="lr-btn" class="middle-button" onclick="changeBomLayout('left-right')"
  4122. title="BOM left, drawings right"></button>
  4123. <button id="tb-btn" class="right-most-button" onclick="changeBomLayout('top-bottom')"
  4124. title="BOM top, drawings bot"></button>
  4125. </div>
  4126. <div class="button-container hideonprint">
  4127. <button id="bom-grouped-btn" class="left-most-button" onclick="changeBomMode('grouped')"
  4128. title="Grouped BOM"></button>
  4129. <button id="bom-ungrouped-btn" class="middle-button" onclick="changeBomMode('ungrouped')"
  4130. title="Ungrouped BOM"></button>
  4131. <button id="bom-netlist-btn" class="right-most-button" onclick="changeBomMode('netlist')"
  4132. title="Netlist"></button>
  4133. </div>
  4134. <div class="hideonprint menu">
  4135. <button class="statsbtn"></button>
  4136. <div class="menu-content">
  4137. <table class="stats">
  4138. <tbody>
  4139. <tr>
  4140. <td width="40%">Board stats</td>
  4141. <td>Front</td>
  4142. <td>Back</td>
  4143. <td>Total</td>
  4144. </tr>
  4145. <tr>
  4146. <td>Components</td>
  4147. <td id="stats-components-front">~</td>
  4148. <td id="stats-components-back">~</td>
  4149. <td id="stats-components-total">~</td>
  4150. </tr>
  4151. <tr>
  4152. <td>Groups</td>
  4153. <td id="stats-groups-front">~</td>
  4154. <td id="stats-groups-back">~</td>
  4155. <td id="stats-groups-total">~</td>
  4156. </tr>
  4157. <tr>
  4158. <td>SMD pads</td>
  4159. <td id="stats-smd-pads-front">~</td>
  4160. <td id="stats-smd-pads-back">~</td>
  4161. <td id="stats-smd-pads-total">~</td>
  4162. </tr>
  4163. <tr>
  4164. <td>TH pads</td>
  4165. <td colspan=3 id="stats-th-pads">~</td>
  4166. </tr>
  4167. </tbody>
  4168. </table>
  4169. <table class="stats">
  4170. <col width="40%"/><col />
  4171. <tbody id="checkbox-stats">
  4172. <tr>
  4173. <td colspan=2 style="border-top: 0">Checkboxes</td>
  4174. </tr>
  4175. </tbody>
  4176. </table>
  4177. </div>
  4178. </div>
  4179. <div class="hideonprint menu">
  4180. <button class="iobtn"></button>
  4181. <div class="menu-content">
  4182. <div class="menu-label menu-label-top">
  4183. <div style="margin-left: 5px;">Save board image</div>
  4184. <div class="flexbox">
  4185. <input id="render-save-width" class="menu-textbox" type="text" value="1000" placeholder="Width"
  4186. style="flex-grow: 1; width: 50px;" oninput="validateSaveImgDimension(this)">
  4187. <span>X</span>
  4188. <input id="render-save-height" class="menu-textbox" type="text" value="1000" placeholder="Height"
  4189. style="flex-grow: 1; width: 50px;" oninput="validateSaveImgDimension(this)">
  4190. </div>
  4191. <label>
  4192. <input id="render-save-transparent" type="checkbox">
  4193. Transparent background
  4194. </label>
  4195. <div class="flexbox">
  4196. <button class="savebtn" onclick="saveImage('F')">Front</button>
  4197. <button class="savebtn" onclick="saveImage('B')">Back</button>
  4198. </div>
  4199. </div>
  4200. <div class="menu-label">
  4201. <span style="margin-left: 5px;">Config and checkbox state</span>
  4202. <div class="flexbox">
  4203. <button class="savebtn" onclick="saveSettings()">Export</button>
  4204. <button class="savebtn" onclick="loadSettings()">Import</button>
  4205. <button class="savebtn" onclick="resetSettings()">Reset</button>
  4206. </div>
  4207. </div>
  4208. <div class="menu-label">
  4209. <span style="margin-left: 5px;">Save bom table as</span>
  4210. <div class="flexbox">
  4211. <button class="savebtn" onclick="saveBomTable('csv')">csv</button>
  4212. <button class="savebtn" onclick="saveBomTable('txt')">txt</button>
  4213. </div>
  4214. </div>
  4215. </div>
  4216. </div>
  4217. </div>
  4218. </div>
  4219. <div id="topdivider">
  4220. <div class="hideonprint">
  4221. <div id="toptoggle" onclick="topToggle()">︽</div>
  4222. </div>
  4223. </div>
  4224. <div id="bot" class="split" style="flex: 1 1">
  4225. <div id="bomdiv" class="split split-horizontal">
  4226. <div style="width: 100%">
  4227. <input id="reflookup" class="textbox searchbox reflookup hideonprint" type="text" placeholder="Ref lookup"
  4228. oninput="updateRefLookup(this.value)">
  4229. <input id="filter" class="textbox searchbox filter hideonprint" type="text" placeholder="Filter"
  4230. oninput="updateFilter(this.value)">
  4231. <div class="button-container hideonprint" style="float: left; margin: 0;">
  4232. <button id="copy" title="Copy bom table to clipboard"
  4233. onclick="saveBomTable('clipboard')"></button>
  4234. </div>
  4235. </div>
  4236. <div id="dbg"></div>
  4237. <table class="bom" id="bomtable">
  4238. <thead id="bomhead">
  4239. </thead>
  4240. <tbody id="bombody">
  4241. </tbody>
  4242. </table>
  4243. </div>
  4244. <div id="canvasdiv" class="split split-horizontal">
  4245. <div id="frontcanvas" class="split" touch-action="none" style="overflow: hidden">
  4246. <div style="position: relative; width: 100%; height: 100%;">
  4247. <canvas id="F_bg" style="position: absolute; left: 0; top: 0; z-index: 0;"></canvas>
  4248. <canvas id="F_fab" style="position: absolute; left: 0; top: 0; z-index: 1;"></canvas>
  4249. <canvas id="F_slk" style="position: absolute; left: 0; top: 0; z-index: 2;"></canvas>
  4250. <canvas id="F_hl" style="position: absolute; left: 0; top: 0; z-index: 3;"></canvas>
  4251. </div>
  4252. </div>
  4253. <div id="backcanvas" class="split" touch-action="none" style="overflow: hidden">
  4254. <div style="position: relative; width: 100%; height: 100%;">
  4255. <canvas id="B_bg" style="position: absolute; left: 0; top: 0; z-index: 0;"></canvas>
  4256. <canvas id="B_fab" style="position: absolute; left: 0; top: 0; z-index: 1;"></canvas>
  4257. <canvas id="B_slk" style="position: absolute; left: 0; top: 0; z-index: 2;"></canvas>
  4258. <canvas id="B_hl" style="position: absolute; left: 0; top: 0; z-index: 3;"></canvas>
  4259. </div>
  4260. </div>
  4261. </div>
  4262. </div>
  4263. </div>
  4264. </body>
  4265. </html>