FileUpload now implements HasChangeHandlers, which is fired when a user changes the file in the widget.
Patch by: jlabanca
Review by: ecc (desk)
Issue: 3187
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@4768 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/Issue3187.java b/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/Issue3187.java
new file mode 100644
index 0000000..162a816
--- /dev/null
+++ b/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/Issue3187.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2008 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.museum.client.defaultmuseum;
+
+import com.google.gwt.event.dom.client.ChangeEvent;
+import com.google.gwt.event.dom.client.ChangeHandler;
+import com.google.gwt.museum.client.common.AbstractIssue;
+import com.google.gwt.user.client.Window;
+import com.google.gwt.user.client.ui.FileUpload;
+import com.google.gwt.user.client.ui.Widget;
+
+/**
+ * {@link FileUpload} onChange event fires correctly in all browsers.
+ */
+public class Issue3187 extends AbstractIssue {
+ @Override
+ public Widget createIssue() {
+ FileUpload fileUpload = new FileUpload();
+ fileUpload.addChangeHandler(new ChangeHandler() {
+ public void onChange(ChangeEvent event) {
+ Window.alert("Value Changed");
+ }
+ });
+ return fileUpload;
+ }
+
+ @Override
+ public String getInstructions() {
+ return "Change the file path and verify an alert dialog appears. In "
+ + "Opera, the onChange event should only be fired when the box is "
+ + "blurred.";
+ }
+
+ @Override
+ public String getSummary() {
+ return "FileUpload supports change events";
+ }
+
+ @Override
+ public boolean hasCSS() {
+ return false;
+ }
+}
diff --git a/user/src/com/google/gwt/user/FileUpload.gwt.xml b/user/src/com/google/gwt/user/FileUpload.gwt.xml
new file mode 100644
index 0000000..56cfadd
--- /dev/null
+++ b/user/src/com/google/gwt/user/FileUpload.gwt.xml
@@ -0,0 +1,28 @@
+<!-- -->
+<!-- Copyright 2007 Google Inc. -->
+<!-- Licensed under the Apache License, Version 2.0 (the "License"); you -->
+<!-- may not use this file except in compliance with the License. You may -->
+<!-- may obtain a copy of the License at -->
+<!-- -->
+<!-- http://www.apache.org/licenses/LICENSE-2.0 -->
+<!-- -->
+<!-- Unless required by applicable law or agreed to in writing, software -->
+<!-- distributed under the License is distributed on an "AS IS" BASIS, -->
+<!-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -->
+<!-- implied. License for the specific language governing permissions and -->
+<!-- limitations under the License. -->
+
+<!-- Deferred binding rules for FileUpload. -->
+<!-- -->
+<!-- This module is typically inherited via com.google.gwt.user.User -->
+<!-- -->
+<module>
+ <inherits name="com.google.gwt.core.Core"/>
+ <inherits name="com.google.gwt.user.UserAgent"/>
+
+ <!-- Opera fires change events on every character typed -->
+ <replace-with class="com.google.gwt.user.client.ui.FileUpload.FileUploadImplOpera">
+ <when-type-is class="com.google.gwt.user.client.ui.FileUpload.FileUploadImpl"/>
+ <when-property-is name="user.agent" value="opera"/>
+ </replace-with>
+</module>
diff --git a/user/src/com/google/gwt/user/User.gwt.xml b/user/src/com/google/gwt/user/User.gwt.xml
index af4102c..87c4bb7 100644
--- a/user/src/com/google/gwt/user/User.gwt.xml
+++ b/user/src/com/google/gwt/user/User.gwt.xml
@@ -41,6 +41,7 @@
<inherits name="com.google.gwt.user.Window" />
<inherits name="com.google.gwt.user.Tree"/>
<inherits name="com.google.gwt.user.Hyperlink"/>
+ <inherits name="com.google.gwt.user.FileUpload"/>
<inherits name="com.google.gwt.user.datepicker.DatePicker"/>
<super-source path="translatable"/>
diff --git a/user/src/com/google/gwt/user/client/ui/FileUpload.java b/user/src/com/google/gwt/user/client/ui/FileUpload.java
index f1bbf02..dba1f02 100644
--- a/user/src/com/google/gwt/user/client/ui/FileUpload.java
+++ b/user/src/com/google/gwt/user/client/ui/FileUpload.java
@@ -15,9 +15,15 @@
*/
package com.google.gwt.user.client.ui;
+import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.InputElement;
+import com.google.gwt.event.dom.client.ChangeEvent;
+import com.google.gwt.event.dom.client.ChangeHandler;
+import com.google.gwt.event.dom.client.HasChangeHandlers;
+import com.google.gwt.event.shared.HandlerRegistration;
+import com.google.gwt.user.client.Event;
/**
* A widget that wraps the HTML <input type='file'> element. This widget
@@ -29,7 +35,70 @@
* {@example com.google.gwt.examples.FormPanelExample}
* </p>
*/
-public class FileUpload extends Widget implements HasName {
+public class FileUpload extends Widget implements HasName, HasChangeHandlers {
+ /**
+ * Implementation class for {@link FileUpload}.
+ */
+ private static class FileUploadImpl {
+ /**
+ * Initialize the impl class.
+ *
+ * @param fileUpload the {@link FileUpload} to handle
+ */
+ public void init(FileUpload fileUpload) {
+ }
+
+ /**
+ * Handle the browser event.
+ *
+ * @param event the native event
+ * @return true to fire the event normally, false to ignore it
+ */
+ public boolean onBrowserEvent(Event event) {
+ return true;
+ }
+ }
+
+ /**
+ * Opera fires an onChange event every time a character is typed, but we only
+ * want to fire one when the input element is blurred.
+ */
+ @SuppressWarnings("unused")
+ private static class FileUploadImplOpera extends FileUploadImpl {
+ private FileUpload fileUpload;
+ private boolean eventPending;
+ private boolean allowEvent;
+
+ @Override
+ public void init(FileUpload fileUpload) {
+ this.fileUpload = fileUpload;
+ fileUpload.sinkEvents(Event.ONBLUR);
+ }
+
+ @Override
+ public boolean onBrowserEvent(Event event) {
+ switch (event.getTypeInt()) {
+ case Event.ONCHANGE:
+ // When we fire the change event onBlur, we allow it to pass to
+ // Widget#onBrowserEvent().
+ if (!allowEvent) {
+ eventPending = true;
+ return false;
+ }
+ break;
+ case Event.ONBLUR:
+ // Trigger a change event now.
+ if (eventPending) {
+ allowEvent = true;
+ fileUpload.getElement().dispatchEvent(Document.get().createChangeEvent());
+ allowEvent = false;
+ eventPending = false;
+ }
+ break;
+ }
+ return true;
+ }
+ }
/**
* Creates a FileUpload widget that wraps an existing <input
@@ -54,12 +123,16 @@
return fileUpload;
}
+ private FileUploadImpl impl;
+
/**
* Constructs a new file upload widget.
*/
public FileUpload() {
setElement(Document.get().createFileInputElement());
setStyleName("gwt-FileUpload");
+ impl = GWT.create(FileUploadImpl.class);
+ impl.init(this);
}
/**
@@ -74,6 +147,10 @@
setElement(element);
}
+ public HandlerRegistration addChangeHandler(ChangeHandler handler) {
+ return addDomHandler(handler, ChangeEvent.getType());
+ }
+
/**
* Gets the filename selected by the user. This property has no mutator, as
* browser security restrictions preclude setting it.
@@ -88,6 +165,13 @@
return getInputElement().getName();
}
+ @Override
+ public void onBrowserEvent(Event event) {
+ if (impl.onBrowserEvent(event)) {
+ super.onBrowserEvent(event);
+ }
+ }
+
public void setName(String name) {
getInputElement().setName(name);
}