fs-danaus
2023-03-30 665b0603d09890014f982fdfbd6ec47938f504b0
提交 | 用户 | age
25ab64 1 // -----------------------------------------------------------------------------------------------------------
F 2 // Functions for search
3 // -----------------------------------------------------------------------------------------------------------
4 MS.Search;
5 // -----------------------------------------------------------------------------------------------------------
6 // Calls DoSearch asynchronous
7 TGP.SearchRows = function(action,noshow,nosync){
8 if(this.InSearchRows) return;
9 this.InSearchRows = 1;
10 if(this.EditMode && this.EndEdit(1)==-1){ this.InSearchRows = 0; return; }
11 if(this.Paging==3 && !(this.OnePage&4) && !this.CanReload()) { this.InSearchRows = 0; return; }
12 var T = this;
13 function search(){ 
14    T.DoSearch(action,noshow);
15    T.HideMessage();
16    MS.Sync;
17    if(T.Sync["search"] && !nosync){
18       for(var i=0;i<Grids.length;i++){
19          var G = Grids[i];
20          if(G&&G!=T&&!G.Loading&&G.SyncId==T.SyncId&&G.Sync["search"]) {
21             for(var r=T.XS.firstChild,i1=0;r;r=r.nextSibling){
22                if(r.Kind=="Search"){
23                   var rr = G.GetRowById(r.id);
24                   if(!rr && !r.id) for(var i2=0,rr=G.XS.firstChild;rr;rr=r.nextSibling) if(rr.Kind=="Search") if(i2++==i1) break;
25                   if(rr){
26                      for(var j=0;j<r.Cells.length;j++){
27                         var c = r.Cells[j];
28                         if(rr[c]!=r[c]) { rr[c] = r[c]; G.RefreshCell(rr,c); }
29                         }
30                      }
31                   
32                   i1++;
33                   }
34                }
35             G.SearchExpression = T.SearchExpression;
36             G.SearchMethod = T.SearchMethod;
37             G.SearchCells = T.SearchCells;
38             G.SearchCaseSensitive = T.SearchCaseSensitive;
39             G.SearchDefs = T.SearchDefs;
40             G.SearchCols = T.SearchCols;
41             G.SearchRows(action,noshow,1);
42             }
43          }
44       }
45    ME.Sync;
46      }
47 if(this.RowCount<this.SynchroCount || action=="Find" || action=="FindPrev") search();  
48 else {
49    this.ShowMessage(this.GetText("Search"));
50    setTimeout(search,10);
51      }
52 this.InSearchRows = 0;     
53 }
54 // -----------------------------------------------------------------------------------------------------------
55 TGP.SearchIn = function(r,A,Z,c,sn,i){
56 var tn = 0; if(sn) { tn = this.GetType(r,c); tn = tn=="Int" || tn=="Float"; }
57 var v = Get(r,c+"FilterValue");
58 if(v==null) v = tn ? this.GetValue(r,c) : this.GetString(r,c,2);
59 if(Grids.OnGetFilterValue) { var tmp = Grids.OnGetFilterValue(this,r,c,v); if(tmp!=null) v = tmp; }
60 if(tn) { 
61    Z[i] = A[i]-0==v;
62    if(!Z[i]){
63       if(sn==3) {
64          if(A[i]>=0) v = Math.abs(v);
65          if(!(A[i]%1)) v = Math.floor(v);
66          Z[i] = A[i]-0==v;
67          }
68       else if(sn==2 && !(A[i]%1)) Z[i] = A[i]-0==Math.round(v);
69       }
70    }
71 else if(!v) Z[i] = A[i]=="#";
72 else { 
73    v += "";
74    if(!this.SearchCaseSensitive) v = v.toLocaleLowerCase ? v.toLocaleLowerCase() : v.toLowerCase();
75    if(this.SearchWhiteChars) v = v.replace(GetWhiteChars(this.SearchWhiteChars),"");
76    MS.CharCodes; if(this.SearchCharCodes) v = UseCharCodes(v,this.SearchCharCodes); ME.CharCodes;
77    Z[i] = A[i]?v.indexOf(A[i])>=0:0;
78    }
79 }
80 // -----------------------------------------------------------------------------------------------------------
81 TGP.GetSearchValue = function(str,row,col,txt){
82 var v = row[col+"FilterValue"]; if(v==null && row.Def) v = row.Def[col+"FilterValue"];
83 if(v==null) {
84    if(txt) v = this.GetString(row,col,2);
85    else { v = row[col]; if(v==null && row.Def) v = row.Def[col]; }
86    }
87 if(Grids.OnGetFilterValue) { var tmp = Grids.OnGetFilterValue(this,row,col,v); if(tmp!=null) v = tmp; }
88 if(v-0||v=="0"||!v){
89    if(str) return v+"";
90    return v||v=="0"?v-0:"";
91    }
92 if(!this.SearchCaseSensitive) v = v.toLocaleLowerCase ? v.toLocaleLowerCase() : v.toLowerCase();
93 if(this.SearchWhiteChars) v = v.replace(GetWhiteChars(this.SearchWhiteChars),"");
94 MS.CharCodes; if(this.SearchCharCodes) v = UseCharCodes(v,this.SearchCharCodes); ME.CharCodes;
95 return v;
96 }
97 // -----------------------------------------------------------------------------------------------------------
98 TGP.BuildSearch = function(V,back){
99 var spec = !this.SearchCaseSensitive || this.SearchWhiteChars || this.SearchCharCodes;
100 var cel = this.SearchCells; 
101 var hid = this.SearchHidden;
102
103 // --- Autodetect method ---
104 var Method = this.SearchMethod;
105 if(!Method){ 
106    if(V.search(/[\(\)\=\!\<\>]/)>=0) Method = 2;
107    }
108
109 // --- SearchDefs ---
110 var DS = "";
111 var Defs = this.SearchDefs;
112 if(Defs){
113    Defs = Defs.split(/[,;]/);
114    for(var i=0;i<Defs.length;i++) {
115       if(!this.Def[Defs[i]]) { MS.Debug;this.Debug(2,"Unknown default ",Defs[i]," in SearchDefs");ME.Debug; continue; }
116       DS+=(DS?":1,":"")+Defs[i];
117       }
118    if(DS) DS = "if(!{"+DS+":1}[Row.Def.Name]) return -1;";
119    }
120
121 if(!Method || Method==2 || Method==4){
122    function IsText(c){
123       return c>=48 && c<=57 
124          || c>=65 && c<=90  
125          || c>=97 && c<=122 
126          || c==46 || c==44  
127          || c==95             
128          || c==34 || c==39  
129          || c==35 || c==36 || c==64  
130          || c>=128
131       }
132    var A = [], B = [], C = []; 
133    for(var p=0,i=0,t=-1;V;i++){
134       var c = V.charCodeAt(i);
135       if(!c){
136          if(V && V.charCodeAt(0)>32) A[p++] = V;
137          break;
138          }
139       if(c<=32 && !i) { V=V.slice(1); i=-1; continue; }
140       var x = IsText(c);
141       if(!i){
142          if(c==34 || c==39){ 
143             for(i++;;i++){
144                var d = V.charCodeAt(i);
145                if(!d) break;
146                if(d==c){ 
147                   if(V.charCodeAt(i+1)==c) V = V.slice(0,i) + V.slice(i+1); 
148                   else break;
149                   }
150                }
151             }
152          t=x;
153          }
154       else if(t && !x || !t && x || c<=32){ 
155          A[p++] = V.slice(0,i);
156          V = V.slice(i);
157          i=-1;
158          }
159       }
160       
161    function Replace(N,by,by2,nclr){ 
162       N = (N+"").split(",");
163       for(var i=0;i<N.length;i++){
164          var lwr = N[i].toLowerCase();
165          for(var j=0;j<A.length;j++){
166             var s = A[j].toLowerCase();
167             if(lwr==s && B[j]==null && (!A[j+1]||A[j+1].charAt(0)!='(')){
168                B[j] = by;
169                C[j] = by2;
170                
171                }
172             if(lwr.indexOf(s)==0){ 
173                for(var x=j+1;s.length<lwr.length&&A[x];x++) s+=' '+A[x].toLowerCase();
174                if(lwr==s && B[j]!="" && (B[j]==null || x-j>1)){
175                   B[j] = by; 
176                   if(by2) A[j]=by2;
177                   while(x>j+1){ 
178                      B[--x]="";
179                      if(!nclr) C[x]="";
180                      }
181                   
182                   }
183                }
184             }
185          }
186       }
187       
188    for(var c in this.Cols) Replace(this.GetCaption(c,1),this.This+".GetSearchValue(0,Row,'"+c+"',"+(this.Cols[c].SearchText?1:0)+")",null,1);
189    
190    Replace(this.GetText("Starts"),"|*");
191    Replace(this.GetText("Ends"),"*|");
192    Replace(this.GetText("Contains"),"*|*");
193    
194    if(!Method){ 
195       for(var i=0,a=0;i<B.length;i++) if(B[i]) a++;
196       if(a>=2) Method = 2;
197       else Method = 1;
198       }
199
200    if(Method==2 || Method==4){   
201       var GN = {"parseInt":1,"parseFloat":1,"escape":1,"unescape":1,"isFinite":1,"isNaN":1,"Date":1,"TGGet":1,"TGIs":1};
202       Replace(this.GetText("And"),"&&");
203       Replace(this.GetText("Or"),"||");
204       Replace(this.GetText("Not"),"!");
205       Replace("<>","!=");
206    
207       for(var i=0;i<A.length;i++){
208          var s = A[i], c = s.charCodeAt(0);
209          if(c==34 || c==39){ 
210             if(spec){ 
211                function Test(idx){ 
212                   var a = B[idx]?B[idx]:A[idx];
213                   return a=="=="||a=="!="||a==">"||a==">="||a=="<"||a=="<="||a=="|*"||a=="*|"||a=="*|*";
214                   }
215                if(Test(i-1) || Test(i+1)) {
216                   if(!this.SearchCaseSensitive) A[i] = A[i].toLocaleLowerCase ? A[i].toLocaleLowerCase() : A[i].toLowerCase();
217                   if(this.SearchWhiteChars) A[i] = A[i].replace(GetWhiteChars(this.SearchWhiteChars),"");
218                   MS.CharCodes; if(this.SearchCharCodes) A[i] = UseCharCodes(A[i],this.SearchCharCodes); ME.CharCodes;
219                   }
220                }
221             continue;               
222             }
223          if(B[i]!=null) continue; 
224          var idx = s.indexOf('=');
225          if(idx>=0){ 
226             var c1 = idx ? s.charAt(idx-1) : null;
227             if(c1=='=' || c1=='>' || c1=='<' || s.charAt(idx+1)=='=') continue; 
228             B[i]=s.slice(0,idx)+"="+s.slice(idx);
229             }
230          else if(c>=48 && c<=57){ 
231             if(s.indexOf(',')>=0) B[i] = s.replace(',','.'); 
232             }
233          else if(IsText(c)){ 
234             var j = i; s = "";
235             for(;i<A.length;i++){
236                if(!IsText(A[i].charCodeAt(0)) || B[i]!=null) break;
237                var v = A[i];
238                if(spec && v){
239                   if(!this.SearchCaseSensitive) v = v.toLocaleLowerCase ? v.toLocaleLowerCase() : v.toLowerCase();
240                   if(this.SearchWhiteChars) v = v.replace(GetWhiteChars(this.SearchWhiteChars),"");
241                   MS.CharCodes; if(this.SearchCharCodes) v = UseCharCodes(v,this.SearchCharCodes); ME.CharCodes;
242                   }
243                s += ' '+v;
244                }
245             s = s.slice(1); 
246             if(A[i] && A[i].charCodeAt(0)==40) {  
247                if(Method==2 && A[j].search(/Math\.|Date\./)!=0 && !GN[A[j]]) for(;j<i;j++) A[j] = "";
248                continue;
249                }
250             if(Method==4);
251             else if(s.indexOf('"')<0) s = '"'+s+'"';
252             else if(s.indexOf("'")<0) s = "'"+s+"'";
253             else s = '"'+s.replace('"','""')+'"';
254             B[j] = s;
255             C[j] = s;
256             for(j++;j<i;j++) { B[j]=""; C[j]=""; }
257             i--;
258             }
259          }
260       
261       MS.Date;
262       for(var i=0;i<A.length;i++){
263          if(A[i].search(/^\'?\"?\d{1,2}[\/\-\:\.]\d{1,2}([\/\-\:\.]\d{1,4})?(..?\d{1,2}[\:\-]\d{1,2}([\-\:]\d{1,2})?)?\'?\"?$/)>=0 && A[i].search(/^\d*.\d*$/)<0){
264             var s = A[i];
265             if(s.charAt(0)=='"' || s.charAt(0)=="'") s=s.slice(1,s.length-1);
266             B[i] = this.Lang.Format.StringToDate(s,this.SearchDateFormat);
267             var c = s.charAt(0);
268             if(c!='"' && c!="'") s='"'+s+'"';
269             C[i] = s;
270             }
271          if(A[i]=='/' || A[i]=='-' || A[i]==':'){
272             if(!i || B[i-1]!=null || B[i+1]!=null || isNaN(A[i-1]-0) || isNaN(A[i+1]-0)) continue; 
273             var j = A[i+2]==A[i] && !isNaN(A[i+3]) && B[i+3]==null ? i+4 : i+2, j2=null;
274             if(A[j+1]==':' && B[j]==null && B[j+2]==null && !isNaN(A[j]-0) && !isNaN(A[j+2]-0)) { 
275                j2=j;
276                j = A[j+3]==':' && !isNaN(A[j+4]) && B[j+4]==null ? j+5 : j+3;
277                }
278             for(var k=i,SS="";k<j;k++){ 
279                if(k==j2) SS+=' ';
280                SS+=A[k]; B[k]=""; C[k]=""
281                }
282             
283             B[i-1] = this.Lang.Format.StringToDate(A[i-1]+SS,this.SearchDateFormat);
284             
285             C[i-1] = '"'+A[i-1]+SS+'"';
286             if(A[i]==':'){ 
287                if(i>1 && B[i-2]-0){
288                   var c = A[i-2].charAt(0);
289                   if(c!='"' && c!="'"){ 
290                      B[i-2] = this.Lang.Format.StringToDate(A[i-2]+" "+A[i-1]+SS,this.SearchDateFormat);
291                      B[i-1] = "";
292                      C[i-2] = '"'+A[i-2]+" "+A[i-1]+SS+'"';
293                      C[i-1] = "";
294                      }
295                   }
296                }
297             
298             }
299          }
300       ME.Date;
301          
302       for(var i=0;i<A.length;i++){ 
303          var cp = null;
304          switch(B[i]){
305             case '|*' : 
306                B[i]='.indexOf(';
307                cp = "==0";
308                if(i && B[i-1] && B[i-1]=='!'){ B[i-1]=""; cp = "!=0";   }
309                if(B[i+1]) B[i+1] += ")"+cp;
310                else B[i+1] = A[i+1] + ")"+cp;
311                break;
312             case '*|' : 
313                B[i]='.lastIndexOf(';
314                cp = "==";
315                if(i && B[i-1] && B[i-1]=='!'){ B[i-1]=""; cp = "!=";   }
316                var v1 = B[i-1]?B[i-1]:A[i-1], v2 = B[i+1]?B[i+1]:A[i+1];
317                B[i+1] = v2+")"+cp+"("+v1+".length-("+v2+"+'').length)";
318                break;
319             case '*|*' : 
320                B[i]='.indexOf(';
321                cp = ">=0";
322                if(i && B[i-1] && B[i-1]=='!'){ B[i-1]=""; cp = "<0";   }
323                if(B[i+1]) B[i+1] += ")"+cp;
324                else B[i+1] = A[i+1] + ")"+cp;
325                break;
326             }
327          if(cp && B[i-1]) B[i-1] = (B[i-1]+"").replace("GetSearchValue(0","GetSearchValue(1");
328          }
329       
330       var S = "", NS = "";
331       for(var i=0;i<A.length;i++){
332          S += (i&&Method!=4?" ":"")+(B[i]!=null ? B[i] : A[i]);
333          NS += (i&&C[i]!=""&&Method!=4?" ":"")+(C[i]!=null ? C[i] : A[i]);    
334          }
335       this.SearchExpression = NS;
336       if(Grids.OnRowSearch) S = DS+"var found="+S+",tmp=TGGrids.OnRowSearch("+this.This+",Row,null,found,arguments.callee,UserVal);return tmp!=null?tmp:found;";
337       else S = DS+"return "+S+";";
338       }
339    }
340    
341 // --- Google search ---
342 if(Method==1 || Method==3){
343    var num = this.SearchNumbers; if(num==null) num = Method==1 ? 1 : 0;
344    V = this.SearchExpression; 
345    
346    // --- Google search ---
347    if(Method==1){
348       var S = '([^\\"\\s]*)?\\s*(\"([^\\"]*)\")?\\s*'; 
349       for(var i=0;i<4;i++) S+=S;
350       S = "^\\s*"+S+"$";
351       var X = "", P = [], A = [], p = 0;
352       if(V){
353          if(!(V.split('"').length%2)) return null; 
354             V = V.match(S);
355             if(!V) return null; 
356          var Neg = []; 
357          for(var i=1;i<V.length;i++) if(V[i]) { if(V[i].charAt(0)=='"') Neg[p] = 1; else P[p++] = V[i]; } 
358          for(var i=0,x=0;i<p;i++){ 
359                if(P[i]=="OR") continue;
360             if(i) X += P[i-1]=="OR" ? "||" : "&&";
361             if(P[i+1]=="OR" && (!i || P[i-1]!="OR")) X+="(";
362             if(P[i].charAt(0)=='-' && !Neg[i]){ X+="!"; P[i]=P[i].slice(1); }
363             X+="Z["+x+"]";
364             A[x++] = P[i];
365             if(i && P[i+1]!="OR" && P[i-1]=="OR") X+=")";
366             
367             }
368          }
369       }
370
371    // --- Exact Search ---      
372    else {
373       var A = [V], X = "Z[0]";
374       }   
375       
376    // --- SearchCols ---
377    var SC = this.SearchCols, Cols = [];
378    if(SC){
379       SC = SC.split(/[,;]/);
380       for(var i=0;i<SC.length;i++) { var C = this.Cols[SC[i]]; if(C && C.CanSearch && (C.Visible||hid)) Cols[Cols.length] = '\"'+SC[i]+'\"'; }
381       }
382    else for(var c in this.Cols){ var C = this.Cols[c]; if(C && C.CanSearch && (C.Visible||hid)) Cols[Cols.length] = '\"'+c+'\"'; }
383    
384    var S = DS;
385    S+="var Z=[];";
386    S+="var A=[";
387    for(var i=0;i<A.length;i++) {
388       var v = A[i];
389       if(!this.SearchCaseSensitive) v = v.toLocaleLowerCase ? v.toLocaleLowerCase() : v.toLowerCase();
390       if(this.SearchWhiteChars) v = v.replace(GetWhiteChars(this.SearchWhiteChars),"");
391       MS.CharCodes; if(this.SearchCharCodes) v = UseCharCodes(v,this.SearchCharCodes); ME.CharCodes;
392       S += (i?",":"")+"\""+v.replace(/[\"\\]/g,"\\$&")+"\"";
393       }
394    S+="];";
395
396    // --- Search in cell ---
397    if(cel){
398       S+="var Cols=["+Cols.join(",")+"],i="+(back?"Cols.length-1":"0")+";";
399       S+="if(Col){";
400       S+=(back?"for(;i>=0;i--)":"for(;i<Cols.length;i++)")+"if(Cols[i]==Col) { i"+(back?"--":"++")+"; break; }";
401       S+="}";
402       S+=(back?"for(;i>=0;i--)":"for(;i<Cols.length;i++)")+"{";
403       S+="for(var k=0;k<A.length;k++) "+this.This+".SearchIn(Row,A,Z,Cols[i],"+num+",k);";
404       S+="var found="+X+";";
405       if(Grids.OnRowSearch) S+="var tmp=TGGrids.OnRowSearch("+this.This+",Row,Cols[i],found,arguments.callee,UserVal);if(tmp!=null)found=tmp;";
406       S+="if(found==-1) return -1;";
407       S+="if(found==1) return Cols[i];"; 
408       S+="if(found) return found;";      
409       S+="} return 0;";
410       }
411    // --- Search in row ---
412    else {
413       S+="var Cols=["+Cols.join(",")+"];";
414       S+="for(var k=0;k<A.length;k++){";
415       S+="for(var j=0;j<Cols.length;j++){"
416       S+=this.This+".SearchIn(Row,A,Z,Cols[j],"+num+",k);";
417       S+="if(Z[k]) break;}}";
418       if(Grids.OnRowSearch) S += "var found="+X+",tmp=TGGrids.OnRowSearch("+this.This+",Row,null,found,arguments.callee,UserVal);return tmp!=null?tmp:found;";
419       else S += "return "+X+";";
420       }
421    }
422
423 if(Try) {
424    var F = new Function("Row","Col","UserVal",S); 
425    return [F,Method];
426    }
427 else if(Catch){
428    return null;
429    }
430 }
431
432 // -----------------------------------------------------------------------------------------------------------
433 // Searches in grid according to parameters Search...
434 TGP.DoSearch = function(action,noshow,noundo){
435 if(!this.Searching || this.Locked["search"]) return;
436 if(action=="Last") action = this.SearchActionLast;
437 if(Grids.OnSearch && Grids.OnSearch(this,action,!noshow)) return;
438 if(action=="Help"){
439    this.Alert("SearchHelp");
440    return;
441    }
442 if(this.Undo&16&&!noundo&&action!="Find"&&action!="FindPrev") this.AddUndo({Type:"Search",OAction:this.SearchAction,Action:action});
443
444 if(action=="Refresh"){
445    var old = this.SearchAction;
446    if(old) {
447       this.DoSearch("Clear",old=="Filter"?noshow:1); 
448       this.DoSearch(old,noshow);
449       }
450    else this.SaveCfg();
451    return;
452    }
453
454 var V = this.SearchExpression; if(!V && V!==0) V = ""; else V += ""; this.SearchExpression = V;
455 if(this.SearchColorNew && V!=this.SearchExpressionOld){ this.SearchColorIdx++; this.SearchColorNew = 0; }
456 this.SearchExpressionOld = V;
457
458 var oldaction = this.SearchAction;
459 if(!V && action!="Clear") { this.SearchActionLast = action; action = "Clear"; }
460 if(this.SearchAction!=action){
461    this.ClearSearch(noshow);
462    if((this.Undo&18)==18&&!noundo&&this.SearchAction=="Select") this.MergeUndo();
463    this.SearchAction = action;
464    
465    }
466 if(action=="Clear"){
467    this.SearchAction="";
468    
469    this.CalculateSpaces(!noshow);
470    this.SaveCfg();
471    return;
472    }
473 this.SearchActionLast = this.SearchAction;
474
475 // --- server paging ---
476 MS.Paging;
477 if(this.formid!=9646&&this.Paging==3 && (!(this.OnePage&4) || this.AllPages)){//*****增加对9646的排除
478    this.Calculate(!noshow,1,1);
479    this.SaveCfg();
480    this.ReloadBody(null,0,"Search");
481    if(Grids.OnSearchFinish) Grids.OnSearchFinish(this,action,!noshow);
482    return 1;
483    }
484 ME.Paging;
485
486 MS.Debug; this.Debug(4,"Searching in grid, action "+action); this.StartTimer("Search"); ME.Debug;
487
488 // --- Build search ---
489 var cel = this.SearchCells, exp = this.SearchExpand, foc = this.SearchFocused; 
490 var F = this.BuildSearch(V,action&&action.indexOf("FindPrev")>=0);
491 if(!F){
492    this.Alert("SearchError");
493    this.SearchAction = "";
494    return;
495    }
496 var Method = F[1]; F = F[0];
497
498 // --- Run Action ---
499 var cnt = null; this.SearchCount = null;
500 if(this.Searched && action) {
501    action = action.split(/[,;]/);
502    for(var i=0;i<action.length;i++){
503       switch(action[i]){
504          case "Filter" : 
505             MS.Filter;
506             if(this.SearchCount==null) this.SearchCount = "";
507             this.Filter2 = F; 
508             var F1 = null; if(!this.Filtered) { F1 = this.Filter1; this.Filter1 = null; this.Filtered = 1; }
509             this.DoFilterT(noshow ? 0 : (BIE8Strict&&this.RowSpan || this.Paging ? 2 : 1));
510             if(F1){ this.Filter1 = F1; this.Filtered = 0; }
511             cnt = this.FilterCount;
512             ME.Filter;
513             break;
514          case "Select" :
515             MS.Select;
516             MS.Animate; var S = this.AnimateRows && !this.SuppressAnimations ? [] : null, N = S ? [] : null; ME.Animate;
517             var zal = this.CalculateSelected; this.CalculateSelected = null; cnt = 0;
518             var cs = this.ClearSelected, typ = cs&8?1:0, flt = cs&2, hid = cs&4; 
519             for(var r=this.GetFirst(typ);r;r=this.GetNext(r,typ)){
520                if(flt&&r.Filtered||hid&&!r.Visible&&!r.Filtered&&!r.Deleted||!this.CanSelect(r)) continue;
521                try { var found = F(r); } catch(e) { found = 0; }
522                MS.RowSpan; if(r.RowSpan && typeof(found)=="string" && r[found+"RowSpan"]==0) found = 0; ME.RowSpan;
523                found  = typeof(found)=="string" || found>0;
524                if(found) cnt++;
525                var sel = r.Selected&this.SelAnd;
526                if(sel && !found) {
527                   this.SelectRow(r); 
528                   MS.Animate; if(N) N[N.length] = r; ME.Animate;
529                   }
530                else if(!sel && found){
531                   this.SelectRow(r);
532                   if(exp) this.ExpandParents(r);
533                   MS.Animate; if(S) S[S.length] = r; ME.Animate;
534                   }
535                }
536             this.SearchCount = cnt;
537             this.CalculateSpaces(!noshow);
538             this.CalculateSelected = zal;
539             if((this.Undo&18)==18&&!noundo) this.MergeUndo();
540             MS.Animate; if(S) this.AnimRows([S,"SelectRows"],[N,"DeselectRows"]); ME.Animate;
541             MX.Select;
542             if(!this.SelectRow) NoModule("Select");
543             ME.Select;
544             break;
545          case "Mark" :
546             MS.Color;
547             this.SearchColorNew = 1; this.SearchActionMark = 1; cnt = 0;
548             if(!this.SearchColorIdx) this.SearchColorIdx = 1;
549             var clear = this.SearchColorIdx > this.SearchMaxMark;
550             if(clear) this.SearchColorIdx = 1;
551             
552             var Color = this.Colors["Found"+this.SearchColorIdx];
553             if(!Color){ Color = this.Colors["Found1"]; this.SearchColorIdx=1; }
554             
555             if(cel && (Method==1||Method==3)) for(var r=this.GetFirstVisible();r;r=this.GetNextVisible(r)){ 
556                if(clear) this.ClearMarkRow(r);
557                try { var found = F(r);} catch(e) { found = 0; }
558                while(found && typeof(found)=="string"){
559                   MS.RowSpan; if(r.RowSpan && r[found+"RowSpan"]==0){ found = F(r,found); continue; } ME.RowSpan;
560                   cnt++;
561                   var f = found;
562                   MS.ColSpan; if(r.Spanned && r[f+"Span"]==0) f = this.GetPrevCol(f,r); ME.ColSpan;
563                   r[f+"MarkColor"] = Color;
564                   MS.Animate; if(r.Animating||r.AnimatingCels&&r.AnimatingCells[f]) this.AnimCell(r,f); ME.Animate;
565                   if(this.SearchClass) { 
566                      r[f+"MarkClass"] = "Found"+this.SearchColorIdx;
567                      this.RefreshCellAnimate(r,f,"Mark");
568                      }
569                   else this.ColorCell(r,f);
570                   if(exp) this.ExpandParents(r);
571                   found = F(r,found);
572                   r.Marked = 1;
573                   }
574                }
575             else for(var r=this.GetFirstVisible();r;r=this.GetNextVisible(r)){
576                if(clear) this.ClearMarkRow(r);
577                try { var found = F(r)>0;} catch(e) { found = 0; }
578                if(found){
579                   cnt++;
580                   r.MarkColor = Color;
581                   r.MarkClass = "Found"+this.SearchColorIdx;
582                   this.ColorRow(r);
583                   if(exp) this.ExpandParents(r);
584                   }
585                }
586             this.SearchCount = cnt;
587             this.CalculateSpaces(1);
588             ME.Color;   
589             break;
590          case "Find" :
591          case "FindPrev":
592             var start = this.FRow&&!this.FRow.Fixed&&(foc || oldaction&&oldaction.indexOf("Find")>=0) ? this.FRow: null, back = action[i]=="FindPrev", found = 0; 
593             cnt = null;
594             if(this.FRow && this.FRow.Space!=null) this.Focus();
595             if(cel && (Method==1||Method==3) && start && this.FCol){ 
596                var fcol = this.FCol;
597                do {
598                   try { var found = F(start,fcol);} catch(e) { found = 0; break; }
599                   if(typeof(found)=="string"){ 
600                      MS.ColSpan; if(start.Spanned && start[found+"Span"]==0) found = this.GetPrevCol(found,start); ME.ColSpan;
601                      if(found==fcol){ found = 0; break; }
602                      if(!this.CanFocus(start,found)){ fcol = found; continue; }
603                      MS.Animate; if(start.Animating||start.AnimatingCels&&start.AnimatingCells[found]) this.AnimCell(start,found); ME.Animate;
604                      this.Focus(start,found,null,null,1);
605                      MS.Animate; this.AnimCell(start,found,"Find",null,null,null,1); ME.Animate;
606                      break;
607                      }
608                   else if(found<0) found = 0;
609                   } while(found);
610                }
611             if(found) break;
612             var r = back ? (start?this.GetPrevVisible(start):this.GetLastVisible()) : (start?this.GetNextVisible(start):this.GetFirstVisible());
613             for(;!found&&r!=start;r=back?this.GetPrevVisible(r):this.GetNextVisible(r)){
614                if(!r){
615                   if(start && foc>1){
616                      if(foc==3 && !this.Confirm(this.GetAlert(back?"SearchEnd":"SearchStart"))) { found = 1; break; }
617                      r = back ? this.GetLastVisible() : this.GetFirstVisible();
618                      }
619                   else break;
620                   }
621                var fcol = null;
622                do {
623                   try { var found = F(r,fcol);} catch(e) { found = 0; }
624                   if(found){
625                      if(typeof(found)=="string"){ 
626                         MS.ColSpan; if(r.Spanned && r[found+"Span"]==0) found = this.GetPrevCol(found,r); ME.ColSpan;
627                         if(found==fcol){ found = 0; break; }
628                         if(!this.CanFocus(r,found)){ fcol = found; continue; }
629                         MS.Animate; if(r.Animating||r.AnimatingCels&&r.AnimatingCells[found]) this.AnimCell(r,found); ME.Animate;
630                         this.Focus(r,found,null,null,1);
631                         MS.Animate; this.AnimCell(r,found,"Find",null,null,null,1); ME.Animate;
632                         break;
633                         }
634                      else if(found>0){
635                         if(!this.CanFocus(r,this.FCol)){ found = 0; break; }
636                         this.Focus(r,this.FCol,null,null,1);
637                         MS.Animate; this.AnimCell(r,this.FCol,"Find",null,null,null,1); ME.Animate;
638                         break;
639                         }
640                      else found = 0;
641                      }
642                   } while(found);
643                }
644             if(!found && this.SearchNotFound) {
645                if(this.SearchNotFound==1) this.Alert("NotFound");
646                else this.ShowMessageTime(this.GetAlert("NotFound"),this.SearchNotFound>10||this.SearchNotFound<0?this.SearchNotFound:0);
647                }
648             this.CalculateSpaces(1);
649             break;
650          }
651       }
652    }
653 if(!this.Loading) this.SaveCfg();
654 if(this.SearchAlertFound && cnt!=null){
655    var txt = this.GetAlert(cnt?"FoundResults":"NotFound").replace("%d",cnt);
656    if(txt){
657       if(this.SearchAlertFound==1) this.Alert(txt);
658       else this.ShowMessageTime(txt,this.SearchAlertFound>10||this.SearchAlertFound<0?this.SearchAlertFound:0);
659       }
660    }
661 if(Grids.OnSearchFinish) Grids.OnSearchFinish(this,action,!noshow);
662 MS.Debug; 
663 this.StopTimer("Search"); 
664 if(!noshow) this.Debug(4,"Search completed in ",this.GetTimer("Search")," ms");
665 ME.Debug;
666 return 1;
667 }
668 // -----------------------------------------------------------------------------------------------------------
669 TGP.ClearSearch = function(noshow){
670 MS.Debug; 
671 if(this.Searched && this.SearchAction && !noshow) { 
672    this.Debug(4,"Clearing search action "+this.SearchAction);
673    this.StartTimer("Search"); 
674    }
675 ME.Debug;
676 this.SearchCount = null;
677 if(this.Searched && this.SearchAction) {
678    var action = this.SearchAction.split(/[,;]/);
679    for(var i=0;i<action.length;i++){
680       switch(action[i]){
681          case "Filter" :
682               MS.Filter;
683             this.Filter2 = null; 
684             var F1 = null; if(!this.Filtered) { F1 = this.Filter1; this.Filter1 = null; this.Filtered = 1; }
685             this.DoFilterT(noshow ? 0 : (BIE8Strict&&this.RowSpan || this.Paging ? 2 : 1));
686             if(F1){ this.Filter1 = F1; this.Filtered = 0; }
687             ME.Filter;
688             break;
689          case "Select" :
690             MS.Select; 
691             MS.Animate; var N = this.AnimateRows && !this.SuppressAnimations ? [] : null; ME.Animate;
692             var and = this.SelAnd, zal = this.CalculateSelected; this.CalculateSelected = null;
693             var cs = this.ClearSelected, typ = cs&8?1:0, flt = cs&2, hid = cs&4; 
694             for(var r=this.GetFirst(typ);r;r=this.GetNext(r,typ)) if(r.Selected&and){
695                if(flt&&r.Filtered||hid&&!r.Visible&&!r.Filtered&&!r.Deleted||!this.CanSelect(r)) continue;
696                this.SelectRow(r);
697                MS.Animate; if(N) N[N.length] = r; ME.Animate;
698                }
699             this.CalculateSelected = zal;
700             MS.Animate; if(N) this.AnimRows(N,"DeselectRows"); ME.Animate;
701             ME.Select;   
702             break;
703          case "Find" :
704          case "FindPrev":
705             if(action=="Clear") this.Focus(); 
706             break;
707          case "Mark" :
708             MS.Color;
709             for(var r=this.GetFirstVisible();r;r=this.GetNextVisible(r)) this.ClearMarkRow(r);
710             this.SearchColorIdx = 0; this.SearchColorNew = 1;
711             ME.Color;
712             this.SearchActionMark = 0;
713             break;
714          }
715       }
716    }
717 MS.Debug; 
718 if(this.Searched && this.SearchAction && !noshow) { 
719    this.StopTimer("Search"); 
720    this.Debug(4,"Clearing search completed in ",this.GetTimer("Search")," ms");
721    }
722 ME.Debug;   
723 }
724 // -----------------------------------------------------------------------------------------------------------
725 TGP.ClearMarkRow = function(r){
726 if(r.MarkColor){
727    r.MarkColor = null;
728    r.MarkClass = null;
729    MS.Animate; if(r.Animating||r.AnimatingCells) this.AnimRow(r); ME.Animate;
730    this.ColorRow(r);
731    }
732 if(r.Marked){
733    for(var c in this.Cols){
734          if(r[c+"MarkColor"]){
735          r[c+"MarkColor"] = null;
736          if(this.SearchClass) { 
737             r[c+"MarkClass"] = null;
738             this.RefreshCellAnimate(r,c,"Mark");
739             }
740          else this.ColorCell(r,c);
741          }
742       }
743    r.Marked = null;
744    }
745 }
746
747 // -----------------------------------------------------------------------------------------------------------
748 TGP.ActionSearchOff = function(dummy,T,noundo){
749 if(!this.Searching || !this.Searched || this.Locked["search"]) return false;
750 if(T) return !!this.SearchAction;
751 if(this.Undo&16&&!noundo) this.AddUndo({Type:"Searched",OSearched:1,Searched:0});
752 this.ClearSearch();
753 this.Searched = false;
754 for(var r=this.XS.firstChild;r;r=r.nextSibling) if(r.Kind=="Search") this.UpdatePanel(r);
755 this.CalculateSpaces(1);
756 this.SaveCfg();
757 return true;
758 }
759 // -----------------------------------------------------------------------------------------------------------
760 TGP.ActionSearchOn = function(dummy,T,noundo){
761 if(!this.Searching || this.Searched || this.Locked["search"]) return false;
762 if(T) return !!this.SearchAction;
763 if(this.Undo&16&&!noundo) this.AddUndo({Type:"Searched",OSearched:0,Searched:1});
764 this.Searched = true;
765 if(this.SearchAction) this.DoSearch(this.SearchAction,0,1);
766 for(var r=this.XS.firstChild;r;r=r.nextSibling) if(r.Kind=="Search") this.UpdatePanel(r);
767 this.CalculateSpaces(1);
768 this.SaveCfg();
769 return true;
770 }
771 // -----------------------------------------------------------------------------------------------------------
772 ME.Search;
773