Subversion Repositories eFlore/Archives.cel-v1

Rev

Rev 8 | Rev 10 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 8 Rev 9
1
/*
1
/*
2
Auto-Completion Textbox for GWT
2
Auto-Completion Textbox for GWT
3
Copyright (C) 2006 Oliver Albers http://gwt.components.googlepages.com/
3
Copyright (C) 2006 Oliver Albers http://gwt.components.googlepages.com/
4
 
4
 
5
This library is free software; you can redistribute it and/or
5
This library is free software; you can redistribute it and/or
6
modify it under the terms of the GNU Lesser General Public
6
modify it under the terms of the GNU Lesser General Public
7
License as published by the Free Software Foundation; either
7
License as published by the Free Software Foundation; either
8
version 2.1 of the License, or (at your option) any later version.
8
version 2.1 of the License, or (at your option) any later version.
9
 
9
 
10
This library is distributed in the hope that it will be useful,
10
This library is distributed in the hope that it will be useful,
11
but WITHOUT ANY WARRANTY; without even the implied warranty of
11
but WITHOUT ANY WARRANTY; without even the implied warranty of
12
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
Lesser General Public License for more details.
13
Lesser General Public License for more details.
14
 
14
 
15
You should have received a copy of the GNU Lesser General Public
15
You should have received a copy of the GNU Lesser General Public
16
License along with this library; if not, write to the Free Software
16
License along with this library; if not, write to the Free Software
17
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
 
18
 
19
*/
19
*/
20
package org.tela_botanica.client;
20
package org.tela_botanica.client;
21
 
21
 
22
 
22
 
23
// TODO : traiter latence (augmenter en fonction rapidité saisie + texte vide)
23
// TODO : traiter latence (augmenter en fonction rapidité saisie + texte vide)
24
// TODO : traitement espace apres l'espece (%20)
24
// TODO : traitement espace apres l'espece (%20)
25
 
25
 
26
import com.google.gwt.user.client.HTTPRequest;
26
import com.google.gwt.user.client.HTTPRequest;
27
import com.google.gwt.user.client.ResponseTextHandler;
27
import com.google.gwt.user.client.ResponseTextHandler;
28
import com.google.gwt.user.client.ui.KeyboardListener;
28
import com.google.gwt.user.client.ui.KeyboardListener;
29
import com.google.gwt.user.client.ui.ListBox;
29
import com.google.gwt.user.client.ui.ListBox;
30
import com.google.gwt.user.client.ui.PopupPanel;
30
import com.google.gwt.user.client.ui.PopupPanel;
31
import com.google.gwt.user.client.ui.RootPanel;
31
import com.google.gwt.user.client.ui.RootPanel;
32
import com.google.gwt.user.client.ui.TextBox;
32
import com.google.gwt.user.client.ui.TextBox;
33
import com.google.gwt.user.client.ui.Widget;
33
import com.google.gwt.user.client.ui.Widget;
34
import com.google.gwt.user.client.DOM;
34
import com.google.gwt.user.client.DOM;
35
import com.google.gwt.user.client.Event; 
35
import com.google.gwt.user.client.Event; 
36
 
36
 
37
import java.util.Vector;
37
import java.util.Vector;
38
import java.util.HashMap;
38
import java.util.HashMap;
39
 
39
 
40
 
40
 
41
 
41
 
