Revision: 6072 Author: [email protected] Date: Wed Sep 2 07:58:52 2009 Log: Recommitting r6024, r6022, r6021, and r6020.
Patch by: t.broyer Review by: jlabanca http://code.google.com/p/google-web-toolkit/source/detail?r=6072 Added: /trunk/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/Issue3962.java /trunk/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/Issue3973.java /trunk/user/src/com/google/gwt/user/client/ui/ResetButton.java /trunk/user/src/com/google/gwt/user/client/ui/SubmitButton.java Modified: /trunk/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/DefaultMuseum.java /trunk/user/src/com/google/gwt/dom/client/DOMImpl.java /trunk/user/src/com/google/gwt/dom/client/DOMImplSafari.java /trunk/user/src/com/google/gwt/dom/client/DOMImplTrident.java /trunk/user/src/com/google/gwt/dom/client/Document.java /trunk/user/src/com/google/gwt/user/client/ui/Button.java /trunk/user/src/com/google/gwt/user/client/ui/FormPanel.java /trunk/user/test/com/google/gwt/dom/client/DocumentTest.java /trunk/user/test/com/google/gwt/dom/client/ElementTest.java /trunk/user/test/com/google/gwt/user/UISuite.java /trunk/user/test/com/google/gwt/user/client/ui/ButtonTest.java /trunk/user/test/com/google/gwt/user/client/ui/FormPanelTest.java ======================================= --- /dev/null +++ /trunk/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/Issue3962.java Wed Sep 2 07:58:52 2009 @@ -0,0 +1,61 @@ +/* + * Copyright 2009 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.museum.client.common.AbstractIssue; +import com.google.gwt.user.client.Window; +import com.google.gwt.user.client.ui.Button; +import com.google.gwt.user.client.ui.FormPanel; +import com.google.gwt.user.client.ui.Widget; +import com.google.gwt.user.client.ui.FormPanel.SubmitEvent; +import com.google.gwt.user.client.ui.FormPanel.SubmitHandler; + +/** + * Buttons default to type=submit in WebKit (Safari and Chrome) and IE8 (in IE8 + * mode). + */ +public class Issue3962 extends AbstractIssue { + private FormPanel form; + + @Override + public Widget createIssue() { + form = new FormPanel(); + form.addSubmitHandler(new SubmitHandler() { + public void onSubmit(SubmitEvent event) { + Window.alert("Form is being submitted."); + event.cancel(); + } + }); + form.setWidget(new Button("Submit")); + return form; + } + + @Override + public String getInstructions() { + return "Click the button, it should have no effect."; + } + + @Override + public String getSummary() { + return "In IE8 (in IE8 mode) and WebKit (Safari and Chrome), buttons default" + + " to type submit."; + } + + @Override + public boolean hasCSS() { + return false; + } +} ======================================= --- /dev/null +++ /trunk/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/Issue3973.java Wed Sep 2 07:58:52 2009 @@ -0,0 +1,64 @@ +/* + * Copyright 2009 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.museum.client.common.AbstractIssue; +import com.google.gwt.user.client.Window; +import com.google.gwt.user.client.ui.FormPanel; +import com.google.gwt.user.client.ui.TextBox; +import com.google.gwt.user.client.ui.Widget; +import com.google.gwt.user.client.ui.FormPanel.SubmitEvent; +import com.google.gwt.user.client.ui.FormPanel.SubmitHandler; + +/** + * When a {...@link FormPanel} does not use a synthesized hidden iframe and is + * being submit by means other than {...@link FormPanel#submit()}, it doesn't fire + * submit events. + */ +public class Issue3973 extends AbstractIssue { + private FormPanel form; + + @Override + public Widget createIssue() { + form = new FormPanel("_blank"); + form.setAction("http://www.google.com/search"); + form.addSubmitHandler(new SubmitHandler() { + public void onSubmit(SubmitEvent event) { + Window.alert("Did you see me?"); + event.cancel(); + } + }); + TextBox box = new TextBox(); + box.setName("q"); + form.setWidget(box); + return form; + } + + @Override + public String getInstructions() { + return "Enter some text and press the ENTER key, it should show an alert. It shouldn't open Google within a new window/tab!"; + } + + @Override + public String getSummary() { + return "FormPanel doesn't hook events when not using a synthesized hidden iframe."; + } + + @Override + public boolean hasCSS() { + return false; + } +} ======================================= --- /dev/null +++ /trunk/user/src/com/google/gwt/user/client/ui/ResetButton.java Wed Sep 2 07:58:52 2009 @@ -0,0 +1,95 @@ +/* + * Copyright 2009 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.user.client.ui; + +import com.google.gwt.dom.client.ButtonElement; +import com.google.gwt.dom.client.Document; +import com.google.gwt.event.dom.client.ClickHandler; + +/** + * A standard push-button widget which will automatically reset its enclosing + * {...@link FormPanel} if any. + * + * <h3>CSS Style Rules</h3> + * <dl> + * <dt>.gwt-ResetButton</dt> + * <dd>the outer element</dd> + * </dl> + */ +public class ResetButton extends Button { + + /** + * Creates a ResetButton widget that wraps an existing <button> element. + * + * This element must already be attached to the document. If the element is + * removed from the document, you must call + * {...@link RootPanel#detachNow(Widget)}. + * + * @param element the element to be wrapped + */ + public static Button wrap(com.google.gwt.dom.client.Element element) { + // Assert that the element is attached. + assert Document.get().getBody().isOrHasChild(element); + + ResetButton button = new ResetButton(element); + + // Mark it attached and remember it for cleanup. + button.onAttach(); + RootPanel.detachOnWindowClose(button); + + return button; + } + + /** + * Creates a button with no caption. + */ + public ResetButton() { + super(Document.get().createResetButtonElement()); + setStyleName("gwt-ResetButton"); + } + + /** + * Creates a button with the given HTML caption. + * + * @param html the HTML caption + */ + public ResetButton(String html) { + this(); + setHTML(html); + } + + /** + * Creates a button with the given HTML caption and click listener. + * + * @param html the HTML caption + * @param handler the click handler + */ + public ResetButton(String html, ClickHandler handler) { + this(html); + addClickHandler(handler); + } + + /** + * This constructor may be used by subclasses to explicitly use an existing + * element. This element must be a <button> element with type reset. + * + * @param element the element to be used + */ + protected ResetButton(com.google.gwt.dom.client.Element element) { + super(element); + assert "reset".equalsIgnoreCase(element.<ButtonElement> cast().getType()); + } +} ======================================= --- /dev/null +++ /trunk/user/src/com/google/gwt/user/client/ui/SubmitButton.java Wed Sep 2 07:58:52 2009 @@ -0,0 +1,97 @@ +/* + * Copyright 2009 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.user.client.ui; + +import com.google.gwt.dom.client.ButtonElement; +import com.google.gwt.dom.client.Document; +import com.google.gwt.event.dom.client.ClickHandler; + +/** + * A standard push-button widget which will automatically submit its enclosing + * {...@link FormPanel} if any. + * + * <h3>CSS Style Rules</h3> + * <dl> + * <dt>.gwt-SubmitButton</dt> + * <dd>the outer element</dd> + * </dl> + */ +public class SubmitButton extends Button { + + /** + * Creates a SubmitButton widget that wraps an existing <button> + * element. + * + * This element must already be attached to the document. If the element is + * removed from the document, you must call + * {...@link RootPanel#detachNow(Widget)}. + * + * @param element the element to be wrapped + */ + public static Button wrap(com.google.gwt.dom.client.Element element) { + // Assert that the element is attached. + assert Document.get().getBody().isOrHasChild(element); + + SubmitButton button = new SubmitButton(element); + assert "submit".equalsIgnoreCase(button.getButtonElement().getType()); + + // Mark it attached and remember it for cleanup. + button.onAttach(); + RootPanel.detachOnWindowClose(button); + + return button; + } + + /** + * Creates a button with no caption. + */ + public SubmitButton() { + super(Document.get().createSubmitButtonElement()); + setStyleName("gwt-SubmitButton"); + } + + /** + * Creates a button with the given HTML caption. + * + * @param html the HTML caption + */ + public SubmitButton(String html) { + this(); + setHTML(html); + } + + /** + * Creates a button with the given HTML caption and click listener. + * + * @param html the HTML caption + * @param handler the click handler + */ + public SubmitButton(String html, ClickHandler handler) { + this(html); + addClickHandler(handler); + } + + /** + * This constructor may be used by subclasses to explicitly use an existing + * element. This element must be a <button> element with type submit. + * + * @param element the element to be used + */ + protected SubmitButton(com.google.gwt.dom.client.Element element) { + super(element); + assert "submit".equalsIgnoreCase(element.<ButtonElement> cast().getType()); + } +} ======================================= --- /trunk/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/DefaultMuseum.java Fri Aug 28 06:46:54 2009 +++ /trunk/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/DefaultMuseum.java Wed Sep 2 07:58:52 2009 @@ -49,6 +49,8 @@ addIssue(new Issue2553()); addIssue(new Issue2855()); addIssue(new Issue3172()); + addIssue(new Issue3962()); + addIssue(new Issue3973()); } public void addVisuals() { ======================================= --- /trunk/user/src/com/google/gwt/dom/client/DOMImpl.java Fri Aug 28 06:46:54 2009 +++ /trunk/user/src/com/google/gwt/dom/client/DOMImpl.java Wed Sep 2 07:58:52 2009 @@ -25,6 +25,12 @@ button.click(); }-*/; + public native ButtonElement createButtonElement(Document doc, String type) /*-{ + var e = doc.createElement("BUTTON"); + e.type = type; + return e; + }-*/; + public native Element createElement(Document doc, String tag) /*-{ return doc.createElement(tag); }-*/; ======================================= --- /trunk/user/src/com/google/gwt/dom/client/DOMImplSafari.java Tue Jul 21 07:15:12 2009 +++ /trunk/user/src/com/google/gwt/dom/client/DOMImplSafari.java Wed Sep 2 07:58:52 2009 @@ -20,6 +20,17 @@ */ class DOMImplSafari extends DOMImplStandard { + /** + * The type property on a button element is read-only in safari, so we need to + * set it using setAttribute. + */ + @Override + public native ButtonElement createButtonElement(Document doc, String type) /*-{ + var e = doc.createElement("BUTTON"); + e.setAttribute('type', type); + return e; + }-*/; + @Override public native NativeEvent createKeyEvent(Document doc, String type, boolean canBubble, boolean cancelable, boolean ctrlKey, boolean altKey, boolean shiftKey, ======================================= --- /trunk/user/src/com/google/gwt/dom/client/DOMImplTrident.java Fri Aug 28 06:46:54 2009 +++ /trunk/user/src/com/google/gwt/dom/client/DOMImplTrident.java Wed Sep 2 07:58:52 2009 @@ -21,11 +21,17 @@ * This field *must* be filled in from JSNI code before dispatching an event * on IE. It should be set to the 'this' context of the handler that receives * the event, then restored to its initial value when the dispatcher is done. - * See {...@link com.google.gwt.user.client.impl.DOMImplTrident#initEventSystem()} + * See + * {...@link com.google.gwt.user.client.impl.DOMImplTrident#initEventSystem()} * for an example of how this should be done. */ private static EventTarget currentEventTarget; + @Override + public native ButtonElement createButtonElement(Document doc, String type) /*-{ + return doc.createElement("<BUTTON type='" + type + "'></BUTTON>"); + }-*/; + @Override public Element createElement(Document doc, String tagName) { if (tagName.contains(":")) { @@ -48,8 +54,8 @@ } @Override - public native NativeEvent createHtmlEvent(Document doc, String type, boolean canBubble, - boolean cancelable) /*-{ + public native NativeEvent createHtmlEvent(Document doc, String type, + boolean canBubble, boolean cancelable) /*-{ // NOTE: IE doesn't support changing bubbling and canceling behavior (this // is documented publicly in Document.createHtmlEvent()). var evt = doc.createEventObject(); @@ -63,9 +69,9 @@ }-*/; @Override - public native NativeEvent createKeyEvent(Document doc, String type, boolean canBubble, - boolean cancelable, boolean ctrlKey, boolean altKey, boolean shiftKey, - boolean metaKey, int keyCode, int charCode) /*-{ + public native NativeEvent createKeyEvent(Document doc, String type, + boolean canBubble, boolean cancelable, boolean ctrlKey, boolean altKey, + boolean shiftKey, boolean metaKey, int keyCode, int charCode) /*-{ // NOTE: IE doesn't support changing bubbling and canceling behavior (this // is documented publicly in Document.createKeyEvent()). var evt = doc.createEventObject(); @@ -81,10 +87,10 @@ }-*/; @Override - public native NativeEvent createMouseEvent(Document doc, String type, boolean canBubble, - boolean cancelable, int detail, int screenX, int screenY, int clientX, - int clientY, boolean ctrlKey, boolean altKey, boolean shiftKey, - boolean metaKey, int button, Element relatedTarget) /*-{ + public native NativeEvent createMouseEvent(Document doc, String type, + boolean canBubble, boolean cancelable, int detail, int screenX, + int screenY, int clientX, int clientY, boolean ctrlKey, boolean altKey, + boolean shiftKey, boolean metaKey, int button, Element relatedTarget) /*-{ // NOTE: IE doesn't support changing bubbling and canceling behavior (this // is documented publicly in Document.createMouseEvent()). var evt = doc.createEventObject(); @@ -168,7 +174,7 @@ /** * IE returns a numeric type for some attributes that are really properties, - * such as offsetWidth. We need to coerce these to strings to prevent a + * such as offsetWidth. We need to coerce these to strings to prevent a * runtime JS exception. */ @Override @@ -192,6 +198,7 @@ return elem.innerText; }-*/; + @Override public String getTagName(Element elem) { String tagName = getTagNameInternal(elem); String scopeName = getScopeNameInternal(elem); ======================================= --- /trunk/user/src/com/google/gwt/dom/client/Document.java Fri Aug 28 06:46:54 2009 +++ /trunk/user/src/com/google/gwt/dom/client/Document.java Wed Sep 2 07:58:52 2009 @@ -68,7 +68,8 @@ * @return the newly created element */ public final QuoteElement createBlockQuoteElement() { - return (QuoteElement) DOMImpl.impl.createElement(this, QuoteElement.TAG_BLOCKQUOTE); + return (QuoteElement) DOMImpl.impl.createElement(this, + QuoteElement.TAG_BLOCKQUOTE); } /** @@ -89,12 +90,28 @@ /** * Creates a <button> element. + * <p> + * <b>Warning!</b> The button type is actually implementation-dependent and is + * read-only. * * @return the newly created element + * @deprecated use {...@link #createPushButtonElement()}, + * {...@link #createResetButtonElement()} or + * {...@link #createSubmitButtonElement()} instead. */ + @Deprecated public final ButtonElement createButtonElement() { return (ButtonElement) DOMImpl.impl.createElement(this, ButtonElement.TAG); } + + /** + * Creates an <input type='button'> element. + * + * @return the newly created element + */ + public final InputElement createButtonInputElement() { + return DOMImpl.impl.createInputElement(this, "button"); + } /** * Creates a <caption> element. @@ -102,7 +119,8 @@ * @return the newly created element */ public final TableCaptionElement createCaptionElement() { - return (TableCaptionElement) DOMImpl.impl.createElement(this, TableCaptionElement.TAG); + return (TableCaptionElement) DOMImpl.impl.createElement(this, + TableCaptionElement.TAG); } /** @@ -140,8 +158,8 @@ * @param metaKey <code>true</code> if the meta key is depressed * @return the event object */ - public final NativeEvent createClickEvent(int detail, int screenX, int screenY, - int clientX, int clientY, boolean ctrlKey, boolean altKey, + public final NativeEvent createClickEvent(int detail, int screenX, + int screenY, int clientX, int clientY, boolean ctrlKey, boolean altKey, boolean shiftKey, boolean metaKey) { // We disallow setting the button here, because IE doesn't provide the // button property for click events. @@ -156,7 +174,8 @@ * @return the newly created element */ public final TableColElement createColElement() { - return (TableColElement) DOMImpl.impl.createElement(this, TableColElement.TAG_COL); + return (TableColElement) DOMImpl.impl.createElement(this, + TableColElement.TAG_COL); } /** @@ -165,7 +184,8 @@ * @return the newly created element */ public final TableColElement createColGroupElement() { - return (TableColElement) DOMImpl.impl.createElement(this, TableColElement.TAG_COLGROUP); + return (TableColElement) DOMImpl.impl.createElement(this, + TableColElement.TAG_COLGROUP); } /** @@ -204,8 +224,8 @@ * @param metaKey <code>true</code> if the meta key is depressed * @return the event object */ - public final NativeEvent createDblClickEvent(int detail, int screenX, int screenY, - int clientX, int clientY, boolean ctrlKey, boolean altKey, + public final NativeEvent createDblClickEvent(int detail, int screenX, + int screenY, int clientX, int clientY, boolean ctrlKey, boolean altKey, boolean shiftKey, boolean metaKey) { // We disallow setting the button here, because IE doesn't provide the // button property for click events. @@ -266,7 +286,8 @@ * @return the newly created element */ public final FieldSetElement createFieldSetElement() { - return (FieldSetElement) DOMImpl.impl.createElement(this, FieldSetElement.TAG); + return (FieldSetElement) DOMImpl.impl.createElement(this, + FieldSetElement.TAG); } /** @@ -311,7 +332,8 @@ * @return the newly created element */ public final FrameSetElement createFrameSetElement() { - return (FrameSetElement) DOMImpl.impl.createElement(this, FrameSetElement.TAG); + return (FrameSetElement) DOMImpl.impl.createElement(this, + FrameSetElement.TAG); } /** @@ -577,8 +599,8 @@ * {...@link NativeEvent#BUTTON_LEFT} et al) * @return the event object */ - public final NativeEvent createMouseDownEvent(int detail, int screenX, int screenY, - int clientX, int clientY, boolean ctrlKey, boolean altKey, + public final NativeEvent createMouseDownEvent(int detail, int screenX, + int screenY, int clientX, int clientY, boolean ctrlKey, boolean altKey, boolean shiftKey, boolean metaKey, int button) { return createMouseEvent("mousedown", true, true, detail, screenX, screenY, clientX, clientY, ctrlKey, altKey, shiftKey, metaKey, button, null); @@ -643,8 +665,8 @@ * {...@link NativeEvent#BUTTON_LEFT} et al) * @return the event object */ - public final NativeEvent createMouseMoveEvent(int detail, int screenX, int screenY, - int clientX, int clientY, boolean ctrlKey, boolean altKey, + public final NativeEvent createMouseMoveEvent(int detail, int screenX, + int screenY, int clientX, int clientY, boolean ctrlKey, boolean altKey, boolean shiftKey, boolean metaKey, int button) { return createMouseEvent("mousemove", true, true, detail, screenX, screenY, clientX, clientY, ctrlKey, altKey, shiftKey, metaKey, button, null); @@ -670,8 +692,8 @@ * @param relatedTarget the event's related target * @return the event object */ - public final NativeEvent createMouseOutEvent(int detail, int screenX, int screenY, - int clientX, int clientY, boolean ctrlKey, boolean altKey, + public final NativeEvent createMouseOutEvent(int detail, int screenX, + int screenY, int clientX, int clientY, boolean ctrlKey, boolean altKey, boolean shiftKey, boolean metaKey, int button, Element relatedTarget) { return createMouseEvent("mouseout", true, true, detail, screenX, screenY, clientX, clientY, ctrlKey, altKey, shiftKey, metaKey, button, @@ -698,8 +720,8 @@ * @param relatedTarget the event's related target * @return the event object */ - public final NativeEvent createMouseOverEvent(int detail, int screenX, int screenY, - int clientX, int clientY, boolean ctrlKey, boolean altKey, + public final NativeEvent createMouseOverEvent(int detail, int screenX, + int screenY, int clientX, int clientY, boolean ctrlKey, boolean altKey, boolean shiftKey, boolean metaKey, int button, Element relatedTarget) { return createMouseEvent("mouseover", true, true, detail, screenX, screenY, clientX, clientY, ctrlKey, altKey, shiftKey, metaKey, button, @@ -722,8 +744,8 @@ * {...@link NativeEvent#BUTTON_LEFT} et al) * @return the event object */ - public final NativeEvent createMouseUpEvent(int detail, int screenX, int screenY, - int clientX, int clientY, boolean ctrlKey, boolean altKey, + public final NativeEvent createMouseUpEvent(int detail, int screenX, + int screenY, int clientX, int clientY, boolean ctrlKey, boolean altKey, boolean shiftKey, boolean metaKey, int button) { return createMouseEvent("mouseup", true, true, detail, screenX, screenY, clientX, clientY, ctrlKey, altKey, shiftKey, metaKey, button, null); @@ -753,7 +775,8 @@ * @return the newly created element */ public final OptGroupElement createOptGroupElement() { - return (OptGroupElement) DOMImpl.impl.createElement(this, OptGroupElement.TAG); + return (OptGroupElement) DOMImpl.impl.createElement(this, + OptGroupElement.TAG); } /** @@ -789,7 +812,8 @@ * @return the newly created element */ public final ParagraphElement createPElement() { - return (ParagraphElement) DOMImpl.impl.createElement(this, ParagraphElement.TAG); + return (ParagraphElement) DOMImpl.impl.createElement(this, + ParagraphElement.TAG); } /** @@ -800,6 +824,15 @@ public final PreElement createPreElement() { return (PreElement) DOMImpl.impl.createElement(this, PreElement.TAG); } + + /** + * Creates a <button type='button'> element. + * + * @return the newly created element + */ + public final ButtonElement createPushButtonElement() { + return DOMImpl.impl.createButtonElement(this, "button"); + } /** * Creates a <q> element. @@ -819,6 +852,24 @@ public final InputElement createRadioInputElement(String name) { return DOMImpl.impl.createInputRadioElement(this, name); } + + /** + * Creates a <button type='reset'> element. + * + * @return the newly created element + */ + public final ButtonElement createResetButtonElement() { + return DOMImpl.impl.createButtonElement(this, "reset"); + } + + /** + * Creates an <input type='reset'> element. + * + * @return the newly created element + */ + public final InputElement createResetInputElement() { + return DOMImpl.impl.createInputElement(this, "reset"); + } /** * Creates a <script> element. @@ -887,6 +938,15 @@ public final StyleElement createStyleElement() { return (StyleElement) DOMImpl.impl.createElement(this, StyleElement.TAG); } + + /** + * Creates a <button type='submit'> element. + * + * @return the newly created element + */ + public final ButtonElement createSubmitButtonElement() { + return DOMImpl.impl.createButtonElement(this, "submit"); + } /** * Creates an <input type='submit'> element. @@ -912,7 +972,8 @@ * @return the newly created element */ public final TableSectionElement createTBodyElement() { - return (TableSectionElement) DOMImpl.impl.createElement(this, TableSectionElement.TAG_TBODY); + return (TableSectionElement) DOMImpl.impl.createElement(this, + TableSectionElement.TAG_TBODY); } /** @@ -921,7 +982,8 @@ * @return the newly created element */ public final TableCellElement createTDElement() { - return (TableCellElement) DOMImpl.impl.createElement(this, TableCellElement.TAG_TD); + return (TableCellElement) DOMImpl.impl.createElement(this, + TableCellElement.TAG_TD); } /** @@ -930,7 +992,8 @@ * @return the newly created element */ public final TextAreaElement createTextAreaElement() { - return (TextAreaElement) DOMImpl.impl.createElement(this, TextAreaElement.TAG); + return (TextAreaElement) DOMImpl.impl.createElement(this, + TextAreaElement.TAG); } /** @@ -958,7 +1021,8 @@ * @return the newly created element */ public final TableSectionElement createTFootElement() { - return (TableSectionElement) DOMImpl.impl.createElement(this, TableSectionElement.TAG_TFOOT); + return (TableSectionElement) DOMImpl.impl.createElement(this, + TableSectionElement.TAG_TFOOT); } /** @@ -967,7 +1031,8 @@ * @return the newly created element */ public final TableSectionElement createTHeadElement() { - return (TableSectionElement) DOMImpl.impl.createElement(this, TableSectionElement.TAG_THEAD); + return (TableSectionElement) DOMImpl.impl.createElement(this, + TableSectionElement.TAG_THEAD); } /** @@ -976,7 +1041,8 @@ * @return the newly created element */ public final TableCellElement createTHElement() { - return (TableCellElement) DOMImpl.impl.createElement(this, TableCellElement.TAG_TH); + return (TableCellElement) DOMImpl.impl.createElement(this, + TableCellElement.TAG_TH); } /** @@ -994,7 +1060,8 @@ * @return the newly created element */ public final TableRowElement createTRElement() { - return (TableRowElement) DOMImpl.impl.createElement(this, TableRowElement.TAG); + return (TableRowElement) DOMImpl.impl.createElement(this, + TableRowElement.TAG); } /** ======================================= --- /trunk/user/src/com/google/gwt/user/client/ui/Button.java Fri Aug 28 06:46:54 2009 +++ /trunk/user/src/com/google/gwt/user/client/ui/Button.java Wed Sep 2 07:58:52 2009 @@ -28,9 +28,10 @@ * </p> * * <h3>CSS Style Rules</h3> - * <ul class="css"> - * <li>.gwt-Button { }</li> - * </ul> + * <dl> + * <dt>.gwt-Button</dt> + * <dd>the outer element</dd> + * </dl> * * <p> * <h3>Example</h3> @@ -53,6 +54,7 @@ assert Document.get().getBody().isOrHasChild(element); Button button = new Button(element); + assert "button".equalsIgnoreCase(button.getButtonElement().getType()); // Mark it attached and remember it for cleanup. button.onAttach(); @@ -61,22 +63,11 @@ return button; } - static native void adjustType(Element button) /*-{ - // Check before setting this attribute, as not all browsers define it. - if (button.type == 'submit') { - try { - button.setAttribute("type", "button"); - } catch (e) { - } - } - }-*/; - /** * Creates a button with no caption. */ public Button() { - super(Document.get().createButtonElement()); - adjustType(getElement()); + super(Document.get().createPushButtonElement()); setStyleName("gwt-Button"); } @@ -132,8 +123,12 @@ getButtonElement().click(); } - private ButtonElement getButtonElement() { + /** + * Get the underlying button element. + * + * @return the {...@link ButtonElement} + */ + protected ButtonElement getButtonElement() { return getElement().cast(); } } - ======================================= --- /trunk/user/src/com/google/gwt/user/client/ui/FormPanel.java Fri Aug 28 06:46:54 2009 +++ /trunk/user/src/com/google/gwt/user/client/ui/FormPanel.java Wed Sep 2 07:58:52 2009 @@ -569,24 +569,23 @@ // Create and attach a hidden iframe to the body element. createFrame(); Document.get().getBody().appendChild(synthesizedFrame); - - // Hook up the underlying iframe's onLoad event when attached to the DOM. - // Making this connection only when attached avoids memory-leak issues. - // The FormPanel cannot use the built-in GWT event-handling mechanism - // because there is no standard onLoad event on iframes that works across - // browsers. - impl.hookEvents(synthesizedFrame, getElement(), this); - } + } + // Hook up the underlying iframe's onLoad event when attached to the DOM. + // Making this connection only when attached avoids memory-leak issues. + // The FormPanel cannot use the built-in GWT event-handling mechanism + // because there is no standard onLoad event on iframes that works across + // browsers. + impl.hookEvents(synthesizedFrame, getElement(), this); } @Override protected void onDetach() { super.onDetach(); - if (synthesizedFrame != null) { - // Unhook the iframe's onLoad when detached. - impl.unhookEvents(synthesizedFrame, getElement()); - + // Unhook the iframe's onLoad when detached. + impl.unhookEvents(synthesizedFrame, getElement()); + + if (synthesizedFrame != null) { // And remove it from the document. Document.get().getBody().removeChild(synthesizedFrame); synthesizedFrame = null; ======================================= --- /trunk/user/test/com/google/gwt/dom/client/DocumentTest.java Fri Aug 28 06:46:54 2009 +++ /trunk/user/test/com/google/gwt/dom/client/DocumentTest.java Wed Sep 2 07:58:52 2009 @@ -37,7 +37,6 @@ assertEquals("blockquote", doc.createBlockQuoteElement().getTagName().toLowerCase()); assertEquals("br", doc.createBRElement().getTagName().toLowerCase()); - assertEquals("button", doc.createButtonElement().getTagName().toLowerCase()); assertEquals("caption", doc.createCaptionElement().getTagName().toLowerCase()); assertEquals("col", doc.createColElement().getTagName().toLowerCase()); @@ -91,6 +90,20 @@ assertEquals("tr", doc.createTRElement().getTagName().toLowerCase()); assertEquals("ul", doc.createULElement().getTagName().toLowerCase()); + assertEquals("button", + doc.createPushButtonElement().getTagName().toLowerCase()); + assertEquals("button", + doc.createResetButtonElement().getTagName().toLowerCase()); + assertEquals("button", + doc.createSubmitButtonElement().getTagName().toLowerCase()); + + assertEquals("button", + doc.createPushButtonElement().getType().toLowerCase()); + assertEquals("reset", + doc.createResetButtonElement().getType().toLowerCase()); + assertEquals("submit", + doc.createSubmitButtonElement().getType().toLowerCase()); + assertEquals("input", doc.createCheckInputElement().getTagName().toLowerCase()); assertEquals("input", @@ -106,6 +119,8 @@ assertEquals("input", doc.createTextInputElement().getTagName().toLowerCase()); + assertEquals("button", + doc.createButtonInputElement().getType().toLowerCase()); assertEquals("checkbox", doc.createCheckInputElement().getType().toLowerCase()); assertEquals("file", doc.createFileInputElement().getType().toLowerCase()); @@ -116,6 +131,9 @@ doc.createPasswordInputElement().getType().toLowerCase()); assertEquals("radio", doc.createRadioInputElement("foo").getType().toLowerCase()); + assertEquals("reset", doc.createResetInputElement().getType().toLowerCase()); + assertEquals("submit", + doc.createSubmitInputElement().getType().toLowerCase()); assertEquals("text", doc.createTextInputElement().getType().toLowerCase()); } ======================================= --- /trunk/user/test/com/google/gwt/dom/client/ElementTest.java Fri Aug 28 06:46:54 2009 +++ /trunk/user/test/com/google/gwt/dom/client/ElementTest.java Wed Sep 2 07:58:52 2009 @@ -75,7 +75,7 @@ * Test round-trip of the 'disabled' property. */ public void testDisabled() { - ButtonElement button = Document.get().createButtonElement(); + ButtonElement button = Document.get().createPushButtonElement(); assertFalse(button.isDisabled()); button.setDisabled(true); assertTrue(button.isDisabled()); ======================================= --- /trunk/user/test/com/google/gwt/user/UISuite.java Fri Aug 28 06:46:54 2009 +++ /trunk/user/test/com/google/gwt/user/UISuite.java Wed Sep 2 07:58:52 2009 @@ -133,6 +133,7 @@ suite.addTestSuite(FlexTableTest.class); suite.addTestSuite(FlowPanelTest.class); suite.addTestSuite(FocusPanelTest.class); + // Old Mozilla complains about the cross-site forms in FormPanelTest. // suite.addTestSuite(FormPanelTest.class); suite.addTestSuite(GridTest.class); suite.addTestSuite(HiddenTest.class); ======================================= --- /trunk/user/test/com/google/gwt/user/client/ui/ButtonTest.java Fri Aug 28 06:46:54 2009 +++ /trunk/user/test/com/google/gwt/user/client/ui/ButtonTest.java Wed Sep 2 07:58:52 2009 @@ -19,12 +19,16 @@ import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.junit.client.GWTTestCase; +import com.google.gwt.user.client.Timer; +import com.google.gwt.user.client.ui.FormPanel.SubmitEvent; +import com.google.gwt.user.client.ui.FormPanel.SubmitHandler; /** * Tests for {...@link Button}. */ public class ButtonTest extends GWTTestCase { + @Override public String getModuleName() { return "com.google.gwt.user.User"; } @@ -38,6 +42,26 @@ clicked = true; } } + + private static class H2 implements SubmitHandler { + boolean submitted; + + public void onSubmit(SubmitEvent event) { + submitted = true; + event.cancel(); + } + } + + public void testButton() { + Button pushButton = new Button(); + assertEquals("button", pushButton.getButtonElement().getType()); + + ResetButton resetButton = new ResetButton(); + assertEquals("reset", resetButton.getButtonElement().getType()); + + SubmitButton submitButton = new SubmitButton(); + assertEquals("submit", submitButton.getButtonElement().getType()); + } public void testClick() { Button b = new Button(); @@ -53,5 +77,30 @@ // synthesized clicks. This tests the workaround in DOMImplMozillaOld. assertEquals(b.getElement(), h.target); } -} - + + /** + * Tests issues 1585 and 3962: a button shouldn't submit a form. + */ + public void testPushButton() { + FormPanel f = new FormPanel(); + f.setAction("javascript:''"); + RootPanel.get().add(f); + + Button b = new Button(); + f.setWidget(b); + + final H2 h = new H2(); + f.addSubmitHandler(h); + + delayTestFinish(5000); + new Timer() { + @Override + public void run() { + assertFalse(h.submitted); + finishTest(); + } + }.schedule(2500); + + b.click(); + } +} ======================================= --- /trunk/user/test/com/google/gwt/user/client/ui/FormPanelTest.java Fri Aug 28 06:46:54 2009 +++ /trunk/user/test/com/google/gwt/user/client/ui/FormPanelTest.java Wed Sep 2 07:58:52 2009 @@ -18,18 +18,22 @@ 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.junit.client.GWTTestCase; import com.google.gwt.user.client.Timer; +import com.google.gwt.user.client.ui.FormPanel.SubmitEvent; +import com.google.gwt.user.client.ui.FormPanel.SubmitHandler; import com.google.gwt.user.client.ui.HasWidgetsTester.WidgetAdder; /** * Tests the FormPanel. * - * @see FormPanelTestServlet + * @see com.google.gwt.user.server.ui.FormPanelTestServlet */ public class FormPanelTest extends GWTTestCase { public static boolean clicked = false; + @Override public String getModuleName() { return "com.google.gwt.user.FormPanelTest"; } @@ -161,15 +165,48 @@ form.submit(); } + + public void testNamedTargetSubmitEvent() { + // Create a form and frame in the document we can wrap. + String uid = Document.get().createUniqueId(); + HTML formAndFrame = new HTML( + "<form id='" + + uid + + "' method='post' target='targetFrame' action='" + + GWT.getModuleBaseURL() + + "formHandler?sendHappyHtml'>" + + "<input type='submit' id='submitBtn'></input></form>" + + "<iframe src='javascript:\'\'' id='targetMe' name='targetFrame'></iframe>"); + RootPanel.get().add(formAndFrame); + + // Wrap the form and make sure its target frame is intact. + FormPanel form = FormPanel.wrap(Document.get().getElementById(uid)); + assertEquals("targetFrame", form.getTarget()); + + // Ensure that no synthesized iframe was created. + assertNull(form.getSynthesizedIFrame()); + + // Submit the form using the submit button and make sure the submit event fires. + delayTestFinish(5000); + form.addSubmitHandler(new SubmitHandler() { + public void onSubmit(SubmitEvent event) { + finishTest(); + } + }); + + Document.get().getElementById("submitBtn").<InputElement>cast().click(); + } public void testReset() { FormPanel form = new FormPanel(); + RootPanel.get().add(form); TextBox textBox = new TextBox(); textBox.setText("Hello World"); form.setWidget(textBox); assertEquals("Hello World", textBox.getText()); form.reset(); assertEquals("", textBox.getText()); + RootPanel.get().remove(form); } public void testSubmitAndHideDialog() { @@ -219,6 +256,7 @@ delayTestFinish(10000); Timer t = new Timer() { + @Override public void run() { // Make sure the frame got the contents we expected. assertTrue(isHappyDivPresent(frame.getElement())); --~--~---------~--~----~------------~-------~--~----~ http://groups.google.com/group/Google-Web-Toolkit-Contributors -~----------~----~----~----~------~----~------~--~---
