Subversion Repositories eFlore/Archives.cel-v1

Rev

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

Rev 27 Rev 28
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
// TODO : Utiliser Suggestbox et les Associating Data Transfer Objects (DTOs) with Suggestion Objects
25
 
26
 
26
import com.google.gwt.user.client.HTTPRequest;
27
import com.google.gwt.user.client.HTTPRequest;
27
import com.google.gwt.user.client.ResponseTextHandler;
28
import com.google.gwt.user.client.ResponseTextHandler;
28
import com.google.gwt.user.client.ui.KeyboardListener;
29
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.ListBox;
30
import com.google.gwt.user.client.ui.PopupPanel;
31
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;
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;
-
 
62
  protected boolean visible = false;
61
  protected boolean visible = false;
63
  
62
  
64
  /**
63
  /**
65
   * Value linked to current text
64
   * Value linked to current text
66
   */
65
   */
67
  protected String currentValue = null;
66
  protected String currentValue = null;
68
  
67
  
69
   
68
   
70
   
69
   
71
  /**
70
  /**
72
   * Default Constructor
71
   * Default Constructor
73
   *
72
   *
74
   */
73
   */
75
  public AutoCompleteAsyncTextBox(ResponseTextHandler rsp)
74
  public AutoCompleteAsyncTextBox(ResponseTextHandler rsp)
76
  {
75
  {
77
    super();
76
    super();
78
    responseTextHandler=rsp;
77
    responseTextHandler=rsp;
79
    this.addKeyboardListener(this);
78
    this.addKeyboardListener(this);
80
    choices.sinkEvents(Event.ONCLICK); 
79
    choices.sinkEvents(Event.ONCLICK); 
81
    this.setStyleName("AutoCompleteAsyncTextBox");
80
    this.setStyleName("AutoCompleteAsyncTextBox");
82
       
81
       
83
    choicesPopup.add(choices);
82
    choicesPopup.add(choices);
84
    choicesPopup.addStyleName("AutoCompleteChoices");
83
    choicesPopup.addStyleName("AutoCompleteChoices");
85
       
84
       
86
    choices.setStyleName("list");
85
    choices.setStyleName("list");
87
    
86
    
88
  }
87
  }
89
 
88
 
90
 
89
 
91
  
90
  
92
  public void addAutoCompleteAsyncTextBoxListener(AutoCompleteAsyncTextBoxListener listener) {
91
  public void addAutoCompleteAsyncTextBoxListener(AutoCompleteAsyncTextBoxListener listener) {
93
	    if (autoCompleteAsyncTextBoxListeners == null) {
92
	    if (autoCompleteAsyncTextBoxListeners == null) {
94
	      autoCompleteAsyncTextBoxListeners = new AutoCompleteAsyncTextBoxListenerCollection();
93
	      autoCompleteAsyncTextBoxListeners = new AutoCompleteAsyncTextBoxListenerCollection();
95
	    }
94
	    }
96
	    autoCompleteAsyncTextBoxListeners.addElement(listener);
95
	    autoCompleteAsyncTextBoxListeners.addElement(listener);
97
  }
96
  }
98
 
97
 
99
 
98
 
100
 
99
 
101
  public void setSearchUrl(String url) {
100
  public void setSearchUrl(String url) {
102
	  
101
	  
103
	  this.searchUrl=url;
102
	  this.searchUrl=url;
104
  }
103
  }
105
  
104
  
106
  private void doFetchURL(String match) {
105
  private void doFetchURL(String match) {
107
	  /*
106
	  /*
108
	   * Here we fetch the URL and call the handler
107
	   * Here we fetch the URL and call the handler
109
	   */	  
108
	   */	  
110
	
109
	
111
 
110
 
112
	  String rematch=match.replaceAll(" ","/");
111
	  String rematch=match.replaceAll(" ","/");
113
	  rematch=rematch.replaceAll("%","");
112
	  rematch=rematch.replaceAll("%","");
114
	  
113
	  
115
	  if (this.searchUrl!=null && searching==false) {
114
	  if (this.searchUrl!=null && searching==false) {
116
		  searching=true;
115
		  searching=true;
117
	 //     HTTPRequest.asyncGet(URL.encodeComponent(this.searchUrl) + rematch, responseTextHandler );
116
	 //     HTTPRequest.asyncGet(URL.encodeComponent(this.searchUrl) + rematch, responseTextHandler );
118
	      HTTPRequest.asyncGet(this.searchUrl + rematch, responseTextHandler );
117
	      HTTPRequest.asyncGet(this.searchUrl + rematch, responseTextHandler );
119
 
118
 
120
	  }
119
	  }
121
  }
120
  }
122
 
121
 
123
  
122
  