42
public class AutoCompleteAsyncTextBox extends TextBox
42
public class AutoCompleteAsyncTextBox extends TextBox
43
    implements KeyboardListener, SourcesAutoCompleteAsyncTextBoxEvents {
43
    implements KeyboardListener, SourcesAutoCompleteAsyncTextBoxEvents {
44
   
44
   
45
  private String searchUrl = null; 
45
  private String searchUrl = null; 
46
  private AutoCompleteAsyncTextBoxListenerCollection autoCompleteAsyncTextBoxListeners=null;  
46
  private AutoCompleteAsyncTextBoxListenerCollection autoCompleteAsyncTextBoxListeners=null;  
47
    
47
    
48
  private HashMap cache = new HashMap();
48
  private HashMap cache = new HashMap();
49
  private boolean searching = false;
49
  private boolean searching = false;
50
  private ResponseTextHandler responseTextHandler=null;
50
  private ResponseTextHandler responseTextHandler=null;
51
		  
51
		  
52
  protected PopupPanel choicesPopup = new PopupPanel(true);
52
  protected PopupPanel choicesPopup = new PopupPanel(true);
53
  protected ListBox choices = new ListBox() {
53
  protected ListBox choices = new ListBox() {
54
	  public void onBrowserEvent(Event event) {
54
	  public void onBrowserEvent(Event event) {
55
		  if (Event.ONCLICK == DOM.eventGetType(event)) {
55
		  if (Event.ONCLICK == DOM.eventGetType(event)) {
56
			  complete();
56
			  complete();
57
		  }
57
		  }
58
	  } 
58
	  } 
59
  };
59
  };
60
  protected Vector items = new Vector(); 
60
  protected Vector items = new Vector(); 
61
  protected boolean popupAdded = false;
61
  protected boolean popupAdded = false;
62
  protected boolean visible = false;
62
  protected boolean visible = false;
63
  protected String currentValue = null;
63
  protected String currentValue = null;
64
  
64
  
65
   
65
   
66
   
66
   
67
  /**
67
  /**
68
   * Default Constructor
68
   * Default Constructor
69
   *
69
   *
70
   */
70
   */
71
  public AutoCompleteAsyncTextBox(ResponseTextHandler rsp)
71
  public AutoCompleteAsyncTextBox(ResponseTextHandler rsp)
72
  {
72
  {
73
    super();
73
    super();
74
    responseTextHandler=rsp;
74
    responseTextHandler=rsp;
75
    this.addKeyboardListener(this);
75
    this.addKeyboardListener(this);
76
    choices.sinkEvents(Event.ONCLICK); 
76
    choices.sinkEvents(Event.ONCLICK); 
77
    this.setStyleName("AutoCompleteAsyncTextBox");
77
    this.setStyleName("AutoCompleteAsyncTextBox");
78
       
78
       
79
    choicesPopup.add(choices);
79
    choicesPopup.add(choices);
80
    choicesPopup.addStyleName("AutoCompleteChoices");
80
    choicesPopup.addStyleName("AutoCompleteChoices");
81
       
81
       
82
    choices.setStyleName("list");
82
    choices.setStyleName("list");
83
    
83
    
84
  }
84
  }
85
 
85
 
86
 
86
 
87
  
87
  
88
  public void addAutoCompleteAsyncTextBoxListener(AutoCompleteAsyncTextBoxListener listener) {
88
  public void addAutoCompleteAsyncTextBoxListener(AutoCompleteAsyncTextBoxListener listener) {
89
	    if (autoCompleteAsyncTextBoxListeners == null) {
89
	    if (autoCompleteAsyncTextBoxListeners == null) {
90
	      autoCompleteAsyncTextBoxListeners = new AutoCompleteAsyncTextBoxListenerCollection();
90
	      autoCompleteAsyncTextBoxListeners = new AutoCompleteAsyncTextBoxListenerCollection();
91
	    }
91
	    }
92
	    autoCompleteAsyncTextBoxListeners.addElement(listener);
92
	    autoCompleteAsyncTextBoxListeners.addElement(listener);
93
  }
93
  }
94
 
94
 
95
 
95
 
96
 
96
 
97
  public void setSearchUrl(String url) {
97
  public void setSearchUrl(String url) {
98
	  
98
	  
99
	  this.searchUrl=url;
99
	  this.searchUrl=url;
100
  }
100
  }
101
  
101
  
102
  private void doFetchURL(String match) {
102
  private void doFetchURL(String match) {
103
	  /*
103
	  /*
104
	   * Here we fetch the URL and call the handler
104
	   * Here we fetch the URL and call the handler
105
	   */	  
105
	   */	  
106
	 
106
	 
-
 
107
	  String rematch=match.replaceAll(" ","/");
107
	  String rematch=match.replaceFirst(" ","/");
108
	  rematch=rematch.replaceAll("%","");
108
	  
109
	  
109
	  if (this.searchUrl!=null && searching==false) {
110
	  if (this.searchUrl!=null && searching==false) {
110
		  searching=true;
111
		  searching=true;
-
 
112
	 //     HTTPRequest.asyncGet(URL.encodeComponent(this.searchUrl) + rematch, responseTextHandler );
111
	      HTTPRequest.asyncGet(this.searchUrl + rematch, responseTextHandler );
113
	      HTTPRequest.asyncGet(this.searchUrl + rematch, responseTextHandler );
112
 
114
 
113
	  }
115
	  }
114
  }
116
  }
115
 
117
 
116
  
118
  
117
  /**
119
  /**
118
   * Not used at all
120
   * Not used at all
119
   */
121
   */
120
  public void onKeyDown(Widget arg0, char arg1, int arg2) {
122
  public void onKeyDown(Widget arg0, char arg1, int arg2) {
121
	  
123
	  
122
	  
124
	  
123
	  if(arg1 == KEY_ENTER)
125
	  if(arg1 == KEY_ENTER)
124
	    {
126
	    {
125
	      enterKey(arg0, arg1, arg2);
127
	      enterKey(arg0, arg1, arg2);
126
	    }
128
	    }
127
	    else if(arg1 == KEY_DOWN)
129
	    else if(arg1 == KEY_DOWN)
128
	    {
130
	    {
129
	      downKey(arg0, arg1, arg2);
131
	      downKey(arg0, arg1, arg2);
130
	    }
132
	    }
131
	    else if(arg1 == KEY_UP)
133
	    else if(arg1 == KEY_UP)
132
	    {
134
	    {
133
	      upKey(arg0, arg1, arg2);
135
	      upKey(arg0, arg1, arg2);
134
	    }
136
	    }
135
	    else if(arg1 == KEY_ESCAPE)
137
	    else if(arg1 == KEY_ESCAPE)
136
	    {
138
	    {
137
	      escapeKey(arg0, arg1, arg2);
139
	      escapeKey(arg0, arg1, arg2);
138
	    }
140
	    }
139
	  	
141
	  	
140
	  
142
	  
141
  }	 
143
  }	 
142
  /**
144
  /**
143
   * Not used at all (probleme avec ie, qui ne comprend pas les touches meta)
145
   * Not used at all (probleme avec ie, qui ne comprend pas les touches meta)
144
   */
146
   */
145
  public void onKeyPress(Widget arg0, char arg1, int arg2) {
147
  public void onKeyPress(Widget arg0, char arg1, int arg2) {
146
	
148
	
147
 
149
 
148
  }
150
  }
149
  
151
  
150
  // The down key was pressed.
152
  // The down key was pressed.
151
  protected void downKey(Widget arg0, char arg1, int arg2) {
153
  protected void downKey(Widget arg0, char arg1, int arg2) {
152
	  
154
	  
153
	    int selectedIndex = choices.getSelectedIndex();
155
	    int selectedIndex = choices.getSelectedIndex();
154
	    selectedIndex++;
156
	    selectedIndex++;
155
	    if (selectedIndex >= choices.getItemCount())
157
	    if (selectedIndex >= choices.getItemCount())
156
	    {
158
	    {
157
	      selectedIndex = 0;
159
	      selectedIndex = 0;
158
	    }
160
	    }
159
	    choices.setSelectedIndex(selectedIndex);
161
	    choices.setSelectedIndex(selectedIndex);
160
 }
162
 }
161
 
163
 
162
  // The up key was pressed.
164
  // The up key was pressed.
163
  protected void upKey(Widget arg0, char arg1, int arg2) {
165
  protected void upKey(Widget arg0, char arg1, int arg2) {
164
    int selectedIndex = choices.getSelectedIndex();
166
    int selectedIndex = choices.getSelectedIndex();
165
    selectedIndex--;
167
    selectedIndex--;
166
    if(selectedIndex < 0)
168
    if(selectedIndex < 0)
167
    {
169
    {
168
      selectedIndex = choices.getItemCount() - 1;
170
      selectedIndex = choices.getItemCount() - 1;
169
    }
171
    }
170
    choices.setSelectedIndex(selectedIndex);
172
    choices.setSelectedIndex(selectedIndex);
171
  } 
173
  } 
172
 
174
 
173
  // The enter key was pressed.
175
  // The enter key was pressed.
174
  protected void enterKey(Widget arg0, char arg1, int arg2) {
176
  protected void enterKey(Widget arg0, char arg1, int arg2) {
175
      if(visible)
177
      if(visible)
176
      {
178
      {
177
        complete();
179
        complete();
178
      }
180
      }
179
      else {
181
      else {
180
    	 // Validation de l'entree : appel asynchrone  
182
    	 // Validation de l'entree : appel asynchrone  
181
          if (autoCompleteAsyncTextBoxListeners!= null) {
183
          if (autoCompleteAsyncTextBoxListeners!= null) {
182
              autoCompleteAsyncTextBoxListeners.fireTextBoxEnter(this,this.getText(),currentValue);
184
              autoCompleteAsyncTextBoxListeners.fireTextBoxEnter(this,this.getText(),currentValue);
183
          }
185
          }
184
    	  currentValue=null;
186
    	  currentValue=null;
185
    	  this.setText("");
187
    	  this.setText("");
186
      }
188
      }
187
 
189
 
188
  }
190
  }
189
 
191
 
190
//The escape key was pressed.
192
//The escape key was pressed.
191
  protected void escapeKey(Widget arg0, char arg1, int arg2) {
193
  protected void escapeKey(Widget arg0, char arg1, int arg2) {
192
    choices.clear();
194
    choices.clear();
193
    items.clear();
195
    items.clear();
194
    choicesPopup.hide();
196
    choicesPopup.hide();
195
    visible = false;
197
    visible = false;
196
 
198
 
197
  } 
199
  } 
198
 
200
 
199
 
201
 
200
  // Any other non-special key was pressed.
202
  // Any other non-special key was pressed.
201
  protected void otherKey(Widget arg0, char arg1, int arg2) {
203
  protected void otherKey(Widget arg0, char arg1, int arg2) {
202
   
204
   
203
	
205
	
204
    // Lancement appel 
206
    // Lancement appel 
205
    String text = this.getText();
207
    String text = this.getText();
206
    
208
    
207
    	
209
    	
208
	    if(text.length() > 0)
210
	    if(text.length() > 0)
209
	    {
211
	    {
210
	    
212
	    
211
		      items.clear();
213
		      items.clear();
212
		      
214
		      
213
		      if (getFromCache(text)!=null) {
215
		      if (getFromCache(text)!=null) {
214
		    	  items=getFromCache(text);
216
		    	  items=getFromCache(text);
215
		    	  displayList();
217
		    	  displayList();
216
		      }
218
		      }
217
		      else {
219
		      else {
218
		     
220
		     
219
		    	  this.doFetchURL(text);
221
		    	  this.doFetchURL(text);
220
		      }
222
		      }
221
		 }
223
		 }
222
   
224
   
223
	
225
	
224
	    
226
	    
225
    
227
    
226
  } 
228
  } 
227
  
229
  
228
  public void onKeyUp(Widget arg0, char arg1, int arg2) {
230
  public void onKeyUp(Widget arg0, char arg1, int arg2) {
229
	  
231
	  
230
	  switch(arg1) {
232
	  switch(arg1) {
231
      case KEY_ALT:
233
      case KEY_ALT:
232
      case KEY_CTRL:
234
      case KEY_CTRL:
233
      case KEY_DOWN:
235
      case KEY_DOWN:
234
      case KEY_END:
236
      case KEY_END:
235
      case KEY_ENTER:
237
      case KEY_ENTER:
236
      case KEY_ESCAPE:
238
      case KEY_ESCAPE:
237
      case KEY_HOME:
239
      case KEY_HOME:
238
      case KEY_LEFT:
240
      case KEY_LEFT:
239
      case KEY_PAGEDOWN:
241
      case KEY_PAGEDOWN:
240
      case KEY_PAGEUP:
242
      case KEY_PAGEUP:
241
      case KEY_RIGHT:
243
      case KEY_RIGHT:
242
      case KEY_SHIFT:
244
      case KEY_SHIFT:
243
      case KEY_TAB:
245
      case KEY_TAB:
244
      case KEY_UP:
246
      case KEY_UP:
245
        break;
247
        break;
246
      default:
248
      default:
247
        otherKey(arg0, arg1, arg2);
249
        otherKey(arg0, arg1, arg2);
248
        break;
250
        break;
249
    }
251
    }
250
 
252
 
251
  }
253
  }
252
    
254
    
253
  
255
  
254
  // Display assistant
256
  // Display assistant
255
  
257
  
256
    public void displayList() { 
258
    public void displayList() { 
257
    	
259
    	
258
    	searching=false;
260
    	searching=false;
259
	    if(this.items.size() > 0)
261
	    if(this.items.size() > 0)
260
	    {
262
	    {
261
	    	
263
	    	
262
	      addToCache(this.getText(),(Vector) items.clone());
264
	      addToCache(this.getText(),(Vector) items.clone());
263
	      
265
	      
264
	      choices.clear();
266
	      choices.clear();
265
	           
267
	           
266
	      for(int i = 0; i < items.size(); i++)
268
	      for(int i = 0; i < items.size(); i++)
267
	      {
269
	      {
268
	        choices.addItem(((String [])items.get(i))[0],((String [])items.get(i))[1]);
270
	        choices.addItem(((String [])items.get(i))[0],((String [])items.get(i))[1]);
269
	      }
271
	      }
270
	      
272
	      
271
	           
273
	           
272
	      // if there is only one match and it is what is in the
274
	      // if there is only one match and it is what is in the
273
	      // text field anyways there is no need to show autocompletion
275
	      // text field anyways there is no need to show autocompletion
274
	    //  if(items.size() == 1 && (((String []) items.get(0))[0]).compareTo(this.getText()) == 0)
276
	    //  if(items.size() == 1 && (((String []) items.get(0))[0]).compareTo(this.getText()) == 0)
275
	     // {
277
	     // {
276
	       // choicesPopup.hide();
278
	       // choicesPopup.hide();
277
	     // } else {
279
	     // } else {
278
	        choices.setSelectedIndex(0);
280
	        choices.setSelectedIndex(0);
279
	        choices.setVisibleItemCount(items.size());
281
	        choices.setVisibleItemCount(items.size());
280
	               
282
	               
281
	        if(!popupAdded)
283
	        if(!popupAdded)
282
	        {
284
	        {
283
	          RootPanel.get().add(choicesPopup);
285
	          RootPanel.get().add(choicesPopup);
284
	          popupAdded = true;
286
	          popupAdded = true;
285
	        }
287
	        }
286
	        choicesPopup.show();
288
	        choicesPopup.show();
287
	        visible = true;
289
	        visible = true;
288
	        choicesPopup.setPopupPosition(this.getAbsoluteLeft(),
290
	        choicesPopup.setPopupPosition(this.getAbsoluteLeft(),
289
	        this.getAbsoluteTop() + this.getOffsetHeight());
291
	        this.getAbsoluteTop() + this.getOffsetHeight());
290
	        choicesPopup.setWidth(this.getOffsetWidth() + "px");
292
	        choicesPopup.setWidth(this.getOffsetWidth() + "px");
291
	        choices.setWidth(this.getOffsetWidth() + "px");
293
	        choices.setWidth(this.getOffsetWidth() + "px");
292
	    //  }
294
	    //  }
293
	
295
	
294
	    } else {
296
	    } else {
295
	      visible = false;
297
	      visible = false;
296
	      choicesPopup.hide();
298
	      choicesPopup.hide();
297
	    }
299
	    }
298
	  }
300
	  }
299
 
301
 
300
  /**
302
  /**
301
   * A mouseclick in the list of items
303
   * A mouseclick in the list of items
302
   */
304
   */
303
  public void onChange(Widget arg0) {
305
  public void onChange(Widget arg0) {
304
    complete();
306
    complete();
305
  }
307
  }
306
  
308
  
307
 
309
 
308
  public void onClick(Widget arg0) {
310
  public void onClick(Widget arg0) {
309
    complete();
311
    complete();
310
  }
312
  }
311
   
313
   
312
  // add selected item to textbox
314
  // add selected item to textbox
313
  protected void complete()
315
  protected void complete()
314
  {
316
  {
315
    if(choices.getItemCount() > 0)
317
    if(choices.getItemCount() > 0)
316
    {
318
    {
317
      this.setText(choices.getItemText(choices.getSelectedIndex()));
319
      this.setText(choices.getItemText(choices.getSelectedIndex()));
318
      currentValue=choices.getValue(choices.getSelectedIndex());
320
      currentValue=choices.getValue(choices.getSelectedIndex());
319
    }
321
    }
320
 
322
 
321
    visible=false;
323
    visible=false;
322
    items.clear();
324
    items.clear();
323
    choices.clear();
325
    choices.clear();
324
    choicesPopup.hide();
326
    choicesPopup.hide();
325
  }
327
  }
326
  
328
  
327
  
329
  
328
  public void addItem(String item, String value) {
330
  public void addItem(String item, String value) {
329
	  items.add(new String [] {item, value});
331
	  items.add(new String [] {item, value});
330
  }
332
  }
331
  
333
  
332
  private void addToCache (String query, Vector result)
334
  private void addToCache (String query, Vector result)
333
  {
335
  {
334
	cache.put(query.toLowerCase(),result);
336
	cache.put(query.toLowerCase(),result);
335
  }
337
  }
336
 
338
 
337
  private Vector getFromCache (String query)
339
  private Vector getFromCache (String query)
338
  {
340
  {
339
	return (Vector) cache.get(query.toLowerCase());
341
	return (Vector) cache.get(query.toLowerCase());
340
  }
342
  }
341
  
343
  
342
 
344
 
343
 
345
 
344
  
346
  
345
}
347
}
346
 
348