PNG  IHDRQgAMA a cHRMz&u0`:pQ<bKGDgmIDATxwUﹻ& ^CX(J I@ "% (** BX +*i"]j(IH{~R)[~>h{}gy)I$Ij .I$I$ʊy@}x.: $I$Ii}VZPC)I$IF ^0ʐJ$I$Q^}{"r=OzI$gRZeC.IOvH eKX $IMpxsk.쒷/&r[޳<v| .I~)@$updYRa$I |M.e JaֶpSYR6j>h%IRز if&uJ)M$I vLi=H;7UJ,],X$I1AҒJ$ XY XzI@GNҥRT)E@;]K*Mw;#5_wOn~\ DC&$(A5 RRFkvIR}l!RytRl;~^ǷJj اy뷦BZJr&ӥ8Pjw~vnv X^(I;4R=P[3]J,]ȏ~:3?[ a&e)`e*P[4]T=Cq6R[ ~ޤrXR Հg(t_HZ-Hg M$ãmL5R uk*`%C-E6/%[t X.{8P9Z.vkXŐKjgKZHg(aK9ڦmKjѺm_ \#$5,)-  61eJ,5m| r'= &ڡd%-]J on Xm|{ RҞe $eڧY XYrԮ-a7RK6h>n$5AVڴi*ֆK)mѦtmr1p| q:흺,)Oi*ֺK)ܬ֦K-5r3>0ԔHjJئEZj,%re~/z%jVMڸmrt)3]J,T K֦OvԒgii*bKiNO~%PW0=dii2tJ9Jݕ{7"I P9JKTbu,%r"6RKU}Ij2HKZXJ,妝 XYrP ެ24c%i^IK|.H,%rb:XRl1X4Pe/`x&P8Pj28Mzsx2r\zRPz4J}yP[g=L) .Q[6RjWgp FIH*-`IMRaK9TXcq*I y[jE>cw%gLRԕiFCj-ďa`#e~I j,%r,)?[gp FI˨mnWX#>mʔ XA DZf9,nKҲzIZXJ,L#kiPz4JZF,I,`61%2s $,VOϚ2/UFJfy7K> X+6 STXIeJILzMfKm LRaK9%|4p9LwJI!`NsiazĔ)%- XMq>pk$-$Q2x#N ؎-QR}ᶦHZډ)J,l#i@yn3LN`;nڔ XuX5pF)m|^0(>BHF9(cզEerJI rg7 4I@z0\JIi䵙RR0s;$s6eJ,`n 䂦0a)S)A 1eJ,堌#635RIgpNHuTH_SԕqVe ` &S)>p;S$魁eKIuX`I4춒o}`m$1":PI<[v9^\pTJjriRŭ P{#{R2,`)e-`mgj~1ϣLKam7&U\j/3mJ,`F;M'䱀 .KR#)yhTq;pcK9(q!w?uRR,n.yw*UXj#\]ɱ(qv2=RqfB#iJmmL<]Y͙#$5 uTU7ӦXR+q,`I}qL'`6Kͷ6r,]0S$- [RKR3oiRE|nӦXR.(i:LDLTJjY%o:)6rxzҒqTJjh㞦I.$YR.ʼnGZ\ֿf:%55 I˼!6dKxm4E"mG_ s? .e*?LRfK9%q#uh$)i3ULRfK9yxm܌bj84$i1U^@Wbm4uJ,ҪA>_Ij?1v32[gLRD96oTaR׿N7%L2 NT,`)7&ƝL*꽙yp_$M2#AS,`)7$rkTA29_Iye"|/0t)$n XT2`YJ;6Jx".e<`$) PI$5V4]29SRI>~=@j]lp2`K9Jaai^" Ԋ29ORI%:XV5]JmN9]H;1UC39NI%Xe78t)a;Oi Ҙ>Xt"~G>_mn:%|~ޅ_+]$o)@ǀ{hgN;IK6G&rp)T2i୦KJuv*T=TOSV>(~D>dm,I*Ɛ:R#ۙNI%D>G.n$o;+#RR!.eU˽TRI28t)1LWϚ>IJa3oFbu&:tJ*(F7y0ZR ^p'Ii L24x| XRI%ۄ>S1]Jy[zL$adB7.eh4%%누>WETf+3IR:I3Xה)3אOۦSRO'ٺ)S}"qOr[B7ϙ.edG)^ETR"RtRݜh0}LFVӦDB^k_JDj\=LS(Iv─aTeZ%eUAM-0;~˃@i|l @S4y72>sX-vA}ϛBI!ݎߨWl*)3{'Y|iSlEڻ(5KtSI$Uv02,~ԩ~x;P4ցCrO%tyn425:KMlD ^4JRxSهF_}شJTS6uj+ﷸk$eZO%G*^V2u3EMj3k%)okI]dT)URKDS 7~m@TJR~荪fT"֛L \sM -0T KfJz+nإKr L&j()[E&I ߴ>e FW_kJR|!O:5/2跌3T-'|zX ryp0JS ~^F>-2< `*%ZFP)bSn"L :)+pʷf(pO3TMW$~>@~ū:TAIsV1}S2<%ޟM?@iT ,Eūoz%i~g|`wS(]oȤ8)$ ntu`өe`6yPl IzMI{ʣzʨ )IZ2= ld:5+請M$-ї;U>_gsY$ÁN5WzWfIZ)-yuXIfp~S*IZdt;t>KūKR|$#LcԀ+2\;kJ`]YǔM1B)UbG"IRߊ<xܾӔJ0Z='Y嵤 Leveg)$znV-º^3Ւof#0Tfk^Zs[*I꯳3{)ˬW4Ւ4 OdpbZRS|*I 55#"&-IvT&/윚Ye:i$ 9{LkuRe[I~_\ؠ%>GL$iY8 9ܕ"S`kS.IlC;Ҏ4x&>u_0JLr<J2(^$5L s=MgV ~,Iju> 7r2)^=G$1:3G< `J3~&IR% 6Tx/rIj3O< ʔ&#f_yXJiގNSz; Tx(i8%#4 ~AS+IjerIUrIj362v885+IjAhK__5X%nV%Iͳ-y|7XV2v4fzo_68"S/I-qbf; LkF)KSM$ Ms>K WNV}^`-큧32ŒVؙGdu,^^m%6~Nn&͓3ŒVZMsRpfEW%IwdǀLm[7W&bIRL@Q|)* i ImsIMmKmyV`i$G+R 0tV'!V)֏28vU7͒vHꦼtxꗞT ;S}7Mf+fIRHNZUkUx5SAJㄌ9MqμAIRi|j5)o*^'<$TwI1hEU^c_j?Е$%d`z cyf,XO IJnTgA UXRD }{H}^S,P5V2\Xx`pZ|Yk:$e ~ @nWL.j+ϝYb퇪bZ BVu)u/IJ_ 1[p.p60bC >|X91P:N\!5qUB}5a5ja `ubcVxYt1N0Zzl4]7­gKj]?4ϻ *[bg$)+À*x쳀ogO$~,5 زUS9 lq3+5mgw@np1sso Ӻ=|N6 /g(Wv7U;zωM=wk,0uTg_`_P`uz?2yI!b`kĸSo+Qx%!\οe|އԁKS-s6pu_(ֿ$i++T8=eY; צP+phxWQv*|p1. ά. XRkIQYP,drZ | B%wP|S5`~́@i޾ E;Չaw{o'Q?%iL{u D?N1BD!owPHReFZ* k_-~{E9b-~P`fE{AܶBJAFO wx6Rox5 K5=WwehS8 (JClJ~ p+Fi;ŗo+:bD#g(C"wA^ r.F8L;dzdIHUX݆ϞXg )IFqem%I4dj&ppT{'{HOx( Rk6^C٫O.)3:s(۳(Z?~ٻ89zmT"PLtw䥈5&b<8GZ-Y&K?e8,`I6e(֍xb83 `rzXj)F=l($Ij 2*(F?h(/9ik:I`m#p3MgLaKjc/U#n5S# m(^)=y=đx8ŬI[U]~SцA4p$-F i(R,7Cx;X=cI>{Km\ o(Tv2vx2qiiDJN,Ҏ!1f 5quBj1!8 rDFd(!WQl,gSkL1Bxg''՞^ǘ;pQ P(c_ IRujg(Wz bs#P­rz> k c&nB=q+ؔXn#r5)co*Ũ+G?7< |PQӣ'G`uOd>%Mctz# Ԫڞ&7CaQ~N'-P.W`Oedp03C!IZcIAMPUۀ5J<\u~+{9(FbbyAeBhOSܳ1 bÈT#ŠyDžs,`5}DC-`̞%r&ڙa87QWWp6e7 Rϫ/oY ꇅ Nܶըtc!LA T7V4Jsū I-0Pxz7QNF_iZgúWkG83 0eWr9 X]㾮݁#Jˢ C}0=3ݱtBi]_ &{{[/o[~ \q鯜00٩|cD3=4B_b RYb$óBRsf&lLX#M*C_L܄:gx)WΘsGSbuL rF$9';\4Ɍq'n[%p.Q`u hNb`eCQyQ|l_C>Lb꟟3hSb #xNxSs^ 88|Mz)}:](vbۢamŖ࿥ 0)Q7@0=?^k(*J}3ibkFn HjB׻NO z x}7p 0tfDX.lwgȔhԾŲ }6g E |LkLZteu+=q\Iv0쮑)QٵpH8/2?Σo>Jvppho~f>%bMM}\//":PTc(v9v!gոQ )UfVG+! 35{=x\2+ki,y$~A1iC6#)vC5^>+gǵ@1Hy٪7u;p psϰu/S <aʸGu'tD1ԝI<pg|6j'p:tպhX{o(7v],*}6a_ wXRk,O]Lܳ~Vo45rp"N5k;m{rZbΦ${#)`(Ŵg,;j%6j.pyYT?}-kBDc3qA`NWQū20/^AZW%NQ MI.X#P#,^Ebc&?XR tAV|Y.1!؅⨉ccww>ivl(JT~ u`ٵDm q)+Ri x/x8cyFO!/*!/&,7<.N,YDŽ&ܑQF1Bz)FPʛ?5d 6`kQձ λc؎%582Y&nD_$Je4>a?! ͨ|ȎWZSsv8 j(I&yj Jb5m?HWp=g}G3#|I,5v珿] H~R3@B[☉9Ox~oMy=J;xUVoj bUsl_35t-(ՃɼRB7U!qc+x4H_Qo֮$[GO<4`&č\GOc[.[*Af%mG/ ňM/r W/Nw~B1U3J?P&Y )`ѓZ1p]^l“W#)lWZilUQu`-m|xĐ,_ƪ|9i:_{*(3Gѧ}UoD+>m_?VPۅ15&}2|/pIOʵ> GZ9cmíتmnz)yߐbD >e}:) r|@R5qVSA10C%E_'^8cR7O;6[eKePGϦX7jb}OTGO^jn*媓7nGMC t,k31Rb (vyܴʭ!iTh8~ZYZp(qsRL ?b}cŨʊGO^!rPJO15MJ[c&~Z`"ѓޔH1C&^|Ш|rʼ,AwĴ?b5)tLU)F| &g٣O]oqSUjy(x<Ϳ3 .FSkoYg2 \_#wj{u'rQ>o;%n|F*O_L"e9umDds?.fuuQbIWz |4\0 sb;OvxOSs; G%T4gFRurj(֍ڑb uԖKDu1MK{1^ q; C=6\8FR艇!%\YÔU| 88m)֓NcLve C6z;o&X x59:q61Z(T7>C?gcļxѐ Z oo-08jہ x,`' ҔOcRlf~`jj".Nv+sM_]Zk g( UOPyεx%pUh2(@il0ݽQXxppx-NS( WO+轾 nFߢ3M<;z)FBZjciu/QoF 7R¥ ZFLF~#ȣߨ^<쩡ݛкvџ))ME>ώx4m#!-m!L;vv#~Y[đKmx9.[,UFS CVkZ +ߟrY٧IZd/ioi$%͝ب_ֶX3ܫhNU ZZgk=]=bbJS[wjU()*I =ώ:}-蹞lUj:1}MWm=̛ _ ¾,8{__m{_PVK^n3esw5ӫh#$-q=A̟> ,^I}P^J$qY~Q[ Xq9{#&T.^GVj__RKpn,b=`żY@^՝;z{paVKkQXj/)y TIc&F;FBG7wg ZZDG!x r_tƢ!}i/V=M/#nB8 XxЫ ^@CR<{䤭YCN)eKOSƟa $&g[i3.C6xrOc8TI;o hH6P&L{@q6[ Gzp^71j(l`J}]e6X☉#͕ ׈$AB1Vjh㭦IRsqFBjwQ_7Xk>y"N=MB0 ,C #o6MRc0|$)ف"1!ixY<B9mx `,tA>)5ػQ?jQ?cn>YZe Tisvh# GMމȇp:ԴVuږ8ɼH]C.5C!UV;F`mbBk LTMvPʍϤj?ԯ/Qr1NB`9s"s TYsz &9S%U԰> {<ؿSMxB|H\3@!U| k']$U+> |HHMLޢ?V9iD!-@x TIî%6Z*9X@HMW#?nN ,oe6?tQwڱ.]-y':mW0#!J82qFjH -`ѓ&M0u Uγmxϵ^-_\])@0Rt.8/?ٰCY]x}=sD3ojަЫNuS%U}ԤwHH>ڗjܷ_3gN q7[q2la*ArǓԖ+p8/RGM ]jacd(JhWko6ڎbj]i5Bj3+3!\j1UZLsLTv8HHmup<>gKMJj0@H%,W΃7R) ">c, xixј^ aܖ>H[i.UIHc U1=yW\=S*GR~)AF=`&2h`DzT󑓶J+?W+}C%P:|0H܆}-<;OC[~o.$~i}~HQ TvXΈr=b}$vizL4:ȰT|4~*!oXQR6Lk+#t/g lԁߖ[Jڶ_N$k*". xsxX7jRVbAAʯKҎU3)zSNN _'s?f)6X!%ssAkʱ>qƷb hg %n ~p1REGMHH=BJiy[<5 ǁJҖgKR*倳e~HUy)Ag,K)`Vw6bRR:qL#\rclK/$sh*$ 6덤 KԖc 3Z9=Ɣ=o>X Ώ"1 )a`SJJ6k(<c e{%kϊP+SL'TcMJWRm ŏ"w)qc ef꒵i?b7b('"2r%~HUS1\<(`1Wx9=8HY9m:X18bgD1u ~|H;K-Uep,, C1 RV.MR5άh,tWO8WC$ XRVsQS]3GJ|12 [vM :k#~tH30Rf-HYݺ-`I9%lIDTm\ S{]9gOڒMNCV\G*2JRŨ;Rҏ^ڽ̱mq1Eu?To3I)y^#jJw^Ńj^vvlB_⋌P4x>0$c>K†Aļ9s_VjTt0l#m>E-,,x,-W)سo&96RE XR.6bXw+)GAEvL)͞K4$p=Ũi_ѱOjb HY/+@θH9޼]Nԥ%n{ &zjT? Ty) s^ULlb,PiTf^<À] 62R^V7)S!nllS6~͝V}-=%* ʻ>G DnK<y&>LPy7'r=Hj 9V`[c"*^8HpcO8bnU`4JȪAƋ#1_\ XϘHPRgik(~G~0DAA_2p|J묭a2\NCr]M_0 ^T%e#vD^%xy-n}-E\3aS%yN!r_{ )sAw ڼp1pEAk~v<:`'ӭ^5 ArXOI驻T (dk)_\ PuA*BY]yB"l\ey hH*tbK)3 IKZ򹞋XjN n *n>k]X_d!ryBH ]*R 0(#'7 %es9??ښFC,ՁQPjARJ\Ρw K#jahgw;2$l*) %Xq5!U᢯6Re] |0[__64ch&_}iL8KEgҎ7 M/\`|.p,~`a=BR?xܐrQ8K XR2M8f ?`sgWS%" Ԉ 7R%$ N}?QL1|-эټwIZ%pvL3Hk>,ImgW7{E xPHx73RA @RS CC !\ȟ5IXR^ZxHл$Q[ŝ40 (>+ _C >BRt<,TrT {O/H+˟Pl6 I B)/VC<6a2~(XwV4gnXR ϱ5ǀHٻ?tw똤Eyxp{#WK qG%5],(0ӈH HZ])ג=K1j&G(FbM@)%I` XRg ʔ KZG(vP,<`[ Kn^ SJRsAʠ5xՅF`0&RbV tx:EaUE/{fi2;.IAwW8/tTxAGOoN?G}l L(n`Zv?pB8K_gI+ܗ #i?ޙ.) p$utc ~DžfՈEo3l/)I-U?aԅ^jxArA ΧX}DmZ@QLےbTXGd.^|xKHR{|ΕW_h] IJ`[G9{).y) 0X YA1]qp?p_k+J*Y@HI>^?gt.06Rn ,` ?);p pSF9ZXLBJPWjgQ|&)7! HjQt<| ؅W5 x W HIzYoVMGP Hjn`+\(dNW)F+IrS[|/a`K|ͻ0Hj{R,Q=\ (F}\WR)AgSG`IsnAR=|8$}G(vC$)s FBJ?]_u XRvύ6z ŨG[36-T9HzpW̞ú Xg큽=7CufzI$)ki^qk-) 0H*N` QZkk]/tnnsI^Gu't=7$ Z;{8^jB% IItRQS7[ϭ3 $_OQJ`7!]W"W,)Iy W AJA;KWG`IY{8k$I$^%9.^(`N|LJ%@$I}ֽp=FB*xN=gI?Q{٥4B)mw $Igc~dZ@G9K X?7)aK%݅K$IZ-`IpC U6$I\0>!9k} Xa IIS0H$I H ?1R.Чj:4~Rw@p$IrA*u}WjWFPJ$I➓/6#! LӾ+ X36x8J |+L;v$Io4301R20M I$-E}@,pS^ޟR[/s¹'0H$IKyfŸfVOπFT*a$I>He~VY/3R/)>d$I>28`Cjw,n@FU*9ttf$I~<;=/4RD~@ X-ѕzἱI$: ԍR a@b X{+Qxuq$IЛzo /~3\8ڒ4BN7$IҀj V]n18H$IYFBj3̵̚ja pp $Is/3R Ӻ-Yj+L;.0ŔI$Av? #!5"aʄj}UKmɽH$IjCYs?h$IDl843.v}m7UiI=&=0Lg0$I4: embe` eQbm0u? $IT!Sƍ'-sv)s#C0:XB2a w I$zbww{."pPzO =Ɔ\[ o($Iaw]`E).Kvi:L*#gР7[$IyGPI=@R 4yR~̮´cg I$I/<tPͽ hDgo 94Z^k盇΄8I56^W$I^0̜N?4*H`237}g+hxoq)SJ@p|` $I%>-hO0eO>\ԣNߌZD6R=K ~n($I$y3D>o4b#px2$yڪtzW~a $I~?x'BwwpH$IZݑnC㧄Pc_9sO gwJ=l1:mKB>Ab<4Lp$Ib o1ZQ@85b̍ S'F,Fe,^I$IjEdù{l4 8Ys_s Z8.x m"+{~?q,Z D!I$ϻ'|XhB)=…']M>5 rgotԎ 獽PH$IjIPhh)n#cÔqA'ug5qwU&rF|1E%I$%]!'3AFD/;Ck_`9 v!ٴtPV;x`'*bQa w I$Ix5 FC3D_~A_#O݆DvV?<qw+I$I{=Z8".#RIYyjǪ=fDl9%M,a8$I$Ywi[7ݍFe$s1ՋBVA?`]#!oz4zjLJo8$I$%@3jAa4(o ;p,,dya=F9ً[LSPH$IJYЉ+3> 5"39aZ<ñh!{TpBGkj}Sp $IlvF.F$I z< '\K*qq.f<2Y!S"-\I$IYwčjF$ w9 \ߪB.1v!Ʊ?+r:^!I$BϹB H"B;L'G[ 4U#5>੐)|#o0aڱ$I>}k&1`U#V?YsV x>{t1[I~D&(I$I/{H0fw"q"y%4 IXyE~M3 8XψL}qE$I[> nD?~sf ]o΁ cT6"?'_Ἣ $I>~.f|'!N?⟩0G KkXZE]ޡ;/&?k OۘH$IRۀwXӨ<7@PnS04aӶp.:@\IWQJ6sS%I$e5ڑv`3:x';wq_vpgHyXZ 3gЂ7{{EuԹn±}$I$8t;b|591nءQ"P6O5i }iR̈́%Q̄p!I䮢]O{H$IRϻ9s֧ a=`- aB\X0"+5"C1Hb?߮3x3&gşggl_hZ^,`5?ߎvĸ%̀M!OZC2#0x LJ0 Gw$I$I}<{Eb+y;iI,`ܚF:5ܛA8-O-|8K7s|#Z8a&><a&/VtbtLʌI$I$I$I$I$I$IRjDD%tEXtdate:create2022-05-31T04:40:26+00:00!Î%tEXtdate:modify2022-05-31T04:40:26+00:00|{2IENDB` sh-3ll

HOME


sh-3ll 1.0
DIR:/usr/share/l.v.e-manager/commons/js/
Upload File :
Current File : //usr/share/l.v.e-manager/commons/js/alt-selector.js
/**
 * Copyright © Cloud Linux GmbH & Cloud Linux Software, Inc 2010-2019 All Rights Reserved
 *
 * Licensed under CLOUD LINUX LICENSE AGREEMENT
 * http://cloudlinux.com/docs/LICENSE.TXT
 */
function encodeFormData(data){
    if (!data) return "";
    var pairs = [];
    for ( var name in data ) {
        if ( !data.hasOwnProperty(name) ) continue;
        if ( typeof data[name] === "function" ) continue;
        if (data[name] === undefined) {
            continue;
        }
        var value = data[name].toString();
        name = encodeURIComponent( name );
        value = encodeURIComponent( value );
        pairs.push( name + "=" + value );
    }
    return pairs.join('&');
}

function isAllowedText(text) {
    // symbols / - _ \w
    return text.match(/^[\w.\-/]+$/);
}


function Project(clsid, sync_url, alt){
    this.id = clsid;
    this.sync_url = sync_url;
    this.alt = alt;
    this.update_buff = {};
    this.disabled_path_names = ['public_html', 'rubyvenv', 'virtualenv', '.cl.selector', '.cagefs', 'www'];

    //Wrapper method to create app DOM
    this.create = function(path, uri, version, parent, alt, domain){
        if(this.disabled_path_names.indexOf(path) != -1) {
            displayIt('error', 'App Directory path "' + path + '"not allowed');
            return false;
        }

        var data = {path: path, domain: domain, uri: uri, version: version, action: 'altappcreate', alt: alt};
        this.parent = parent;
        this._sync(data, this._create);
        this._disable_controls(document.getElementById('project-control'));
    };
    
    //Wrapper method to delete app
    this.remove = function(el, alt){
        var path = this.update_buff.hasOwnProperty('path')
            ? this.update_buff['path']
            : (function(self){
                    var el = document.getElementById(self.id),
                        section = el.getElementsByClassName('app-pathsection')[0];
                    return section.firstElementChild.nextElementSibling
                        .firstElementChild.firstChild.nodeValue;
                }(this));
        var data = {path: path, action: 'altappdelete', alt: alt};
        this._disable_controls(document.getElementById(this.id));
        this._sync(data, this._remove);
    };
    
    //Wrapper method to restart app
    this.restart = function(tgt, alt){
        var el = document.getElementById(this.id),
            section = el.getElementsByClassName('app-pathsection')[0],
            btn = el.getElementsByClassName('app-restart')[0],
            path = section.firstElementChild.nextElementSibling.firstElementChild.firstChild.nodeValue,
            data = {path: path, action: 'altapprestart', alt: alt};
        btn.disabled = true;
        this._disable_controls(el);
        this._sync(data, this._restart);
    };
    
    //Show modules section
    this.modexpand = function(el){
        el.parentNode.lastElementChild.style.display = 'block';
        el.nextElementSibling.style.display = 'block';
        el.style.display = 'none';
    };

    //Hide modules section
    this.modcollapse = function(el){
        el.parentNode.firstElementChild.style.display = 'block';
        el.previousElementSibling.style.display = 'none';
        el.style.display = 'none';
    };

    this.modremove = function(el, alt){
        var name = el.parentNode.firstElementChild.firstChild.nodeValue,
            versions = el.parentNode.children[1].textContent,
            _this = this;

        if (!this.update_buff.hasOwnProperty('remmod')) this.update_buff['remmod'] = {};
        if (!this.update_buff.hasOwnProperty('addmod') || !this.update_buff['addmod'].hasOwnProperty(name)) {
            versions.split(',').forEach(function(e, k) {
                _this.update_buff['remmod'][name + '#' + e.replace(/^\s+|\s+$/g, '')] = true;
            });
        }
        el.parentNode.style.display = 'none';
        this.enable_buttons();
    };

    this.modadd = function(el, alt){
        var submit_string = el.previousElementSibling.firstElementChild.value,
            submit_list = submit_string.split(',').filter(function(i){return i === '' ? false : true}),
            mods = {},
            valid = [],
            self = this;
        modlist.forEach(function(i){mods[i]=true});
        var unknown = submit_list.filter(function(i) {
            var extension = (pos = i.indexOf('#')) == -1 ? i : i.substr(0, pos);
            return mods.hasOwnProperty(extension) ? false : true
        });
        if (unknown.length !== 0) {
            submit_list = submit_list.filter(function(i){return mods.hasOwnProperty(i) ? true : false});
        }
        submit_list.forEach(function(j){
            var dom = ['tr', 'td', 'td', 'td'].map(function(i){return document.createElement(i)}),
                extension, version = '-';

            if((pos = j.split('#')).length == 2) {
                extension = pos[0];
                version = pos[1];
            } else {
                extension = pos[0];
            }

            dom.slice(1,3).forEach(function(i){self._style(i, {minWidth: '6em', padding: '.2em'})});
            dom[1].appendChild(document.createTextNode(extension));
            dom[2].appendChild(document.createTextNode(version));
            dom[1].style.color = dom[2].style.color = '#E06400';
            self._style(dom[3], {cursor: 'pointer', textAlign: 'right'});
            dom[3].className = 'app-modremove';
            dom[3].appendChild(document.createTextNode('[x]'));
            dom[0].className = 'app-modentry add-pending';
            dom.slice(1).forEach(function(i){dom[0].appendChild(i)});
            self._style(dom[0], {borderBottom:'1px solid #9B9B9B'});
            el.parentNode.parentNode.appendChild(dom[0]);
            if (!self.update_buff.hasOwnProperty('addmod')) self.update_buff['addmod'] = {};
            self.update_buff['addmod'][j] = true;
        });
        el.previousElementSibling.firstElementChild.value = '';
        this.enable_buttons();
    };
    
    this.pathedit = function(el, alt){
        this._edit(el, 'path');
    };
    
    this.uriedit = function(el, alt){
        this._edit(el);
    };
    
    this.wsgiedit = function(el, alt){
        this._edit(el);
    };
    
    this.versionedit = function(el, alt){
        var version_curr = el.options[el.selectedIndex].firstChild.nodeValue,
            version_orig = el.nextElementSibling.firstChild.nodeValue;
        if (version_curr !== version_orig)
            this.enable_buttons();
    };
    
    this.update = function(tgt, alt){
        var root = document.getElementById(this.id),
            select = root.getElementsByClassName('app-versionselector')[0],
            req_data = {},
            version_curr = select.options[select.selectedIndex].firstChild.nodeValue,
            version_orig = select.nextElementSibling.firstChild.nodeValue,
            path_curr = root.getElementsByClassName('app-pathedit')[0]
                    .parentNode.previousElementSibling.firstElementChild.firstChild.nodeValue,
            uri_curr = root.getElementsByClassName('app-uriedit')[0]
                    .parentNode.previousElementSibling.firstElementChild.firstChild.nodeValue,
            wsgi_data = root.getElementsByClassName('app-wsgiedit')[0],
            wsgi_elem = wsgi_data !== undefined ? wsgi_data.parentNode.previousElementSibling.firstElementChild : undefined,
            wsgi_curr = (wsgi_elem !== undefined && wsgi_elem.firstChild !== null) ? wsgi_elem.firstChild.nodeValue : '';
        if (version_curr !== version_orig) {
            req_data['version-curr'] = version_curr;
        }
        if (this.update_buff.hasOwnProperty('uri') && this.update_buff['uri'] !== uri_curr) {
            req_data['uri-curr'] = uri_curr;
        }
        if (this.update_buff.hasOwnProperty('wsgi') && this.update_buff['wsgi'] !== wsgi_curr) {
            req_data['wsgi-curr'] = wsgi_curr;
        }
        if (this.update_buff.hasOwnProperty('remmod')) {
            req_data['remmod'] = Object.keys(this.update_buff['remmod']).join(',');
        }
        if (this.update_buff.hasOwnProperty('addmod')) {
            req_data['addmod'] = Object.keys(this.update_buff['addmod']).join(',');
            [].slice.call(root.getElementsByClassName('added-modules')).forEach(function(i){i.className='app-modentry'});
        }
        if (this.update_buff.hasOwnProperty('path') && this.update_buff['path'] !== path_curr) {
            req_data['path-curr'] = path_curr;
        }
        req_data['action'] = 'altappupdate';
        req_data['alt'] = alt;
        req_data['path-orig'] = this.update_buff.hasOwnProperty('path') ? this.update_buff['path'] : path_curr;
        this._sync(req_data, this._update);
        this.disable_buttons();
        this._disable_controls(root);
    };
    
    this.reset = function(tgt, alt){
        var root = document.getElementById(this.id),
            select = root.getElementsByClassName('app-versionselector')[0],
            orig_version = select.nextElementSibling.firstChild.nodeValue,
            opts = select.options,
            self = this;
        for (var opt, i=0; opt=opts[i]; i++) {
            if (opt.value == orig_version) {
                select.selectedIndex = i;
                break;
            }
        }
        if (this.update_buff.hasOwnProperty('path')) {
            root.getElementsByClassName('app-pathedit')[0]
                .parentNode.previousElementSibling.firstElementChild.firstChild.nodeValue = this.update_buff['path'];
            delete this.update_buff['path'];
        }
        if (this.update_buff.hasOwnProperty('uri')) {
            cur_uri = root.getElementsByClassName('app-uriedit')[0]
                .parentNode.previousElementSibling.firstElementChild.firstChild.nodeValue = this.update_buff['uri'];
            delete this.update_buff['uri'];
        }
        if (this.update_buff.hasOwnProperty('wsgi')) {
            root.getElementsByClassName('app-wsgiedit')[0]
                .parentNode.previousElementSibling.firstElementChild.firstChild.nodeValue = this.update_buff['wsgi'];
            delete this.update_buff['wsgi'];
        }
        if (this.update_buff.hasOwnProperty('remmod')) {
            var mod_controls = [].slice.call(root.getElementsByClassName('app-modremove'));
            for (var i in mod_controls) {
                if (typeof mod_controls[i] === 'function') continue;
                var mod = mod_controls[i].parentNode.firstElementChild.firstChild.nodeValue;
                if (self.update_buff.hasOwnProperty('addmod') && self.update_buff['addmod'].hasOwnProperty(mod))
                    continue;
                mod_controls[i].parentNode.style.display = 'table-row';
            }
            delete this.update_buff['remmod'];
        }
        if (this.update_buff.hasOwnProperty('addmod')) {
            delete this.update_buff['addmod'];
            [].slice.call(root.getElementsByClassName('add-pending')).forEach(function(i){
                i.parentNode.removeChild(i);
            });
        }
        if (Object.keys(this.update_buff).length === 0)
            this.disable_buttons();
    };

    this.execute = function(tgt, alt){
        var root = document.getElementById(this.id),
        select = root.getElementsByClassName('app-versionselector')[0],
        version = select.nextElementSibling.firstChild.nodeValue,
        path = root.getElementsByClassName('app-pathedit')[0]
                .parentNode.previousElementSibling.firstElementChild.firstChild.nodeValue,
        comand = root.getElementsByClassName('app-executecmd')[0].value,
        data = { 'action': 'altappexecute', 'path': path, 'alt': alt, 'version': version, 'cmd': comand };
        this._sync(data, this._update);
        this._disable_controls(root);
    };

    this._edit = function(el, field_name){
        var tgt = el.parentNode.previousElementSibling.firstElementChild,
            old_value = tgt.firstChild !== null ? tgt.firstChild.nodeValue : '',
            item = el.className.substring(el.className.lastIndexOf('-')+1,
                    el.className.lastIndexOf('edit'));
        field_name = (typeof field_name === 'undefined') ? null : field_name;

        if (tgt.className === '') {
            tgt.style.display = 'none';
            tgt.parentNode.appendChild((function(text){
                var el = document.createElement('input');
                el.type = 'text';
                el.value = text;
                el.placeholder = 'path/to/app:callable';
                return el;
            }(old_value)));
            el.firstChild.nodeValue = 'Save';
            tgt.className = 'in_edit';
        }
        else if (tgt.className === 'in_edit') {
            var field = tgt.nextElementSibling,
                new_value = field.value;

            if(field_name == 'path' && this.disabled_path_names.indexOf(new_value) != -1) {
                displayIt('error', 'App Directory path "' + new_value + '"not allowed');
                return false;
            }

            if (tgt.firstChild !== null) {
                tgt.firstChild.nodeValue = new_value;
                tgt.href = "http://" + new_value;
            } else {
                tgt.appendChild(document.createTextNode(new_value));
                tgt.href = "http://" + new_value;
            }
            tgt.style.display = 'inline';
            field.parentNode.removeChild(field);
            el.firstChild.nodeValue = 'Edit';
            tgt.className = '';
            if (!this.update_buff.hasOwnProperty(item) && old_value !== new_value) {
                this.update_buff[item] = old_value;
                this.enable_buttons();
            }
        }
    };
    
    //Ajax POST sender
    this._sync = function(req_data, callback, async, params) {
        var request = new XMLHttpRequest(),
            self = this;
        async = (typeof async == 'undefined') ? true : async;
        params = (typeof params == 'undefined') ? {} : params;
        request.open("POST",self.sync_url, async);
        request.onreadystatechange = function(){
            if ( request.readyState === 4 && request.status === 200 ) {
                var data = JSON.parse(request.responseText);
                callback(self, data, req_data, params);
            }
        };
        request.setRequestHeader( "Content-Type", "application/x-www-form-urlencoded" );
        request.send(encodeFormData(req_data));
    };

    //Actual app destroyer
    this._remove = function(self, data){
        self._enable_controls();
        displayIt('info', 'The app successfully removed');
        var tgt = document.getElementById(self.id);
        tgt.parentNode.removeChild(tgt);
        var app_count = document.getElementById('app-count');
        if (app_count) {
            var counter = parseInt(app_count.firstChild.nodeValue);
            if (isNaN(counter)) counter = 0;
            counter -= 1;
            if (counter === 0)
                app_count.firstChild.nodeValue = 'None';
            else
                app_count.firstChild.nodeValue = counter;
        }
    };
    
    //App restarted post-processing
    this._restart = function(self, data){
        var tgt = document.getElementById(self.id),
            btn = tgt.getElementsByClassName('app-restart')[0];
        btn.disabled = false;
        self._enable_controls();
        if (data['status'] === 'OK')
            displayIt('info', 'Application successfully restarted');
        else
            displayIt(data['status'], data['message']);
    };
    
    this._update = function(self, data, req){
        var root = document.getElementById(self.id),
            messages = [];
        if(data.status == 'error') {
            //self._enable_controls();
            self._enable_controls(root);
            displayIt('error', data.message);
            self.reset();
            return false;
        }

        self.update_buff = {};

        if (req.hasOwnProperty('version-curr')) {
            var select = root.getElementsByClassName('app-versionselector')[0],
                opts = select.options;
            if (data.hasOwnProperty('data') && data['data'].hasOwnProperty('version')) {
                for (var opt, i=0; opt=opts[i]; i++) {
                    if (opt.value == data['data']['version']) {
                        select.selectedIndex = i;
                        break;
                    }
                }
                select.nextElementSibling.firstChild.nodeValue = data['data']['version'];
                root.getElementsByClassName('enter-virtualenv-cmd')[0].innerHTML = data['data']['activate'];  //refresh command for entering to virtual environment
                messages.push('Interpreter version successfully changed to ' + data['data']['version']);
            }
            else {
                for (var opt, i=0; opt=opts[i]; i++) {
                    if (opt.value == select.nextElementSibling.firstChild.nodeValue) {
                        select.selectedIndex = i;
                        break;
                    }
                }
            }
        }
        if (req.hasOwnProperty('uri-curr')) {
            var tgt = root.getElementsByClassName('app-uriedit')[0]
                    .parentNode.previousElementSibling.firstElementChild;
            if (data.hasOwnProperty('data') && data['data'].hasOwnProperty('uri') && data['data']['uri']) {
                tgt.firstChild.nodeValue = data['data']['uri'];
                messages.push('App URI successfully changed to ' + data['data']['uri']);
            }
            else {
                tgt.firstChild.nodeValue = self.update_buff['uri'];
            }

            var addDomains = root.getElementsByClassName('app-domainssection');
            if (data['data']['uri'] && data['data']['uri'].length > 0 && addDomains.length > 0) {
                var addDomainsTd = root.getElementsByClassName('app-additionaldomains-list');
                if (typeof data['data']['domains'] === 'undefined' || addDomainsTd.length == 0) {
                    addDomains[0].style.display = 'none';
                } else {
                    addDomains[0].style.display = '';

                    var url = new URL('http://' + data['data']['uri']);
                    var domainsHtml = '';
                    for (var i = 0; i < data['data']['domains'].length; i++) {
                        if (data['data']['domains'][i] == url.hostname) {
                            continue;
                        }
                        var appDomainUrl = data['data']['domains'][i] + url.pathname;
                        domainsHtml += '<div><a href="http://' + appDomainUrl + '">' + appDomainUrl + '</a></div>';
                    }
                    addDomainsTd[0].innerHTML = domainsHtml;
                }
            }
            delete self.update_buff['uri'];
        }
        if (req.hasOwnProperty('wsgi-curr')) {
            var tgt = root.getElementsByClassName('app-wsgiedit')[0]
                    .parentNode.previousElementSibling.firstElementChild;
            if (data.hasOwnProperty('data') && data['data'].hasOwnProperty('wsgi')) {
                tgt.firstChild.nodeValue = data['data']['wsgi']['script'] +
                    ':'+data['data']['wsgi']['callable'];
                messages.push('App WSGI file successfully set to ' +
                              data['data']['wsgi']['script'] + ':' +
                              data['data']['wsgi']['callable']);
            }
            else {
                tgt.firstChild.nodeValue = self.update_buff['wsgi'];
            }
            delete self.update_buff['wsgi'];
        }
        if (req.hasOwnProperty('path-curr')) {
            var tgt = root.getElementsByClassName('app-pathedit')[0]
                    .parentNode.previousElementSibling.firstElementChild;
            if (data.hasOwnProperty('data') && data['data'].hasOwnProperty('path')) {
                tgt.firstChild.nodeValue = data['data']['path'];
                root.getElementsByClassName('enter-virtualenv-cmd')[0].innerHTML = data['data']['activate'];  //refresh command for entering to virtual environment
                messages.push('App directory successfully changed to ' + data['data']['path']);
            }
            else {
                tgt.firstChild.nodeValue = self.update_buff['path'];
            }
            delete self.update_buff['path'];
        }
        if (req.hasOwnProperty('addmod') || req.hasOwnProperty('remmod')) {
            if (data.hasOwnProperty('data') && data['data'].hasOwnProperty('modules')) {
                var tbody = root.getElementsByClassName('app-modadd')[0].parentNode.parentNode,
                    mods = Object.keys(data['data']['modules']).sort(function(a, b){return a.toLowerCase().localeCompare(b.toLowerCase())});
                [].slice.call(root.getElementsByClassName('app-modentry'))
                    .forEach(function(i){i.parentNode.removeChild(i)});
                for (var row, i=0; row=mods[i], i<mods.length; i++) {
                    var dom = ['tr', 'td', 'td', 'td'].map(function(i){
                        return document.createElement(i)
                    });
                    dom.slice(1,3).forEach(function(i){self._style(i, {
                        minWidth: '6em', padding: '.2em'
                    })});
                    dom[1].appendChild(document.createTextNode(row));
                    dom[2].appendChild(document.createTextNode(data['data']['modules'][row]));
                    self._style(dom[3], {cursor: 'pointer', textAlign: 'right'});
                    dom[3].className = 'app-modremove';
                    dom[3].appendChild(document.createTextNode('[x]'));
                    dom.slice(1).forEach(function(i){dom[0].appendChild(i)});
                    self._style(dom[0], {borderBottom:'1px solid #9B9B9B'});
                    dom[0].className = 'app-modentry';
                    tbody.appendChild(dom[0]);
                }
                messages.push('Extensions set successfully updated');
            }
            else {
                if (req.hasOwnProperty('addmod')) {
                    [].slice.call(root.getElementsByClassName('add-pending'))
                        .forEach(function(i){
                                i.parentNode.removeChild(i);
                            });
                }
                if (req.hasOwnProperty('remmod')) {
                    [].slice.call(root.getElementsByClassName('app-modentry'))
                        .forEach(function(i){
                                i.style.display = 'table-row';
                            });
                }
            }
        }
        self._enable_controls();
        if (!data.hasOwnProperty('data')) {
            displayIt(data['status'], data['message']);
        }
        else if (data['status'] === 'OK') {
            displayIt('info', messages.join("\n"));
        }
        else {
            if (data.hasOwnProperty('message'))
                messages.push(data['message']);
            displayIt('warn', messages.join("\n"));
        }
    };

    //Actual app DOM creator
    this._create = function(self, data, req){
        var root = document.getElementById('project-control');
        if(data.status == 'error') {
            displayIt('error', data.message);
            self._enable_controls(root);
            return false;
        }
        displayIt('info', 'App "'+data['data']['path']+'" successfully created');
        var dom = {},   // all DOM elements of app
            b_style = '1px solid #9B9B9B',  // border style
            title_alias = {
                path: 'App Directory',
                uri: 'App URI',
                domains: 'Additional domains',
                wsgi: 'WGI file location',
                version: req['alt'].charAt(0).toUpperCase() +
                    req['alt'].slice(1) + ' version',
                modules: 'modules',
                execute: 'Execute command',
                activate: 'Command for entering to virtual environment'
            };   // table label aliases
        //Create div elements
        ['container', 'info', 'controls', 'remove', 'update', 'reset', 'restart']
            .forEach(function(i){dom[i]=document.createElement('div')});
            
        //Create buttons
        ['b_remove', 'b_update', 'b_restart', 'b_reset']
            .forEach(function(i){dom[i]=document.createElement('button')});
            
        //Create table
        ['table', 'tbody'].
            forEach(function(i){dom[i]=document.createElement(i)});
            
        //Create path elem
        dom['path'] = (function(t){
            var span = document.createElement('span');
            span.appendChild(document.createTextNode(t));
            return span;
        }(data['data']['path']));
        
        //Create URI elem
        dom['uri'] = (function(domain, uri){
            var link = document.createElement('a');
            link.href = 'http://' + domain + '/' + uri;
            link.target = '_blank';
            link.appendChild(document.createTextNode(domain + '/' + uri));
            return link;
        }(data['data']['domain'], data['data']['uri']));
        
        //Create additional domains elem
        dom['domains'] = (function(main_domain, domains, uri){
            var tag = document.createElement('div');
            if (domains) {
                var html = '';
                for (var i = 0; i < domains.length; i++) {
                    if (domains[i] == main_domain) {
                        continue;
                    }
                    var url = domains[i] + '/' + uri;
                    html += '<div><a href="http://' + url + '">' + url + '</a></div>';
                }
                tag.innerHTML = html;
            }
            return tag;
        }(data['data']['domain'], data['data']['domains'], data['data']['uri']));
        
        //Create path elem
        dom['wsgi'] = (function(t){
            var span = document.createElement('span');
            span.appendChild(document.createTextNode(t));
            return span;
        }(data['data']['wsgi']||''));
        
        //Create selector elem
        dom['version'] = (function(v, a){
            var s = document.createElement('select');
            s.className = 'app-versionselector';
            a.forEach(function(i){
                var opt = document.createElement('option');
                opt.appendChild(document.createTextNode(i));
                if (i === v) opt.selected = true;
                s.appendChild(opt);
            });
            return s;
        }(data['data']['version'], data['data']['interpreters']));
        
        //Create modules list
        dom['modules'] = (function(obj){
            var table = (function(){
                    var t = document.createElement('table');
                    t.style.borderCollapse = 'collapse';
                    return t
                }()),
                tbody = document.createElement('tbody'),
                divs = [1, 2, 3, 4].map(function(v){
                    return document.createElement('div')
                });
            tbody.appendChild((function(data){
                var dom = ['tr', 'td', 'td', 'input'].map(function(i){
                    return document.createElement(i)
                });
                dom[1].colSpan = '2';
                dom[2].className = 'app-modadd';
                dom[2].appendChild(document.createTextNode('Add'));
                self._style(dom[2], {
                    textAlign: 'left',
                    padding: '.2em',
                    cursor: 'pointer',
                    textDecoration: 'underline'
                });
                dom[3].type = 'text';
                dom[3].className = 'app-modaddfield';
                dom[1].appendChild(dom[3]);
                dom.slice(1,3).forEach(function(i){dom[0].appendChild(i)});
                return dom[0];
            }(data['data'])));
            
            //Path and URI rows styling
            [divs[0], divs[2]].forEach(function(i){
                self._style(i, {    
                    textAlign: 'left',
                    padding: '.2em',
                    cursor: 'pointer',
                    textDecoration: 'underline'
                });
            });
            //Creating table rows for modules
            for (var row in obj) {
                if (!obj.hasOwnProperty(row)) continue;
                tbody.appendChild((function(row, data){
                    var dom = ['tr', 'td', 'td', 'td'].map(function(i){
                        return document.createElement(i)
                    });
                    dom.slice(1,2).forEach(function(i){self._style(i, {
                        minWidth: '6em', padding: '.2em'
                    })});
                    dom[1].appendChild(document.createTextNode(row));
                    dom[2].appendChild(document.createTextNode(obj[row]));
                    self._style(dom[3], {
                        cursor: 'pointer', padding: '.2em', textAlign: 'right'
                    });
                    dom[3].className = 'app-modremove';
                    dom[3].appendChild(document.createTextNode('[x]'));
                    dom.slice(1).forEach(function(i){dom[0].appendChild(i)});
                    self._style(dom[0], {borderBottom:b_style});
                    dom[0].className = 'app-modentry';
                    return dom[0];
                }(row, data['data'])));
            }
            table.appendChild(tbody);
            divs[0].className = 'app-modexpand';
            divs[0].appendChild(document.createTextNode('show'));
            divs[1].appendChild(table);
            divs[2].className = 'app-modcollapse';
            divs[2].appendChild(document.createTextNode('hide'));
            divs.slice(1,3).forEach(function(i){self._style(i, {display: 'none'})});
            divs.slice(0,3).forEach(function(i){divs[3].appendChild(i)});
            return divs.pop();
        }(data['data']['modules']));

        //Create execute
        dom['execute'] = (function(){
            var fragment = document.createDocumentFragment();
            var input = document.createElement('input'); input.type = 'text';
            input.setAttribute('class', 'app-executecmd form-control');
            input.setAttribute('style', 'width: 50%; float:left;');
            input.setAttribute('placeholder', '0-9a-zA-Z /_-.,"~>< symbols are allowed');
            fragment.appendChild(input);

            var button = document.createElement('button');
            self._style(button, {minWidth: '5.2em'});
            button.appendChild(document.createTextNode('Run'));
            button.setAttribute('class', 'app-execute btn btn-default input-button');
            fragment.appendChild(button);

            return fragment;
        }());

        //Create show virtual environment activate command
        dom['activate'] = (function(activate_cmd){
            var activate_line = document.createElement('span');
            activate_line.setAttribute('class', 'enter-virtualenv-cmd');
            activate_line.appendChild(document.createTextNode(activate_cmd));
            return activate_line;
        }(data['data']['activate']));

        //Creating app table rows
        var titles = req['alt'] === 'python'
            ? ['path', 'uri', 'domains', 'wsgi', 'version', 'modules', 'execute', 'activate']
            : ['path', 'uri', 'domains', 'version', 'modules', 'execute', 'activate'];
        titles.forEach(function(i){
            var cells = ['tr', 'td', 'td', 'td'].map(function(j){
                return document.createElement(j)
            });
            cells[0].className = 'app-' + i + 'section';
            self._style(cells[1], {
                borderRight: b_style,
                borderBottom: b_style,
                width: '20%',
                textAlign: 'right',
                fontSize: '.92em',
                padding: '.1em .6em',
                height: '2em'
            });
            cells[1].appendChild(document.createTextNode(title_alias[i]));
            self._style(cells[2], {
                borderBottom: b_style,
                width: '73%',
                fontSize: '.92em',
                padding: '.1em .6em',
                height: '2em'
            });
            cells[2].appendChild(dom[i]);
            if (i === 'version') {
                cells[2].appendChild((function(v){
                    var el = document.createElement('span');
                    self._style(el, {display:'none'});
                    el.appendChild(document.createTextNode(v));
                    return el;
                }(data['data']['version'])));
            } else if (i === 'domains') {
                cells[2].className = 'app-additionaldomains-list';
            }
            self._style(cells[3], {
                borderBottom: b_style,
                width: '7%',
                fontSize: '.92em',
                padding: '.1em .6em',
                height: '2em'
            });
            if (i === 'path' || i === 'uri' || i === 'wsgi') {
                cells[3].appendChild((function(t){
                    var el = document.createElement('span');
                    self._style(el, {cursor:'pointer', textDecoration:'underline'});
                    el.className = 'app-' + i + 'edit';
                    el.appendChild(document.createTextNode(t));
                    return el;
                }('Edit')));
            } else {
                cells[3].appendChild(document.createTextNode('\u00A0'));
            }
            if (i === 'domains' && cells[2].getElementsByTagName("a").length == 0) {
                cells[0].style.display = 'none';
            }
            cells.slice(1).forEach(function(j){cells[0].appendChild(j)});
            dom['tbody'].appendChild(cells[0]);
        });
        
        self._style(dom['table'], {borderSpacing: '0', width: '100%'});
        dom['table'].appendChild(dom['tbody']);
        self._style(dom['info'], {margin: '.2em'});
        dom['info'].appendChild(dom['table']);
        self._style(dom['controls'], {height: '2.32em', paddingLeft: '1em'});
        ['update', 'reset', 'restart', 'remove'].forEach(function(i){
            var b = 'b_'+i;
            dom[b].className = 'app-'+ i + ' btn btn-default input-button';
            dom[b].style.minWidth = '5.2em';
            dom[b].appendChild(document.createTextNode(i.charAt(0).toUpperCase() + i.slice(1)));
            if (i === 'remove')
                self._style(dom[i], {marginLeft: '2em'});
            else if (i === 'update' || i === 'reset')
                dom[b].disabled = true;
            dom[i].appendChild(dom[b]);
            self._style(dom[i], {cssFloat: 'left', minWidth: '5.2em'});
            dom['controls'].appendChild(dom[i]);
        });
        ['info', 'controls'].forEach(function(i){
            dom['container'].appendChild(dom[i])
        });
        self._style(dom['container'], {
            border: b_style, borderRadius: '.2em', margin: '.4em 1em'
        });
        dom['container'].className = 'app-container';
        dom['container'].id = self.id;
        self.parent.appendChild(dom['container']);
        self.add_hook();
        var path_field = document.getElementById('project-path-field'),
            uri_field = document.getElementById('project-uri-field');
        if (path_field !== null) path_field.value = '';
        if (uri_field !== null) uri_field.value = '';
        var app_count = document.getElementById('app-count');
        if (app_count) {
            var counter = parseInt(app_count.firstChild.nodeValue);
            if (isNaN(counter)) counter = 0;
            app_count.firstChild.nodeValue = counter+1;
        }
        self._enable_controls();
    };
    
    //Batch style setter
    this._style = function(o, s){
        s = s || {};
        for (var i in s) {
            if (!s.hasOwnProperty(i)) continue;
            o.style[i] = s[i];
        }
    };
    
    this.empty = function(el){
        while (el.firstChild)
            el.removeChild(el.firstChild);
    };

    this.enable_buttons = function(){
        var controls = document.getElementById(this.id).lastElementChild,
            upd = controls.firstElementChild.firstElementChild,
            rst = controls.firstElementChild.nextElementSibling.firstElementChild;
        upd.disabled = false;
        rst.disabled = false;
    };
    
    this.disable_buttons = function(){
        var controls = document.getElementById(this.id).lastElementChild,
            upd = controls.firstElementChild.firstElementChild,
            rst = controls.firstElementChild.nextElementSibling.firstElementChild;
        upd.disabled = true;
        rst.disabled = true;
    };

    /**
     * Display layout over the passed 'parent'element with message: Please wait... or another message
     * @param parent:
     * @param message
     * @private
     */
    this._disable_controls = function(parent, message){
        if (parent === undefined)
            parent = document.getElementById('project-control');
        if (parent === null) return;
        var div = document.createElement('div'),
            span = document.createElement('span'),
            top = (parent.offsetTop+2) + 'px',
            left = (parent.offsetLeft+2) + 'px',
            width = (parseInt(window.getComputedStyle(parent, null).width)-1) + 'px',
            height = (parseInt(window.getComputedStyle(parent, null).height)-1) + 'px';
        div.id = 'modal-layer';
        div.setAttribute('class', 'modal-layer');
        this._style(div, {
            position: 'absolute',
            top: top,
            left: left,
            width: width,
            height: height,
            zIndex: '9999',
            backgroundColor: 'rgba(155,163,178,.3)',
            color: '#000',
            textAlign: 'center',
            lineHeight: height
        });
        this._style(span, {fontSize: '4em', fontWeight: 'bold'});
        span.appendChild(document.createTextNode(message || 'Please wait...'));
        div.appendChild(span);
        parent.appendChild(div);
    };
    
    this._enable_controls = function(parent){
        var div;
        if(parent){
            div = parent.getElementsByClassName('modal-layer')[0] || null;
        } else {
            div = document.getElementById('modal-layer');
        }
        if (div === null) return;
        div.parentNode.removeChild(div);
    };
    
    this.appendlist = function(list, el){
        var popup = document.getElementById('listpopup'),
            o = window.pageYOffset ? window.pageYOffset : 0,
            r = el.getBoundingClientRect(),
            maxlen = Math.max.apply(null, list.map(function(i){return i.length})),
            self = this,
            appDiv = document.getElementById(this.id);
        this.empty(popup);
        for (i in list) {
            if (typeof list[i] === 'function') continue;
            var item = document.createElement('div');
            this._style(item, {height:'1.2em'});
            item.className = 'app-modadditem';
            item.onmouseover = function(e){self._style(e.target, {backgroundColor:'#DBDBDB'})};
            item.onmouseout = function(e){self._style(e.target, {backgroundColor:'#FFF'})};
            item.onclick = function(e){
                var curr = el.value,
                    pos = curr.lastIndexOf(','),
                    extension = e.target.firstChild.nodeValue,
                    data = {};

                self._disable_controls(appDiv);
                data = { extension: extension, action: self.alt + 'modver' };
                self._sync(data, self.getVersionList, false, { field: el });   // synchronous request
                self._enable_controls();

                if(popup.getAttribute('verCount')) {
                    return;
                }

                if (pos !== -1)
                    curr = curr.substring(0, pos);
                else
                    curr = '';
                el.value = (curr !== '' ? curr + ',' + extension : extension) + ',';
            };
            item.appendChild(document.createTextNode(list[i]));
            popup.appendChild(item);
        }
        this._style(popup, {top:(Math.round(r.bottom)+o)+'px',left:Math.round(r.left)+'px',overflow:'auto', width:maxlen+'em', zIndex:'9000'});
        popup.style.maxHeight = '11.2em';
        popup.style.display = 'block';
    };
    
    this.add_hook = function(){
        var self = this,
            el = document.getElementById(self.id),
            char_patt = /[a-zA-Z0-9\-_]/;
        if (el === null) return;
        var f = el.getElementsByClassName('app-modaddfield')[0];
	if (!f) return;
        f.addEventListener('keypress', function(evt){
            var charCode = evt.which || evt.keyCode,
                charTyped = String.fromCharCode(charCode),
                tgt = evt.target,
                pos = tgt.value.lastIndexOf(','),
                found = false,
                data,
                list = [];
            if (modlist.length === 0) return;
            if (pos !== -1) {
                data = tgt.value.substring(pos+1);
            }
            else {
                data = tgt.value;
            }
            if (char_patt.test(charTyped)) {
                data += charTyped;
            }
            else if (charCode === 8) {
                data = data.substring(0,data.length-1);
                if (data === '')
                    data = tgt.value.charAt(tgt.value.length-1) === ',' ? tgt.value.substring(0, tgt.value.length-1) : tgt.value;
            }
            for (var i in modlist) {
                if (modlist[i].toString().toLowerCase().indexOf(data.toLowerCase()) !== 0) {
                    if (!found)
                        continue;
                    else
                        break;
                }
                else {
                    if (!found)
                        found = true;
                    list.push(modlist[i]);
                }
            }
            if (list.length === 0) {
                var popup = document.getElementById('listpopup');
                self.empty(popup);
                popup.style.display = 'none';
                return;
            }
            self.appendlist(list, tgt);
        }, false);
    };

    this.getVersionList = function(self, data, req, params) {
        var popup = document.getElementById('listpopup'),
            div, versions,
            sLength = 0;

        if(data.status != 'OK') return false;

        for(key in data.data) {
            versions = data.data[key].versions;

            if(versions.length <= 1)
                continue;

            popup.innerHTML = '';

            for(var i=0; i<versions.length; i++) {
                div = document.createElement('div');
                div.setAttribute('version', key + '#' + versions[i]);
                div.innerHTML = versions[i];
                div.onmouseover = function(e) {self._style(e.target, { backgroundColor:'#ccc', cursor: 'pointer' })};
                div.onmouseout = function(e) {self._style(e.target, { backgroundColor:'#fff', cursor: 'default' })};
                div.onclick = function(e) {
                    var field = params.field,
                        item = e.target,
                        curr = field.value,
                        pos = curr.lastIndexOf(','),
                        extension = item.getAttribute('version');

                    curr = (pos !== -1) ? curr.substring(0, pos) : '';
                    field.value = (curr !== '' ? curr + ',' + extension : extension) + ',';

                    popup.removeAttribute('verCount');
                };

                popup.appendChild(div);
            }

            popup.setAttribute('verCount', versions.length);
        };
    }
}