From b16c0d21a29f490e2a12268367bad03f7f649448 Mon Sep 17 00:00:00 2001 From: Patrick Balsiger Date: Sun, 22 Oct 2017 22:46:04 +0200 Subject: [PATCH] setup base frontend framework --- data/favicon-16x16.png | Bin 1754 -> 0 bytes data/favicon-96x96.png | Bin 19767 -> 0 bytes data/index.html | 51 ++------- data/scripts.js | 185 +++++++++++++++++++++++++++++++ data/styles.css | 8 ++ frontend/pages/favicon-16x16.png | Bin 1754 -> 0 bytes frontend/pages/favicon-96x96.png | Bin 19767 -> 0 bytes frontend/pages/index.html | 51 ++------- frontend/scripts/pmjq.js | 88 +++++++++++++++ frontend/scripts/sui.js | 73 ++++++++++++ frontend/scripts/zMain.js | 26 +++++ frontend/styles/main.less | 12 ++ package.json | 4 +- 13 files changed, 417 insertions(+), 81 deletions(-) delete mode 100644 data/favicon-16x16.png delete mode 100644 data/favicon-96x96.png create mode 100644 data/scripts.js delete mode 100644 frontend/pages/favicon-16x16.png delete mode 100644 frontend/pages/favicon-96x96.png create mode 100644 frontend/scripts/pmjq.js create mode 100644 frontend/scripts/sui.js create mode 100644 frontend/scripts/zMain.js diff --git a/data/favicon-16x16.png b/data/favicon-16x16.png deleted file mode 100644 index 806956c3a2ddd0905acf8ec1613b46436299761c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1754 zcmZ`(X;c$e6u!u=#aK~6HpA+INoGPw!hk?RwjoS_BXr+@s}{%`APPk)r*M^BIGof*z4^|U#6-n;LMTHBY~f~S1Hh`@jyAU$0Ru}zEsHi2Z?p3q7T#{*Tbmcn zhDD2=Zy#Fny7@kaclwutZob#SyG)C;nQt{NT3dNXGI_6sx0-lb#G5gQzL}?y4b#!k zxAJWm6wQXr$d3^;+>+wxAW}@k-DQA{Z$qPb#>(5VTnoQUD3!o;iHGJL2tcGnf;@;s zDhx_gI7&PsAtPmpBhm_uh$i6Ck#?~!n@|@8Fvu^K5R{07f)a^Y#0!G)&=85aXjmFG zNWO!2N}b{ogQ#3eZ0B84Tto^2R#um&Br$j+(y@pQ3NRFdZ0Lycuxm`Gkr|g5N0{V@ z0+ufk0b=jcc?!pcCW09$SG+7UY7;R>*o)fAWU>lJ$2>cz*ioFGTC$TE7&fSyi~^J%imm3SX5lHMfi-<(&eRPJ8;XoZA+~RBx9G;q^*{0CQ)ixrXDrX2J-OBK z-1PIU=PDOoSb!H_dij;}7hb)1vFWu-mtTM53S?eYyxFNCuW@g^ef`Ee@2-d3^!MKX z;KPemAKkpQ{o_wEkbOhOr=NZP#g|`wUHr|r8?pVlzS1jKWgL2yoVl0tdpMTzjj=d^ znjm!wl2EACZc;;$dP+l769h#NW%u}&eVd05{(nwBJA#L@71b(o?5Nm%j%Svp+tShjeiti1)$9i(>3Gp%-?3@cY6Q; diff --git a/data/favicon-96x96.png b/data/favicon-96x96.png deleted file mode 100644 index f4bffd8bd8b59d6f55de6e569f5e209b3eae6eff..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19767 zcmV(oLGiwcP)Px#AY({UO#lFTCIA3{ga82g0001h=l}q9FaQARU;qF* zm;eA5aGbhPJOBUy24YJ`L;(K){{a7>y{D4^000SaNLh0L002k;002k;M#*bF002s= zNklM%V$JF|INa!vvYih_z@4hRY=AR>x_qGCiar)$oF5fwze zh=>RZh?o-yf+9KRw7YEHnd$E7?yB?q1NB}n;Cs{Sz3=z;d_M5U>q?&#CUJK6TD1 z!hZ=SWM07$;&A$NIMuG>x(2me+uBFailGko*>9$iUL10mDB?yyW%p;*iRPj?vrK>x{`k9NnRfC|N0 zwJtBob?qHE$A%mpC7}+JkPQ`7j6g;Nk(5Q&4gzfkuovJG6K1JFMjZeKDB`o99Uy1~ zaD4(b4-hu@*vkzOLW5SRL2Mz2HBqvDh*9i^IO01l(Fdg$sKvO;y7T`(1{m&Ki6~oC zN2%-@u00}+^vNNICxr+*FgOQ52*A~#B?(l+;JOG!QaW@7IOelo>?2?T)e4Am08mf` z3>DX5ut`Q4m{JU-g^>Aj|G#VoM*&0#Pz148hrTRI(f6|{`>Xm?T$1K=_=^4F|GNel z<=%iCWa}H$#uiCVo$A3mM?!XGuuY)7I`j=X>B}`}D;cUJm+~qTh|6-WDDsi%5<(uQ zpqhjn8UXf~WUdsTO#mr|YLj9A2mlQ=(tN?R#UOKWoU&HO5UVQZiii(CPk@^E92^lM z>?9#u0>}~&+f6b*wGo|NpNf~iT=QaTYW_R8C^G2(4Fg>1UW07P*0;#5?UP6j^4RMy zA=?nhHDP>ZQS`km#J-D?T{6%(KV8i=G(Y^fK_yq6AR&7xR?P`iE{N8ch%AjDvLTz| zRl|%+oegRu3kbB++R|(O>vlEQ?!nDra6JjxF+kWW z;GnyLDv3~JPMor47f}A@YsARR@!m-oYz)la!+TG6*cs^~=s_Sag2<;avL`hbjlX#_ znBpYkmA~HWzuo{p1k2IY>5MCkt8@17-T`S&kM!Xm4nQ|xtc+3YxkjSl`%S1(?Hakh zz=PM)gLhbnphv*ru_40zpGnxoP*n_O280ITYoygEsA?U?hA6BRCYf6Z6isvba1WUy z0W?)C^A*@INY4<2PasV}_kW z9ws0vEVAb0Ap510^j<%0Qk&)Y=+pn*1{m#*#i`oKVq*Aums+m9IpnaXfUpAuuqg6g zAr-zFBJ`4+I$S|^_c+r{K{eK)m6{a!#Dwvqf+|r^Nex;+KdUF9Gzl5iq2~hJTtW5n zICHduDhCkLp&J%i9|F9Pf!!v|x?IXhWl<~u2m*vku8P!fO%?<7eE9t{?Db0Ylgb)_0yq~2C>FBB*`QK-N!Rbp7BRjU2 z_YQK{8Kse)i6D~k;TJ_=eahgS9%l{%p@9Z1rJxS?*vmD^cqa!ruXfeDtlO(f!{?&o z4rrU1(Kgi)J+%|!rCfHF4}WmTVS&lEV{ivcHf}_0pW~W0AENjNJfA4bs1iB3hk7YCy7k*>4=Q{o&3?(B^8n79EqFF~S_4y@z)X^brg;VSbxOx$jnU zO`{OOsQ`5jIOrH4h$JXJM}ggd{pKc_Qwpi@J&(Qg^w`vY*#P2Sxp6neXVuXYuS|8d!%tBkF`e2#-ibtk;aJUaw+#Z z4Ps9csRzE3i>`K&$vHiJ_WoJquh3CD49M}3pm^;S#)wG?#P9Uk?^MQRH|J8$`jfO1 zZ_7dU$OuL5)SxY`l%YT?btAsP_aO3Le23+UZSex$bTT=OqxoZ3pk%_@X@y z|35##OP zoxu*$ciLnxBT%M{_dNz6t60>#?5@ad&omd!w~cW}%l^)Q<7&9}J{{UeEvd!Bl2!Ew zvG)#2{wU{qJo)Tn=pPx-Ey>A;31V+OsyBK;_}!8yS%)Ma047E!z=9PnkP8+TQQ^%5 zs;=RhN6s?_b-nk6yKs{?=74K%v&JGBuYzFO(SYjTPM|$?sC&4TXw_o0a~lrR+E>oY zd@wDWvTq0>BNbeEtpJgLXkNutFZ6c?oYKeWOQYNy{wV|e!%x6)XCxYlMv=wx`%41^ zBcq6}@ZmRb*y*K1|Gr2RUj23W?YgI}C-9R0G8$8(HWgek-XL>zKIM&PF!}7~)o`t? zpol;mqnMYVcrwYU+SXdD5Y1n&h(Wjb-#y{>*JEIATXBjYT1ts>6LZLG7(+-?u0rC^Oc=x>w#YI%_R*$`k7Ss%{ z%E>rIoOomfSH2`5nj2)4XE@VLLG4aZ;^qOy1s{GDe#Nib6aV)NaH%sK^{Ae?TCEx3 zvOC72NTq~K0aO^U@8weNH8cI`OKywag$7hC7Rm1$m+`)bLk>@~$^IflC$gBb)3Nq|>j! zM!#Xs2$*CVm8!CZ1E;5iJVvo<1VWM-yNF0AsMB+h{ep!0$cG10wUjm z(?~+L2@rIaEIVt^el*GaC_(YBPSSeq9;RK)=Vb;D@!21qP1qV`0W-60yZU3rvu z{rmR2AKl=N#8t*3F0bN;#2T>YGaERIriN*?m2S8~;8gNzT`h*lGK zsGY~U>|V%(20C=c9>cT#3piHmc623Iy%r*DokdwMH=)MQ?%*9`7|?Q&^I9!x2T4{PbkaY|quhB_ zTzxe|`JF}Q+e^9Bd((dHpzRNIE*lc!fsU3*U6`90D|KbVEsXdnKvdG_ps zj{FhMRcIqx>0iljZVC`|Dx|`(9(!doW77|ieZYGdcbDCP;e{i!OS$Zf3^ErhRtkVE zAhy_Kzt&VVS)S%}@S6R~LHlyPb0I8P#pS&3Ngev~6SN-BY*L%$!Q`LMyo9GRMS~c{JmUqjSKg#2u0>Kqb4_| zkgj~ke(QJn{oQ5gMd?e>jG9^%TzNx);AETZ*PB!G2X?5PMIL+C0Vwp4>10#%m1flR zE*tjR2MQlHJh@mtllvL4#;2i4_n z>kgnPpp#a6yx#qT2qH@*WH$xXI7asSvwwVVX$ZkYfDgQw8LMFQEXg>GktgQo@?r%USx23=s#zG+uS=bHS;F6@Rrj(_AW7D&aX#B_tz8k z(kY~_4iFs1;6>R;+&pLgtl2ptCsVl zcer;S^7^6X5cJTF#i+>0A2jIm9XP{|(~eEN9lUc;`IGe%F*}@Fr;{-^Kyd1iGcK*y zO*;k=ME10&_K%n_U-#kXWH{5KnrkjOTkjn-qDC(nFg|zKxo#_O?eli+pYeO&2!}Ml z8nq4=L@sPr$H}n*q9l*d2Mop&gHGB)(;4t(NP$Zc{sOcjR_>QGfM3VSThGfL*k+U3bbveLcMWi{GYp+XN23NcS4znCF|r?hFPOICNUclL z6sN9_ATqlF)xRgj>GGfAOVD0#hgE6~h8mYfeFVpA&=yVbUr5#$^$vQ|d2&9^G|r5A z$n@1o|M*>h>Yn;k|B$3HGq$R2INur6)@ApK2t_7Mj=cKi#rk0E=G|U%(ex!jVtWm0 zZfGmo#vXPb!SA7oXoPn%Z|&7#%=6)&bEa{6Y_a_Qpt6OOkJF7)N(5=E0{AD5(y!E> z%#6cJ(dRKcoXazv>EGs2-ZeV3vJ}$8PSkovj-bOATd<~v2)ooFd2J`rDLT}>{O>cs zgv_h>BK!)g)tVDL&RlB1_^b&vopZ4{tf-tT9+r>|6O?$NlB;Up{VQ*v4<89`jd5>{oaYS6@e$;es?wuFgw0}zE&eI7LQIH0hxKyPL6scp zUWWEsJ2Qp!2#vHgokYi(H~V9GqCEj`Mc=?~wWltJa>g^G#U9?%dzv=|fAS8#1bi{` zGS1Y_#54A@dKO|!6u99&Ro*Q?kbRXi%AVxEuHh5>I${Uu1M!mos*J!~5OUb|6ZLss z36}r>#z&vV9r1hdLHPc%IK}S{IOw%Xtr>cM^xiOwVsB{BHoNRzv`K9~ZAxY`9`GJM zK%WC<#{ub!kWGo~Eo$o|AO6X?lsn{b(ebM#>WBMXcCU?6^r2TGFFo|I|0qxV`IWIG z`~lZ{H=%&?&voIB$fLYVx2o+`-L+$)rK+@<3$J5{upNV&NyuEq%1}@Z7+e&g$Wj9B z)*x0#5LsSG1#2g|FQ;C~nuseSBd|uU!*$+`NFZ@+3aR_D5E~O9SoLA-gI{&N$sL1d zs-Hyf>~n_u@Xs!$;wxRa74O;m-|b`E+t5KAMxV!0ID=- z+f6dk4Bn?f-w0rRF6FE}UOTR8e)x$ppf|7Knpd(Y>uw*x;`y;Tzutd{b1CXm{m3%; z)AIp>Gjk~Cnrn=!<~^NodJl#s=trRUo{b#yj|^h?>zln9IJJsH-ooY)S|9` zh~Pwk0LCUkV!H`*o5x;91$A(D;g zt@gZjiE%M*`S}}Tm0W|1oS|qcn)I&W+9@W?4Y`yvg27rjm(Nn*;shnG{>Y#G=5>*q z@Z4X0CF_6PiFIl{1{wo$Hp$JGFgR*c^u1EG@5m5gKacju~)7VG2 z%DdL8P?gQols+TF-tgVLr{6jD`4byyjTS7COPVO~;Wo@iK9^s}d9m3CJj$)9H6F7b zDmlwJ=PMunDZTYG=ag`1^u^%i0U7o$AkaRGtVy|)ySR;Lz3)|jlI);&fKB$^6jDd) z(3ge?OFywc#KW1#^>u1pVKvuu3=#HnkiKm;-L|XMn!5t{r!lbFg7rjw zsz34(UtwQ(gktjufaNzV2B-Uxrew0voCL%v{*N#C0 zts(Mii&4$B`BTEFSJt5BX#vqjgPyb~@`?}t+c)jk>bjUm;NIwO!~Tc}8nh_03KV2g zvi$Y8r=pLeui1x-sA$(2+NsZEBXPfi?3L#99bl}P5PiNT7r8hT;uJ@rDBQqcx0nWeHAtc!FxVLQtGq-A51vaPHpxsFFn-hCB>QDN9eqr;5p8yCQCr?L zNFNVy!h?H737010jjv@ATfUui@$OEv&Bx7^H z!8rr;3$oYA^#>ZDk}I)QZfmc=T`aP;Y0&aRgoXK(_euttW*Uj=9LnCEpac?}O(*KT zx|VRsGXcVrZA8aqQT!R5^zvNFt<0jVLz1LHK!Yv-2nO@d4$1^Zc~;K-T&^l$Pg zZ;VOiOHr~uI68G4j@FMlWZOB&!7-6oCwT!T)1cI z(Caj4yBJ(t%B5Y(xa`*_M+boG-O(6tJ%ux!z9;L@t0c>M60(I&_L!+#-rRFWi?cfl zh;99ibL-{>ADJ%)uk_0xbD0kPn?fp>yisi`%|TAjfP>H{KN+xpNRmPh0m`^Uq?<6Z zLJAHlcaL=k0N@?GwH3g)U;aJ}iw@cL&#|2h;3NDU(4ZlLh?#~%3d&KChm_T!L5J=t zNHa>&nyJw@$DQX4T$F}$O(~bQO&~F@M3rvqpdD6GhuVD-vgNU&`;70@qV5v17lT(D zWULP0pV?18=iA}#Ncrm%uv_iMQ1`NY33-$OW1|PJmLIzBjX~jxZa&=LX(|-?F|0`fH zB&z~uHXJzB8O|J1)*=fwY*&M>LJrM=?nV5qTClht6^#`Tbv0c3SPRko$Ty;s91YrT z3Dxo*_f9X4_++1bEyJ1iHtdBGs@)>>efDaGA@gR9L5Rcd>1ahF68ipIK}UM-<~nsV=s8!eiaM`LlFZY62I$WEueff5)G3& z8D$J^yi4uIqHytl!~h<9NFmh_gp5sgZItXo%1S6mNcv?Ljlrmhmmok`)_@v3Vvzn_ z4cFc~&>eClfSmy9-)BE)PPeD7GDx4IAR7Wm5vVT3sqWj7?{BiXD#paN;CQO(xbO5oC>Ft?&Fu{Hf!2U;Bhb{?Z8qjs| zJ5JWtqBWj(#jD;mpwjV(E+i1nIDY5K>6UghZH=LphHuPzzRH zV_t(tt-ma#4ANo1Olzb?HE7w|Z$B@7+i~l5oMH8W2JyY*u+?(8qPT)9{%`|qlAAHS zU}Pdh*o8pfKbd((K4%?z8&QFwpt2;S@56Tj{AHed!=8w8-k0elI!x3_`_^Oc0tUwb zA`>R2*?-<K4jT$3vX>u$yLznxDFxYVFbzz5O$Q1ISC|odGN4YEyoes z;cWy&!lLK{bLG6BM(CI0;pm@!qnr&JHreGR?1YtERTv^%&&=qP?uT|-TceyS@@l!Z zaT-n`fuafuA;P$XY?wr{=MQq()CavsaF=!aA42|;U@30N+>RXNbYiH6*_3b#si6I3 z?iFf?Gb{z5uDxiRPIFp45`7TNj1$r)Lq{}MfKopE^xt|nC)*P-*tsOrT(p?DPOWPv zS+?p8 zPS#J#->vpsr=W@$TzR}W7SG$`4(O0Z8U#coK~xaXaGTnOi`~l#m~i|`x#|=}sx1RC z1(hbIvMw%Y6gAt#dCB zBw_{|>jDIE1$EHQex-ssMnGE?u;2E2cXV8L*(;Wi9ent90*QqR%C;%$4YG!`s6zGGG1#vrDLkJ* zdAoQoJ_zRGT%*r#ZXBm9oLJXWof+-B+u`)xA&esoGG-=_m|ZOD?MQPv{JpKh{{(*C z^iKj<`?tT1cE_Sv6u-M%E-$L%R1c56^UG1uPeBzXC^6+^;|x4wJ%MrfZ8+lBask$5 ztrRzUW148t<^XKfadPl{d(K1WIv3Omh@ApL*P!KPzzu7;wvkA3U26&1L_lmM(8_=V z7ff7(+VjEKain(SryBG<0$R)2_Iu*9@bll?^b+TC#1PYZN6+b(;mja_*e3h+kGIWz z=18r}mgl0+{MV8HKjG=<6SyUEv+Ak$D4pxgn$b>cbCpi|j}o$;2e*G7Vmty z`+jrXKHi6?{AZ#HvJrvSTCk=_$YaiT2DJy^g$UCEv@Ar>fWi4mq}qryoTdzp88DUz zh)MvmhHHx@%i}DvX3h!cx*D{#3aZr;nWwY%slPb$M!7fO7;%jLgIYGkg*VnFdzwYo zR1aSF(JjYD*Q&MuP{;qWo7I++ zW(BkHT;`8Y{rq>~CU-1mcyFVO_npn)dU0euTP*60CK9EUT=i&g^Q=~H1#jaWe+B>` zK!6PVmIMl7l(lnOFkMApekfUWm5_xDh6ZgrfZYl*n?UVEhBK`Jq;(jpC6pq9m0|w` z0rBly;oEglM3GI2Z30viAUJZRT!p7H82fn<#J_7HWCjjR!41DJ8vwcg4iX_<^K{P zeaGCdHlp7hrFFsGkvnllb{`lpmMO^Af+$-e^!Jxdpme}tu?P_4G1&FsNdTD;p(#kL zeARv_*<3UO5upf$Xh;oK2#DP-+%s15nzIzkBXf{Fey7@1GdyzHugc$U-GbBflQDC_ z^q;aQc3;53NgLFr+cao-U6S1n86WfCfX~7&(YUS!EV7FBs6BTpsN-@d``&je-(GW? zehO}|t_85)ozh+FhR3akzBkF7;&Ep9NqWyV8Dx6vq%S>LKWSGzss|#12@^K#O#z1y zX4r*Pm}a1oKq(0s6AH>=FbD8Shwcc7Y6frUo;m@KSo=dej?s?B962v#k~u5n;QTb4 zu_i^{9~XUmWm~Ncdh2KYrX$Zq$KmE)x8Qwy#<$s&xJ|O`xQll`(M&YyFe`YUu5)kv zPjh_$#<;h^=ZxsCb?Z{1O2#p`O%7#`oncS=?zW;k@u>CCZ{#Q2ui~!EecXWRPbW~t zKCXCBLUoD2oc(_IfqXUk5&*y^8~Gx?lEK>)WSxabI*)Sebm%nz3_<(TZ8Qx!#bBo+ zh?K{WwJ(qIevRq8!MYa5YTeL~8hoXo+>k?~fb!qH-W|iQL=V2odCGbmFK1rG%y9bB zVo~pU9eSpQYbXCXn0m%@&Nw{fjr&h?{wuC@u0emTA3g8CctIssz9dN7TO^9Ed(VC6 z#}|SL2ax{@2I&K^Kz>&fr>w~yd&diijfZQUeyUIPf90+THO7n9c-JIjoq#CKz|X`G zO9QA@P~sQAafHFbg=+-}vR$}Yf4e#1v4=X;MHnyvm>JI4A;RD7*b21@NxKdXJ2`Uy zva42umIC2_E%pDOfgk~w90I6_3E4XI-4?9s!S+yGYhHcG>*`Z|nEUsU)&Bof=&{HC zUwKN~h*qE)0)c8wid3GipAwdGnXjNy42A%h36ztEJj+KA4-pn9sK#H&FEQDF6990h zdk;SF-$O0eou!kOG0EIjgW6%8wIlRPoXZZX+!fB%=%5`YF7k)r19_8Jrz}e+o z@kA?X+3Kxe8eZ~V{>?QboROGjO`$!!X8?oi7g6CI0@{iU{B!&1=V({B`=6XDuEJ01 zr|f{k4hkxl!Dbd^nFNXp2qg@dH3}->!Ob&aWJM{ulR(W@tF;AHT#ZkI&r#0hsNtHU zn30u5S)a|c-&w3fpPNGJx^s-Pn=Fvu{i@h#cPys3uj8xm+fy>|Z?edme5^S3Wd(Mo z#isnHx&B=|Vm%12ql1-d)%rpz7)zkKYSi3+xYnuRJURc@QT>efEaryu(BB<+bcX$* z5sJL_aro(43z2ythuuF5zi3j*WdHyV9#ZTy5ukb|Of#SIBQ;!;FCiNc$P)ne0f-Ys zGaW_@ptTJ4lALVs!o{1x6!g)0YaTME3lggi6YX|h=w8f4RPZ_hwN+d_rhxJj7djUM z05+-3IL{i`I?1V93>Y7rpdJ6_4&D(?{y*Z7voss)vsR*#t4a&0;9df86<3XIOif}# zoJ+yXm=n&$iCV8_NlxCWlfIz6XgB*ry%%yRcL{)$1NZnJ;6jYu8qe3vaREJIh`)wpbTe2(@5UVA^9@DJ1$z>PI)bawws=Wc@i%-JO z!|RM|uug5L$VT>~l4a{%ylYe(aqA-I613J@MUqI4B2alD6--(xe+(x6PTc>0BZvq$ z8#iL3+Efxp{Bg;$%XZ$@Z))wE7~~E?u_!LAMCIK?lq{mcXSb{EUNMUBMs!l8PWrNd z{hsIP=b9_jO7zqF+5jJ|L3|Y;bW=zf60$XbIDlQkqR3W@B9$6xZ6#E$g34Hkd@fma zxzZciC=CZ`q+0-NS+G{;Q7(EI$KxEm4`w8%t;?pwgFXkR?o>Ok?kbLoY?Pai4I#T{ zQPxXa)Yhuu=CJ=XpZ^rjFi%5gaRg@C@2oJ$c+2C=r314sYGlGJ+{fjAV&=j;%DsP+ z+EjL~aSp~upT=qF-fY5L$Uw6SR29{79rkibdkNKmAimr0j1y+aVMhiV8fn`^fN+C^ zDplb68bl)kiG0dm0YWm3)X6`{9}yxvOe1Y?fyggQPyzsOk98-mN{qsL_B#u+DC+?U zb=IfyvwJ=EMrzO&x7XTz-%_-|*~VG_X)gb1OtN3bAa@8FQvF#3O4XwF+EOlkikTba zQ~qu9{ZBUzG6vuha|nnC7DW(&u}MMcNlrHV(0v~n_-APl>ka6;wf*rUi4fsY0Hh9W zjWA*CAW&LBcmQ<}B#h?NG-<$?6CgahpK(qxgIfz|n_sbBbXro2Ulp8Szku5^ci{tj z##aeS+~FhWltJdK2+YkUBCP*StmXeTyz0M(>E2XCDH;$_S(=?u0Lfg+xp{`1we~*i zE{u-c_^W)BY{V&1AxP{~kgWzp2e$}0>}DZ4D@swJLz6ydT7(GO6UYIuRm2hB$gENV zwB3Po7=vTGcsCVL{-*%EJ!;Q|60%{4aL1A9Zn(s}_%}*EW<7-aGY?^A_|6Xo^p7=Y z)h@h2i{zrmYqK0kfoUO`k>(6>`jC&iN z{DX|}PVg?~gmckT>v47xsaq9P9fOsC&;ST9Y6Qd`)F>-_{0lQZzo@Yz4=T;trY8#wjl-@gs0Oc4kOF)D->`DF%f7a^rjee_d^2SEWxGX#1peRM@8~~(4kGt&N!o+$#tqF1u zk$CaHfqdkln2MpGYMD71Bm0>UvVs7WpzJE0^zug3uy(av6aJFvz93u-1+^(ec*+jm z8P9O$00RtlE<-bFYA#fZI%?2X=TOeH_rnj>Lb(XXYsVG1>}FYHtx-@-;>cPw#=Ax7 zO+;fvV6Jl6y;hOR0H|}}p8QGb!wu(VT>wQ~O^kF1dD;B%8hmzPfMAeC(a#8!28aU$_>=!&La}USk@bECnU)&#)lEf{l5EO`Xh;q4 zM)jnWAn{`c{s}s1`y^ziI@I->TRjUp^nk%$2AS_ISTARgxni9+#nRV^8cELKe4wYPWf&w?P z5#1;`Y-^J7+05Vrzl(MR#QoNNI5p=iL}7g`Sr+RsaxJpyuXkXF+t$4WM`N#a<}l-n|<~N#$Z2joq6@A z3~mIVm$AhKY<3#Cy*H+ zem9fMZ=SLqD{1_5E`k7n=As!UJFnJ8V1AfkzqtYz88DV8=H}n31!w8d*M^YIzL!h0 z&o>5Pjas*+kP7b5plwORxxcq@?v>e;i0EYK5;FVuI<1oq6OpK5DN~$EA1W&PYUg^; zF2Z^4z{8&nUbycI`Q_1%`%mIt_klyU{aEHnG_Pxev(x>KIwO7d#lxHt*@K)Rhm_B7 z1}?jfVkIMpM0GlJUPFpgsN$+D1*NhnVfNO}9$v?FPYH;9xs*F*zWj7qAFU5+Ia#P! z)zct0oEII~MMCwn$=+zeN-3zu79w-5a|bz;IY!&Vdk)#|Hnjs2?N>#H zGZ$po|I=PBxsREfVaNVW_rHaJfJPe8{)z#Id~ZJMKZi244-zsr;Gq5<-g{pFzju_P z&$kfG?~lOTEM&5L< z!|rt!MW)#l`x6tlU8ue*{3W^VU?@|inCMR|U~qez>?atkS8?_Da|+Houa0XI*a1xQ z|56)BkN|-aM5JesaYFv>9`}vz7(C%Uqb&>;H)tdp3<%i2fx$w9_E8ZPjhb!GoSlsv zZ;Jgou5)k1r_p&7!0(}vw!4OF&nA$jLEAu}+C z=R&#YzG|)+ub{Hx6dyaso;4+#5~i(FZk4+_iIBpI%6;)d=)*k<3U%*>6LxFvz2g2k!`nR5%MV2Ou}mrL1r!Fra?bo$)R;Nte; zurU=};lK4awK<16m!XIXtyOCEGXU-RFgp988#AN%MC}Bc5zJ~{hh)D1K`#bJh-sq$ zZPv-y7$E4*;BFB_#sRPc1kIVbITJSrz{Ir1qR1D;RJ>|C?|6WiR(~nK9(Q|WEbh1N z1ps{Pe}>VSF=#59^l{joV3M)Vg7tuaR$0R}Qvj$O${w~wZT;#_>o#2YSK0c%F#t2; zOs5ZGh;=CEigy)MaW3UtJU4iM-r2^v{pvXRT!bR;o}!&}%SN>+ocwb+vTyuvaDVU! zqOi_L!?_`sa)*T+?i;9IK%dJm5|v!lJb>RuLbYb71_q2+2AO6d%O(aHpJ>pw5NKTv zWv^*PEqB!+8UA&7_`d1$V8T4S7PU{>h~Axs^ZjS`N52k$5B%A9$bSs=sHmsI?!7sb zbCZwE$~m!F0QP4@9;F>gvw{x_D!B590Kw4=ZWD4?6e2tVK!pZvw@$hzAW8+qdJSTA zF6C~lPxZ?-tIg7YSzN&tuh|rR+F|#z8PT_qr{w_vE_N z(fRqM@`pzqxYt@_z1)d9+*ro@yuaNS|IG|YM7Y!$j+69W>!t?NUQ2QM;S{GYz1+NV zL2v!^*^`1d>bdNVSR#KoW>z@;yQjVJ7;W8vo@P&+lRh6&ver55!e_s=4}af9<{%zI z7uEt;{*M3d@|L0n&6l6(%+Qv}pE}o3-JkL)@3|6HvgWJUXNQax%B37M7tPl!mfwHt z!W-6#TCBau8T#v@{mo!1+KM*0C8~6|PWtCvv?JDRQk#Fh{sHSgVE-grJ~Np0Sx3>~ z^C`hJW0hRhr51IML}A@8psk8iR@g~&bZ*nf26NPhILGYs>!7rt+7Jj)imoS!U&${~ zrMSSk5OrMJCFJ15D6ChSQ}Y+rsr83v;P=;{ZOK8-#2?f$?@sF$Ov7&ta6m%u8}=m3 z3_egflsm6OOvnYlF6qE@T zyL|XPKHfPOqrF>xZFi740A2N?_^!z9!791R%cGnXf@wz$*Pi-S>@!^N-E_#w^-cRV z{3L&pS;%^mSvB0ryN2{MdWy@OD{zH#HBQuf>g8N<853tGDE{VB`Gb7Jo^;T*&NKSs z1^;EfzsWtm2d|sP+UELH{CyNw0-C&2)`(Jx zWWV4e81zvvzt3yYS8$Orh~|eMpBEtLYr`J*u0MVEVWR!-wzWg;z@TkIng$%67NN-d zU&(LX)AiF1D!W~6$1rz9Ziw(GgY>UIm0$SBYTa<3`yfupoP-vld9yO!_oU?T$Q)!p zzf}HMwMA_`HN%;6BZz!aNCkiXJp5cvK1B7%gBsv|>mCfyFF<$gn6GTICxi$)mvi}D zEk(Tr9uG(c007!Tt{5cm-E!!Z2g#*H=ZZ{@s$nmpND9Wc?&ji@L!C+S`EYf74YQi4lPa0RAOw)w#F|GOWDpYrdWFYsFCb$l#8#TVgM$At)c zWl?O>GWApHPV?Yi&@tW^oS+{c2@ss4llI+hkz04?Q7$s@>__~^ha{1@Ph-&}LXpL} zlskE$TokE5<@F)LE-{Kdb+U2d*B6^ZFvdFc>-Bdl=T47K#U{16JRkY@>(G~^Ieqm` zwd>YA*e}m)~a>*DO`3y+ou?( zpo2IJU9`@NO&IgiaIQUCJF3Cl@ZgnZzE_KY3P6Vu{Z=kGDL~LogT79%*x|CCiZ$JG08neR>ae{Vy!!**Pbm()B)sFq4ooI_rMyCU0nHf8H2iC~7T_t2&3(@zx zXoqtx*B!otcRiAU-`9e*NJ1u~u*SC+?aEimRihntMpzV?){q)ZUJx#nlcF!<_wYZ4 zDBtDXiw9GGLjUN%UKLz1Q9?F|!G5-b*5TQ;YTb1bvT0Lla#tyr9qY3{2*5s@qO*Ji zCrg$&twpPwYEhd!)FD0Rrw73%JGYd}9?_sxwHB=&tmbOxmm2){xPQVC+7a|_I3qvJ z&M_{#=PIbi1{oh0QQ!p!CFGSc2K)%m@+c;(2*-o^5+l1-5aCzK8j(<8g zeLf5rEoxEsunF_)!PPPjWbW<#k0f98=3!<<-=&pC)x?Sy1X-*?f zS>|rFr?U%ppkmpPAWC)8zKJ2WG*0pD%|!E*1w;EdMrxO9|8n1V%lbtJ@s&{)2bzM$yf>5sXo=ezl_TUr`Z{$Ltj-y zMI)EWA6DKJxgIw}uKgdm{kwzohdP&`0W~mIsa03ha@~Ur&Wa*BJ5KR0lbjqFA@h|f zkv~uUju&D|FttGq*Yxx`=p!M!YS2~+66!YxC0JJXy&kZ4&0O-&~1d&Jxd2SNP z;R52bpOtG2kPs}^>!dHtq3rLE)w=E5rnal6qfh*eewV|5VbpR>s}$0`6jXNwRUeFU zL9|6c2npFcfy6Ts>QjaaUARhtS#?}_G*o{ZAKRE@t&p;1oiJubmNAlb6dGH$L>Xf+ zi5X+8Q;~HDAu5HCUo(kOwvvcS${HpliXveQzZS|e^WJ{vJ?HIx&w2m2=iYO^pXYhL z_ug~v{XWn4`Fzryw8U+a<%F1RmyRxqZU4P60CX@- z5Z3Ir9cNm-tIYdse7=KB5Rd51A_ zC@1n=NkaUdej&MP7?5`ks19QR`oC4i-nsF5xh!gJhwiFlf(e69zTQ3CUkK!BBVvtT z9nvTFRs=4&`%}i|t;_mS-DCS`^TZDyuEv6TX2on@>aeCV4;zIPyGa zpAb|~9dW#%(bqDNf%2GX@5|2}=jq9IfU}M&9-o!Tdzom=SpD<3@Qt$phSz7~1GQv(_?JYiHXC%GJ}skN2tI>mP{eJwrbw#y9{SmKiq z0q~T%psSZtj^0MS`HP20#ImPKO*i4UEo*TzSI!E@o>}U zRo%JbI^`S9;p;=8QZ0X%%|?U#b0d*;dGzo(rBR0~+HREj6RUg4Q-SgG+K*)z zKPUCgU;=b&9Yq^yv+m}zXGwF#uA%HlT3&m-G9@U(pU-H7i@pwoUp?6U9P4`P(_k-N zbVtagXJO{c&-D`4*S2YJb6q4HAAXn!OP<{XXDIXO zneMi8L5OqneoD*c8o%VxHZrM&^_OGb%TZ!aXK^;(N4@6}?Kvl^z4nU5&y^gg1pZV* zs@(ub%A<1#bdPytSI%{Xqx|V6b?zqPr6{knUgI$O7GmU~41UWj=croLc94bWTarc| z+O%(8W=}(j-0=ey0JUJ3#ONC`HrYVGCH=yL@DAtFyEj{7n|=06H5rU6aNF;5Gf>CP z?w2L$rintF2g?Tr$~iImhN7HbsGs8St;aPng*2Gc5Dn+KV)e|2rLZFjD|EH5Ln=Fx)c$P*B~FE(KHd|B*XRMiE%^nKK!QP3FEhOc+w=c-2jIba2jwS5n}9Y3s@%14!tVXQaXcW(*qssb$g8gF_~4lvN|Z|mC|#Z1@{x>*TTO3j3*P# zf~EyK-&PvmT)0PTv>Pw=?T$O}>W*#Vlsl-zTGA{9vV`iiaLt9FvM~GCDfq#aPiUw0 z^!27+HWDk_!Dcpjsd|y{<)x)M69;t|p`(gCtsK@qrenD%B#hN?&yhUGkZgU8e{ffj zUx2wUeh0%1#q7X!#&H+741t{e^gTh`~ z+2wj)yEqYin^gK}eqm(8QI>DELc)%;cC;#ds@9IU5Q)2iX8Y}};}G%{99|w2X+(>@ zy$o`%oK|F&JxWuI7ME_==YqEWd{F4~hA_v-|2AcR*Km1#QpIT&(mXaI@teTuZBwYL zlci!+I}%w|7Z1N$FHmi}42gk+c>F5xx|*HB?}?^qR;k%Lb!tBK6?rrHsdq{mrz^A` zp4|IJczrObk)1*uDO)#4pKKG<5Z|q}1yl zkgzM<@s5^|p4s`F3&m&yvK<9!Z1Qq+qd8pYNo&`8nH{(jV9D*$hQg{a?+xnE8q$3? zImE#GOXcW(&sj9_ojQFpq+=Xp88a3AQgt{g!E%?p!<8ndG`Q;KO?5*+2F8Cn33;_-Elw8)U2gpD99%P{LsUr zJRBIbx{<3)pGYs~5->pOI)IxS0$F*17s20+Xm zV7~>3)G*cSHv(Bh^_DYUY({*)d0xv*eDz`4`0|>{vUz$_1?+di?crNg zIOA?@Ju4I#(I>*0B*Y(}LEOzL^XNn3-$-!qGD6EUZ>hPX(Rz+8%D|wpje=jpEL;vgea` z{wR%wexu)asIeDTG>n>724qy8_V$S|J=M2b0JRyk!(!d5REBXkHcsJZ&Cn4Qc{15E zaRn;CzJ{>Kavd=P7OR@h1m(!?kFrdL>}KuPZ|SmU9*#FlhTSnbH{f`20Tox=;{+6$ zoJGQqlo<%U_z1zsA!CmT2NCsWxrMps=?IHw=V>ZM;Q~)rdv)NJyT4S14dbds?s-`o z7wEl9g}j@8y%Rj&2<}yZ)m<^TyF;EO=rW@oqJF$dN~S58j0dG9j``=C!Y}+R283LE zL~~63P9X2&-!yE8Uz6>%vS^iJePv~PR#jcuUm4%RSuM<6QYiMnr{UseSs=h1DIfh( z*|JBN`1+PWlASW`hXO~M>6;Aoa%oEG7Vz2Uiz#nR*~OP>H3z#JHT& zxZ1^Pc-?-QtK;eB+I-#FC!vIIr@|7Syzt|;0)^JhREq0KrP0QiDMfioY#`+ANh>2a z7bFOrY;Q^4HMmDGOji1Y(NJ^>L`S1Q$Pxl^w49M2>n&I{+a5j;WGLh;$EHMaMw3|>Kn?ir;_l%!Tq8e<;Jx}J<9Es4k68h>tb zoNr#}!?Tzc6N#O?Dt!)+uhOJqys3dWDglkB5P%cN0D&}tArUYG19zk$8i_(1B6JZ5 zGyQqm;)03zP*r1n6MYoS zR22wm2tydbkOr!*NMqFyDwT|e!((D%^ohUGzyYB3NtED;v?ahHX!mcA?jccO0cf-> z2_F?k2&baaE&wzVgkv5CLS5ak6Du`zQSi;g0lm diff --git a/data/index.html b/data/index.html index 5541332..51fd3b6 100644 --- a/data/index.html +++ b/data/index.html @@ -3,38 +3,9 @@ Esp8266 laserspiro controller - - - + - - - +
@@ -122,21 +93,21 @@
- some tests: - + + + + + + + +
last uri:
last respone:
-
+

