Subversion Repositories eFlore/Archives.cel-v1

Rev

Rev 7 | Rev 9 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

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