From 43725eb8d3d04fbdf712b48bb086eb5ca5787985 Mon Sep 17 00:00:00 2001 From: metalwolf Date: Tue, 9 Apr 2024 21:28:16 -0500 Subject: [PATCH] patch v0.3.0 --- README.md | 28 +- examples/public/skins/4gl/dommask-upload.png | Bin 0 -> 5663 bytes examples/public/skins/4gl/textfield-error.png | Bin 0 -> 737 bytes examples/public/skins/css/4gl.css | 84 ++- groupcontainer.go | 2 +- js/containers/floatingContainer.js | 530 ++++++++++++++ js/containers/floatingContainer.none | 488 ------------- js/containers/gridContainer.js | 611 ++++++++++++---- js/containers/groupContainer.js | 180 +++-- js/containers/tabContainer.js | 3 + js/containers/treeContainer.js | 249 ++++++- js/elements/ggraphElement.js | 158 +++- js/elements/lovfieldElement.js | 117 ++- js/elements/mmcfieldElement.js | 304 ++++++-- js/elements/searchabletextfieldElement.js | 677 ++++++++++++++++++ js/elements/textareafieldElement.js | 14 +- js/elements/textfieldElement.js | 14 +- js/managers/ajaxManager.js | 17 +- js/managers/wa4glManager.js | 2 + js/system/core.js | 2 +- js/system/corebrowser.js | 29 +- js/system/coretemplate.js | 143 ++++ lovfieldelement.go | 2 +- mmcfieldelement.go | 6 +- searchabletextfieldelement.go | 16 + wajaf.go | 2 +- 26 files changed, 2804 insertions(+), 874 deletions(-) create mode 100644 examples/public/skins/4gl/dommask-upload.png create mode 100644 examples/public/skins/4gl/textfield-error.png create mode 100644 js/containers/floatingContainer.js delete mode 100644 js/containers/floatingContainer.none create mode 100644 js/elements/searchabletextfieldElement.js create mode 100644 searchabletextfieldelement.go diff --git a/README.md b/README.md index 271b930..a834691 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,6 @@ [![Go Report Card](https://goreportcard.com/badge/github.com/webability-go/wajaf)](https://goreportcard.com/report/github.com/webability-go/wajaf) [![GoDoc](https://godoc.org/github.com/webability-go/wajaf?status.png)](https://godoc.org/github.com/webability-go/wajaf) -[![GolangCI](https://golangci.com/badges/github.com/webability-go/wajaf.svg)](https://golangci.com) WAJAF for GO v0.1 ============================= @@ -52,7 +51,7 @@ For objects: - WA.extend: Will extends an object from another (inheritance). - WA.clone: Will clone an object and all its children. -- If you dont care the type of object but only its attributes, you can use WA.clone(object, true) --- If you use the normal method WA.clone(object), it will close the whole object with attributes and methods. +-- If you use the normal method WA.clone(object), it will clone the whole object with attributes and methods. - WA.sizeof: Will calculates the size (number of attributes) of an object. For DOM nodes: @@ -109,6 +108,31 @@ TO DO: Version Changes Control ======================= +v0.3.0 - 2024-04-09 +------------------------ +- Added searcheabletextfieldElement, go and JS modified +- mmcFieldElement now supports multifile upload too, and a template to present information +- lovFieldElement now supports radio and checkboxes, and multiple select +- groupContainer now supports sub-forms for master-details administration screens with templates to format detail records +- Errors corrected con crowser getNodeDocumentLeft and getNodeDocumentTop to be correctly calculated with scroll offsets +- Added function findNodeByClass in browser class +- Added coretemplate.js to inject templates with data sets +- Added floatingContainer for floating windows in page +- Added resize of columns, order of columns and drag and drop for order into gridContainer +- Error corrected on tabContainer when unloading the instance +- TreeContainer now supports dragging and hover, sinchronized with server with the listener +- textfieldElement and textareafieldElement corrected to display correctly the number of words and letters +- New classes into css for new components + + +v0.1.4 - 2022-12-02 +------------------------ +- Added listener option to AjaxRequest to follow the upload of request to the server +- Error corrected in the 4GL Manager, the node with an inner application was not linking the application attribute +- ggraphElement has been changed to control errors with try-catch when calling the google library +- mmcFieldElement has been modified to work as expected and be able to manage any kind of files +- gridContainer has been modified to be able to order the information by columns + v0.1.3 - 2022-06-12 ------------------------ - Added CodeNode.go to create a node of code. diff --git a/examples/public/skins/4gl/dommask-upload.png b/examples/public/skins/4gl/dommask-upload.png new file mode 100644 index 0000000000000000000000000000000000000000..f81255513e584b534e71970f5d2ea4d04677df04 GIT binary patch literal 5663 zcmai2c{tQ<+qRo6W{klI8T-CxPmHlg6GEuWV=am(WF7j=pb{b^+Y~~QB^lZBBeY=3 zR#``dtP@#U$DKlSu-XR`g|V@*?X$5a zII^*E0)I{p&OHQ>6fWNj2;vcE3%0};v$M0iySq`%lZPIU6tb~l`fUhi&XFIMCfd)B zS&OoDki=+t;=e98XX={UPL|M--hjHVx#T#U!56lm0)ZBZu8Fy3ijJG z&%dk>_XyXQ!O~3P4SpNxi|YlieA!qE^J$aV{h=dqP?hud`|(3dNv^2^Z7Hu?KPJsW zBEsWzZIW7pl0*DilO*teo)U+QIgbY{Q;R4?n8p`9x$xz|fVsMlZj`XoaPo z88|Cr%3%GX?Y+fM_Y^+Ib~s5l1Lz1(<9*562W@>&(kT%;cAP z1vkF{su>_oJY*v#)s*RkXV$eM6%dM)1XHF1LGc@R|DgixTXQd-mSW8LUNrSFm~BiV zD0?27QnRxbqn=)a9|O4?YNYK&9N`{s0aOD6Ehod@x%ej52IOw7k+u_g3-_o4P^}EK z?6@{n8p#cn7X$5Wz;tuE+L@J#0bCILC3#NF)SDZ6)D4*Ryur$~qRU!|tU+Q8z+|iW z6jUL$%v;5RJ}uDg2=ID>rdMkQWWSX{n#d14QX#mpRKJ5xN_hG-`ut0z1PjWE1!GNU z>fS3U`~k)&tj5RGZV?p7eV^r-$RazvyCpe3Cuou`d0n3p$N_{o6xVV9!6zt|K zU)52hUS&k3@aAPo+y?%XhG(Rrcp=Hvd)V$UF6;15^>~m?AzbZ1VBB$-`^VqAY2#&r7ZWRzcu$DBybeCuZ{o~1&tePevSsfm@jl-Jz|1&0wA3LQ_bQAjb?MBKd9S@ z2#TyNg!(+&sRI_dsdmPEq!XrtN?K1$%7pps(A5P(PqSW7qD!HzQune=T3L@uq33AL zx~(COc?`jYnTTG>nB~YDDPbxIWP9pkXnB0l<1)TTm(wIe{_$gwVodtla}Ewos1tDfA>Ng_+o{M2ex7BC)k?LO^&XMP}ynY3o*-Epr zwBdYn4?WX4HtWV;Rz3Zbdr zCS-EU`Dzchlm#z{P0G&%c7@@iI`>Q!Cjb4YOez5v^C&veKZOL(wIHj`&Y zE+a%(oZ4tB7h5SUDPVH)qtZDuMy;49fRe@9I#S$J+jv zJQw8f?^-?9^0kmD3oMZ>)oPIg-K{qzALplC54J}Bn96REKbqWJwUU~A>`AhR0H8T1 zRm-ab#?I76fYlZ1rt?$kw>7MS;7GaGYbc((R?>uhgED$xtP^7i7%~T7OLH2GyS>MR&I}oxFdR^dYR; zCqaY=(L^_%8BogPo{4%64$bw++oQ^=v66u(4-DLCG&a2<*@S}p+Cu#CLA+Az!b5jb z_m2lQ+5q;^4cbdo>sbo+(Jl=}u)_iT3q4rbBzxqCs+;omNWW@&8H{kXNuKp+qEF?v z0#Z@Si}JWD2Dr{v@g{5#@W+J7aU%YCKeg9%a;g) zQs-UdUr+R%alIb0|AS(m;_b3PcanH_lToPs;>jf4cz@%Yrc2H)N!**i$1u$P6)uWnc zEa)4p@=731lX)tZVy1~RyXJOFLrqR50Hp}PtpnYN+jZ5K=7ljU!wq~_z*So_-Wkh- zAiYMT%3u7$%xd%Pp?bcZ8E_&Bc4Y>C@tRwzMtG$1VAg5tqUR@a8aMyQF*~j`G7^4y zRZ!Qe%E!5V@!Ra@@+exE_$dQu=Z|69rReC*k|^4ufa8>XauDi4E+^kO&?}UI-yYg{ zdLgFAsM^9!=+oS4trL7|f8{Wl7Fw4Hi~(M$(22nt(K%nm3CV6el#|V~zs3w(+^+ax1w(ge zKgFLVL7A#jq5IBE9a8baM_$vngt8l5@6o^+TXjMC*_seUNL;p9<7m#$(vRkp=vxqW z4;OACP6v4?i^Ybd{+Y#QX>fRIdofEmn9xr#Ubq?y&z_|w-g%o#Cr=I9)gfRFM+K*| zgdw=9z^m^U;UVvXtx@}+S02*-Fb5_Inhqa)Ym{mCfMozT^mk}j^~eH}R@^~Yu# z*P+)`0Xzq)KK_eI$w2}Xr~1c!HDJjGJq@Ir#;^(FM}m9waW&W2G1PPo0*pOj8>x0( zl9VjCg3mKAXCVZs);LKdGuYgn3?daT2BVe{DgXuNqR+0A#MnAyQC#*y5m(~I!yRu0 zE&004r1Wn!vZ(-7qOBmjAjd3W3d8k2tFs>hpttVqui?Wz#8DWUhD+*1T=~Hgq~Vj~ z(Sf&Qpm-!5KmS20jvtfgZZ1Fzl-wlaiTASz^TuvyGEn27n8IicjDn)TP;&uXaiAd= zgkO?mEpu@IH6|TFIv_wL;7#Le=hT4DR2{tO4SI`%IK{tMLq-5^X+Ngj(!8n%nR}Tbkk|WCfMQ=__$Mi@7R&xNDZ#|e zpoJy~yFW{jQhb?U6pG}izDah3c+jRUAvw)xM7BQF=PB7gK5?$9Vgt1JA6#s<^qWf_qYZWe@ zyQhOzpbUSb9$DbxtKzG^&sI`13Nqjc9=_jT(201HcvCelwJU3T`OhGaZ}@qw@>f#$ zt-7f;z&7Q}{q_WhD*+ZOy5(kA zk{QV*e9FV5`MNmwNhYtpqH*GWvG=x2aNg@e2WQE&EPX~s`IZyiHq+U_VESF;ZvC~} z1>a*=?XEo0@0e?A)?UBUp?$I(p{xn&I#WwUm|RNcMwS6)z5x~#bGTCH_s}?NeU4W( zC=}l_t?^{YqYkYqi;+T;@?N4x>^7b0RnB4JI9PlJ-G6p4J%m@qT=^zbM8!PN9Uul$ zH)>dds-1pr?<`-{c>W0tr?YPL@a@l~iT8&jX43}YP}Ro>)kZej2;yOLF$<~Q8AYV0 z3lQf8TqCh+;bG1S zL-|bc80rR@h0y5qGu7vLT~l?c+@Q0#2A)fMxR;slH!+u&4C3_Lj+wmGu)uz_Y&0oN zdEy$(?S;?XS<(1f&1^i)`z8bbI>fGt7(v~)jqv#0q}z+o%Yt9>cS{(k;VGh>rt{w> zy^uEsUhlo_hYDz%MKsP`F~hco`x$v@437i-@!uQD$-|I?quc8Sr04i$tOHX!AM|%i z8eqtaX_()}>N2&1_V&~P);?{)A`;f5Qz?czoYNrxT6Fh|Bs&FDvm!dBL>m~~ro2wa zissSw712^nPXD;50B6NioK7yH!HaOSKbTAKV*h|xJM4;?|F+u`(nwPF>SzwSSM+pK zI##Q*0XD|MhBLL7w9LO^Z!opRwD)3Rhkqn@5fc+iP4gY&i%E?yndM|qEPd(lBBt72 zGfWd7D&MBbF&vXUhN`wVe5ktL+EPfk$;q4y#8@&myLhX31G=j|mUYB?zM9|e_sO~A zkcQE1b|&@@>hX3KOtX{B;?eA^J4>@^A9f8(+&l4n)7oMTp348BzeeN=)0(oL!cN0Wz`9|zd(7IPV6AkGo*rq)mvP? zqF#V0Q6y;@vGT|vG$m;v;ab7XqF1`yMQ64I7CRR?fQXLFo}WtDYnjT^^&9}Le)y-7 z(9`y#f=>=Yjz2y>yw1feXPch+M1IcuV4l|Y`cBTZYuDc2(Ti@5X;Ud~=PwA>6t0Za z$sZdVJ1ij~;TPOk-}vZg4u7@~GlQ~GX$drYfuRICzq&CSdPEwOqF%LVi%W)$xq;2) zEJ3?SG0ch=^ye`qufp^z#R7HTF*e(Pr2fx^@FXJWew}eez~v)AoOpgmpDALqt?Lj; zm8t51#+wT`d;~_V@p=xC2}8^tShVRdMO>Y0L9OyDzIf%XfI63GwBARGY38wwNF2jw zXyTeiO+MRTuA%w^s2NGPtlnAxynZCm2HY=5lC^^ z1qnxR8nneoT|fK8kpj7w=TM0(CWp2-<4oC)+X-`g`+iFn|J~l+JB9e$vu{U$X&q-? zPf%zZP*=s+#v}EzVZmK`II|fhdtaNb4@`;<%&9}@HewvNH zl+2otjyeI{j3yXm5<}D6UdUt_>zwluu#H0+y$8HI(nz|rao*bOWBLNWMEuY%3#z{O zU zO14{tFD+8=$XLE$x8f|JQiFYrfA_WI=BeGeCKc>dKH6*;tW>;0fEA< z*+n4Q`y*vVdGDU#)gAi+KK{Y_@|Lv|QQ)A2yT;ggwcW;Q08iWVoR@fHHXo zI`FjJI3PB*pb$|XKQ|73FO3M*IKYVJ?U`HOt@wSpBd67P>ar}Y+zzH#l8*o9qJz(E zG!cxj!BGSqt^Z!=LO5lw|D^2+st?t6-~U_pr$f_b7cBQ*Mt@m;`hfm#UEt9w@_*F( kA0v*k|HtSTm9oq3JMtp4eY8P-@5h(T#=?P6jrU6Y2PoS-!2kdN literal 0 HcmV?d00001 diff --git a/examples/public/skins/4gl/textfield-error.png b/examples/public/skins/4gl/textfield-error.png new file mode 100644 index 0000000000000000000000000000000000000000..1554c12c8ae8a60a5eea4667181f6e7a4cac14db GIT binary patch literal 737 zcmV<70v`Q|P)l0000PbVXQnQ*UN; zcVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU!gGod|RCwBA{Qu)S!=u=s{|uvma`5xd zkZ>mBvvBYKqTSO+BWwf#CT@G@(NGv+03d)EABK947VRUbXa`67??;bDBYmV5@1sF5 z@&G^pF+Kqn?_zC}Mnhs0jDledSXdaD7#P{vM?+#1jDled00M~dbyw5pZ>Nv*j0VLh z814KHec^@Y;2<;F$zY(aBjLY@$!y_!YCL8!yJr`z>b1ZFcLEQ|39Psp;0gj zhC2WVz|I}pAPmF+6!qPaP%;4>b@riS6goDcViF{lNS!uCQY46iAuPQ&!fz~Dvdi?i z@BR4_$6<)*Iz<2=p~Lcd$LV@g0st}(^wLU1wR#7D%xe8#u5Ftd0FYGqJ(!ta&t)CQ zK3Y=*022BNz|I|;APfZo7`_+9GLRxe1av0{a0FZT2w1p{BM2!htb&4wkQlLb0-t=} z2-o}^k9%q8PI1|7r=jmn1K`^*MvOk;;`hyuZ9A>jn<%QvGyovipf}AjW_4{60FZOg zi?WR5{u}`E4tgYKYXFeDLd*f+AA;`w902|x=pUjE0C@-f{3;~iZ0SqT# z%=gKW&;7~Fymb9J#NTe)Hj`OQ;v@2S9G$v082|tPcxRwDt7Y4te?@Pxh-xq}5dZ)H zC?LoA6y536Z|(p908lc}Q%aA`EGg&b$^C~JkJ14E0N|~jCH@-Z;v4_~07?XUG6ett z04N>kowl_&6#xJLN(Xv1`i%eM(Ifx>0H9=`57(P~`QBenzlVtAx;p>>0F-b8S8#Y* TVD&PA00000NkvXXu0mjf^Ncq= literal 0 HcmV?d00001 diff --git a/examples/public/skins/css/4gl.css b/examples/public/skins/css/4gl.css index 1c1607a..b919af5 100644 --- a/examples/public/skins/css/4gl.css +++ b/examples/public/skins/css/4gl.css @@ -108,6 +108,9 @@ .group>fieldset>.hidden { display: none; } +.group>.group>fieldset { + margin-left: 50px; border-left: 1px solid black; +} /* grid CONTAINER CLASSES */ @@ -116,10 +119,13 @@ /* 3 types of zones: title, field, control */ .grid .grid-header { position: absolute; left: 0px; right: 0px; top: 0px; height: 20px; background-color: #eee; border-bottom: 1px solid #ccc; overflow: hidden; } .grid .grid-header-content { position: relative; } -.grid .grid-header-column { float: left; } +.grid .grid-header-column { float: left; position: relative; } +.grid .grid-header-column.hover { color: #336; } .grid .grid-header-column-title { background-color: white; height: 16px; padding-top: 3px; padding-left: 5px; border-bottom: 1px solid #999; border-right: 1px solid #999; } .grid .grid-header-column-sizer { float: right; background-color: green; width: 3px; height: 20px; cursor: col-resize; } - +.grid .grid-header-column-order { float: right; width: 15px; height: 16px; background-image: url('../../skins/4gl/order-asc.png'); background-repeat: no-repeat; } +.grid .grid-header-column-order-asc { width: 15px; height: 16px; background-image: url('../../skins/4gl/order-asc.png'); background-repeat: no-repeat; background-position: center; position: absolute; right: 1px; top: 1px; background-color: #fff; border-radius: 50%; } +.grid .grid-header-column-order-desc { width: 15px; height: 16px; background-image: url('../../skins/4gl/order-desc.png'); background-repeat: no-repeat; background-position: center; position: absolute; right: 1px; top: 1px; background-color: #fff; border-radius: 50%; } .grid .grid-body { position: absolute; left: 0px; right: 0px; top: 21px; bottom: 21px; background-color: #eee; overflow: auto; } .grid .grid-body-content { position: relative; } @@ -218,10 +224,34 @@ margin-left: 0px; } .textfield.ok>.field { border-left: 1px solid #44aa44; border-bottom: 1px solid #44aa44; background-color: #eef8cc; } .textfield.error>.field { border-left: 1px solid #cc8800; border-bottom: 1px solid #cc8800; background-color: #ffeeee; } .textfield.edition>.field { border-left: 1px solid #8888ff; border-bottom: 1px solid #8888ff; background-color: #eeeeff; } - +.textfield>.selected { + border: 0px; + padding: 2px; + height: 15px; + border-left: 1px solid #aaa; + border-bottom: 1px solid #aaa; + background-color: #eee; + color: #888; +} .textfield>.help { display: block; padding: 5px; color: #999; float: right; width: 400px; } .textfield>.error { display: block; padding: 5px; color: #f00; float: right; width: 400px; } - +.textfield>.list { + position: absolute; + top: 20px; + background-color: #cceeff; + border: 2px solid blue; + height: 100px; + display: none; + z-index: 10; + overflow-y: scroll; +} +.textfield>.list>.item { + cursor: pointer; +} +.textfield>.list>.item:hover, .textfield>.list>.item.selected { + background-color: blue; + color: white; +} .textfieldlabel.medium { } .textfieldlabel.tiny { width: auto; float: none; text-align: left; padding-left: 20px; } @@ -273,6 +303,9 @@ margin-left: 0px; } .lovfield>.count { color: #999; font-size: 10px; padding-top: 3px; } .lovfield>.value { } .lovfield>.field { width: 270px; border: 0px; height: 20px; border-left: 1px solid #aaa; border-bottom: 1px solid #aaa; background-color: #eee; } +.lovfield>div.field { + height: auto; +} .lovfield.ok>.field { border-left: 1px solid #44aa44; border-bottom: 1px solid #44aa44; background-color: #eef8cc; } .lovfield.error>.field { border-left: 1px solid #cc8800; border-bottom: 1px solid #cc8800; background-color: #ffeeee; } .lovfield.edition>.field { border-left: 1px solid #8888ff; border-bottom: 1px solid #8888ff; background-color: #eeeeff; } @@ -364,9 +397,46 @@ margin-left: 0px; } .dommaskcolorfield.maskdisabled .entryinput { border: 0px; background-color: #eeeeee; padding: 2px; height: 15px; } - - - +/* MMC field */ + +.mmcfieldlabel { float: left; width: 140px; padding-top: 1px; text-align: right; display: block; color: #333; font-size: 12px; font-weight: bold; line-height: 18px; + width: auto; float: none; text-align: left; padding-left: 20px; } +.mmcfieldlabel.error { color: red; } + +.mmcfield { padding-left: 20px; background-repeat: no-repeat; background-position: 2px 4px; position: relative; min-height: 50px; } +.mmcfield.ok { background-image: url('../../skins/4gl/field-ok.png'); } +.mmcfield.error { background-image: url('../../skins/4gl/field-error.png'); } +.mmcfield.edition { background-image: url('../../skins/4gl/field-edition.png'); } + +.mmcfield .upload { border-left: 2px dashed #aaa; border-bottom: 2px dashed #aaa; background-color: #eee; margin: 1px; font-size: 10px; font-weight: bold; min-height: 50px; padding-top: 5px; cursor: pointer; } +.mmcfield .upload-icon { background-image: url('../../skins/4gl/filefield-upload.png'); background-size: cover; background-position: center; background-repeat: no-repeat; width: 25px; height: 25px;} +.mmcfield.ok .upload { border-left: 2px dashed #44aa44; border-bottom: 2px dashed #44aa44; background-color: #eef8cc; color: #0a0; } +.mmcfield.error .upload { border-left: 2px dashed #cc8800; border-bottom: 2px dashed #cc8800; background-color: #ffeeee; color: #a00; } +.mmcfield.edition .upload { border-left: 2px dashed #8888ff; border-bottom: 2px dashed #8888ff; background-color: #eeeeff; color: #00a; } +.mmcfield.ok .upload.dragover { border-left: 2px solid #44aa44; border-bottom: 2px solid #44aa44; background-color: #eef8cc; color: #0a0; } +.mmcfield.error .upload.dragover { border-left: 2px solid #cc8800; border-bottom: 2px solid #cc8800; background-color: #ffeeee; color: #a00; } +.mmcfield.edition .upload.dragover { border-left: 2px solid #8888ff; border-bottom: 2px solid #8888ff; background-color: #eeeeff; color: #00a; } + +.mmcfield .uploading { position: relative; border-left: 2px solid #8888ff; border-bottom: 2px solid #8888ff; background-color: #eeeeff; margin: 1px; font-size: 12px; font-weight: bold; min-height: 50px; } +.mmcfield .uploading-icon { background-image: url('../../skins/4gl/loader.gif'); background-size: cover; background-position: center; background-repeat: no-repeat; width: 25px; height: 25px; margin-left: 10px; margin-top: 10px; float: left;} +.mmcfield .uploading-name { position: absolute; top: 10px; left: 60px; } +.mmcfield .uploading-perc { position: absolute; top: 10px; right: 5px; } +.mmcfield .uploading-bar { position: absolute; bottom: 10px; right: 5px; height: 10px; width: calc(100% - 55px); background-color: white;} +.mmcfield .uploading-progressbar { position: absolute; left: 0; width: 0; height: 10px; background-color: #77a;} + +.mmcfield .uploaded { position: relative; margin: 3px; font-size: 10px; font-weight: bold; min-height: 50px; } +.mmcfield.editing .uploaded { background-color: #eef;} +.mmcfield .uploaded-icon { max-height: 50px; max-width: 50px; float: left; } +.mmcfield .uploaded-image { max-height: 50px; max-width: 100px; float: left; margin-right: 5px; } +.mmcfield .uploaded-value { margin-left: 5px; } +.mmcfield .uploaded-delete { width: auto; border: 1px solid red; padding: 5px; position: absolute; bottom: 0; right: 0; cursor: pointer; } +.mmcfield .uploaded-delete:hover { background-color: red; color: white; } + +.mmcfield>.help { display: block;padding: 5px; color: #999; float: right; width: 400px; } +.mmcfield>.error { display: block; padding: 5px; color: #f00; float: right; width: 400px; } + +.mmcfieldlabel.tiny { width: auto; float: none; text-align: left; padding-left: 20px; } +.mmcfield.tiny { margin-left: 0px; } diff --git a/groupcontainer.go b/groupcontainer.go index 9c8d514..fdee6af 100644 --- a/groupcontainer.go +++ b/groupcontainer.go @@ -13,7 +13,7 @@ func NewGroupContainer(id string) *GroupContainer { c.RegisterKnownAttributes([]string{"display", "style", "classname", "classnamezone", "left", "width", "right", "top", "height", "bottom", "haslistener", - "varmode", "varorder", "varkey", + "varmode", "varorder", "varkey", "maingroup", "mode", "authmodes", "key"}) // c.RegisterKnownMessages([]string{"alertmessage", "servermessage", "titleinsert", "titleupdate", "titledelete", "titleview", "insertok", "updateok", "deleteok"}) c.RegisterKnownChildren([]string{"zone", "dataset", "event", "help"}) diff --git a/js/containers/floatingContainer.js b/js/containers/floatingContainer.js new file mode 100644 index 0000000..f874f41 --- /dev/null +++ b/js/containers/floatingContainer.js @@ -0,0 +1,530 @@ + +/* + floatingContainer.js, WAJAF, the WebAbility(r) Javascript Application Framework + Contains container to control moveable zones + (c) 2008-2010 Philippe Thomassigny + + This file is part of WAJAF + + WAJAF is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + WAJAF is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with WAJAF. If not, see . +*/ + +/* The floating Container is a division-nav-sized that lock windows in it with a overflow: hidden */ +/* The floating Container have a list of windows accesible to switch windows on the left */ + +WA.Containers.floatingContainer = function(domNodeFather, domID, code, listener) +{ + var self = this; + + WA.Containers.floatingContainer.sourceconstructor.call(this, domNodeFather, domID, code, 'div', { classname: 'float' }, listener); + + this.classes = WA.getClasses(code.attributes, + { + classname: 'float', + classnameheader: 'float-header', classnameheadercontent: 'float-header-content', + classnamebody: 'float-body', classnamebodycontent: 'float-body-content', + classnameclose: 'buttonmenudisconnect', + }); + + this.haslistener = (code.attributes.haslistener === 'yes'); + this.params = code.attributes.params ? '&' + code.attributes.params : ''; + this.hasdd = !!WA.Managers.dd; + this.zones = {}; + this.zoneactive = this.code.attributes.startzone ? this.code.attributes.startzone : null; + + this.domNode.style.display = 'none'; + this.domNodeContainer = document.createElement('div'); + this.domNodeContainer.id = "domNodeContainer"; + this.domNodeContainer.style.display = 'none'; + this.domNodeContainer.style.position = 'absolute'; + this.domNodeContainer.style.left = '0px'; + this.domNodeContainer.style.right = '0px'; + this.domNodeContainer.style.top = '0px'; + this.domNodeContainer.style.bottom = '0px'; + this.domNodeContainer.style.backgroundColor = 'transparent'; + this.domNodeContainer.style.zIndex = '10'; + document.body.appendChild(this.domNodeContainer); + + this.domNodeModal = document.createElement('div'); + this.domNodeModal.id = "domNodeModal"; + this.domNodeModal.style.position = 'absolute'; + this.domNodeModal.style.left = '0px'; + this.domNodeModal.style.right = '0px'; + this.domNodeModal.style.top = '0px'; + this.domNodeModal.style.bottom = '0px'; + this.domNodeModal.style.backgroundColor = 'black'; + this.domNodeModal.style.opacity = '0.6'; + this.domNodeModal.style.zIndex = '11'; + this.domNodeContainer.appendChild(this.domNodeModal); + + //this.domNodeModal.onclick = hide; + + start(); + //this.addEvent('start', start); + this.addEvent('stop', stop); + + this.newZone = newZone; + function newZone(id, title, classname, style, application, closeable, shortcut, params) { + var code = {}; + code.tag = 'zone'; + code.attributes = { id: id, title: title, classname: classname, style: style, closeable: closeable, shortcut: shortcut, application: application, params: params }; + self.app.createTree(self, code); + } + + // id is unique id, code are all needed parameters + this.createZone = createZone; + function createZone(id, code, notify) { + var ldomID = WA.parseID(id, self.xdomID); + if (!ldomID) + throw 'Error: the zone id is not valid in floatingContainer.createZone: id=' + domID; + // check the zone does not exists YET ! + if (self.zones[ldomID[2]]) + throw 'Error: the zone already exists in floatingContainer.createZone: id=' + ldomID[2]; + + // 1. call event precreate, can we create ? + if (!self.callEvent('precreate', { id: ldomID[2] })) + return null; + + var z = new WA.Containers.floatingContainer.floatingZone(self, ldomID[3], code, notify); + self.zones[ldomID[2]] = z; + z.start(); + + if (!self.zoneactive) { + self.zoneactive = ldomID[2]; + z.show(); + } + + self.callEvent('postcreate', { id: ldomID[2] }); + if (self.state == 5) { + z.propagate('start'); + } + return z; + } + + this.showZone = showZone; + function showZone(id) { + var ldomID = WA.parseID(id, self.xdomID); + if (!ldomID) + throw 'Error: the zone id is not valid in floatingContainer.showZone: id=' + id; + // check the zone does not exists YET ! + if (!self.zones[ldomID[2]]) + throw 'Error: the zone does not exists in floatingContainer.showZone: id=' + ldomID[2]; + var result = true; + result &= self.callEvent('preshow', ldomID[2]); + if (self.zoneactive && ldomID[2] !== self.zoneactive) + result &= self.callEvent('prehide', self.zones[self.zoneactive].xdomID[2]); + if (!result) + return; + + // first hide actual + if (self.zoneactive && ldomID[2] !== self.zoneactive) { + self.zones[self.zoneactive].hide(); + self.callEvent('posthide', self.zones[self.zoneactive].xdomID[2]); + self.zoneactive = null; + } + + // then show the specified zone + self.zones[ldomID[2]].show(); + self.zoneactive = ldomID[2]; + self.callEvent('postshow', ldomID[2]); + self.zones[ldomID[2]].propagate('focus'); + if (self.state == 5) { + self.propagate('resize'); + } + } + + this.activateZone = activateZone; + function activateZone(id) { + self.showZone(id); + } + + this.destroyZone = destroyZone; + function destroyZone(id) { + var ldomID = WA.parseID(id, self.xdomID); + if (!ldomID) + throw 'Error: the zone id is not valid in floatingContainer.destroyone: id=' + id; + // check the zone does not exists YET ! + if (!self.zones[ldomID[2]]) + throw 'Error: the zone does not exists in floatingContainer.destroyZone: id=' + ldomID[2]; + + // 2. call event predestroy + if (!self.callEvent('predestroy', { id: ldomID[2] })) + return; + + var available = null; + if (ldomID[2] == self.zoneactive) { + var next = false; + // take next available + for (var i in self.zones) { + if (i == self.zoneactive && available == null) { + next = true; + continue; + } + if (i == self.zoneactive) + break; + available = i; + if (next) + break; + } + } + + self.app.destroyTree(ldomID[2]); + delete self.zones[ldomID[2]]; + + if (ldomID[2] == self.zoneactive) { + self.zoneactive = null; + if (available) + self.activateZone(available); + } + + self.callEvent('postdestroy', { id: ldomID[2] }); + self.propagate('resize'); + } + + + this.start = start; + function start() { + if (self.hasdd){ + console.log("floatingcontainer REGISTRANDO GROUPO", self.domNode, self.domNodeContainer); + WA.Managers.dd.registerGroup(self.domNode, 'caller', true, self.domNode, null); + } + } + + function stop() { + if (self.hasdd) + WA.Managers.dd.unregisterGroup(self.domID); + } + + this.destroy = destroy; + function destroy(fast) { + self.zones = null; + self.domNodeContainer = null; + WA.Containers.floatingContainer.source.destroy.call(self, fast); + self = null; + } + + // =========================================================== + // PRIVATE FUNCTIONS + + /* + // Put each division on original place + this.restart = restart; + function restart() + { + for (var i=0, l=self.floatings.length; i < l; i++) + { + self.floatings[i].restart(); + } + } +*/ + this.show = show; + function show() { + self.domNodeContainer.style.display = 'block'; + self.resize(); + } + + this.hide = hide; + function hide() { + self.domNodeContainer.style.display = 'none'; + } +/* + // put division on a new position by program + this.setPosition = setPosition; + function setPosition(id, left, top) + { + for (var i=0, l=self.floatings.length; i < l; i++) + { + if (self.floatings[i].getID() == id) + { + self.floatings[i].setPosition(left, top); + } + } + } + */ +/* + + this.getWidth = getWidth; + function getWidth() + { + return self.width; + } + + this.getHeight = getHeight; + function getHeight() + { + return self.height; + } + + this.selectormouseover = selectormouseover; + function selectormouseover(id) + { + // we create the list of windows + // -> [ onclick item of window => window set focus, then close the list ] + + // we attach the list to the container + + // we listen the list: on mouse out ==> close it + + + } +*/ +} + +// Add basic container code +WA.extend(WA.Containers.floatingContainer, WA.Managers.wa4gl._container); + +WA.Containers.floatingContainer.floatingZone = function (maincontainer, domID, code, notify) { + var self = this; + WA.Containers.floatingContainer.floatingZone.sourceconstructor.call(this, maincontainer, domID, code, 'div', { classname: 'zone' }, notify); + maincontainer.domNodeContainer.appendChild(this.domNode); + //self.container = WA.toDOM("main|single|workarea"); + + this.left = parseInt(code.attributes.left, 10); + this.top = parseInt(code.attributes.top, 10); + this.width = parseInt(code.attributes.width, 10); + this.height = parseInt(code.attributes.height, 10); + + this.domNode.style.position = "absolute"; + this.domNode.style.top = this.top + 'px'; + this.domNode.style.left = this.left + 'px'; + this.domNode.style.width = this.width + 'px'; + this.domNode.style.height = this.height + 'px'; + this.domNode.style.border = "1px solid #99bbe8"; + this.domNode.style.backgroundColor = "white"; + this.domNode.style.zIndex = '12'; + + //if(this.domNode.id == 'control|single|clientsearchcontainer') + addHead(code); + + function addHead(code) + { + // header division + self.domNodeHeader = WA.createDomNode('div', domID+'_header', self.father.classes.classnameheader); + self.domNode.insertAdjacentElement('afterbegin', self.domNodeHeader); + self.domNodeHeader.style.backgroundColor = "#f5f6f7"; + self.domNodeHeader.style.border = "1px solid #99bbe8"; + self.domNodeHeader.style.top = '0px'; + self.domNodeHeader.style.left = '0px'; + self.domNodeHeader.style.width = code.attributes.width - 4 + 'px'; + self.domNodeHeader.style.height = '20px'; + + var nodeClose = WA.createDomNode('div', domID+'_header_close', self.father.classes.classnameclose); + nodeClose.style.width = '16px'; + nodeClose.style.height = '16px'; + nodeClose.style.position = 'absolute'; + nodeClose.style.right = '10px'; + nodeClose.style.top = '2px'; + self.domNodeHeader.appendChild(nodeClose); + nodeClose.onclick = self.father.hide; + + setTimeout(()=>{ + self.domNode.lastChild.style.top = '20px'; + },400) + } + + var top = 0; + var bottom = 0; + var left = 0; + var right = 0; + var xCursor = 0; + var yCursor = 0; + + this.move = move; + function move(order, id1, lineid, zone, metrics) + { + switch (order) { + case 'start': + var n = WA.toDOM(self.domNodeHeader.id); + n.getAttribute('class'); + if(/dragged/.exec(n.getAttribute('class')) == null) + self.domNodeHeader.className += ' dragged'; + self.domNode.style.position = 'absolute'; + self.domNode.style.left = metrics.dragdocumentleft + 'px'; + self.domNode.style.top = metrics.dragdocumenttop + 'px'; + self.domNode.style.width = metrics.mainwidth + 'px'; + self.domNode.style.height = metrics.mainheight + 'px'; + + top = WA.browser.getNodeDocumentTop(self.domNode); + bottom = WA.browser.getNodeDocumentTop(self.domNode) + WA.browser.getNodeHeight(self.domNode); + left = WA.browser.getNodeDocumentLeft(self.domNode); + right = WA.browser.getNodeDocumentLeft(self.domNode) + WA.browser.getNodeWidth(self.domNode); + break; + case 'drag': + var l = dragPos(metrics.xmouse, metrics.ymouse); + left += l.l; + top += l.r; + self.domNode.style.left = left + l.l + 'px'; + self.domNode.style.top = top + l.r + 'px'; + break; + case 'drop': + top = 0; + bottom = 0; + left = 0; + right = 0; + xCursor = 0; + yCursor = 0; + break; + } + } + + + function dragPos(x, y) + { + var l = xCursor == 0 ? 1 : x - xCursor; + var r = yCursor == 0 ? 1 : y - yCursor; + + if(x < xCursor) + l = l * 2 - l; + + if(y < yCursor) + r = r * 2 - r; + + xCursor = x; + yCursor = y; + + return {l,r}; + } + + + this.start = start; + function start() + { + if (self.father.hasdd) { + console.log('floatingContainer REGISTEROBJECT') + //self.father.domNodeContainer, self.domNode, self.domNode + WA.Managers.dd.registerObject(maincontainer.domNode, self.domNodeHeader, self.domNode, move); + } + } + + /* + this.resize = resize; + function resize() { + console.log("RESIZING ZONE", self.domID, "visible=", self.visible, "running=", self.father.visible, "state=", self.state); + // cannot resize if not visible or not running + if (!self.visible || !self.father.visible) + return; + self.domNode.style.height = self.height + 'px'; + + // cannot resize if not visible or not running + if (self.state != 5) + return; + // ask for an inner resize + self.callEvent('pleaseresize'); + } + */ + +/* + + this.startdrag = startdrag; + function startdrag(e) { + if (!self.isok) + return false; + focus(e); + self.statusdd = true; + self.clickx = WA.browser.getCursorX(e); + self.clicky = WA.browser.getCursorY(e); + self.originleft = parseInt(WA.toDOM(self.uid).style.left); + self.origintop = parseInt(WA.toDOM(self.uid).style.top); + + // we create a division to drag on top + var container = document.createElement('div'); + container.id = self.uid + '_drag'; + // take the size of the screen with a minimum size (NS calculates bad the real size for 2 pixels!) + container.style.visibility = 'visible'; + container.style.position = 'absolute'; + container.style.width = (self.fC.width - (WA.browser.isNS() ? 2 : 0)) + 'px'; + container.style.height = (self.fC.height - (WA.browser.isNS() ? 2 : 0)) + 'px'; + container.style.left = '0px'; + container.style.top = '0px'; + container.style.border = '2px Solid #FF0000'; + container.style.backgroundColor = '#EEEE00'; + container.style.opacity = 0.2; + container.style.filter = "alpha(opacity: 20)"; + container.style.cursor = 'pointer'; + container.style.overflow = 'hidden'; + container.style.zIndex = WA.browser.getNextZIndex(); + container.onmousemove = move; + container.onmouseup = stopdrag; + self.dragcontainer = container; + document.body.appendChild(container); + WA.toDOM(self.uid + '_drag').focus(); + + return true; + } + + this.stopdrag = stopdrag; + function stopdrag(e) { + if (!self.isok) + return false; + + // we destroy the drag division + self.dragcontainer.onmousemove = null; + self.dragcontainer.onmouseup = null; + document.body.removeChild(WA.toDOM(self.uid + '_drag')); + self.dragcontainer = null; + + self.originleft = parseInt(WA.toDOM(self.uid).style.left); + self.origintop = parseInt(WA.toDOM(self.uid).style.top); + self.statusdd = false; + if (self.feedback) + self.feedback(self); + + return true; + } + + this.move = move; + function move(e) { + if (!self.isok) + return false; + if (self.statusdd) { + WA.toDOM(self.uid).style.left = self.originleft + (WA.browser.getCursorX(e) - self.clickx) + 'px'; + WA.toDOM(self.uid).style.top = self.origintop + (WA.browser.getCursorY(e) - self.clicky) + 'px'; + return true; + } + return false; + } +*/ +/* + this.restart = restart; + function restart() { + if (!self.isok) + return false; + WA.toDOM(self.uid).style.left = self.systemleft + 'px'; + WA.toDOM(self.uid).style.top = self.systemtop + 'px'; + self.originleft = parseInt(WA.toDOM(self.uid).style.left); + self.origintop = parseInt(WA.toDOM(self.uid).style.top); + if (self.feedback) + self.feedback(self); + } + + this.focus = focus; + function focus(e) { + if (!self.isok) + return false; + WA.toDOM(self.uid).style.zIndex = WA.browser.getNextZIndex(); + } + + this.setPosition = setPosition; + function setPosition(left, top) { + if (!self.isok) + return false; + WA.toDOM(self.uid).style.left = left + 'px'; + WA.toDOM(self.uid).style.top = top + 'px'; + } +*/ + +} + +// Add basic zone code +WA.extend(WA.Containers.floatingContainer.floatingZone, WA.Managers.wa4gl._zone); diff --git a/js/containers/floatingContainer.none b/js/containers/floatingContainer.none deleted file mode 100644 index 29e3c0e..0000000 --- a/js/containers/floatingContainer.none +++ /dev/null @@ -1,488 +0,0 @@ - -/* - floatingContainer.js, WAJAF, the WebAbility(r) Javascript Application Framework - Contains container to control moveable zones - (c) 2008-2010 Philippe Thomassigny - - This file is part of WAJAF - - WAJAF is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - WAJAF is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with WAJAF. If not, see . -*/ - -function floating(id, iddd, feedback, fC) -{ - // we use a trick for functions since 'this' is caller when it is called from events callbacks and not this real object ! - var self = this; - this.uid = ''; - this.uiddd = ''; - this.isok = false; - this.statusdd = false; - this.systemleft = 0; - this.systemtop = 0; - this.originleft = 0; - this.origintop = 0; - this.clickx = 0; - this.clicky = 0; - this.feedback = feedback; - this.dragcontainer = null; - this.fC = fC; - - this.getID = getID; - function getID() - { - return this.uid; - } - - this.startdrag = startdrag; - function startdrag(e) - { - if (!self.isok) - return false; - focus(e); - self.statusdd = true; - self.clickx = WA.browser.getCursorX(e); - self.clicky = WA.browser.getCursorY(e); - self.originleft = parseInt(WA.toDOM(self.uid).style.left); - self.origintop = parseInt(WA.toDOM(self.uid).style.top); - - // we create a division to drag on top - var container = document.createElement('div'); - container.id = self.uid + '_drag'; - // take the size of the screen with a minimum size (NS calculates bad the real size for 2 pixels!) - container.style.visibility = 'visible'; - container.style.position = 'absolute'; - container.style.width = (self.fC.width - (WA.browser.isNS()?2:0))+'px'; - container.style.height = (self.fC.height - (WA.browser.isNS()?2:0))+'px'; - container.style.left = '0px'; - container.style.top = '0px'; - container.style.border = '2px Solid #FF0000'; - container.style.backgroundColor = '#EEEE00'; - container.style.opacity = 0.2; - container.style.filter = "alpha(opacity: 20)"; - container.style.cursor = 'pointer'; - container.style.overflow='hidden'; - container.style.zIndex = WA.browser.getNextZIndex(); - container.onmousemove = move; - container.onmouseup = stopdrag; - self.dragcontainer = container; - document.body.appendChild(container); - WA.toDOM(self.uid+'_drag').focus(); - - return true; - } - - this.stopdrag = stopdrag; - function stopdrag(e) - { - if (!self.isok) - return false; - - // we destroy the drag division - self.dragcontainer.onmousemove = null; - self.dragcontainer.onmouseup = null; - document.body.removeChild(WA.toDOM(self.uid+'_drag')); - self.dragcontainer = null; - - self.originleft = parseInt(WA.toDOM(self.uid).style.left); - self.origintop = parseInt(WA.toDOM(self.uid).style.top); - self.statusdd = false; - if (self.feedback) - self.feedback(self); - - return true; - } - - this.move = move; - function move(e) - { - if (!self.isok) - return false; - if (self.statusdd) - { - WA.toDOM(self.uid).style.left = self.originleft+(WA.browser.getCursorX(e)-self.clickx)+'px'; - WA.toDOM(self.uid).style.top = self.origintop+(WA.browser.getCursorY(e)-self.clicky)+'px'; - return true; - } - return false; - } - - this.restart = restart; - function restart() - { - if (!self.isok) - return false; - WA.toDOM(self.uid).style.left = self.systemleft+'px'; - WA.toDOM(self.uid).style.top = self.systemtop+'px'; - self.originleft = parseInt(WA.toDOM(self.uid).style.left); - self.origintop = parseInt(WA.toDOM(self.uid).style.top); - if (self.feedback) - self.feedback(self); - } - - this.focus = focus; - function focus(e) - { - if (!self.isok) - return false; - WA.toDOM(self.uid).style.zIndex = WA.browser.getNextZIndex(); - } - - this.setPosition = setPosition; - function setPosition(left, top) - { - if (!self.isok) - return false; - WA.toDOM(self.uid).style.left = left+'px'; - WA.toDOM(self.uid).style.top = top+'px'; - } - - this.unload = unload; - function unload() - { - // MAYBE WE CAN CALL THE FEEDBACK TO SAY WE ARE UNLOADING ? (to do) - - // desactive floating - self.isok = false; - - // unregister anything of the floating - var interfase = WA.toDOM(self.uiddd); - if (typeof self.uiddd == 'object') - { - for (var i = 0, l = interfase.length; i < l; i++) - { - interfase[i].onmousemove = null; - interfase[i].onmousedown = null; - interfase[i].onmouseup = null; - interfase[i].onmouseout = null; - } - } - else - { - interfase.onmousemove = null; - interfase.onmousedown = null; - interfase.onmouseup = null; - interfase.onmouseout = null; - } - WA.toDOM(self.uid).onmousedown = null; - if (self.feedback) - self.feedback = null; - // remove memory leak - self = null; - } - - this.uid = id; - this.uiddd = iddd; - if (WA.toDOM(this.uid) == null || WA.toDOM(this.uiddd) == null) - { - alert('Could not find the element ' + this.uid + ' or ' + this.uiddd); - return false; - } - - this.systemleft = parseInt(WA.toDOM(this.uid).style.left); - this.systemtop = parseInt(WA.toDOM(this.uid).style.top); - - var interfase = WA.toDOM(this.uiddd); - if (typeof self.uiddd == 'object') - { - for (var i = 0, l = interfase.length; i < l; i++) - { - interfase[i].onmousemove = move; - interfase[i].onmousedown = startdrag; - interfase[i].onmouseup = stopdrag; - interfase[i].onmouseout = move; - } - } - else - { - interfase.onmousemove = move; - interfase.onmousedown = startdrag; - interfase.onmouseup = stopdrag; - interfase.onmouseout = move; - } - WA.toDOM(this.uid).onmousedown = focus; - - this.isok = true; - - return this; -} - -/* The floating Container is a division-nav-sized that lock windows in it with a overflow: hidden */ -/* The floating Container have a list of windows accesible to switch windows on the left */ - -function floatingContainer(domID, params, feedback, _4glNode) -{ - var self = this; - this.domID = domID; - this._4glNode = _4glNode; - this.params = params; - this.feedback = feedback; - - // the zone is the domID itself. id is ignored. params may have 'classname' - this.createZone = createZone; - function createZone(id, params) - { - if (params['classname']) - self.domNode.className = params['classname']; - return self; - } - - // nothing to start - this.start = start; - function start() - { - } - - // nothing explicit to resize - this.resize = resize; - function resize() - { - } - - // nothing to save - this.getvalues = getvalues; - function getvalues() - { - return null; - } - - // nothing to load - this.setvalues = setvalues; - function setvalues(values) - { - } - - // nothing to stop - this.stop = stop; - function stop() - { - } - - this.destroy = destroy; - function destroy() - { - this.domID = null; - this._4glNode = null; - this.params = null; - this.feedback = null; - this.domNode = null; - } - - - - - - - var self = this; - this.floatings = new Array(); - this.id = id; // if desktop with id exists, take it and ignore mins, or create a window nav desktop - this.mode = mode || ''; // mode = "jail" if the floatings cannot go outside, "hide" if can go outside without resize, and "resize" if can go outside and resize the desktop - this.minwidth = minwidth; // minimum size of desktop - this.minheight = minheight; // minimum size of desktop - this.width = 0; - this.height = 0; - this.container = null; - this.selector = selector; // true to use the control planel, false for no - - // =========================================================== - // PRIVATE FUNCTIONS - - // =========================================================== - // PUBLIC FUNCTIONS - - // register a division that can be dragged and droped - // id is the id of the division - // iddd is the id of the drag-drop zone (td, layer or full division maybe) - this.register = register; - function register(id, iddd, feedback) - { - var fnode = WA.toDOM(id); - if (fnode == null || WA.toDOM(iddd) == null) // there is no floating to register ! - return null; - - var f = new floating(id, iddd, feedback, self); - try - { - // we keep old father - f.oldParent = fnode.parentNode; - // we move to our new container - self.container.appendChild(WA.toDOM(id)); - self.floatings.push(f); - } - catch (e) - { - f.unload(); - e.printStackTrace(); - } - - // We must put the floating as child of our container ! - return f; - } - - this.unregister = unregister; - function unregister(id) - { - var f = null; - for (var i=0, l=self.floatings.length; i < l; i++) - { - if (self.floatings[i].getID() == id) - { - f = self.floatings[i]; - break; - } - } - if (f) - { - f.unload(); - f.oldParent.appendChild(WA.toDOM(f.getID())); - self.floatings.splice(i, 1); - } - } - - // Put each division on original place - this.restart = restart; - function restart() - { - for (var i=0, l=self.floatings.length; i < l; i++) - { - self.floatings[i].restart(); - } - } - - // put division on a new position by program - this.setPosition = setPosition; - function setPosition(id, left, top) - { - for (var i=0, l=self.floatings.length; i < l; i++) - { - if (self.floatings[i].getID() == id) - { - self.floatings[i].setPosition(left, top); - } - } - } - - this.getWidth = getWidth; - function getWidth() - { - return self.width; - } - - this.getHeight = getHeight; - function getHeight() - { - return self.height; - } - - this.selectormouseover = selectormouseover; - function selectormouseover(id) - { - // we create the list of windows - // -> [ onclick item of window => window set focus, then close the list ] - - // we attach the list to the container - - // we listen the list: on mouse out ==> close it - - - } - - // thsi function reserve a slot to be minimized, and send back the coords of the slot - this.reserveSlot = reserveSlot; - function reserveSlot(id) - { - return [30,200,80,20]; - } - - this.resize = resize; - function resize() - { - var w = WA.browser.getClientWidth() - (WA.browser.isNS()?2:0); - var h = WA.browser.getClientHeight() - (WA.browser.isNS()?2:0); - w = max(w, minwidth); - h = max(h, minheight); - self.width = w; - self.height = h; - self.container.style.width = w+'px'; - self.container.style.height = h+'px'; - } - - // TEMPORAL - this.show = show; - function show(id) - { - for (var i=0, l=self.floatings.length; i < l; i++) - { - WA.toDOM(id).innerHTML += " "+self.floatings[i].getID(); - } - } - - // search for id: - var container = WA.toDOM(id); - if (!container) - { - // create a full window container - container = document.createElement("div"); - container.id = self.id; - - // take the size of the screen with a minimum size (NS calculates bad the real size for 2 pixels!) - var w = WA.browser.getClientWidth() - (WA.browser.isNS()?2:0); - var h = WA.browser.getClientHeight() - (WA.browser.isNS()?2:0); - w = max(w, minwidth); - h = max(h, minheight); - self.width = w; - self.height = h; - - container.style.visibility = 'hidden'; - container.style.position = 'absolute'; - container.style.width = w+'px'; - container.style.height = h+'px'; - container.style.left = '0px'; - container.style.top = '0px'; - container.style.border = '1px Solid #677788'; - if (this.mode == 'jail' || this.mode == 'hide') - container.style.overflow='hidden'; - else - container.style.overflow='scroll'; - - document.body.appendChild(container); - window.onresize = this.resize; - } - - this.container = container; - - if (self.selector == true) - { - // create the left-bottom button and properties - selector = document.createElement("div"); - selector.id = this.id+'_selector'; - selector.style.position = 'absolute'; - selector.style.width = '13px'; - selector.style.height = '13px'; - selector.style.left = '0px'; - selector.style.top = (h-15)+'px'; - selector.style.border='1px Solid black'; - selector.style.backgroundColor='#880000'; - selector.style.color='white'; - selector.style.visibility='visible'; - selector.style.display='inline'; - selector.style.overflow='hidden'; - selector.style.textAlign='center'; - selector.onmouseover = this.selectormouseover; - container.appendChild(selector); - WA.browser.setInnerHTML(selector, '*'); - } -} - -// Needed aliases -WA.Containers.floatingContainer = floatingContainer; diff --git a/js/containers/gridContainer.js b/js/containers/gridContainer.js index 30d51d9..b3f1b6b 100644 --- a/js/containers/gridContainer.js +++ b/js/containers/gridContainer.js @@ -32,6 +32,9 @@ WA.Containers.gridContainer = function(fatherNode, domID, code, listener) classnameheadercolumn:'grid-header-column', classnameheadercolumntitle:'grid-header-column-title', classnameheadercolumnsizer:'grid-header-column-sizer', + classnameordercolumn:'grid-header-column-order', + classnameordercolumnasc:'grid-header-column-order-asc', + classnameordercolumndesc:'grid-header-column-order-desc', classnamebody:'grid-body', classnamebodycontent:'grid-body-content', classnamebodycolumn: 'grid-body-column', classnamebodycell:'grid-body-cell', @@ -41,17 +44,21 @@ WA.Containers.gridContainer = function(fatherNode, domID, code, listener) this.haslistener = (code.attributes.haslistener==='yes'); this.minload = code.attributes.minload?parseInt(code.attributes.minload, 10):50; this.params = code.attributes.params?'&'+code.attributes.params:''; - + this.hasdd = !!WA.Managers.dd; + this.domNodeDrag = null; + this.domNodeDrag1 = null; + this.domNodesDrag = []; + this.columns = {}; // all the columns (zones) this.lines = []; // all the lines of data this.data = null; // all the loaded data this.total = -1; this.fullloaded = false; - + this.populatemin = 0; this.populatemax = this.minload-1; - + this.loading = false; this.toptoload = 0; this.lineheight = 0; @@ -80,11 +87,11 @@ WA.Containers.gridContainer = function(fatherNode, domID, code, listener) this.domNode.appendChild(this.domNodeFooter); this.domNodeFooterContent = WA.createDomNode('div', domID+'_footercontent', this.classes.classnamefootercontent); this.domNodeFooter.appendChild(this.domNodeFooterContent); - + this.footer = new WA.Containers.gridContainer.gridFooter(this, domID+'_footer', this.domNodeFooterContent); -/* + /* this.selectable = (code.attributes.selectable==='yes'); this.changes = (code.attributes.changes==='deferred'); // true = deferred on user click, false: online changes (if haslistener obviously) this.isselectable = this.selectable; // global selectable indicator (row or any field selectable) @@ -102,7 +109,7 @@ WA.Containers.gridContainer = function(fatherNode, domID, code, listener) classnamecelltitle:'grid-celltitle', classnamecelltitleempty:'grid-celltitleempty', classnamecelltitleasc:'grid-celltitleasc', classnamecelltitledesc:'grid-celltitledesc', classnamecelltitlefiltered:'grid-celltitlefiltered', classnameline:'grid-line',classnamelineselected:'grid-lineselected',classnamelinenew:'grid-linenew', -classnamecellmodified:'grid-cellmodified', + classnamecellmodified:'grid-cellmodified', classnameviewicon:'grid-viewicon', classnameselecticon:'gridselecticon', classnameediticon:'grid-editicon', classnameselectclear:'grid-selectclear', classnameselectall:'gridselectall', classnameselectinverse:'grid-selectinverse', classnameeditnew:'grid-editnew', classnameeditsave:'grid-editsave', classnameeditdelete:'grid-editdelete' @@ -114,22 +121,40 @@ classnamecellmodified:'grid-cellmodified', this.locali = false; this.localid = null; -*/ + */ this.addEvent('start', start); this.addEvent('stop', stop); this.addEvent('resize', resize); - + WA.Managers.event.on('mouseover', self.domNode, findcell, true); WA.Managers.event.on('click', self.domNode, click, true); WA.Managers.event.on('scroll', self.domNodeBody, scrollBody, true); + var fieldorder = ''; + var direction = ''; + +/* + function doDrag(e) { + nodoTarget.style.width = (startWidth + e.clientX - startX) + 'px'; + nodoDetalle.style.width = (startWidth + e.clientX - startX) + 'px'; + //endWidth = parseInt(document.defaultView.getComputedStyle(nodoTarget, "").width, 10); + //nodoPadre.style.height = (startHeight + e.clientY - startY) + 'px'; + } + + function stopDrag(e) { + document.documentElement.removeEventListener('mousemove', doDrag, false); + document.documentElement.removeEventListener('mouseup', stopDrag, false); + } +*/ + function sendServer(order, code, feedback) { if (!self.haslistener) return; + // send information to server based on mode - var request = WA.Managers.ajax.createRequest(WA.Managers.wa4gl.url + WA.Managers.wa4gl.prelib + self.app.applicationID + WA.Managers.wa4gl.premethod + self.id + WA.Managers.wa4gl.preformat + WA.Managers.wa4gl.format, 'POST', 'Order='+order+(self.params?'&'+self.params:''), feedback, false); + var request = WA.Managers.ajax.createRequest(WA.Managers.wa4gl.url + WA.Managers.wa4gl.prelib + self.app.applicationID + WA.Managers.wa4gl.premethod + self.id + WA.Managers.wa4gl.preformat + WA.Managers.wa4gl.format, 'POST', 'Order='+order+(self.params?'&'+self.params:'')+(direction!=''?'&sort='+direction+'&field='+fieldorder:''), feedback, false); if (request) { @@ -154,12 +179,14 @@ classnamecellmodified:'grid-cellmodified', if (!code.attributes.id) throw 'Error: the id is missing in the tree construction of '+domID; - if (!self.firstfield) + if (!self.firstfield)stop self.firstfield = code.attributes.field; - + // we create the column itself var c = new WA.Containers.gridContainer.gridColumn(self, domID+'_column', self.domNodeHeaderContent, code, notify); self.columns[code.attributes.field] = c; + c.start(); + var z = new WA.Containers.gridContainer.gridZone(self, domID, self.domNodeBodyContent, code, notify); self.zones[code.attributes.field] = z; @@ -190,7 +217,7 @@ classnamecellmodified:'grid-cellmodified', self.app.destroyTree(ldomID[2]); delete self.zones[ldomID[2]]; - + self.columns[ldomID[2]].destroy(); delete self.columns[ldomID[2]]; @@ -223,15 +250,23 @@ classnamecellmodified:'grid-cellmodified', { } - + function scrollBody(event) { if (!self.lineheight) + { + // this should not happen: when we get the focus for the 1rst time, the height is fixed if it was not return; + } var pos = self.domNodeBody.scrollTop; var line = Math.floor(pos / self.lineheight); self.populatemin = line; self.populatemax = line + self.minload - 1; + + // Header scroll + var nHead = WA.toDOM(self.domNode.id + '_header'); + nHead.scrollLeft = self.domNodeBody.scrollLeft; + fillData(); } @@ -239,14 +274,14 @@ classnamecellmodified:'grid-cellmodified', { self.loading = false; removeLoading(); - + self.countload = 0; var code = WA.JSON.decode(r.responseText); - if ((code.row.length || Object.keys(code.row).length) && !self.data) + self.total = code.total; + if (code.row.length && !self.data) { self.data = code.row; - self.total = code.total; } else { @@ -259,14 +294,15 @@ classnamecellmodified:'grid-cellmodified', } if (self.total > 0) fillData(); + else + self.footer.populate(); } function fillData() { - // 2 levels: lines and data. + // 2 levels: lines and data. // If lines are not defined, try to define them and fill // if data is not set, try to load it (delayed) - var mintoload = -1; var maxtoload = -1; var settoload = []; @@ -274,19 +310,19 @@ classnamecellmodified:'grid-cellmodified', for (var i = self.populatemin; i <= self.populatemax; i++) { // we are at the end of the total lines, nothing more to do - if (self.total != -1 && i >= self.total) + if (self.total > 0 && i >= self.total) break; // If the line has already been populated, nothing to do if (self.lines[i]) continue; - + // If the data exists, just populate it if (self.data && self.data[i]) { createLine(self.data[i], i); continue; } - + // creates the array to load if (mintoload == -1) mintoload = maxtoload = i; else if (maxtoload == i-1) maxtoload++; @@ -302,7 +338,7 @@ classnamecellmodified:'grid-cellmodified', putLoading(); // put "Loading...." } - + if (mintoload != -1 && !self.loading && self.serverlistener) { if (self.countload++ > 3) @@ -318,7 +354,7 @@ classnamecellmodified:'grid-cellmodified', adjustHeight(); self.footer.populate(); } - + function createLine(data, index) { // desplazar esto @@ -326,18 +362,17 @@ classnamecellmodified:'grid-cellmodified', self.domNodeBodyContent.style.width = size + 'px'; // first cell of first line will set lineheight (very important !) - var line = new WA.Containers.gridContainer.gridLine(self, self.domID+'_l-'+index, data, index); + var line = new WA.Containers.gridContainer.gridLine(self, self.domID+'_line_'+index, data, index); line.start(); self.lines[index] = line; - return line; } - + function adjustHeight() { if (!self.lineheight) return; - + // adjust the height of the container // based on data.total // get the height of a row @@ -354,30 +389,30 @@ classnamecellmodified:'grid-cellmodified', self.lines[i].destroy(); for (var i in self.zones) WA.browser.setInnerHTML(self.zones[i].domNode, ''); -// WA.browser.setInnerHTML(self.domNodeBodyContent, ''); + //WA.browser.setInnerHTML(self.domNodeBodyContent, ''); self.linecount = 0; self.lines = []; } function putLoading() { - + } - + function removeLoading() { - + } - - + + function findcell(event) { // gets the target and hover the things - + var node = event.target; var column = node.column; var line = node.line; - + // change class if (currentcolumn) { @@ -405,19 +440,14 @@ classnamecellmodified:'grid-cellmodified', currentline = line; } } - + function click(event) { - var node = event.target; - var column = node.column; - var line = node.line; - - // send data line - self.propagate('click', {column:column,line:line,data:self.data[line]}); + return; } - - - + + + // ======================================================================================== // system functions, called ONLY BY 4GL // constructor is called when creating the object. @@ -429,9 +459,15 @@ classnamecellmodified:'grid-cellmodified', this.start = start; function start() { + if (self.hasdd) + { + console.log("REGISTRANDO GROUPO", self.domID, self.domNodeBody); + WA.Managers.dd.registerGroup(self.domID, 'caller', false, self.domID, null); + } + self.countload = 0; - fillData(); self.footer.start(); + fillData(); } this.reload = reload; @@ -449,6 +485,22 @@ classnamecellmodified:'grid-cellmodified', { if (!WA.Containers.gridContainer.source.resize.call(self)) return; + + if (!self.lineheight && self.lines[0]) + { + self.lineheight = WA.browser.getNodeOuterHeight(self.lines[0].cells[self.firstfield]); + // reposition all column heights + adjustHeight(); + // adjust all tops of all existing cells + for (var i = 0, l = self.lines.length; i < l; i++) + { + if (self.lines) + { + for (var j in self.lines[i].cells) + self.lines[i].cells[j].style.top = (i * self.lineheight) + 'px'; + } + } + } // calculate width and height of nodes var size = 0; @@ -465,13 +517,15 @@ classnamecellmodified:'grid-cellmodified', { height = self.total * WA.browser.getNodeHeight(self.lines[0].cells[self.firstfield]); } - self.domNodeBodyContent.style.height = height + 'px'; } this.stop = stop; function stop() { + if (self.hasdd) + WA.Managers.dd.unregisterGroup(self.domID); + if (self.running != 1 && self.running != 2) return; self.running = 4; @@ -510,13 +564,200 @@ classnamecellmodified:'grid-cellmodified', self = null; } + function setLineNodeDrag(lineid, m) + { + var nodes = document.querySelectorAll("[id^='" + lineid + "']"); + var l = m.dragdocumentleft; + for(var i=0; i < nodes.length; i++) + { + var w = parseInt(/\d+/g.exec(nodes[i].parentElement.style.width)[0]); + self.domNodeDrag1 = nodes[i].cloneNode(true); + self.domNodeDrag1.className += ' dragged'; + // we get absolute coords and set them + self.domNodeDrag1.style.position = 'absolute'; + self.domNodeDrag1.style.left = l +'px'; + self.domNodeDrag1.style.top = m.dragdocumenttop + 'px';; + self.domNodeDrag1.style.width = w + 'px'; + self.domNodeDrag1.style.height = m.mainheight + 'px'; + self.domNodeDrag1.style.zIndex = 2; + + l += w; + // we append to the main document the DOM + document.body.appendChild(self.domNodeDrag1); + + //Save reference in array + self.domNodesDrag.push(self.domNodeDrag1); + } + } + + function lineNodeDrag(m) + { + for(var i=0; ii;i++) + { + top = WA.browser.getNodeDocumentTop(zone[i]); + bottom = WA.browser.getNodeDocumentTop(zone[i]) + WA.browser.getNodeHeight(zone[i]); + var left = WA.browser.getNodeDocumentLeft(zone[i]); + var right = WA.browser.getNodeDocumentLeft(zone[i]) + WA.browser.getNodeWidth(zone[i]); + + if((ypointer >= top && ypointer <= bottom && xpointer >= left && xpointer <= right)) + { + onzone = zone[i]; + break; + } + }; + + if (onzone) { + + self.dropmode = 0; + if(onzone.id === lineid) + { + //message = "No se puede mover aquĆ­ " + self.domNodeDrag.id; + return; + } + + onzone.style.backgroundColor = 'red'; + if (ypointer > top && ypointer < top + (bottom - top) / 1.3) { + // before + message = "Mover ANTES de " + onzone.id; + self.dropmode = 1; + } + + if (ypointer > top + (bottom - top) * 2 / 3 && ypointer < bottom) { + // after + message = "Mover DESPUES de " + onzone.id; + self.dropmode = 3; + } + self.dropid = onzone.id; + self.domNodeMessage.innerHTML = message; + } + if (self.lastonzone && self.lastonzone != onzone) { + self.lastonzone.style.backgroundColor = ''; + } + self.lastonzone = onzone; + break; + case 'drop': + // destroy the hover node + document.body.removeChild(self.domNodeDrag); + destroyDomNodeDrag(); + + if (self.lastonzone) { + self.lastonzone.style.backgroundColor = ''; + } + // send the order to the server + if (self.dropmode > 0) { + sendServer('move', { id: lineid, toid: self.dropid, mode: self.dropmode }, moveresponse); + } + // reload anything + self.domNodeMessage = null; + self.domNodeDrag = null; + self.dropmode = 0; + self.dropid = null; + self.lastonzone = null; + break; + } + } + + function moveresponse(request) { + self.loading = false; + removeLoading(); + + self.countload = 0; + var code = WA.JSON.decode(request.responseText); + + self.total = code.total; + if (code.row.length && !self.data) + { + self.data = code.row; + } + else + { + if (!self.data) + self.data = []; + for (var i in code.row) + { + self.data[parseInt(i, 10)] = code.row[i]; + } + } + if (self.total > 0) + fillData(); + else + self.footer.populate(); + } + +/* + // ================================================================ // move divisions by program and mouse this.startdrag = startdrag; function startdrag(sizerID, size, event, group, object, zone, data) { - self.movingsize = size; self.movingID = sizerID; // @@ -539,6 +780,7 @@ classnamecellmodified:'grid-cellmodified', self.movingsize = null; self.movingID = null; } +*/ this.resizecolumns = resizecolumns; function resizecolumns() @@ -556,19 +798,18 @@ classnamecellmodified:'grid-cellmodified', - - - - - - - - - - - - - + + + + + + + + + + + + function scroll(e) { var left = WA.browser.getNodeScrollLeft(self.domNodeBody); @@ -690,12 +931,11 @@ classnamecellmodified:'grid-cellmodified', function quickSort(lo0, hi0, comp, field) { // local ONLY available if full data loaded ! - var lo = lo0; var hi = hi0; var value; - if ( hi0 > lo0) + if ( hi0 > lo0 ) { value = self.data[ Math.ceil((lo0 + hi0 ) / 2) ][field]; while( lo <= hi ) @@ -724,7 +964,19 @@ classnamecellmodified:'grid-cellmodified', this.reorder = reorder; function reorder(field, asc) { - for (var i in self.columns) + if(self.total<=self.populatemax && asc) + { + self.unpopulate(); + self.quickSort(0, self.data.length-1, (asc=='asc'?self.compasc:self.compdesc), field); + fillData(); + }else{ + fieldorder = field; + direction = asc; + reload(); + } + + + /*for (var i in self.columns) { if (self.columns[i].id != field && self.columns[i].order != 0) { @@ -732,9 +984,11 @@ classnamecellmodified:'grid-cellmodified', self.columns[i].setTitle(); } } + self.unpopulate(); self.quickSort(0, self.data.length-1, (asc?self.compasc:self.compdesc), field); - self.populate(); + self.populate();*/ + } @@ -781,7 +1035,7 @@ classnamecellmodified:'grid-cellmodified', } } - + parseTemplates(code); parseRenders(code); parseData(code); @@ -795,20 +1049,19 @@ WA.extend(WA.Containers.gridContainer, WA.Managers.wa4gl._container); WA.Containers.gridContainer.gridColumn = function(father, domID, container, code, listener) { var self = this; - this.classname = code.attributes.classname!=undefined?code.attributes.classname:father.classes.classnameheadercolumn; - WA.Containers.gridContainer.gridColumn.sourceconstructor.call(this, father, domID, code, 'div', { classname:this.classname }, listener); // DOM this.container = container; container.appendChild(this.domNode); this.domNode.style.width = (code.attributes.size?code.attributes.size:'300') + 'px'; - this.domNode.style.display = ''; // is visible - + this.domNode.style.display = ''; // is visible this.classnametitle = code.attributes.classnametitle!=undefined?code.attributes.classnametitle:father.classes.classnameheadercolumntitle; this.classnamesizer = code.attributes.classnamesizer!=undefined?code.attributes.classnamesizer:father.classes.classnameheadercolumnsizer; - + this.classnameorder = code.attributes.classnameorder!=undefined?code.attributes.classnameorder:father.classes.classnameordercolumn; + this.classnameorderasc = code.attributes.classnameorderasc!=undefined?code.attributes.classnameorderasc:father.classes.classnameordercolumnasc; + this.classnameorderdesc = code.attributes.classnameorderdesc!=undefined?code.attributes.classnameorderdesc:father.classes.classnameordercolumndesc; this.field = code.attributes.field; this.sizemin = code.attributes.sizemin?code.attributes.sizemin:0; this.sizemax = code.attributes.sizemax?code.attributes.sizemax:undefined; @@ -822,16 +1075,19 @@ WA.Containers.gridContainer.gridColumn = function(father, domID, container, code */ this.size = WA.browser.getNodeWidth(this.domNode); + this.resizeable = code.attributes.resizeable == "yes"; + this.sortable = code.attributes.sortable == "yes"; + this.domNodeSizer = null; + this.startWidth = 0; // selector, selector pannel, sizer, all hidden - if (code.attributes.resizeable) + if (self.resizeable) { - this.domNodeSizer = WA.createDomNode('div', domID+'_sizer', this.classnamesizer); - this.domNode.appendChild(this.domNodeSizer); + self.domNodeSizer = WA.createDomNode('div', domID+'_sizer', self.classnamesizer); + self.domNode.appendChild(self.domNodeSizer); } - else - this.domNodeSizer = null; + this.orderable = code.attributes.orderable == "yes"; this.domNodeTitle = WA.createDomNode('div', domID+'_titletext', this.classnametitle); this.domNodeTitle.innerHTML = code.attributes.title; this.domNode.appendChild(this.domNodeTitle); @@ -839,21 +1095,19 @@ WA.Containers.gridContainer.gridColumn = function(father, domID, container, code this.setTitle = setTitle; function setTitle() { - return; - - var title = self.code.attributes.title; - switch(self.order) - { - case 1: title = '
' + title; break; - case 2: title = '
' + title; break; - default: title = '
' + title; break; - } - if (self.filtered) - { - title = '
' + title; - } - - WA.browser.setInnerHTML(self.domNodeTitle, title); + if(self.sortable){ + var title = self.code.attributes.title; + switch(self.order) + { + case 1: title = title + '
'; break; + case 2: title = title + '
'; break; + default: title = title + '
'; break; + } + if (self.filtered) + { + title = '
' + title; + } + WA.browser.setInnerHTML(self.domNodeTitle, title);} } this.sethover = sethover; @@ -861,13 +1115,13 @@ WA.Containers.gridContainer.gridColumn = function(father, domID, container, code { self.domNode.className = self.classname + (flag?' hover':''); } - + this.setSize = setSize; function setSize(size) { return; - - + + if (size < self.sizemin) size = self.sizemin; if (self.sizemax != 0 && size > self.sizemax) @@ -879,23 +1133,56 @@ WA.Containers.gridContainer.gridColumn = function(father, domID, container, code this.click = click; function click() + { + if(self.sortable) + { + if (self.pleasenoclick) + { + self.pleasenoclick = false; + return; + } + + self.order++; + if (self.order > 2) + self.order = 0; + + var d = null; + switch(self.order){ + case 1: + d = 'asc'; + break; + case 2: + d = 'desc'; + break; + default: + d = null; + } + self.father.reorder(self.field, d); + self.setTitle(); + } + } + + this.reorder = reorder; + function reorder(field, asc) { return; - if (self.pleasenoclick) + + for (var i in self.columns) { - self.pleasenoclick = false; - return; + if (self.columns[i].id != field && self.columns[i].order != 0) + { + self.columns[i].order = 0; + self.columns[i].setTitle(); + } } - self.order ++; - if (self.order > 2) - self.order = 1; - self.container.reorder(self.id, self.order==1?true:false); - self.setTitle(); + self.unpopulate(); + self.quickSort(0, self.data.length-1, (asc?self.compasc:self.compdesc), field); + self.populate(); } - + this.clicksizer = clicksizer; - function clicksizer() + function clicksizer(order, id1, lineid, zone, metrics) { return; @@ -907,40 +1194,51 @@ WA.Containers.gridContainer.gridColumn = function(father, domID, container, code } this.move = move; - function move(type, event, group, object, zone, data) + function move(order, id1, lineid, zone, metrics) { - return; + var xpointer = metrics.dragleft - 172; + var node = WA.toDOM(lineid).parentNode; - if (type == 'start') - { - self.pleasenoclick = true; - var size = WA.browser.getNodeWidth(self.domNode); - self.container.startdrag(self.id, size, event, group, object, zone, data); - } - else if (type == 'drag' || type == 'drop') - { - self.container.drag(event, group, object, zone, data); - } - if (type == 'drop') - { - self.container.drop(event, group, object, zone, data); - } + switch (order) { + case 'start': + self.domNodeSizer.className += ' dragged'; + self.domNodeSizer.style.position = 'absolute'; + self.domNodeSizer.style.left = metrics.dragdocumentleft + 'px'; + self.domNodeSizer.style.width = metrics.mainwidth + 'px'; + break; + case 'drag': + self.domNodeSizer.style.left = xpointer + 'px'; + node.style.width = xpointer + 1 + 'px'; + var id = /^([^w]+_\d)/; + WA.toDOM(id.exec(self.domNodeSizer.id)[0]).style.width = xpointer + 1 + 'px'; + break; + case 'drop': + break; + } } + this.start = start; function start() { - return; - - - WA.Managers.event.on('click', self.domNodeTitle, self.click, true); - WA.Managers.event.on('click', self.domNodeSizer, self.clicksizer, true); + if(self.sortable) + { + self.order = 0; + self.setTitle(); + WA.Managers.event.on('click', self.domNode, self.click, true); + } - if (self.sizeable) + // Sizer group and object + if(self.resizeable) { - WA.Managers.dd.registerGroup(self.domID+'_sizer', 'caller', false, null, self.move); - WA.Managers.dd.registerObject(self.domID+'_sizer', self.domID+'_sizer', self.domID+'_sizer', null); + if (self.father.hasdd) { + WA.Managers.dd.registerGroup(self.domNodeSizer, 'caller', true, self.father.domID, move); + WA.Managers.dd.registerObject(self.domNodeSizer, self.domNodeSizer, self.domNodeSizer, null); + } } + + return; + WA.Managers.event.on('click', self.domNodeSizer, self.clicksizer, true); } this.stop = stop; @@ -988,6 +1286,7 @@ WA.Containers.gridContainer.gridColumn = function(father, domID, container, code self.domNode = null; self.domNodeTitle = null; self.domNodeSizer = null; + self.domNodeOrder = null; self.domNodeContainer = null; self.code = null; self.notify = null; @@ -997,7 +1296,6 @@ WA.Containers.gridContainer.gridColumn = function(father, domID, container, code self = null; } - this.setTitle(); } WA.extend(WA.Containers.gridContainer.gridColumn, WA.Managers.wa4gl._zone); @@ -1011,10 +1309,10 @@ WA.Containers.gridContainer.gridZone = function(father, domID, container, code, var self = this; this.classname = code.attributes.classname!=undefined?code.attributes.classname:father.classes.classnamebodycolumn; - + WA.Containers.gridContainer.gridZone.sourceconstructor.call(this, father, domID, code, 'div', { classname:this.classname }, listener); this.domNode.style.position = 'relative'; - + this.field = code.attributes.field; this.classnamecell = father.classes.classnamebodycell; @@ -1029,7 +1327,7 @@ WA.Containers.gridContainer.gridZone = function(father, domID, container, code, { self.domNode.className = self.classname + (flag?' hover':''); } - + this.setData = setData; function setData(data) { @@ -1082,6 +1380,13 @@ WA.Containers.gridContainer.gridLine = function(father, domID, data, index) self.cells[i].className = self.father.zones[i].classnamecell + (flag?' hover':''); } } + + this.moving = moving; + function moving(order, id1, id2, zone, metrics) { + + self.moving = true; + self.father.moving(order, id2, metrics); + } function createCell(father, content, data, c) { @@ -1090,10 +1395,10 @@ WA.Containers.gridContainer.gridLine = function(father, domID, data, index) father.domNode.appendChild(domNodeCell); domNodeCell.column = c; domNodeCell.line = self.index; - + if (!self.father.lineheight) self.father.lineheight = WA.browser.getNodeOuterHeight(domNodeCell); - + // top should be index * lineheight domNodeCell.style.position = 'absolute'; domNodeCell.style.left = '0'; @@ -1101,7 +1406,7 @@ WA.Containers.gridContainer.gridLine = function(father, domID, data, index) domNodeCell.style.width = '100%'; // Considerar los TEMPLATES tambien - + if (father.render) { eval( 'var cdata = ' + father.render+'(father.format, content, data);' ); @@ -1110,6 +1415,14 @@ WA.Containers.gridContainer.gridLine = function(father, domID, data, index) else WA.browser.setInnerHTML(domNodeCell, content); + cl = self.father.columns[c]; + if (cl.orderable) { + domNodeCell.style.cursor = 'pointer'; + if (self.father.hasdd) { + console.log("REGISTRANDO OBJECT", self.father.domID, domNodeCell); + WA.Managers.dd.registerObject(self.father.domID, domNodeCell, domNodeCell, moving, null); + } + } return domNodeCell; } @@ -1123,15 +1436,15 @@ WA.Containers.gridContainer.gridLine = function(father, domID, data, index) self.cells[i] = createCell(self.father.zones[i], '', data, i); } } - - - - + + + + this.start = start; function start() { return; - + for (var i in self.cells) WA.Managers.event.on('click', self.cells[i], self.click, true); self.running = 2; @@ -1141,7 +1454,7 @@ WA.Containers.gridContainer.gridLine = function(father, domID, data, index) function stop() { return; - + self.running = 0; for (var i in self.cells) WA.Managers.event.off('click', self.cells[i], self.click, true); @@ -1151,7 +1464,7 @@ WA.Containers.gridContainer.gridLine = function(father, domID, data, index) function select() { return; - + if (self.selected) return; self.selected = true; @@ -1162,7 +1475,7 @@ WA.Containers.gridContainer.gridLine = function(father, domID, data, index) function unselect() { return; - + if (!self.selected) return; self.selected = false; @@ -1173,7 +1486,7 @@ WA.Containers.gridContainer.gridLine = function(father, domID, data, index) function invert() { return; - + if (self.selected) self.unselect(); else @@ -1237,7 +1550,7 @@ WA.Containers.gridContainer.gridLine = function(father, domID, data, index) function blur() { return; - + var data = self.container.zones[this.column].getData(); self.container.zones[this.column].hide(); @@ -1267,7 +1580,7 @@ WA.Containers.gridContainer.gridLine = function(father, domID, data, index) self.cells = null; self = null; } - + populate(); } @@ -1288,14 +1601,14 @@ WA.Containers.gridContainer.gridLine = function(father, domID, data, index) WA.Containers.gridContainer.gridFooter = function(father, domID, container) { var self = this; - + this.father = father; this.container = container; this.domNodeQuantityTitle = WA.createDomNode('div', domID+'_quantitytitle', 'quantity-title'); this.domNodeQuantityTitle.innerHTML = 'Cantidad: '; this.container.appendChild(this.domNodeQuantityTitle); - + this.domNodeQuantity = WA.createDomNode('div', domID+'_quantity', 'quantity'); this.container.appendChild(this.domNodeQuantity); /* @@ -1465,7 +1778,7 @@ WA.Containers.gridContainer.gridFooter = function(father, domID, container) { self.container.saveall(); } - + this.populate = populate; function populate() { diff --git a/js/containers/groupContainer.js b/js/containers/groupContainer.js index 9b418bb..e26843c 100644 --- a/js/containers/groupContainer.js +++ b/js/containers/groupContainer.js @@ -79,10 +79,30 @@ WA.Containers.groupContainer = function(fatherNode, domID, code, listener) { var self = this; - WA.Containers.groupContainer.sourceconstructor.call(this, fatherNode, domID, code, 'form', { classname:'group' }, listener); + + this.maingroup = code.attributes.maingroup ? code.attributes.maingroup : undefined; + if (this.maingroup) + WA.Containers.groupContainer.sourceconstructor.call(this, fatherNode, domID, code, 'div', { classname: 'group' }, listener); + else + WA.Containers.groupContainer.sourceconstructor.call(this, fatherNode, domID, code, 'form', { classname:'group' }, listener); this.domNodeForm = this.domNode; + + this.domNodeTitle = WA.createDomNode('div', domID + '_title', 'title'); + this.domNodeForm.appendChild(this.domNodeTitle); + this.domNode = WA.createDomNode('fieldset', null, null); this.domNodeForm.appendChild(this.domNode); + if (this.maingroup) { + this.domNodeRecords = WA.createDomNode('div', null, null); + this.domNode.appendChild(this.domNodeRecords); + // REGISTER THIS FORM INTO TE PIANEMFORM + var group = null; + if (this.father.father.code.attributes.type == "groupContainer") { + group = this.father.father; + group.registerForm(this.xdomID[2], this); + } + } + this.zoneNotify = null; @@ -108,11 +128,14 @@ WA.Containers.groupContainer = function(fatherNode, domID, code, listener) this.authmodes[i] = (this.code.attributes.authmodes?this.code.attributes.authmodes.indexOf(''+i)!=-1:true); } + this.subForms = {}; this.actionlistener = null; this.fields = []; this.data = {}; this.dataloaded = false; this.datatemporal = {}; + this.tempkey = 1; + this.template = ""; this.error = null; this.help = null; @@ -125,47 +148,48 @@ WA.Containers.groupContainer = function(fatherNode, domID, code, listener) this.title = ['','Insert','Update','Delete','View']; this.result = ['','Insert ok','Update ok','Delete ok']; - for (var i = 0, l = code.children.length; i < l; i++) + if (code.children) { - if (code.children[i].tag == 'dataset' && code.children[i].data) + for (var i = 0, l = code.children.length; i < l; i++) { - try + if (code.children[i].tag == 'dataset' && code.children[i].data) { - self.data = WA.JSON.decode(code.children[i].data); - if (self.data[self.varkey] == self.currentkey) - self.dataloaded = true; - } - catch (e) - { - WA.debug.log('Error on the dataset of groupContainer:', 1); - WA.debug.log(e, 1); - // what do we do if there is an error in the dataset ? error ? alert ? debug ? + try + { + self.data = WA.JSON.decode(code.children[i].data); + if (self.data[self.varkey] == self.currentkey) + self.dataloaded = true; + } + catch (e) + { + WA.debug.log('Error on the dataset of groupContainer:', 1); + WA.debug.log(e, 1); + // what do we do if there is an error in the dataset ? error ? alert ? debug ? + } + continue; } - continue; - } - if (code.children[i].tag == 'alertmessage') - self.mainerroralert = code.children[i].data; - if (code.children[i].tag == 'servermessage') - self.servererroralert = code.children[i].data; - if (code.children[i].tag == 'titleinsert') - self.title[1] = code.children[i].data; - if (code.children[i].tag == 'titleupdate') - self.title[2] = code.children[i].data; - if (code.children[i].tag == 'titledelete') - self.title[3] = code.children[i].data; - if (code.children[i].tag == 'titleview') - self.title[4] = code.children[i].data; - if (code.children[i].tag == 'insertok') - self.result[1] = code.children[i].data; - if (code.children[i].tag == 'updateok') - self.result[2] = code.children[i].data; - if (code.children[i].tag == 'deleteok') - self.result[3] = code.children[i].data; - } - - - this.domNodeTitle = WA.createDomNode('div', domID+'_title', 'title'); - this.domNode.appendChild(this.domNodeTitle); + if (code.children[i].tag == 'alertmessage') + self.mainerroralert = code.children[i].data; + if (code.children[i].tag == 'servermessage') + self.servererroralert = code.children[i].data; + if (code.children[i].tag == 'titleinsert') + self.title[1] = code.children[i].data; + if (code.children[i].tag == 'titleupdate') + self.title[2] = code.children[i].data; + if (code.children[i].tag == 'titledelete') + self.title[3] = code.children[i].data; + if (code.children[i].tag == 'titleview') + self.title[4] = code.children[i].data; + if (code.children[i].tag == 'insertok') + self.result[1] = code.children[i].data; + if (code.children[i].tag == 'updateok') + self.result[2] = code.children[i].data; + if (code.children[i].tag == 'deleteok') + self.result[3] = code.children[i].data; + if (code.children[i].tag == 'template') + self.template = code.children[i].data; + } + } this.domNodeMessage = WA.createDomNode('div', domID+'_message', 'message'); this.domNode.appendChild(this.domNodeMessage); @@ -464,6 +488,17 @@ WA.Containers.groupContainer = function(fatherNode, domID, code, listener) checkClass(); } + this.registerForm = registerForm; + function registerForm(id, form) { + console.log("REGISTER SUBFORM", id) + self.subForms[id] = form; + } + + this.unregisterForm = unregisterForm; + function unregisterForm(field) { + // self.fields.push(field); + } + this.registerField = registerField; function registerField(field) { @@ -542,6 +577,7 @@ WA.Containers.groupContainer = function(fatherNode, domID, code, listener) this.doInsert = doInsert; function doInsert() { + console.log("doInsert", self.lastkey, self.currentkey, self.domID); // we keep the current key for if we cancel the insert mode self.lastkey = self.currentkey; self.currentkey = null; @@ -678,6 +714,12 @@ WA.Containers.groupContainer = function(fatherNode, domID, code, listener) stopLoading(); } + function fillTemplate(templateString, templateVars) { + var tmp = eval("WA.templater`" + templateString + "`;"); + console.log(templateString, templateVars); + return tmp(templateVars); + } + // basic group options this.doSubmit = doSubmit; function doSubmit() @@ -705,6 +747,38 @@ WA.Containers.groupContainer = function(fatherNode, domID, code, listener) return; } + // IF we are into sub-group, we only keep the info local until the main group makes the update + if (self.maingroup) { + var datatemporal = {}; + for (var i = 0, l = self.fields.length; i < l; i++) { + if (self.fields[i].formtype != 'field') + continue; + if (!self.fields[i].editable || !self.fields[i].edition) + continue; + var values = self.fields[i].getValues(); + // if values is an array, please loop ! + datatemporal[self.fields[i].id] = values; + } + datatemporal[self.varkey] = self.currentkey; + datatemporal[self.varmode] = self.mode; + if (!self.currentkey) // new record + { + self.datatemporal['new|' + self.tempkey] = datatemporal; + self.tempkey++; + } else { + self.datatemporal[self.currentkey] = datatemporal; + } + // PRINT the saved records + text = ""; + for (var i in self.datatemporal) { + text += fillTemplate(self.template, self.datatemporal[i]); + } + self.domNodeRecords.innerHTML = text; + + console.log("REC saved locally", self.datatemporal); + return; + } + // we put the "loading" stuff startLoading(); @@ -732,6 +806,19 @@ WA.Containers.groupContainer = function(fatherNode, domID, code, listener) request.addParameter(self.fields[i].id, values); self.datatemporal[self.fields[i].id] = values; } + // SUB GROUPS + if (self.subForms) { + for (var i in self.subForms) { + for (var j in self.subForms[i].datatemporal) + { + for (var k in self.subForms[i].datatemporal[j]) + { + request.addParameter(i + '|' + j + '|' + k, self.subForms[i].datatemporal[j][k]); + } + } + } + } + if (self.mode != 1) request.addParameter(self.varkey, self.currentkey); request.addParameter(self.varmode, self.mode); @@ -793,14 +880,13 @@ WA.Containers.groupContainer = function(fatherNode, domID, code, listener) this.setMessages = setMessages; function setMessages(params) { - console.log("setMessages", params); // 3 ways to put messages: // 1. is POPUP // 2. is any error domID // 3. is any field with its own error if (!params || !params.messages) { - showMessage(self.servererroralert, false); + showMessage(self.servererroralert + (params.message?"
"+params.message.text:""), false); return; } var popup = ''; @@ -824,6 +910,20 @@ WA.Containers.groupContainer = function(fatherNode, domID, code, listener) alert(popup); } + this.getValues = getValues; + function getValues() + { + var values = {}; + for (var i=0, l=self.fields.length; i < l; i++) + { + if (self.fields[i].formtype == 'field') + { + values[self.fields[i].id] = self.fields[i].getValues(); + } + } + return values; + } + this.getFieldValue = getFieldValue; function getFieldValue(fieldid) { diff --git a/js/containers/tabContainer.js b/js/containers/tabContainer.js index 4cb7a19..3a37f05 100644 --- a/js/containers/tabContainer.js +++ b/js/containers/tabContainer.js @@ -379,6 +379,9 @@ WA.Containers.tabContainer = function(domNodeFather, domID, code, listener) function stop() { + if (self.hasdd) + WA.Managers.dd.unregisterGroup(self.domID); + WA.Managers.event.off('click', self.domNodeLeft, self.clickleft, true); WA.Managers.event.off('click', self.domNodeRight, self.clickright, true); WA.Managers.event.off('click', self.domNodeSelect, self.clickselect, true); diff --git a/js/containers/treeContainer.js b/js/containers/treeContainer.js index 4131029..e679609 100644 --- a/js/containers/treeContainer.js +++ b/js/containers/treeContainer.js @@ -29,8 +29,15 @@ WA.Containers.treeContainer = function(fatherNode, domID, code, listener) this.data = null; // all the data rows we can use for this tree this.loaded = false; // the data has been loaded in first instance this.countload = 0; // how many time we try to load: >3 throw error + this.params = code.attributes.params?'&'+code.attributes.params:''; + this.changeorder = this.code.attributes.changeorder ? this.code.attributes.changeorder != "no" : false; + + this.hasdd = !!WA.Managers.dd; + this.domNodeDrag = null; this.addEvent('start', start); + this.addEvent('poststart', poststart); + this.addEvent('stop', stop); /* SYSTEM METHODS */ @@ -111,6 +118,18 @@ WA.Containers.treeContainer = function(fatherNode, domID, code, listener) fillData(); } + function poststart() { + if (self.hasdd && self.changeorder) { + WA.Managers.dd.registerGroup(self.domID, 'caller', false, self.domID, null); + } + } + + function stop() { + if (self.hasdd && self.changeorder) { + WA.Managers.dd.unregisterGroup(self.domID); + } + } + this.destroy = destroy; function destroy(fast) { @@ -141,13 +160,18 @@ WA.Containers.treeContainer = function(fatherNode, domID, code, listener) fillData(); } - function getData(r) + function getDataObject(data) { - self.data = WA.JSON.decode(r.responseText); + self.data = data; self.loaded = true; fillData(); } + function getData(r) + { + getDataObject(WA.JSON.decode(r.responseText)); + } + // any record change should call this this.fillData = fillData; function fillData(newdataset) @@ -161,10 +185,15 @@ WA.Containers.treeContainer = function(fatherNode, domID, code, listener) } // ask to the server the data - var request = WA.Managers.ajax.createRequest(WA.Managers.wa4gl.url + WA.Managers.wa4gl.prelib + self.app.applicationID + WA.Managers.wa4gl.premethod + self.id + WA.Managers.wa4gl.preformat + WA.Managers.wa4gl.format, 'POST', 'Order=get', getData, true); + var request = WA.Managers.ajax.createRequest(WA.Managers.wa4gl.url + WA.Managers.wa4gl.prelib + self.app.applicationID + WA.Managers.wa4gl.premethod + self.id + WA.Managers.wa4gl.preformat + WA.Managers.wa4gl.format, 'POST', 'Order=get'+(self.params?'&'+self.params:''), getData, true); // we put the "loading" + return; + } + else if (!newdataset && !self.loaded) + { + self.callEvent('get', getDataObject); // ask for children to events (somebody should listen to this) return; } @@ -198,12 +227,19 @@ WA.Containers.treeContainer = function(fatherNode, domID, code, listener) myt.attributes = {}; myt.attributes.id = dataset[i].id; myt.attributes.father = dataset[i].father; + myt.attributes.moveable = dataset[i].moveable ? 'yes' : 'no'; myt.attributes.closeable = dataset[i].closeable?'yes':'no'; myt.attributes.closed = dataset[i].closed?'yes':'no'; myt.attributes.loadable = dataset[i].loadable?'yes':'no'; myt.attributes.loaded = dataset[i].loaded?'yes':'no'; // create the tree - self.app.createTree(self, myt); + if (self.state = 5) { + self.state = 4; // temporary "starting", to build the whole template before calling start event + self.app.createTree(self, myt); + self.state = 5; + } else { + self.app.createTree(self, myt); + } } } } @@ -235,6 +271,123 @@ WA.Containers.treeContainer = function(fatherNode, domID, code, listener) } + function moveresponse(request) { + + var data = WA.JSON.decode(request.responseText); + + if (!data || data.message != 'OK') + if (data) + alert(data.message); + else + alert(request.responseText); + else + reload(); +} + + // ************************************************************************** + // PRIVATE METHODS + // ************************************************************************** + this.moving = moving; + function moving(order, zoneid, metrics) { + + if (order == 'start') { + // Copy the node to the top + node = self.zones[zoneid].domNode; + self.domNodeDrag = node.cloneNode(true); + self.domNodeDrag.className += ' dragged'; + // we get absolute coords and set them + self.domNodeDrag.style.position = 'absolute'; + self.domNodeDrag.style.left = metrics.dragdocumentleft + 'px'; + self.domNodeDrag.style.top = metrics.dragdocumenttop + 'px'; + self.domNodeDrag.style.width = metrics.mainwidth + 'px'; + self.domNodeDrag.style.height = metrics.mainheight + 'px'; + self.domNodeDrag.style.zIndex = 2; + // we append to the main document the DOM + document.body.appendChild(self.domNodeDrag); + + self.domNodeMessage = WA.createDomNode('div', null, null); + self.domNodeMessage.style = "position: absolute; left: 50px; top: 40px; border: 2px solid blue; background-color: white; z-index: 3; padding: 10px; font-size: 2em; color: black;"; + self.domNodeDrag.appendChild(self.domNodeMessage); + + self.startPos = metrics.maintopstart; + self.dropmode = 0; + self.dropid = null; + } + else if (order == 'drag') { + // move NODE copied + self.domNodeDrag.style.left = metrics.xmouse + 'px'; + self.domNodeDrag.style.top = metrics.ymouse + 'px'; + // Search for who is under the pointer, "before", "into", "after" + + var onzone = null; + var xpointer = metrics.xmouse; + var ypointer = metrics.ymouse; + for (var i in self.zones) { + var zone = self.zones[i]; + var top = WA.browser.getNodeDocumentTop(zone.domNode); + var bottom = WA.browser.getNodeDocumentTop(zone.domNode) + WA.browser.getNodeHeight(zone.domNode); + var left = WA.browser.getNodeDocumentLeft(zone.domNode); + var right = WA.browser.getNodeDocumentLeft(zone.domNode) + WA.browser.getNodeWidth(zone.domNode); + if (ypointer >= top && ypointer <= bottom && xpointer >= left && xpointer <= right) { + onzone = zone; + break; + } + } + + if (onzone) { + if (onzone.isMoveable(zoneid)) { + + onzone.hover() + + if (ypointer > top && ypointer < top + (bottom - top) / 3) { + // before + message = "Mover ANTES de " + zone.domID; + self.dropmode = 1; + } else if (ypointer > top + (bottom - top) / 3 && ypointer < top + (bottom - top) * 2 / 3) { + // into + message = "Mover COMO HIJO de " + zone.domID; + self.dropmode = 3; + } else if (ypointer > top + (bottom - top) * 2 / 3 && ypointer < bottom) { + // after + message = "Mover DESPUES de " + zone.xdomID[2]; + self.dropmode = 2; + } else { + self.dropmode = 0; + } + self.dropid = zone.xdomID[2]; + self.domNodeMessage.innerHTML = message; + } else { + self.domNodeMessage.innerHTML = "No se puede mover aqui"; + self.dropmode = 0; + } + + } + if (self.lastonzone && self.lastonzone != onzone) { + self.lastonzone.hout() + } + self.lastonzone = onzone; + + } + else if (order == 'drop') { + // destroy the hover node + document.body.removeChild(self.domNodeDrag); + if (self.lastonzone) { + self.lastonzone.hout() + } + // send the order to the server + if (self.dropmode > 0) { + self.lastonzone.sendServer('move', { id: zoneid, toid: self.dropid, mode: self.dropmode }, moveresponse ); + } + + self.startpos = 0; + self.domNodeMessage = null; + self.domNodeDrag = null; + self.dropmode = 0; + self.dropid = null; + self.lastonzone = null; + } + } + this.parseTemplates(code); this.parseData(code); } @@ -251,6 +404,7 @@ WA.Containers.treeContainer.treeZone = function(father, domID, container, code, this.children = {}; + this.moveable = (code.attributes.moveable==='yes'); this.closeable = (code.attributes.closeable==='yes'); this.closed = (code.attributes.closed==='yes'); this.loadable = (code.attributes.loadable==='yes'); @@ -292,21 +446,46 @@ WA.Containers.treeContainer.treeZone = function(father, domID, container, code, this.domNodeMain.appendChild(this.domNodeChildren); this.addEvent('start', start); + this.addEvent('poststart', poststart); this.addEvent('stop', stop); + this.isMoveable = isMoveable; + function isMoveable(zoneid) + { + if (!self.moveable) + return false; + if (zoneid == self.xdomID[2]) + return false; + // Search if this one is child of moved one + + + return true + } + + this.childrenLoadedObject = childrenLoadedObject; + function childrenLoadedObject(data) + { + self.loaded = true; + self.father.fillData(data); + } + this.childrenLoaded = childrenLoaded; function childrenLoaded(r) { var data = WA.JSON.decode(r.responseText); - self.loaded = true; - self.father.fillData(data.row); + childrenLoadedObject(data.row); } this.loadChildren = loadChildren; function loadChildren() { + if (!self.father.serverlistener) + { + self.father.callEvent('getchildren', {id: self.code.attributes.id, listener: childrenLoadedObject}); // ask for children to events (somebody should listen to this) + return; + } // start an ajax request - var request = WA.Managers.ajax.createRequest(WA.Managers.wa4gl.url + WA.Managers.wa4gl.prelib + self.father.app.applicationID + WA.Managers.wa4gl.premethod + self.father.id + WA.Managers.wa4gl.preformat + WA.Managers.wa4gl.format, 'POST', null, childrenLoaded, false); + var request = WA.Managers.ajax.createRequest(WA.Managers.wa4gl.url + WA.Managers.wa4gl.prelib + self.father.app.applicationID + WA.Managers.wa4gl.premethod + self.father.id + WA.Managers.wa4gl.preformat + WA.Managers.wa4gl.format, 'POST', (self.params?self.params:''), childrenLoaded, false); request.addParameter('Order', 'getchildren'); request.addParameter('father', self.code.attributes.id); request.send(); @@ -318,12 +497,13 @@ WA.Containers.treeContainer.treeZone = function(father, domID, container, code, } this.sendServer = sendServer; - function sendServer(order, code) + function sendServer(order, code, response) { if (!self.father.serverlistener) return; // send information to server based on mode - var request = WA.Managers.ajax.createRequest(WA.Managers.wa4gl.url + WA.Managers.wa4gl.prelib + self.father.app.applicationID + WA.Managers.wa4gl.premethod + self.father.id + WA.Managers.wa4gl.preformat + WA.Managers.wa4gl.format, 'POST', 'Order='+order, getResponse, false); + if (!response) response = getResponse; + var request = WA.Managers.ajax.createRequest(WA.Managers.wa4gl.url + WA.Managers.wa4gl.prelib + self.father.app.applicationID + WA.Managers.wa4gl.premethod + self.father.id + WA.Managers.wa4gl.preformat + WA.Managers.wa4gl.format, 'POST', 'Order='+order+(self.params?'&'+self.params:''), response, false); if (request) { for (var i in code) @@ -364,6 +544,43 @@ WA.Containers.treeContainer.treeZone = function(father, domID, container, code, return result; } + this.moving = moving; + function moving(order, id1, id2, zone, metrics) { + + self.moving = true; + self.father.moving(order, self.xdomID[2], metrics); + } + + this.hover = hover; + function hover() { + if (!self.domNodeHover) { + self.domNodeHover = WA.createDomNode('div', this.domID + "_hover", null); + self.domNodeHover.style = "position: absolute; left: 0px; top: 0px; width: 100%; height: 100%; background-color: white; opacity: 0.4; z-index: 2;"; + // we append to the main document the DOM + self.domNode.appendChild(self.domNodeHover); + var n1 = WA.createDomNode('div', this.domID + "_l1", null); + n1.style = "position: absolute; left: 0px; top: 0px; width: 80%; height: 33%; background-color: green; border-top: 1px solid black; z-index: 3;"; + self.domNodeHover.appendChild(n1); + n1 = WA.createDomNode('div', this.domID + "_l2", null); + n1.style = "position: absolute; left: 0px; top: 33%; width: 80%; height: 33%; background-color: red; border-top: 1px solid black; z-index: 3;"; + self.domNodeHover.appendChild(n1); + n1 = WA.createDomNode('div', this.domID + "_l3", null); + n1.style = "position: absolute; left: 0px; top: 66%; width: 80%; height: 34%; background-color: green; border-top: 1px solid black; z-index: 3;"; + self.domNodeHover.appendChild(n1); + n1 = WA.createDomNode('div', this.domID + "_l4", null); + n1.style = "position: absolute; left: 0px; bottom: 0px; width: 80%; height: 1px; background-color: black; z-index: 3;"; + self.domNodeHover.appendChild(n1); + + } + } + + this.hout = hout; + function hout() { + if (self.domNodeHover) + self.domNode.removeChild(self.domNodeHover); + self.domNodeHover = null; + } + function start() { // link open close @@ -377,10 +594,24 @@ WA.Containers.treeContainer.treeZone = function(father, domID, container, code, } } + function poststart() { + if (self.father.hasdd && self.father.changeorder && self.moveable) { + // Search if there is a node with the class 'move' into the tree of this node + var movenode = WA.browser.findNodeByClass(self.domNode, 'move'); + if (!movenode) + movenode = self.domNode; + WA.Managers.dd.registerObject(self.father.domID, movenode, self.domNode, moving, null); + } + } + function stop() { if (self.closeable) WA.Managers.event.off('click', self.domNodeOpenClose, self.openclose, true); + if (self.father.hasdd && self.father.changeorder && self.moveable) { + WA.Managers.dd.unregisterObject(self.father.domID, self.domNode); + } + console.log("stop node"); } this.resize = resize; diff --git a/js/elements/ggraphElement.js b/js/elements/ggraphElement.js index 2b0edb7..75585cf 100644 --- a/js/elements/ggraphElement.js +++ b/js/elements/ggraphElement.js @@ -83,7 +83,6 @@ WA.Elements.ggraphElement = function(fatherNode, domID, code, listener) //console.log(self.state); //console.log(self.loaded); - if (googleready && self.state == 5 && self.loaded) { //console.log(self.data); @@ -92,9 +91,19 @@ WA.Elements.ggraphElement = function(fatherNode, domID, code, listener) var data = new google.visualization.DataTable(); for(var i=0; i { + try { + JSON.parse(txt); + return true; + } catch (error) { + console.error("ERROR JSON:", error); + return false; + } } // any record change should call this this.fillData = fillData; - function fillData(newdataset) + async function fillData(newdataset) { //console.log('into filldata ' + self.domID); //console.log(self.serverlistener); - if (!newdataset && !self.loaded && self.serverlistener) { if (self.countload++ > 3) @@ -211,10 +303,11 @@ WA.Elements.ggraphElement = function(fatherNode, domID, code, listener) // ask to the server the data var request = WA.Managers.ajax.createRequest(WA.Managers.wa4gl.url + WA.Managers.wa4gl.prelib + self.app.applicationID + WA.Managers.wa4gl.premethod + self.id + WA.Managers.wa4gl.preformat + WA.Managers.wa4gl.format, 'POST', 'Order=get', getData, true); - WA.toDOM(self.domID).innerHTML = '
'; + //WA.toDOM(self.domID).innerHTML = '
'; + return; } - + var dataset = null; if (newdataset) { @@ -272,17 +365,6 @@ WA.Elements.ggraphElement = function(fatherNode, domID, code, listener) start(); } - - - - - - - - - - - this.stop = stop; function stop() { diff --git a/js/elements/lovfieldElement.js b/js/elements/lovfieldElement.js index 44b9d56..e141613 100644 --- a/js/elements/lovfieldElement.js +++ b/js/elements/lovfieldElement.js @@ -56,6 +56,7 @@ WA.Elements.lovfieldElement = function(fatherNode, domID, code, listener) // validity checks this.multiselect = (this.code.attributes.multiselect?this.code.attributes.multiselect=='yes':null); + this.radiobutton = (this.code.attributes.radiobutton ? this.code.attributes.radiobutton == 'yes' : null); this.threshold = (this.code.attributes.threshold?this.code.attributes.threshold:3); this.options = {}; @@ -103,10 +104,17 @@ WA.Elements.lovfieldElement = function(fatherNode, domID, code, listener) this.domNodeValue = WA.createDomNode('div', domID+'_value', 'value'); this.domNode.appendChild(this.domNodeValue); - this.domNodeField = WA.createDomNode('select', domID+'_field', 'field'); + if (!this.radiobutton) + { + this.domNodeField = WA.createDomNode('select', domID+'_field', 'field'); + if (this.size) + this.domNodeField.style.width = this.size+'px'; + if (this.multiselect) + this.domNodeField.multiple = true; + } else { + this.domNodeField = WA.createDomNode('div', domID + '_field', 'field'); + } this.domNodeField.name = this.id; - if (this.size) - this.domNodeField.style.width = this.size+'px'; this.domNode.appendChild(this.domNodeField); this.domNodeHelp = WA.createDomNode('p', domID+'_help', 'help'); @@ -176,18 +184,33 @@ WA.Elements.lovfieldElement = function(fatherNode, domID, code, listener) function populate() { - var text = ''; - if (!self.notnull[self.mode]) + if (self.radiobutton) { - text += ''; + if (self.options) + { + var text = ''; + for (var i in self.options) + { + text += ''+self.options[i]+'
'; + } + self.domNodeField.innerHTML = text; + } } - for (var i in self.options) + else { - // we intelligent populate based on option, select or search - // is this the selected option ? - text += ''; + var text = ''; + if (!self.notnull[self.mode]) + { + text += ''; + } + for (var i in self.options) + { + // we intelligent populate based on option, select or search + // is this the selected option ? + text += ''; + } + self.domNodeField.innerHTML = text; } - self.domNodeField.innerHTML = text; } this.checkStatus = checkStatus; @@ -401,6 +424,38 @@ WA.Elements.lovfieldElement = function(fatherNode, domID, code, listener) this.getValues = getValues; function getValues() { + // Case of a multiselect/Radio + if (self.radiobutton) + { + if (self.multiselect) + { + var values = []; + for (var i=0, l=self.domNodeField.childNodes.length; i < l; i++) + { + if (self.domNodeField.childNodes[i].checked) + { + values.push(self.domNodeField.childNodes[i].value); + } + } + return values; + } else { + for (var i = 0, l = self.domNodeField.childNodes.length; i < l; i++) { + if (self.domNodeField.childNodes[i].checked) { + return self.domNodeField.childNodes[i].value; + } + } + return null; + } + } + if (self.multiselect) + { + var values = []; + var selected = self.domNodeField.selectedOptions; + for (var i = 0; i < selected.length; i++) { + values.push(selected[i].value); + } + return values; + } return self.domNodeField.value; } @@ -409,10 +464,19 @@ WA.Elements.lovfieldElement = function(fatherNode, domID, code, listener) { self.firstview = true; self.value = self.domNodeField.value = values; - if (values != undefined && values != null) - self.domNodeValue.innerHTML = values + (self.options[values]?(' - ' + self.options[values]):''); - else - reset(); + // Case of a multiselect/Radio + if (self.radiobutton || self.multiselect) + { + for (var i=0, l=self.domNodeField.childNodes.length; i < l; i++) + { + self.domNodeField.childNodes[i].checked = (values.indexOf(self.domNodeField.childNodes[i].value) != -1); + } + } else { + if (values != undefined && values != null) + self.domNodeValue.innerHTML = values + (self.options[values] ? (' - ' + self.options[values]) : ''); + else + reset(); + } checkAll(); } @@ -455,26 +519,3 @@ WA.Elements.lovfieldElement = function(fatherNode, domID, code, listener) WA.extend(WA.Elements.lovfieldElement, WA.Managers.wa4gl._element); -/* - - this.domNode = document.createElement('select'); - if(this.multiselect) - { - this.classname = params.attributes.classname?params.attributes.classname:'lovmok'; - this.classnameerror = params.attributes.classnameerror?params.attributes.classnameerror:'lovmerror'; - this.classnamefocus = params.attributes.classnamefocus?params.attributes.classnamefocus:'lovmfocus'; - this.classnamedisabled = params.attributes.classnamedisabled?params.attributes.classnamedisabled:'lovmdisabled'; - this.classnamereadonly = params.attributes.classnamereadonly?params.attributes.classnamereadonly:'lovmreadonly'; - this.classnameselected = params.attributes.classname?params.attributes.classname:'lovmselected'; - this.domNode.setAttribute('multiple','1'); - } - this.domNode.id = domID; - this.domNode.name = _4glNode.id; - if (this.width) - this.domNode.style.width = this.width+'px'; - if (this.height) - this.domNode.style.height = this.height+'px'; - domNodefather.appendChild(this.domNode); - // we link with the group container if needed - -*/ diff --git a/js/elements/mmcfieldElement.js b/js/elements/mmcfieldElement.js index 7c7f4ed..67c986c 100644 --- a/js/elements/mmcfieldElement.js +++ b/js/elements/mmcfieldElement.js @@ -36,6 +36,7 @@ WA.Elements.mmcfieldElement = function(fatherNode, domID, code, listener) this.edition = false; this.focus = false; + this.actionlistener = null; this.mode = 0; // Behaviour on modes this.isvisible = []; @@ -62,8 +63,11 @@ WA.Elements.mmcfieldElement = function(fatherNode, domID, code, listener) this.size = (this.code.attributes.size?this.code.attributes.size:''); // defaultvalue is the default for insert mode (code from the code, set below) // value is the value set in this mode by setValues, if we want to undo changes - this.defaultvalue = this.value = ''; + this.defaultvalue = ''; + this.value = this.newvalue = undefined; this.path = (this.code.attributes.path?this.code.attributes.path:''); + this.accept = (this.code.attributes.accept?this.code.attributes.accept:''); + this.multifile = !!(this.code.attributes.multifile == "yes"); // errors on checks this.errorexternal = false; // true when set manually an error @@ -91,40 +95,63 @@ WA.Elements.mmcfieldElement = function(fatherNode, domID, code, listener) if (self.code.data) this.domNodeLabel.innerHTML = self.code.data; - this.domNodeImage = WA.createDomNode('img', domID+'_image', ''); - this.domNodeImage.style = "float: left; max-width: 50; max-height: 50px; margin-right: 10px;"; - this.domNode.appendChild(this.domNodeImage); - - this.domNodeValue = WA.createDomNode('div', domID+'_value', 'value'); - this.domNode.appendChild(this.domNodeValue); - + this.domNodeUpload = WA.createDomNode('div', domID+'_upload', 'upload'); + this.domNodeUpload.style = "float: left; width: "+this.size+"px; text-align: center;"; + this.domNode.appendChild(this.domNodeUpload); + this.domNodeUpload.innerHTML = "

Buscar o soltar un archivo aquĆ­."; + this.domNodeUpload.addEventListener("click", clickupload); + this.domNodeUpload.addEventListener("dragover", dragover); + this.domNodeUpload.addEventListener("dragleave", dragend); + this.domNodeUpload.addEventListener("dragend", dragend); + this.domNodeUpload.addEventListener("drop", drop); + + this.domNodeUploading = WA.createDomNode('div', domID+'_uploading', 'uploading'); + this.domNodeUploading.style = "float: left; width: "+this.size+"px;"; + this.domNode.appendChild(this.domNodeUploading); + + this.domNodeUploadingIcon = WA.createDomNode('img', domID+'_uploadingicon', 'uploading-icon'); + this.domNodeUploading.appendChild(this.domNodeUploadingIcon); + this.domNodeUploadingName = WA.createDomNode('div', domID+'_uploadingname', 'uploading-name'); + this.domNodeUploading.appendChild(this.domNodeUploadingName); + this.domNodeUploadingPerc = WA.createDomNode('div', domID+'_uploadinperc', 'uploading-perc'); + this.domNodeUploading.appendChild(this.domNodeUploadingPerc); + this.domNodeUploadingBar = WA.createDomNode('div', domID+'_uploadingbar', 'uploading-bar'); + this.domNodeUploading.appendChild(this.domNodeUploadingBar); + this.domNodeUploadingProgress = WA.createDomNode('div', domID+'_uploadingprogress', 'uploading-progressbar'); + this.domNodeUploadingBar.appendChild(this.domNodeUploadingProgress); + + this.domNodeUploaded = buildUploadedTemplate(""); + this.domNode.appendChild(this.domNodeUploaded); + this.domNodeIcon = WA.browser.findNodeByClass(this.domNodeUploaded, 'uploaded-icon'); + this.domNodeImage = WA.browser.findNodeByClass(this.domNodeUploaded, 'uploaded-image'); + this.domNodeValue = WA.browser.findNodeByClass(this.domNodeUploaded, 'uploaded-value'); + this.domNodeDelete = WA.browser.findNodeByClass(this.domNodeUploaded, 'uploaded-delete'); + + // the file is the name of the file, already into server this.domNodeFile = WA.createDomNode('input', domID+'_file', 'field'); this.domNodeFile.type = (this.code.attributes.external?'text':'hidden'); + this.domNodeFile.style.display = 'none'; this.domNodeFile.name = this.id + '_file'; this.domNode.appendChild(this.domNodeFile); + // the download file is the new name of the file if any change (show in upload/modify if external authorized) + this.domNodeDownload = WA.createDomNode('input', domID+'_download', 'field'); + this.domNodeDownload.type = 'text'; + this.domNodeDownload.style.display = 'none'; + this.domNodeDownload.name = this.id + '_download'; + this.domNode.appendChild(this.domNodeDownload); + this.domNodeField = WA.createDomNode('input', domID+'_field', 'field'); this.domNodeField.type = 'file'; + if (this.multifile) + this.domNodeField.multiple = true; + this.domNodeField.style.display = "none"; this.domNodeField.name = this.id; - // POR EL MOMENTO ES MONO IMAGE (EXTENDER CON DIV DE LO SUBIDO A MULTI IMAGE) - // this.domNodeField.multiple = true; - this.domNodeField.accept = "image/x-png, image/gif, image/jpeg, image/jpg"; + this.domNodeField.accept = this.accept; if (this.size) this.domNodeField.style.width = this.size+'px'; this.domNode.appendChild(this.domNodeField); - this.domNodeDownload = WA.createDomNode('input', domID+'_download', 'field'); - this.domNodeDownload.type = 'hidden'; - this.domNodeDownload.name = this.id + '_download'; - this.domNode.appendChild(this.domNodeDownload); - - var br = WA.createDomNode('br'); - this.domNode.appendChild(br); - - this.domNodeDelete = WA.createDomNode('div', domID+'_delete', this.classes.classname + 'delete'); - this.domNodeDelete.innerHTML = (this.code.attributes.deletebutton?this.code.attributes.deletebutton:'[Delete]'); - this.domNode.appendChild(this.domNodeDelete); - this.domNodeHelp = WA.createDomNode('p', domID+'_help', 'help'); this.domNode.appendChild(this.domNodeHelp); if (self.helpmessage) @@ -133,6 +160,11 @@ WA.Elements.mmcfieldElement = function(fatherNode, domID, code, listener) this.domNodeError = WA.createDomNode('p', domID+'_error', 'error'); this.domNode.appendChild(this.domNodeError); + // create multifile list + this.domNodeFiles = WA.createDomNode('div', domID + '_files', 'files'); + this.domNodeFiles.style = "width: " + this.size + "px; position: relative;"; + this.domNode.appendChild(this.domNodeFiles); + // responsive design based on container available size, is '', ' medium' or ' tiny' // Not activated for now this.sizemode = ''; @@ -156,6 +188,27 @@ WA.Elements.mmcfieldElement = function(fatherNode, domID, code, listener) this.addEvent('start', start); this.addEvent('stop', stop); + function callListener(action) + { + if (self.actionlistener) + self.actionlistener(action, self.domNodeImage.src, self.domNodeFile.value); + } + + function buildUploadedTemplate(id) { + var domNodeUploaded = WA.createDomNode('div', domID + '_uploaded' + id, 'uploaded'); + domNodeUploaded.style = (self.multifile ? "" : "float: left; ") + "width: " + self.size + "px;"; + var domNodeIcon = WA.createDomNode('img', domID + '_icon', 'uploaded-icon'); + domNodeUploaded.appendChild(domNodeIcon); + var domNodeImage = WA.createDomNode('img', domID + '_image', 'uploaded-image'); + domNodeUploaded.appendChild(domNodeImage); + var domNodeValue = WA.createDomNode('div', domID + '_value', 'uploaded-value'); + domNodeUploaded.appendChild(domNodeValue); + var domNodeDelete = WA.createDomNode('div', domID + '_delete', 'uploaded-delete'); + domNodeDelete.innerHTML = (self.code.attributes.deletebutton ? self.code.attributes.deletebutton : '[Delete]'); + domNodeUploaded.appendChild(domNodeDelete); + return domNodeUploaded; + } + function resize() { WA.Elements.mmcfieldElement.source.resize.call(self); @@ -173,6 +226,15 @@ WA.Elements.mmcfieldElement = function(fatherNode, domID, code, listener) */ } + // specific element functions + this.addListener = addListener; + function addListener(listener) + { + // Send actions of the group to the listener + self.actionlistener = listener; + callListener('add'); + } + this.registerSynchronize = registerSynchronize; function registerSynchronize(element) { @@ -196,6 +258,64 @@ WA.Elements.mmcfieldElement = function(fatherNode, domID, code, listener) this.checkStatus = checkStatus; function checkStatus() { + if (self.newvalue || self.value || self.mode == 3 || self.mode == 4) + { + self.domNodeUpload.style.display = 'none'; + self.domNodeUploading.style.display = 'none'; + self.domNodeUploaded.style.display = 'block'; + + if (self.newvalue) { + if (self.multifile) { + for (var i = 0; i < self.newvalue.temporal.length; i++) { + var domNodeUploaded = buildUploadedTemplate(i); + self.domNodeFiles.appendChild(domNodeUploaded); + console.log("ICONNAME=", self.newvalue.iconname[i]) + + var nodeicon = WA.browser.findNodeByClass(domNodeUploaded, 'uploaded-icon'); + nodeicon.src = self.newvalue.iconname[i]; + var nodeimage = WA.browser.findNodeByClass(domNodeUploaded, 'uploaded-image'); + if (self.newvalue.image[i]) + { + nodeimage.src = self.newvalue.image[i]; + nodeimage.style.display = "block"; + } + var nodevalue = WA.browser.findNodeByClass(domNodeUploaded, 'uploaded-value'); + nodevalue.innerHTML = self.newvalue.filename[i]; +// var nodedelete = WA.browser.findNodeByClass(domNodeUploaded, 'uploaded-delete'); + } + } else { + self.domNodeIcon.src = self.newvalue.iconname; + self.domNodeValue.innerHTML = self.newvalue.filename; + self.domNodeDownload.value = self.newvalue.temporal; + if (self.newvalue.image) { + self.domNodeImage.src = self.newvalue.image; + self.domNodeImage.style.display = "block"; + } else { + self.domNodeImage.style.display = "none"; + } + } + } else if (self.value) { + self.domNodeIcon.src = self.value.iconname; + self.domNodeValue.innerHTML = self.value.filename; + self.domNodeFile.value = self.value.value; + if (self.value.image) { + self.domNodeImage.src = self.value.image; + self.domNodeImage.style.display = "block"; + } else { + self.domNodeImage.style.display = "none"; + } + } + if (self.mode == 1 || self.mode == 2) + self.domNodeDelete.style.display = 'block'; + else + self.domNodeDelete.style.display = 'none'; + + } else { + self.domNodeUpload.style.display = 'block'; + self.domNodeUploading.style.display = 'none'; + self.domNodeUploaded.style.display = 'none'; + } + for (var i in self.errors) self.errors[i] = false; @@ -230,15 +350,14 @@ WA.Elements.mmcfieldElement = function(fatherNode, domID, code, listener) self.domNodeField.disabled == false; if (self.domNodeField.readOnly == true) self.domNodeField.readOnly == false; - var value = self.domNodeFile.value; - if (self.value != undefined && value == self.value && self.mode != 1) + if (self.mode != 1 && (self.newvalue || self.value)) { self.status = 0; self.domNodeError.innerHTML = ''; return; } self.status = 1; - if (self.notnull[self.mode] && value == '') + if (self.notnull[self.mode] && !self.value && !self.newvalue) { self.status = 2; self.errors.statusnotnull = true; @@ -249,7 +368,7 @@ WA.Elements.mmcfieldElement = function(fatherNode, domID, code, listener) if (self.code[0] != undefined && self.code[0].tag != undefined && self.code[0].tag == 'check') eval(self.code[0].data); - console.log(self.errors); + console.log("STATUS=", self.status, self.errors); } this.checkClass = checkClass; @@ -324,9 +443,6 @@ WA.Elements.mmcfieldElement = function(fatherNode, domID, code, listener) function setMode(mode, keep) { self.mode = mode; - console.log('setMODE'); - console.log(mode); - console.log(keep); // Set all the data based on the mode if (!self.isvisible[mode]) @@ -341,12 +457,11 @@ WA.Elements.mmcfieldElement = function(fatherNode, domID, code, listener) if (keep) self.domNodeValue.innerHTML = self.domNodeFile.value; - self.domNodeValue.style.display = (self.info[mode]?'':'none'); - self.domNodeFile.style.display = (self.info[mode]?'none':''); - self.domNodeField.style.display = (self.info[mode]?'none':''); + // self.domNodeValue.style.display = (self.info[mode]?'':'none'); + // self.domNodeFile.style.display = (self.info[mode]?'none':''); + // self.domNodeField.style.display = (self.info[mode]?'none':''); self.domNodeError.style.display = (self.info[mode]?'none':''); self.domNodeDelete.style.display = (self.info[mode]?'none':''); - self.domNodeHelp.style.display = (self.help[mode]?'':'none'); self.edition = !self.info[mode]; @@ -363,20 +478,61 @@ WA.Elements.mmcfieldElement = function(fatherNode, domID, code, listener) return; if (self.mode == 1) { - self.value = self.domNodeField.value = self.domNodeValue.innerHTML = self.defaultvalue; + self.newvalue = self.value = null; } else if (self.mode == 2 || self.mode == 3) { - self.domNodeValue.innerHTML = self.domNodeField.value = self.value; + self.newvalue = null; } checkAll(); } + function clickupload(e) + { + self.domNodeField.click(); + } + + function dragover(e) + { + e.preventDefault(); + self.domNodeUpload.classList.add('dragover'); + } + + function dragend(e) + { + self.domNodeUpload.classList.remove('dragover'); + } + + function drop(e) + { + e.preventDefault(); + if (e.dataTransfer.files.length) + { + // only 1 to download + self.domNodeField.files = e.dataTransfer.files; + dragend(e); + var event = new Event('change'); + self.domNodeField.dispatchEvent(event); + return; + } + dragend(e); + } + function changeImage(e) { - console.log('changeImage'); - + if (this.files.length == 0) + return; + + console.log('changeImage, UPLOADING'); + self.domNodeUpload.style.display = 'none'; + self.domNodeUploading.style.display = 'block'; + self.domNodeUploaded.style.display = 'none'; + + self.domNodeUploadingName.innerHTML = this.files[0].name; + self.domNodeUploadingPerc.innerHTML = "0.0%"; + self.domNodeUploadingProgress.style.width = "0"; + // enviar un POST al group owner formdata = new FormData(); @@ -387,7 +543,7 @@ WA.Elements.mmcfieldElement = function(fatherNode, domID, code, listener) { file = this.files[i]; - if (!!file.type.match(/image.*/)) +// if (!!file.type.match(/image.*/) || !!file.type.match(/video.*/)) { if ( window.FileReader ) { @@ -400,8 +556,8 @@ WA.Elements.mmcfieldElement = function(fatherNode, domID, code, listener) } if (formdata) { - formdata.append("images[]", file); - formdata.append(self.group.varorder, "image"); + formdata.append("file", file); + formdata.append(self.group.varorder, "file"); formdata.append(self.group.varkey, self.group.currentkey); formdata.append(self.group.varfield, self.id); } @@ -411,32 +567,47 @@ WA.Elements.mmcfieldElement = function(fatherNode, domID, code, listener) if (formdata) { var request = WA.Managers.ajax.createRequest(WA.Managers.wa4gl.url + WA.Managers.wa4gl.prelib + self.app.applicationID + WA.Managers.wa4gl.premethod + self.id + WA.Managers.wa4gl.preformat + WA.Managers.wa4gl.format, 'POST', null, getResult, false); + request.setUploadListener(listenUpload); request.send(formdata); } } - + + function listenUpload(e) + { + var progress = e.loaded / e.total * 100; + self.domNodeUploadingProgress.style.width = "" + progress.toFixed(1) + "%"; + self.domNodeUploadingPerc.innerHTML = "" + progress.toFixed(1) + "%"; + } + function getResult(response) { - console.log(response); var code = WA.JSON.decode(response.responseText); - if (code.status != 'OK') + if (!code.success) + { alert(code.message); + } else { - self.domNodeImage.src = code.tempname; - self.domNodeDownload.value = code.name; - self.domNodeFile.value = code.name; - self.value = ''; + if (!self.multifile || !self.newvalue) + self.newvalue = code; + else + { // CONCATENATE NEW ARRIVED FILES + self.newvalue = code; + } + callListener('upload'); } - checkStatus(); + self.domNodeField.type = ''; + self.domNodeField.type = 'file'; + checkAll(); } function deleteImage(e) { - self.value = self.domNodeFile.value = ''; - self.domNodeImage.src = ''; - self.domNodeValue.innerHTML = ''; - self.domNodeDelete.style.display = 'none'; + if (self.newvalue) { + self.newvalue = null; + } else { + self.value = null; + } checkAll(); } @@ -475,34 +646,17 @@ WA.Elements.mmcfieldElement = function(fatherNode, domID, code, listener) this.getValues = getValues; function getValues() { - if (self.domNodeDownload.value) - return 'temp:'+self.domNodeDownload.value; - return self.domNodeFile.value; + if (self.newvalue) + return self.newvalue; + return self.value; } this.setValues = setValues; function setValues(values) { - console.log('MMCFIELD VALUE = '); - console.log(values); self.firstview = true; - self.value = self.domNodeFile.value = values; - if (values != undefined && values != null && !!values) - { - if (values.substr(0,6) == 'http:/' || values.substr(0,7) == 'https:/') - { - // if accept external values, check if starts with http* - self.domNodeImage.src = values; - self.domNodeValue.innerHTML = values; - } - else - { - self.domNodeImage.src = self.path + values; - self.domNodeValue.innerHTML = values; - } - } - else - reset(); + self.value = values; + self.newvalue = null; checkAll(); } diff --git a/js/elements/searchabletextfieldElement.js b/js/elements/searchabletextfieldElement.js new file mode 100644 index 0000000..49335e2 --- /dev/null +++ b/js/elements/searchabletextfieldElement.js @@ -0,0 +1,677 @@ + +/* + textfieldElement.js, WAJAF, the WebAbility(r) Javascript Application Framework + Contains element to control a simple text field + (c) 2008-2012 Philippe Thomassigny + + This file is part of WAJAF + + WAJAF is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + WAJAF is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with WAJAF. If not, see . +*/ + +WA.Elements.searchabletextfieldElement = function(fatherNode, domID, code, listener) +{ + var self = this; + WA.Elements.searchabletextfieldElement.sourceconstructor.call(this, fatherNode, domID, code, 'div', { classname:'textfield' }, listener); + + this.id = this.code.attributes.id; // name of field, to use to send to the server + + // by default the field is part of the record, used by container + this.formtype = 'field'; + this.record = (this.code.attributes.record&&this.code.attributes.record=='no'?false:true); + this.editable = true; // it's a text field, so yes + + this.status = 0; // 0 = neutral, 1 = ok, 2 = error, 3 = r/o, 4 = disabled + this.edition = false; + this.focus = false; + + this.mode = 0; + // Behaviour on modes + this.isvisible = []; + this.info = []; + this.disabled = []; + this.readonly = []; + this.notnull = []; + this.help = []; + for (var i = 1; i < 5; i++) + { + this.isvisible[i] = (this.code.attributes.visible?this.code.attributes.visible.indexOf(''+i)!=-1:true); + this.info[i] = (this.code.attributes.info?this.code.attributes.info.indexOf(''+i)!=-1:false); + this.disabled[i] = (this.code.attributes.disabled?this.code.attributes.disabled.indexOf(''+i)!=-1:false); + this.readonly[i] = (this.code.attributes.readonly?this.code.attributes.readonly.indexOf(''+i)!=-1:false); + this.notnull[i] = (this.code.attributes.notnull?this.code.attributes.notnull.indexOf(''+i)!=-1:false); + this.help[i] = (this.code.attributes.helpmode?this.code.attributes.helpmode.indexOf(''+i)!=-1:false); + } + + // validity checks + // type can be: text, password, integer, float, email + this.texttype = (this.code.attributes.texttype?this.code.attributes.texttype:'text'); + this.format = (this.code.attributes.format?new RegExp(this.code.attributes.format):null); + this.min = (this.code.attributes.min?this.code.attributes.min:''); + this.max = (this.code.attributes.max?this.code.attributes.max:''); + this.minlength = (this.code.attributes.minlength?this.code.attributes.minlength:''); + this.maxlength = (this.code.attributes.maxlength?this.code.attributes.maxlength:''); + this.size = (this.code.attributes.size?this.code.attributes.size:''); + this.minwords = (this.code.attributes.minwords?this.code.attributes.minwords:null); + this.maxwords = (this.code.attributes.maxwords?this.code.attributes.maxwords:null); + this.auto = (this.code.attributes.auto&&this.code.attributes.auto=='yes'?true:false); + // defaultvalue is the default for insert mode (code from the code, set below) + // value is the value set in this mode by setValues, if we want to undo changes + this.defaultvalue = this.value = ''; + this.automessage = ''; + + // errors on checks + this.errorexternal = false; // true when set manually an error + this.errors = {}; + this.errormessages = {}; + this.firstview = true; // set to false when the field has been touched/modified. Used to know if we put the errors + + if (code.children) + { + for (var i = 0, l = code.children.length; i < l; i++) + { + switch (code.children[i].tag) + { + case 'defaultvalue': this.defaultvalue = code.children[i].data?code.children[i].data:''; break; + case 'helpdescription': this.helpmessage = code.children[i].data; break; + case 'statusnotnull': this.errormessages.statusnotnull = code.children[i].data; this.errors.statusnotnull = false; break; + case 'statusbadformat': this.errormessages.statusbadformat = code.children[i].data; this.errors.statusbadformat = false; break; + case 'statustooshort': this.errormessages.statustooshort = code.children[i].data; this.errors.statustooshort = false; break; + case 'statustoolong': this.errormessages.statustoolong = code.children[i].data; this.errors.statustoolong = false; break; + case 'statustoofewwords': this.errormessages.statustoofewwords = code.children[i].data; this.errors.statustoofewwords = false; break; + case 'statustoomanywords': this.errormessages.statustoomanywords = code.children[i].data; this.errors.statustoomanywords = false; break; + case 'statustoolow': this.errormessages.statustoolow = code.children[i].data; this.errors.statustoolow = false; break; + case 'statustoohigh': this.errormessages.statustoohigh = code.children[i].data; this.errors.statustoohigh = false; break; + case 'statuscheck': this.errormessages.statuscheck = code.children[i].data; this.errors.statuscheck = false; break; + case 'automessage': this.automessage = code.children[i].data; break; + } + } + } + // NODES + this.domNodeLabel = WA.createDomNode('label', domID+'_label', this.classes.classname + 'label'); + this.father.domNode.insertBefore(this.domNodeLabel, this.domNode); + if (self.code.data) + this.domNodeLabel.innerHTML = self.code.data; + + this.domNodeValue = WA.createDomNode('div', domID+'_value', 'value'); + this.domNode.appendChild(this.domNodeValue); + + this.domNodeSearch = WA.createDomNode('input', domID + '_search', 'field'); + this.domNodeSearch.type = this.texttype == 'masked' ? 'password' : 'text'; + this.domNodeSearch.autocomplete = "off"; + if (this.maxlength) + this.domNodeSearch.maxLength = this.maxlength; + if (this.size) + this.domNodeSearch.style.width = this.size + 'px'; + this.domNode.appendChild(this.domNodeSearch); + + this.domNodeList = WA.createDomNode('div', domID + '_list', 'list'); + this.domNodeList.style = "width: " + this.size + "px;"; + this.domNode.appendChild(this.domNodeList); + + this.domNodeField = WA.createDomNode('input', domID+'_field', 'selected'); + this.domNodeField.type = 'text'; + this.domNodeField.name = this.id; + this.domNodeField.readOnly = true; + this.domNode.appendChild(this.domNodeField); + + this.domNodeCount = WA.createDomNode('span', domID+'_count', 'count'); + this.domNode.appendChild(this.domNodeCount); + + this.domNodeHelp = WA.createDomNode('p', domID+'_help', 'help'); + this.domNode.appendChild(this.domNodeHelp); + if (self.helpmessage) + this.domNodeHelp.innerHTML = self.helpmessage; + + this.domNodeError = WA.createDomNode('p', domID+'_error', 'error'); + this.domNode.appendChild(this.domNodeError); + this.domNodeResult = WA.createDomNode('div', domID + '_result', 'result'); + this.domNode.appendChild(this.domNodeResult); + + // responsive design based on container available size, is '', ' medium' or ' tiny' + // Not activated for now + this.sizemode = ''; + + // we link with the group. first father is the zone, second father is the group + // ********************************************* + // NOTE: THIS IS WRONG; THERE MAY BE MORE CONTAINERS INTO THE ZONES ETC + // THE GROUP SHOULD BE SEARCH BY ID INTO THE 4GL TREE + this.group = null; + if (this.father.father.code.attributes.type == "groupContainer") + { + this.group = this.father.father; + this.group.registerField(this); + } + else + { + if (this.defaultvalue) + this.domNodeField.value = this.defaultvalue; + } + + // If we control some other fields + this.synchronizer = null; + this.synchronizeelements = []; + + this.addEvent('resize', resize); + this.addEvent('start', start); + this.addEvent('stop', stop); + + function resize() + { + WA.Elements.searchabletextfieldElement.source.resize.call(self); + // size mode for responsive design, not activated for now +/* + var RW = WA.browser.getNodeOuterWidth(self.father.domNode); + var W1 = WA.browser.getNodeOuterWidth(self.domNodeField); // should be always fixed by CSS or code. We consider fields as fixed size always + if (RW > W1*2 + 180 && self.sizemode != '') + self.sizemode = ''; + else if (RW > W1 + 180 && self.sizemode != ' medium') + self.sizemode = ' medium'; + else if (self.sizemode != ' tiny') + self.sizemode = ' tiny'; + checkClass(); +*/ + } + + this.registerSynchronize = registerSynchronize; + function registerSynchronize(element) + { + self.synchronizeelements.push(element); + } + + this.unregisterSynchronize = unregisterSynchronize; + function unregisterSynchronize(element) + { + for (var i=0, l=self.synchronizeelements.length; i < l; i++) + { + if (self.synchronizeelements[i] == element) + { + self.synchronizeelements.splice(i, 1); + break; + } + } + return; + } + + this.checkStatus = checkStatus; + function checkStatus() + { + for (var i in self.errors) + self.errors[i] = false; + + if (self.mode == 0 || !self.edition) + { + self.status = 0; + self.domNodeError.innerHTML = ''; + self.domNodeCount.innerHTML = ''; + return; + } + + // default = ok, status = 1 (ok), 2 (editing), 3 (error), 4 (r/o), 5 (disabled) + if (self.synchronizer) + { + // we rebuild synchronizer + self.synchronizer.checkStatus(); + self.status = self.synchronizer.status; + return; + } + + // we check anything based on the attributes of the field + if (self.disabled[self.mode]) + { + self.status = 4; + return; + } + if (self.readonly[self.mode]) + { + self.status = 3; + return; + } + if (self.domNodeField.disabled == true) + self.domNodeField.disabled == false; + if (self.domNodeField.readOnly == true) + self.domNodeField.readOnly == false; + var value = self.domNodeField.value; + if (self.value != undefined && value == self.value && self.mode != 1) + { + self.status = 0; + self.domNodeError.innerHTML = ''; + self.domNodeCount.innerHTML = ''; + return; + } + if (self.mode == 1 && self.auto) + { + self.status = 0; + return; + } + + self.status = 1; + if (self.notnull[self.mode] && value == '') + { + self.status = 2; + self.errors.statusnotnull = true; + } + + if (self.format && value.match(self.format) == null) + { + self.status = 2; + self.errors.statusbadformat = true; + } + if (self.texttype == "integer") + { + nv = parseInt(value, 10) + min = parseInt(self.min, 10) + max = parseInt(self.max, 10) + if (min != max && nv < min) + { + self.status = 2; + self.errors.statustoolow = true; + } + if (min != max && nv > max) + { + self.status = 2; + self.errors.statustoohigh = true; + } + } + if (self.texttype == "float") + { + nv = parseFloat(value) + min = parseFloat(self.min) + max = parseFloat(self.max) + if (min != max && nv < min) + { + self.status = 2; + self.errors.statustoolow = true; + } + if (min != max && nv > max) + { + self.status = 2; + self.errors.statustoohigh = true; + } + } + if (self.texttype == "text" || self.texttype == "masked") + { + if (self.minlength && value.length < self.minlength) + { + self.status = 2; + self.errors.statustooshort = true; + } + if (self.maxlength && value.length > self.maxlength) + { + self.status = 2; + self.errors.statustoolong = true; + } + var text = value; + text = text.replace(/[\n\t\r]+/g, " "); + text = text.replace(/^[ ]+/, ""); + text = text.replace(/[ ]+$/, ""); + text = text.replace(/[ ]+/g, " "); + var numpalabras = (text.length > 0 ? text.split(" ").length : 0); + if (self.maxwords || self.minwords) + { + if (numpalabras < self.minwords) + { + self.status = 2; + self.errors.statustoofewwords = true; + } + if (numpalabras > self.maxwords) + { + self.status = 2; + self.errors.statustoomanywords = true; + } + } + self.domNodeCount.innerHTML = numpalabras + '/' + value.length; + } + if (self.errorexternal) + self.status = 2; + // user own checks + if (self.code[0] != undefined && self.code[0].tag != undefined && self.code[0].tag == 'check') + eval(self.code[0].data); + } + + this.checkClass = checkClass; + function checkClass() + { + var extras = ''; + switch (self.status) + { + case 4: extras += ' disabled'; self.domNodeField.disabled = true; break; + case 3: extras += ' readonly'; self.domNodeField.readOnly = true; break; + case 2: extras += ' error'; if (self.group) self.father.setStatus(self.focus?1:(self.firstview?0:3)); break; + case 1: extras += ' ok'; if (self.group) self.father.setStatus(self.focus?1:(self.firstview?0:2)); break; + default: if (self.group) self.father.setStatus(self.focus?1:0); break; + } + if (self.focus) + extras += ' edition'; + self.domNodeLabel.className = self.classes.classname + 'label' + extras + self.sizemode; + self.domNode.className = self.classes.classname + extras + self.sizemode; + } + + this.checkChildren = checkChildren; + function checkChildren(onlylocal) + { + if (!onlylocal) + { + for (var i=0, l=self.synchronizeelements.length; i < l; i++) + { + self.synchronizeelements[i].status = self.status; + self.synchronizeelements[i].checkClass(); + self.synchronizeelements[i].checkChildren(); + } + } + } + + this.checkAll = checkAll; + function checkAll(notifygroup) + { + self.checkStatus(); + self.checkClass(); + self.checkChildren(false); + + if (!self.firstview) + { + if (!self.errorexternal) + { + var text = ''; + for (var i in self.errors) + { + if (self.errors[i]) + text += self.errormessages[i] + '
'; + } + self.domNodeError.innerHTML = text; + } + } + else + self.domNodeError.innerHTML = ''; + if (self.group && notifygroup) + { + self.group.pleaseCheck(); + } + } + + this.setError = setError; + function setError(values) + { + self.domNodeError.innerHTML = values; + self.errorexternal = true; + checkAll(); + } + + this.setMode = setMode; + function setMode(mode, keep) + { + self.mode = mode; + + // Set all the data based on the mode + if (!self.isvisible[mode]) + { + if (self.group) + self.father.hide(); + return; + } + if (self.group) + self.father.show(); + + if (keep) + self.domNodeValue.innerHTML = self.domNodeField.value; + if (mode == 1 && self.auto) + { + self.domNodeValue.style.display = ''; + self.domNodeField.style.display = 'none'; + } + else + { + self.domNodeValue.style.display = (self.info[mode]?'':'none'); + self.domNodeField.style.display = (self.info[mode]?'none':''); + } + + self.domNodeHelp.style.display = (self.help[mode]?'':'none'); + self.domNodeCount.style.display = (self.info[mode]?'none':''); + self.domNodeError.style.display = (self.info[mode]?'none':''); + self.edition = !self.info[mode]; + if (mode == 1) + { + reset(); + } + else + checkAll(); + } + + function filllist(list) { + self.domNodeList.innerHTML = ""; + for (var i in list) { + var item = WA.createDomNode('div', self.id + '_list_' + i, 'item'); + item.innerHTML = i + " / " + list[i]; + item.value = list[i]; + item.key = i; + item.onclick = function() { + console.log("CLICK", this.key); + self.domNodeSearch.value = this.value; + self.domNodeField.value = this.key; + self.domNodeList.style.display = 'none'; + self.haslist = false; + self.showlist = false; + checkAll(true); // check and notify group + search(); + } + item.onmouseover = function () { + this.className = 'item selected'; + self.itemover = true; + } + item.onmouseout = function () { + this.className = 'item'; + self.itemover = false; + } + self.domNodeList.appendChild(item); + } + self.haslist = true; + self.showlist = true; + self.domNodeList.style.display = 'block'; + } + + function getResponse(request) { + + var code = WA.JSON.decode(request.responseText); + if (code.status != 1) + { + self.status = 2; + self.errors.statusnotnull = true; + } + else + self.status = 1; + self.checkClass(); + + self.domNodeField.value = code.key; + self.domNodeResult.innerHTML = code.message; + + if (code.list && !code.key) { + // Fill in the list + filllist(code.list); + } else { + self.haslist = false; + self.showlist = false; + self.domNodeList.style.display = 'none'; + if (code.value) + self.domNodeSearch.value = code.value; + } + + checkAll(true); + } + + this.sendServer = sendServer; + function sendServer(order, code, response) { + // send information to server based on mode + if (!response) response = getResponse; + var request = WA.Managers.ajax.createRequest(WA.Managers.wa4gl.url + WA.Managers.wa4gl.prelib + self.app.applicationID + WA.Managers.wa4gl.premethod + self.id + WA.Managers.wa4gl.preformat + WA.Managers.wa4gl.format, 'POST', 'Order=' + order + (self.params ? '&' + self.params : ''), response, false); + if (request) { + for (var i in code) { + request.addParameter(i, code[i]); + } + request.send(); + } + } + + this.reset = reset; + function reset() + { + if (!self.edition) + return; + if (self.mode == 1) + { + self.value = self.domNodeField.value = self.domNodeSearch.value = self.defaultvalue; + self.domNodeValue.innerHTML = self.auto?self.automessage:self.defaultvalue; + } + else if (self.mode == 2 || self.mode == 3) + { + self.domNodeValue.innerHTML = self.domNodeField.value = self.domNodeSearch.value = self.value; + } + checkAll(); + } + + this.search = search; + function search() + { + // if ENTER, send + self.sendServer('search', { id: self.code.attributes.id, key: self.domNodeField.value, q: self.domNodeSearch.value }); + } + + function onkeyup(e) + { + console.log("KEY UP", e, self.id); + self.firstview = false; + self.errorexternal = false; + if ((self.value == undefined || self.value == null || self.value == '') && self.domNodeSearch.value == '') + self.firstview = true; + else if (self.value != undefined && self.value != null && self.domNodeSearch.value == self.value) + self.firstview = true; + setTimeout( function() { checkAll(true); }, 0); // check and notify group + setTimeout( function() { self.callEvent('keyup'); }, 0); // call event key up + self.domNodeField.value = ""; + search(); + } + + function onblur(e) + { + self.focus = false; + setTimeout(function() { + if (self.haslist && !self.itemover) { + self.domNodeList.style.display = 'none'; + self.showlist = false; + } + }, 1); + if (!self.haslist) + { + checkAll(true); // check and notify group + self.callEvent('blur'); + search(); + } +} + + function onfocus(e) + { + self.focus = true; + if (self.haslist) { + console.log("FOCUS") + self.domNodeList.style.display = 'block'; + self.showlist = true; + } + checkAll(true); // check and notify group + if (self.group) + self.father.setStatus(1); + self.callEvent('focus'); + } + + function start() + { + console.log("START", self.id, self.domNodeSearch); + + WA.Managers.event.on('keyup', self.domNodeSearch, onkeyup, true); + WA.Managers.event.on('focus', self.domNodeSearch, onfocus, true); + WA.Managers.event.on('blur', self.domNodeSearch, onblur, true); + + // If we are controled by another field + if (self.code.attributes.synchronizer) + { + self.synchronizer = WA.$N(self.code.attributes.synchronizer); + if (self.synchronizer) + self.synchronizer.registerSynchronize(self); + } + // we do not check, there is still no value. the setMode will do the job + } + + this.getValues = getValues; + function getValues() + { + return self.domNodeField.value; + } + + this.setValues = setValues; + function setValues(values) + { + if (self.group) + { + self.firstview = true; + self.value = self.domNodeField.value = self.domNodeSearch.value = values; + if (values != undefined && values != null) + self.domNodeValue.innerHTML = values; + else + reset(); + checkAll(); + } + else + { + self.domNodeField.value = values; + self.domNodeSearch.value = values; + } + } + + this.stop = stop; + function stop() + { + if (self.group) + self.group.unregisterField(self); + WA.Managers.event.off('keyup', self.domNodeSearch, onkeyup, true); + WA.Managers.event.off('focus', self.domNodeSearch, onfocus, true); + WA.Managers.event.off('blur', self.domNodeSearch, onblur, true); + } + + this.destroy = destroy; + function destroy(fast) + { + WA.Elements.searchabletextfieldElement.source.destroy.call(self, fast); + + self.synchronizer = null; + self.synchronizeelements = []; + self.group = null; + self.domNodeError = null; + self.domNodeHelp = null; + self.domNodeValue = null; + self.domNodeSearch = null; + self.domNodeCount = null; + self.domNodeField = null; + self.domNodeLabel = null; + self.errormessages = null; + self.errors = null; + self.isvisible = null; + self.info = null; + self.disabled = null; + self.readonly = null; + self.notnull = null; + self.help = null; + self = null; + } +} + +// Add basic element code +WA.extend(WA.Elements.searchabletextfieldElement, WA.Managers.wa4gl._element); diff --git a/js/elements/textareafieldElement.js b/js/elements/textareafieldElement.js index 5d9d3f2..4103cbe 100644 --- a/js/elements/textareafieldElement.js +++ b/js/elements/textareafieldElement.js @@ -230,14 +230,14 @@ WA.Elements.textareafieldElement = function(fatherNode, domID, code, listener) self.status = 2; self.errors.statustoolong = true; } + var text = value; + text = text.replace(/^[ ]+/, ""); + text = text.replace(/[ ]+$/, ""); + text = text.replace(/[ ]+/g, " "); + text = text.replace(/[\n]+/g, " "); + var numpalabras = (text.length > 0 ? text.split(" ").length : 0); if (self.maxwords || self.minwords) { - var text = value; - text = text.replace(/^[ ]+/, ""); - text = text.replace(/[ ]+$/, ""); - text = text.replace(/[ ]+/g, " "); - text = text.replace(/[\n]+/g, " "); - var numpalabras = (text.length>0?text.split(" ").length:0); if (numpalabras < self.minwords) { self.status = 2; @@ -248,8 +248,8 @@ WA.Elements.textareafieldElement = function(fatherNode, domID, code, listener) self.status = 2; self.errors.statustoomanywords = true; } - self.domNodeCount.innerHTML = numpalabras + '/' + value.length; } + self.domNodeCount.innerHTML = numpalabras + '/' + value.length; // user own checks if (self.code[0] != undefined && self.code[0].tag != undefined && self.code[0].tag == 'check') eval(self.code[0].data); diff --git a/js/elements/textfieldElement.js b/js/elements/textfieldElement.js index fbd00eb..ced8e7d 100644 --- a/js/elements/textfieldElement.js +++ b/js/elements/textfieldElement.js @@ -300,14 +300,14 @@ WA.Elements.textfieldElement = function(fatherNode, domID, code, listener) self.status = 2; self.errors.statustoolong = true; } + var text = value; + text = text.replace(/[\n\t\r]+/g, " "); + text = text.replace(/^[ ]+/, ""); + text = text.replace(/[ ]+$/, ""); + text = text.replace(/[ ]+/g, " "); + var numpalabras = (text.length > 0 ? text.split(" ").length : 0); if (self.maxwords || self.minwords) { - var text = value; - text = text.replace(/[\n\t\r]+/g, " "); - text = text.replace(/^[ ]+/, ""); - text = text.replace(/[ ]+$/, ""); - text = text.replace(/[ ]+/g, " "); - var numpalabras = (text.length>0?text.split(" ").length:0); if (numpalabras < self.minwords) { self.status = 2; @@ -318,8 +318,8 @@ WA.Elements.textfieldElement = function(fatherNode, domID, code, listener) self.status = 2; self.errors.statustoomanywords = true; } - self.domNodeCount.innerHTML = numpalabras + '/' + value.length; } + self.domNodeCount.innerHTML = numpalabras + '/' + value.length; } if (self.errorexternal) self.status = 2; diff --git a/js/managers/ajaxManager.js b/js/managers/ajaxManager.js index 37a9912..a7462d6 100644 --- a/js/managers/ajaxManager.js +++ b/js/managers/ajaxManager.js @@ -61,10 +61,7 @@ WA.Managers.ajax = new function() { callNotify('create'); var r = new WA.Managers.ajax.Request(url, method, data, feedback, dosend, self.listener, self.statefeedback, self.timeoutabort); - if (r) - { - self.requests.push(r); - } + self.requests.push(r); return r; } @@ -151,6 +148,7 @@ WA.Managers.ajax.Request = function(url, method, data, feedback, autosend, liste this.timerabort = null; this.state = 0; // 0 = nothing, 1 = sent and waiting, 2 = finished, 3 = error this.listener = listener; + this.uploadlistener = null; try { this.request = new XMLHttpRequest(); } catch(e) @@ -173,6 +171,12 @@ WA.Managers.ajax.Request = function(url, method, data, feedback, autosend, liste } } + this.setUploadListener = setUploadListener; + function setUploadListener(listener) + { + self.uploadlistener = listener; + } + // Special parameters this.setPeriodic = setPeriodic; function setPeriodic(period, times) @@ -259,6 +263,9 @@ WA.Managers.ajax.Request = function(url, method, data, feedback, autosend, liste return; self.request.onreadystatechange = process; + if (self.uploadlistener) { + self.request.upload.addEventListener("progress", self.uploadlistener); + } if (self.timeoutabort) self.timerabort = setTimeout( function() { timeabort(); }, self.timeoutabort ); try @@ -278,9 +285,7 @@ WA.Managers.ajax.Request = function(url, method, data, feedback, autosend, liste if (self.method == 'POST') { if (!!form) - { self.request.send(form); - } else { var parameters = buildParametersPost(); diff --git a/js/managers/wa4glManager.js b/js/managers/wa4glManager.js index 058179b..5a8c08d 100644 --- a/js/managers/wa4glManager.js +++ b/js/managers/wa4glManager.js @@ -598,6 +598,8 @@ WA.Managers.wa4gl = new function() if (app.domNode == null) throw 'Error, the application could not be launched.'; + fatherNode.application = app; + self.applications[applicationID+'|'+instanceID] = app; app.start(params); diff --git a/js/system/core.js b/js/system/core.js index 7e8fd97..21b4f17 100644 --- a/js/system/core.js +++ b/js/system/core.js @@ -23,7 +23,7 @@ // -------------------------------------------------------------------------------------------------------- // WA is the main WAJAF Object that will contain anything else (except for the native JS object prototypes) // -------------------------------------------------------------------------------------------------------- -var WA = { version: '0.3.0', +var WA = { version: '0.1.4', running: false }; // Main WAJAF Object definition diff --git a/js/system/corebrowser.js b/js/system/corebrowser.js index a4aa3df..cfc4b50 100644 --- a/js/system/corebrowser.js +++ b/js/system/corebrowser.js @@ -145,12 +145,37 @@ WA.browser.getScrollHeight = function() return WA.browser.getDocumentHeight(); } +WA.browser.findNodeByClass = function(rootnode, className) +{ + // Check if the current node has the desired class + if (rootnode.classList && rootnode.classList.contains(className)) { + return rootnode; + } + + // Iterate over the children of the current node + for (let i = 0; i < rootnode.childNodes.length; i++) { + const childNode = rootnode.childNodes[i]; + + // Recursively call to search the child node tree + const foundNode = WA.browser.findNodeByClass(childNode, className); + + // If the node with the desired class is found, return it + if (foundNode) { + return foundNode; + } + } + + // If no node with the desired class is found in this subtree, return null + return null; +} + + // get the left of a DOM element into the document WA.browser.getNodeDocumentLeft = function(node) { var l = node.offsetLeft; if (node.offsetParent != null) - l += WA.browser.getNodeDocumentLeft(node.offsetParent) + WA.browser.getNodeBorderLeftWidth(node.offsetParent) + WA.browser.getNodeMarginLeftWidth(node.offsetParent); + l += WA.browser.getNodeDocumentLeft(node.offsetParent) - WA.browser.getNodeScrollLeft(node.offsetParent); return l; } @@ -159,7 +184,7 @@ WA.browser.getNodeDocumentTop = function(node) { var t = node.offsetTop; if (node.offsetParent != null) - t += WA.browser.getNodeDocumentTop(node.offsetParent) + WA.browser.getNodeBorderTopHeight(node.offsetParent) + WA.browser.getNodeMarginTopHeight(node.offsetParent); + t += WA.browser.getNodeDocumentTop(node.offsetParent) - WA.browser.getNodeScrollTop(node.offsetParent); return t; } diff --git a/js/system/coretemplate.js b/js/system/coretemplate.js index e69de29..00d4e75 100644 --- a/js/system/coretemplate.js +++ b/js/system/coretemplate.js @@ -0,0 +1,143 @@ + +WA.templates = {}; +WA.templatesstrings = {}; +WA.codes = {}; + +WA.templater = function (strings, ...keys) { + function searchdata(data, key) { + if ((pos = key.indexOf(">")) != -1) { + first = key.substr(0, pos); + val = data[first]; + if (WA.isArray(val) || WA.isObject(val) || WA.isFunction(val)) + return searchdata(val, key.substr(pos + 1)) + return undefined; + } + if (data) + return data[key]; + return null; + } + function searchdatapile(datapile, key) { + if (!key) + return ''; + for (var i = datapile.length - 1; i >= 0; i--) { + var val = searchdata(datapile[i], key); + if (val !== undefined) + return val; + } + return ''; + } + function loop(templates, datapile, data, template) { + if (!templates) + templates = WA.templates; + if (!data || !WA.isArray(data) || data.length == 0) { + if (templates[template + ".none"]) + return templates[template + ".none"](datapile, templates); + return ""; + } + txt = ""; + for (var i = 0; i < data.length; i++) { + datapile.push(data[i]); + if (templates[template + ".key." + i]) + txt += templates[template + ".key." + i](datapile, templates); + else if (i == 0 && templates[template + ".first"]) + txt += templates[template + ".first"](datapile, templates); + else if (i == data.length - 1 && templates[template + ".last"]) + txt += templates[template + ".last"](datapile, templates); + else if (i % 2 == 0 && templates[template + ".even"]) + txt += templates[template + ".even"](datapile, templates); + else if (templates[template]) + txt += templates[template](datapile, templates); + else + txt += ""; + datapile.pop(); + } + return txt; + } + function cond(templates, field, template, datapile) { + if (!templates) + templates = WA.templates; + + val = searchdatapile(datapile, field); + var pushed = false; + if (val != null && (WA.isArray(val) || WA.isObject(val) || WA.isFunction(val))) { + pushed = true; + datapile.push(val); + } + if (!val && templates[template + ".none"]) + text = templates[template + ".none"](datapile, templates); + else if (val && templates[template + "." + val]) + text = templates[template + "." + val](datapile, templates); + else if (templates[template]) + text = templates[template](datapile, templates); + else + text = ""; + if (pushed) + datapile.pop(); + + return text; + } + function call(templates, template, data) { + if (!templates) + templates = WA.templates; + if (templates[template]) + return templates[template](data, templates); + return ""; + } + + return function (data, templates) { + let temp = strings.slice(); + let datapile = data + if (!WA.isArray(data)) + datapile = [data]; + keys.forEach((key, i) => { + if (Array.isArray(key)) { + switch (key[0]) { + case "eval": + temp[i] = temp[i] + eval(key[1]); + break; + case "loop": + val = searchdatapile(datapile, key[1]); + if (!WA.isArray(val)) + val = undefined; + temp[i] = temp[i] + loop(templates, datapile, val, key[2] ? key[2] : key[1]); + break; + case "cond": + temp[i] = temp[i] + cond(templates, key[1], key[2], datapile); + break; + case "call": + if (key[3]) { + template = key[3] + searchdatapile(datapile, key[2]); + temp[i] = temp[i] + call(templates, template, datapile); + } + else { + val = searchdatapile(datapile, key[2]); + var pushed = false; + if (WA.isArray(val) || WA.isObject(val) || WA.isFunction(val)) { + pushed = true; + datapile.push(val); + } + temp[i] = temp[i] + call(templates, key[1], datapile); + if (pushed) + datapile.pop(); + } + break; + default: + temp[i] = temp[i] + ""; + } + } + else { + temp[i] = temp[i] + searchdatapile(datapile, key); + } + }); + return temp.join(''); + } +}; + +WA.XTemplate = function (temps) { + + var templates = temps + + return function run(data) { + return templates.main(data, templates); + } +} diff --git a/lovfieldelement.go b/lovfieldelement.go index 9553205..0f94627 100644 --- a/lovfieldelement.go +++ b/lovfieldelement.go @@ -8,7 +8,7 @@ func NewLOVFieldElement(id string) LOVFieldElement { e.SetID(id) e.RegisterKnownAttributes([]string{"display", "style", "classname", "left", "width", "right", "top", "height", "bottom", - "size", "visible", "info", "disabled", "readonly", "notnull", "helpmode"}) + "size", "visible", "info", "disabled", "readonly", "notnull", "helpmode", "multiselect", "radiobutton"}) // e.RegisterKnownMessages([]string{"defaultvalue", "helpdescription", "statusnotnull", "statuscheck"}) e.RegisterKnownChildren([]string{"options", "code"}) diff --git a/mmcfieldelement.go b/mmcfieldelement.go index 69dbc49..2459b7b 100644 --- a/mmcfieldelement.go +++ b/mmcfieldelement.go @@ -7,7 +7,9 @@ func NewMMCFieldElement(id string) MMCFieldElement { e := NewNode("element", "mmcfieldElement") e.SetID(id) - e.RegisterKnownAttributes([]string{"display", "style", "classname", "left", "width", "right", "top", "height", "bottom"}) - + e.RegisterKnownAttributes([]string{"display", "style", "classname", "left", "width", "right", "top", "height", "bottom", "size", + "visible", "info", "disabled", "readonly", "notnull", "helpmode", + "path", "external", "deletebutton", "loading", "accept", "multifile"}) + // e.RegisterKnownMessages([]string{"defaultvalue", "helpdescription", "statusnotnull"} ) return e } diff --git a/searchabletextfieldelement.go b/searchabletextfieldelement.go new file mode 100644 index 0000000..0e1e613 --- /dev/null +++ b/searchabletextfieldelement.go @@ -0,0 +1,16 @@ +package wajaf + +type SearchableTextFieldElement NodeDef + +func NewSearchableTextFieldElement(id string) SearchableTextFieldElement { + + e := NewNode("element", "searchabletextfieldElement") + e.SetID(id) + + e.RegisterKnownAttributes([]string{"display", "style", "classname", "left", "width", "right", "top", "height", "bottom", + "size", "texttype", "minlength", "maxlength", "minwords", "maxwords", "min", "max", "format", "visible", "info", + "disabled", "readonly", "notnull", "helpmode", "auto"}) + // e.RegisterKnownMessages([]string{"defaultvalue", "helpdescription", "statusnotnull", "statusbadformat", "statustooshort", "statustoolong", "statustoofewwords", "statustoomanywords", "statuscheck"}) + + return e +} diff --git a/wajaf.go b/wajaf.go index 18e0182..184a085 100644 --- a/wajaf.go +++ b/wajaf.go @@ -7,7 +7,7 @@ package wajaf // VERSION is the used version nombre of the XCore library. -const VERSION = "0.1.3" +const VERSION = "0.3.0" // LOG is the flag to activate logging on the library. // if LOG is set to TRUE, LOG indicates to the XCore libraries to log a trace of functions called, with most important parameters.