diff --git a/data/scripts.js b/data/scripts.js new file mode 100644 index 0000000..4c85a3c --- /dev/null +++ b/data/scripts.js @@ -0,0 +1,185 @@ +/** + * Poor Man's JQuery + * Lightweight DOM manipulation utility + */ +var $ = function(selector){ + + var that = this; + var element = selector.nodeType === 1 ? selector : {}; + + // utility functions + this.util = { + // build a fragment from a given html string + buildFragment: function(html){ + // set the html to a temporary element + var nodeHolder = document.createElement('div'); + nodeHolder.innerHTML = html; + // create a document fragment and append all input nodes + var fragment = document.createDocumentFragment(); + while(nodeHolder.firstChild){ + fragment.appendChild(nodeHolder.firstChild); + } + return fragment; + } + }; + // check if the input selector is already an element or a css selector + if(selector.nodeType === 1){ // is element + if(selector.is$ ? selector.is$() : false){ // check if the element is already extended + return selector; + } + element = selector; // set the element to be extended + } else { // the element is in fact a css selector + element = document.querySelector(selector); // search for the element + } + + // overload the innerHTML attribute + element.html = function(val){ + this.innerHTML = val; + return this; + }; + + // overload the value attribute + element.val = function(val){ + this.value = val; + return this; + }; + + // append the given string as child fragment + element.append = function(html){ + var fragment = that.util.buildFragment(html); + this.appendChild(fragment); + return this; + }; + + // prepend the given string as child fragment + element.prepend = function(html){ + var fragment = that.util.buildFragment(html); + this.insertBefore(fragment,this.firstChild); + return this; + }; + + // search for an element inside of an element + element.find = function(what){ + var found = $(what); + if(found){ + return $(found); + } + return; + } + + // get parent of the current element + element.parent = function(){ + if(this.parentElement){ + return $(this.parentElement); + } + } + + // indicates that this element is a $ function + element.is$ = function(){ + return true; + } + + element.on = function(event, func, useCapture) { + this.addEventListener(event, func, useCapture); + return this; + } + + return element; +};var Sui = { + ready: (callback) => { + document.addEventListener("DOMContentLoaded", function() { + callback(); + }, false); + }, + select: (selector) => { + return document.querySelectorAll(selector); + }, + link: function(node){ + return (actuator) => { + let update = function(endpoint, method, props) { + Sui.http.ajax({ + method: method, + endpoint: node.api[endpoint] + props.join('/'), + cache: false + }, actuator.onResponse || null); + }; + Sui.select(actuator.selector).forEach( (domEl) =>{ + let handle = function(event) { + data = [this.value]; + actuator.data ? data.push(actuator.data.call(this)) : undefined; + update.call(this, actuator.api, 'GET', data); + } + $(domEl).on(actuator.event, handle) + }); + }; + }, + util: { + + /** + * serialize a flat json object + */ + serialize: (obj) => { + var str = []; + for(var p in obj){ + str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p])); + } + return str.join("&"); + } + }, + http: { + + /** + * ajax request + * { + * method: <'GET', 'POST', whatever >, + * endpoint: , + * async: , (default true) + * data: , + * cache: (default false) + * } + */ + ajax: (config, callback) => { + var cache = config.cache || false; + var data = config.data || {}; + if(!cache) { + data['_'] = new Date().getTime(); + } + var serializedData = Sui.util.serialize(data); + var endPointUrl = (config.method === 'GET' || config.method === 'DELETE') && data ? config.endpoint+'?'+serializedData : config.endpoint; + var postData = config.method === 'POST' || config.method === 'PUT' ? serializedData : null; + + var request = new XMLHttpRequest(); + request.open(config.method, endPointUrl, config.async || true); + request.onreadystatechange = function () { + // TODO handle response properly + callback ? callback(request.responseText, request.status) : undefined; + }; + request.send(postData); + } + } + };Sui.ready(() => { + let debugResponse = (data) => { + $('#response').html(data); + }; + [{ + api: 'MOTOR', + method: 'GET', + selector: '.motor.slider', + event: 'change', + data: function(){ + return this.getAttribute('data-motor-nr'); + }, + onResponse: debugResponse + }, { + api: 'LASER', + method: 'GET', + selector: '.laser.slider', + event: 'change', + onResponse: debugResponse + }].forEach(Sui.link({ + api: { + MOTOR: '/motor/', // {motorNr}/{value} + LASER: '/laser/' // {value} + } + })); +}); \ No newline at end of file diff --git a/data/styles.css b/data/styles.css index 441c022..e4f896e 100644 --- a/data/styles.css +++ b/data/styles.css @@ -1,3 +1,11 @@ +label { + width: 10%; + display: inline-block; +} +.slider { + width: 80%; + display: inline-block; +} body { font-size: 14px; font-family: "Bookman Old Style", "Serifa BT", "URW Bookman L", "itc bookman", times, serif; diff --git a/frontend/pages/favicon-16x16.png b/frontend/pages/favicon-16x16.png deleted file mode 100644 index 806956c3a2ddd0905acf8ec1613b46436299761c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1754 zcmZ`(X;c$e6u!u=#aK~6HpA+INoGPw!hk?RwjoS_BXr+@s}{%`APPk)r*M^BIGof*z4^|U#6-n;LMTHBY~f~S1Hh`@jyAU$0Ru}zEsHi2Z?p3q7T#{*Tbmcn zhDD2=Zy#Fny7@kaclwutZob#SyG)C;nQt{NT3dNXGI_6sx0-lb#G5gQzL}?y4b#!k zxAJWm6wQXr$d3^;+>+wxAW}@k-DQA{Z$qPb#>(5VTnoQUD3!o;iHGJL2tcGnf;@;s zDhx_gI7&PsAtPmpBhm_uh$i6Ck#?~!n@|@8Fvu^K5R{07f)a^Y#0!G)&=85aXjmFG zNWO!2N}b{ogQ#3eZ0B84Tto^2R#um&Br$j+(y@pQ3NRFdZ0Lycuxm`Gkr|g5N0{V@ z0+ufk0b=jcc?!pcCW09$SG+7UY7;R>*o)fAWU>lJ$2>cz*ioFGTC$TE7&fSyi~^J%imm3SX5lHMfi-<(&eRPJ8;XoZA+~RBx9G;q^*{0CQ)ixrXDrX2J-OBK z-1PIU=PDOoSb!H_dij;}7hb)1vFWu-mtTM53S?eYyxFNCuW@g^ef`Ee@2-d3^!MKX z;KPemAKkpQ{o_wEkbOhOr=NZP#g|`wUHr|r8?pVlzS1jKWgL2yoVl0tdpMTzjj=d^ znjm!wl2EACZc;;$dP+l769h#NW%u}&eVd05{(nwBJA#L@71b(o?5Nm%j%Svp+tShjeiti1)$9i(>3Gp%-?3@cY6Q; diff --git a/frontend/pages/favicon-96x96.png b/frontend/pages/favicon-96x96.png deleted file mode 100644 index f4bffd8bd8b59d6f55de6e569f5e209b3eae6eff..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19767 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 diff --git a/frontend/pages/index.html b/frontend/pages/index.html index 5541332..51fd3b6 100644 --- a/frontend/pages/index.html +++ b/frontend/pages/index.html @@ -3,38 +3,9 @@ Esp8266 laserspiro controller - - - + - - - +
@@ -122,21 +93,21 @@
- some tests: - + + + + + + + +
last uri:
last respone:
-
+

diff --git a/frontend/scripts/pmjq.js b/frontend/scripts/pmjq.js new file mode 100644 index 0000000..896d9a6 --- /dev/null +++ b/frontend/scripts/pmjq.js @@ -0,0 +1,88 @@ +/** + * Poor Man's JQuery + * Lightweight DOM manipulation utility + */ +var $ = function(selector){ + + var that = this; + var element = selector.nodeType === 1 ? selector : {}; + + // utility functions + this.util = { + // build a fragment from a given html string + buildFragment: function(html){ + // set the html to a temporary element + var nodeHolder = document.createElement('div'); + nodeHolder.innerHTML = html; + // create a document fragment and append all input nodes + var fragment = document.createDocumentFragment(); + while(nodeHolder.firstChild){ + fragment.appendChild(nodeHolder.firstChild); + } + return fragment; + } + }; + // check if the input selector is already an element or a css selector + if(selector.nodeType === 1){ // is element + if(selector.is$ ? selector.is$() : false){ // check if the element is already extended + return selector; + } + element = selector; // set the element to be extended + } else { // the element is in fact a css selector + element = document.querySelector(selector); // search for the element + } + + // overload the innerHTML attribute + element.html = function(val){ + this.innerHTML = val; + return this; + }; + + // overload the value attribute + element.val = function(val){ + this.value = val; + return this; + }; + + // append the given string as child fragment + element.append = function(html){ + var fragment = that.util.buildFragment(html); + this.appendChild(fragment); + return this; + }; + + // prepend the given string as child fragment + element.prepend = function(html){ + var fragment = that.util.buildFragment(html); + this.insertBefore(fragment,this.firstChild); + return this; + }; + + // search for an element inside of an element + element.find = function(what){ + var found = $(what); + if(found){ + return $(found); + } + return; + } + + // get parent of the current element + element.parent = function(){ + if(this.parentElement){ + return $(this.parentElement); + } + } + + // indicates that this element is a $ function + element.is$ = function(){ + return true; + } + + element.on = function(event, func, useCapture) { + this.addEventListener(event, func, useCapture); + return this; + } + + return element; +}; \ No newline at end of file diff --git a/frontend/scripts/sui.js b/frontend/scripts/sui.js new file mode 100644 index 0000000..61a69bc --- /dev/null +++ b/frontend/scripts/sui.js @@ -0,0 +1,73 @@ +var Sui = { + ready: (callback) => { + document.addEventListener("DOMContentLoaded", function() { + callback(); + }, false); + }, + select: (selector) => { + return document.querySelectorAll(selector); + }, + link: function(node){ + return (actuator) => { + let update = function(endpoint, method, props) { + Sui.http.ajax({ + method: method, + endpoint: node.api[endpoint] + props.join('/'), + cache: false + }, actuator.onResponse || null); + }; + Sui.select(actuator.selector).forEach( (domEl) =>{ + let handle = function(event) { + data = [this.value]; + actuator.data ? data.push(actuator.data.call(this)) : undefined; + update.call(this, actuator.api, 'GET', data); + } + $(domEl).on(actuator.event, handle) + }); + }; + }, + util: { + + /** + * serialize a flat json object + */ + serialize: (obj) => { + var str = []; + for(var p in obj){ + str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p])); + } + return str.join("&"); + } + }, + http: { + + /** + * ajax request + * { + * method: <'GET', 'POST', whatever >, + * endpoint: , + * async: , (default true) + * data: , + * cache: (default false) + * } + */ + ajax: (config, callback) => { + var cache = config.cache || false; + var data = config.data || {}; + if(!cache) { + data['_'] = new Date().getTime(); + } + var serializedData = Sui.util.serialize(data); + var endPointUrl = (config.method === 'GET' || config.method === 'DELETE') && data ? config.endpoint+'?'+serializedData : config.endpoint; + var postData = config.method === 'POST' || config.method === 'PUT' ? serializedData : null; + + var request = new XMLHttpRequest(); + request.open(config.method, endPointUrl, config.async || true); + request.onreadystatechange = function () { + // TODO handle response properly + callback ? callback(request.responseText, request.status) : undefined; + }; + request.send(postData); + } + } + }; \ No newline at end of file diff --git a/frontend/scripts/zMain.js b/frontend/scripts/zMain.js new file mode 100644 index 0000000..ba0f272 --- /dev/null +++ b/frontend/scripts/zMain.js @@ -0,0 +1,26 @@ +Sui.ready(() => { + let debugResponse = (data) => { + $('#response').html(data); + }; + [{ + api: 'MOTOR', + method: 'GET', + selector: '.motor.slider', + event: 'change', + data: function(){ + return this.getAttribute('data-motor-nr'); + }, + onResponse: debugResponse + }, { + api: 'LASER', + method: 'GET', + selector: '.laser.slider', + event: 'change', + onResponse: debugResponse + }].forEach(Sui.link({ + api: { + MOTOR: '/motor/', // {motorNr}/{value} + LASER: '/laser/' // {value} + } + })); +}); \ No newline at end of file diff --git a/frontend/styles/main.less b/frontend/styles/main.less index 1fcd08c..8f7d17e 100644 --- a/frontend/styles/main.less +++ b/frontend/styles/main.less @@ -1,3 +1,15 @@ + +label { + width: 10%; + display: inline-block; +} +.slider { + width: 80%; + display: inline-block; +} + + + body { font-size: 14px; font-family: "Bookman Old Style","Serifa BT","URW Bookman L","itc bookman",times,serif; diff --git a/package.json b/package.json index fba1e33..caab06a 100644 --- a/package.json +++ b/package.json @@ -8,10 +8,12 @@ "clear": "rm -rf data/*", "cp:config": "cp config/* data/", "build:css": "lessc frontend/styles/main.less data/styles.css", + "build:js": "cat frontend/scripts/* > data/scripts.js", "build:html": "cp -r frontend/pages/* data/", - "build": "npm run build:css && npm run build:html", + "build": "npm run build:css && npm run build:html && npm run build:js", "watch:html": "nodemon -q -w frontend/pages/ --ext \".\" --exec \"npm run build:html\"", "watch:css": "nodemon -q -w frontend/styles --ext \".\" --exec \"npm run build:css\"", + "watch:js": "nodemon -q -w frontend/scripts --ext \".\" --exec \"npm run build:js\"", "watch:config": "nodemon -q -w config --ext \".\" --exec \"npm run cp:config\"", "watch:livereload": "cd data && live-server", "dev": "npm run clear && npm run build && npm-run-all --parallel watch:*"