124
  public void onKeyDown(Widget arg0, char arg1, int arg2) {
123
  public void onKeyDown(Widget arg0, char arg1, int arg2) {
125
	  
124
	  
126
	  
125
	  
127
	  if(arg1 == KEY_ENTER)
126
	  if(arg1 == KEY_ENTER)
128
	    {
127
	    {
129
	      enterKey(arg0, arg1, arg2);
128
	      enterKey(arg0, arg1, arg2);
130
	    }
129
	    }
131
	    else if(arg1 == KEY_DOWN)
130
	    else if(arg1 == KEY_DOWN)
132
	    {
131
	    {
133
	      downKey(arg0, arg1, arg2);
132
	      downKey(arg0, arg1, arg2);
134
	    }
133
	    }
135
	    else if(arg1 == KEY_UP)
134
	    else if(arg1 == KEY_UP)
136
	    {
135
	    {
137
	      upKey(arg0, arg1, arg2);
136
	      upKey(arg0, arg1, arg2);
138
	    }
137
	    }
139
	    else if(arg1 == KEY_ESCAPE)
138
	    else if(arg1 == KEY_ESCAPE)
140
	    {
139
	    {
141
	      escapeKey(arg0, arg1, arg2);
140
	      escapeKey(arg0, arg1, arg2);
142
	    }
141
	    }
143
	  	
142
	  	
144
	  
143
	  
145
  }	 
144
  }	 
146
  /**
145
  /**
147
   * Not used at all (probleme avec ie, qui ne comprend pas les touches meta)
146
   * Not used at all (probleme avec ie, qui ne comprend pas les touches meta)
148
   */
147
   */
149
  public void onKeyPress(Widget arg0, char arg1, int arg2) {
148
  public void onKeyPress(Widget arg0, char arg1, int arg2) {
150
	
149
	
151
 
150
 
152
  }
151
  }
153
  
152
  
154
  // The down key was pressed.
153
  // The down key was pressed.
155
  protected void downKey(Widget arg0, char arg1, int arg2) {
154
  protected void downKey(Widget arg0, char arg1, int arg2) {
156
	  
155
	  
157
	    int selectedIndex = choices.getSelectedIndex();
156
	    int selectedIndex = choices.getSelectedIndex();
158
	    selectedIndex++;
157
	    selectedIndex++;
159
	    if (selectedIndex >= choices.getItemCount())
158
	    if (selectedIndex >= choices.getItemCount())
160
	    {
159
	    {
161
	      selectedIndex = 0;
160
	      selectedIndex = 0;
162
	    }
161
	    }
163
	    choices.setSelectedIndex(selectedIndex);
162
	    choices.setSelectedIndex(selectedIndex);
164
 }
163
 }
165
 
164
 
166
  // The up key was pressed.
165
  // The up key was pressed.
167
  protected void upKey(Widget arg0, char arg1, int arg2) {
166
  protected void upKey(Widget arg0, char arg1, int arg2) {
168
    int selectedIndex = choices.getSelectedIndex();
167
    int selectedIndex = choices.getSelectedIndex();
169
    selectedIndex--;
168
    selectedIndex--;
170
    if(selectedIndex < 0)
169
    if(selectedIndex < 0)
171
    {
170
    {
172
      selectedIndex = choices.getItemCount() - 1;
171
      selectedIndex = choices.getItemCount() - 1;
173
    }
172
    }
174
    choices.setSelectedIndex(selectedIndex);
173
    choices.setSelectedIndex(selectedIndex);
175
  } 
174
  } 
176
 
175
 
177
  // The enter key was pressed.
176
  // The enter key was pressed.
178
  protected void enterKey(Widget arg0, char arg1, int arg2) {
177
  protected void enterKey(Widget arg0, char arg1, int arg2) {
179
      if(visible)
178
      if(visible)
180
      {
179
      {
181
        complete();
180
        complete();
182
      }
181
      }
183
      else {
182
      else {
184
    	 // Validation de l'entree : appel asynchrone  
183
    	 // Validation de l'entree : appel asynchrone  
185
          if (autoCompleteAsyncTextBoxListeners!= null) {
184
          if (autoCompleteAsyncTextBoxListeners!= null) {
186
              autoCompleteAsyncTextBoxListeners.fireTextBoxEnter(this,this.getText(),currentValue);
185
              autoCompleteAsyncTextBoxListeners.fireTextBoxEnter(this,this.getText(),currentValue);
187
          }
186
          }
188
    	  currentValue=null;
187
    	  currentValue=null;
189
    	  this.setText("");
188
    	  this.setText("");
190
      }
189
      }
191
 
190
 
192
  }
191
  }
193
 
192
 
194
//The escape key was pressed.
193
//The escape key was pressed.
195
  protected void escapeKey(Widget arg0, char arg1, int arg2) {
194
  protected void escapeKey(Widget arg0, char arg1, int arg2) {
196
    choices.clear();
195
    choices.clear();
197
    items.clear();
196
    items.clear();
198
    choicesPopup.hide();
197
    choicesPopup.hide();
199
    visible = false;
198
    visible = false;
200
 
199
 
201
  } 
200
  } 
202
 
201
 
203
 
202
 
204
  // Any other non-special key was pressed.
203
  // Any other non-special key was pressed.
205
  protected void otherKey(Widget arg0, char arg1, int arg2) {
204
  protected void otherKey(Widget arg0, char arg1, int arg2) {
206
   
205
   
207
	
206
	
208
    // Lancement appel 
207
    // Lancement appel 
209
    String text = this.getText();
208
    String text = this.getText();
210
    
209
    
211
    	
210
    	
212
	    if(text.length() > 0)
211
	    if(text.length() > 0)
213
	    {
212
	    {
214
	    
213
	    
215
		      items.clear();
214
		      items.clear();
216
		      
215
		      
217
		      if (getFromCache(text)!=null) {
216
		      if (getFromCache(text)!=null) {
218
		    	  items=getFromCache(text);
217
		    	  items=getFromCache(text);
219
		    	  displayList();
218
		    	  displayList();
220
		      }
219
		      }
221
		      else {
220
		      else {
222
		     
221
		     
223
		    	  this.doFetchURL(text);
222
		    	  this.doFetchURL(text);
224
		      }
223
		      }
225
		 }
224
		 }
226
   
225
   
227
	
226
	
228
	    
227
	    
229
    
228
    
230
  } 
229
  } 
231
  
230
  
232
  public void onKeyUp(Widget arg0, char arg1, int arg2) {
231
  public void onKeyUp(Widget arg0, char arg1, int arg2) {
233
	  
232
	  
234
	  switch(arg1) {
233
	  switch(arg1) {
235
      case KEY_ALT:
234
      case KEY_ALT:
236
      case KEY_CTRL:
235
      case KEY_CTRL:
237
      case KEY_DOWN:
236
      case KEY_DOWN:
238
      case KEY_END:
237
      case KEY_END:
239
      case KEY_ENTER:
238
      case KEY_ENTER:
240
      case KEY_ESCAPE:
239
      case KEY_ESCAPE:
241
      case KEY_HOME:
240
      case KEY_HOME:
242
      case KEY_LEFT:
241
      case KEY_LEFT:
243
      case KEY_PAGEDOWN:
242
      case KEY_PAGEDOWN:
244
      case KEY_PAGEUP:
243
      case KEY_PAGEUP:
245
      case KEY_RIGHT:
244
      case KEY_RIGHT:
246
      case KEY_SHIFT:
245
      case KEY_SHIFT:
247
      case KEY_TAB:
246
      case KEY_TAB:
248
      case KEY_UP:
247
      case KEY_UP:
249
        break;
248
        break;
250
      default:
249
      default:
251
        otherKey(arg0, arg1, arg2);
250
        otherKey(arg0, arg1, arg2);
252
        break;
251
        break;
253
    }
252
    }
254
 
253
 
255
  }
254
  }
256
    
255
    
257
  
256
  
258
  // Display assistant
257
  // Display assistant
259
  
258
  
260
    public void displayList() { 
259
    public void displayList() { 
261
    	
260
    	
262
    	searching=false;
261
    	searching=false;
263
	    if(this.items.size() > 0)
262
	    if(this.items.size() > 0)
264
	    {
263
	    {
265
	    	
264
	    	
266
	      addToCache(this.getText(),(Vector) items.clone());
265
	      addToCache(this.getText(),(Vector) items.clone());
267
	      
266
	      
268
	      choices.clear();
267
	      choices.clear();
269
	           
268
	           
270
	      for(int i = 0; i < items.size(); i++)
269
	      for(int i = 0; i < items.size(); i++)
271
	      {
270
	      {
272
	        choices.addItem(((String [])items.get(i))[0],((String [])items.get(i))[1]);
271
	        choices.addItem(((String [])items.get(i))[0],((String [])items.get(i))[1]);
273
	      }
272
	      }
274
	      
273
	      
275
	           
274
	           
276
	      // if there is only one match and it is what is in the
275
	      // if there is only one match and it is what is in the
277
	      // text field anyways there is no need to show autocompletion
276
	      // text field anyways there is no need to show autocompletion
278
	    //  if(items.size() == 1 && (((String []) items.get(0))[0]).compareTo(this.getText()) == 0)
277
	    //  if(items.size() == 1 && (((String []) items.get(0))[0]).compareTo(this.getText()) == 0)
279
	     // {
278
	     // {
280
	       // choicesPopup.hide();
279
	       // choicesPopup.hide();
281
	     // } else {
280
	     // } else {
282
	        choices.setSelectedIndex(0);
281
	        choices.setSelectedIndex(0);
283
	        choices.setVisibleItemCount(items.size());
282
	        choices.setVisibleItemCount(items.size());
284
	               
-
 
285
	        if(!popupAdded)
-
 
286
	        {
-
 
287
	          RootPanel.get().add(choicesPopup);
-
 
288
	          popupAdded = true;
283
	               
289
	        }
-
 
290
	        choicesPopup.show();
284
	        
291
	        visible = true;
285
	        visible = true;
292
	        choicesPopup.setPopupPosition(this.getAbsoluteLeft(),
286
	        choicesPopup.setPopupPosition(this.getAbsoluteLeft(), this.getAbsoluteTop() + this.getOffsetHeight());
293
	        this.getAbsoluteTop() + this.getOffsetHeight());
287
	        choicesPopup.setPopupPosition(this.getAbsoluteLeft(), this.getAbsoluteTop() + this.getOffsetHeight());
294
	        choicesPopup.setWidth(this.getOffsetWidth() + "px");
288
	        choicesPopup.setWidth(this.getOffsetWidth() + "px");
-
 
289
	        choices.setWidth(this.getOffsetWidth() + "px");
-
 
290
	        
-
 
291
	        choicesPopup.show();
295
	        choices.setWidth(this.getOffsetWidth() + "px");
292
 
296
	    //  }
293
	    //  }
297
	
294
	
298
	    } else {
295
	    } else {
299
	      visible = false;
296
	      visible = false;
300
	      choicesPopup.hide();
297
	      choicesPopup.hide();
301
	    }
298
	    }
302
	  }
299
	  }
303
 
300
 
304
  /**
301
  /**
305
   * A mouseclick in the list of items
302
   * A mouseclick in the list of items
306
   */
303
   */
307
  public void onChange(Widget arg0) {
304
  public void onChange(Widget arg0) {
308
    complete();
305
    complete();
309
  }
306
  }
310
  
307
  
311
 
308
 
312
  public void onClick(Widget arg0) {
309
  public void onClick(Widget arg0) {
313
    complete();
310
    complete();
314
  }
311
  }
315
   
312
   
316
  // add selected item to textbox
313
  // add selected item to textbox
317
  protected void complete()
314
  protected void complete()
318
  {
315
  {
319
	  
316
	  
320
    
317
    
321
    if(choices.getItemCount() > 0)
318
    if(choices.getItemCount() > 0)
322
    {
319
    {
323
      this.setText(choices.getItemText(choices.getSelectedIndex()));
320
      this.setText(choices.getItemText(choices.getSelectedIndex()));
324
      currentValue=choices.getValue(choices.getSelectedIndex());
321
      currentValue=choices.getValue(choices.getSelectedIndex());
325
      if (autoCompleteAsyncTextBoxListeners!= null) {
322
      if (autoCompleteAsyncTextBoxListeners!= null) {
326
          autoCompleteAsyncTextBoxListeners.fireTextBoxComplete(responseTextHandler,this.getText(),currentValue);
323
          autoCompleteAsyncTextBoxListeners.fireTextBoxComplete(responseTextHandler,this.getText(),currentValue);
327
      }
324
      }
328
    }
325
    }
329
 
326
 
330
    visible=false;
327
    visible=false;
331
    items.clear();
328
    items.clear();
332
    choices.clear();
329
    choices.clear();
333
    choicesPopup.hide();
330
    choicesPopup.hide();
334
  }
331
  }
335
  
332
  
336
  
333
  
337
  public void addItem(String item, String value) {
334
  public void addItem(String item, String value) {
338
	  items.add(new String [] {item, value});
335
	  items.add(new String [] {item, value});
339
  }
336
  }
340
  
337
  
341
  private void addToCache (String query, Vector result)
338
  private void addToCache (String query, Vector result)
342
  {
339
  {
343
	cache.put(query.toLowerCase(),result);
340
	cache.put(query.toLowerCase(),result);
344
  }
341
  }
345
 
342
 
346
  private Vector getFromCache (String query)
343
  private Vector getFromCache (String query)
347
  {
344
  {
348
	return (Vector) cache.get(query.toLowerCase());
345
	return (Vector) cache.get(query.toLowerCase());
349
  }
346
  }
350
 
347
 
351
 
348
 
352
 
349
 
353
public String getValue() {
350
public String getValue() {
354
	return currentValue;
351
	return currentValue;
355
}
352
}
356
  
353
  
357
 
354
 
358
public  void setValue(String value) {
355
public  void setValue(String value) {
359
	 this.currentValue=value;
356
	 this.currentValue=value;
360
}
357
}
361
  
358
  
362
  
359
  
363
}
360
}
364
 
361