gwtproject / gwt

GWT Open Source Project
http://www.gwtproject.org
1.52k stars 374 forks source link

CellTree in IE7 receives two change events for one checkbox check #5753

Closed dankurka closed 9 years ago

dankurka commented 9 years ago

Originally reported on Google Code with ID 5754

Found in GWT Release (e.g. 1.5.3, 1.6 RC):

2.1 release

Encountered on OS / Browser (e.g. WinXP, IE6-7, FF3):

IE7 (may include other IEs). Windows XP and RHEL.

Detailed description (please be as specific as possible):

This is not an issue in other browsers, and doesn't occur in IE7 if you set a breakpoint
in the relevant onBrowserEvent method, suggesting there may be an issue in the JavaScript
compilation?

The issue is as follows:

I have a custom Cell, which extends AbstractEditableCell<MyRecord, Boolean>. This cell
contains a checkbox, an image and some text. I wish to capture when the checkboxes
are checked / unchecked. In IE7, two "change" events are received by the 

public void onBrowserEvent(Element parent, MyRecord value,
                Object key, NativeEvent event,
                ValueUpdater<MyRecord> valueUpdater)

event for just one click of the checkbox, with TWO DIFFERENT event IDs, so event.stopPropagation()
does not help.

This can be a problem if you depend on the validity of these events to switch values
in your data. E.g. You cannot say "If this checkbox gets clicked, then swap the value
of this boolean" because the event may be called twice, swapping the value back to
its original state.

Shortest code snippet which demonstrates issue (please indicate where
actual result differs from expected result):

private class MyCell extends AbstractEditableCell<MyRecord, Boolean> {

    private static final String INPUT_CHECKED   = "<input type=\"checkbox\" checked/>";
    private static final String INPUT_UNCHECKED = "<input type=\"checkbox\"/>";

    public MyCell() {

        super("change", "keyup");
    }

    @Override
    public void render(MyRecord value, Object key, SafeHtmlBuilder sb) {

        sb.appendHtmlConstant("<div>");

        if (value != null && (value.isSelected()) ) {
            sb.appendHtmlConstant(INPUT_CHECKED);
        } else {
            sb.appendHtmlConstant(INPUT_UNCHECKED);
        }

        //Image
        sb.appendHtmlConstant(AbstractImagePrototype.create(value.getIcon()).getHTML());

        //Text
        sb.appendHtmlConstant(" " + value.getDisplayText() + "<br>");

        sb.appendHtmlConstant("</div>");

    }

    @Override
    public void onBrowserEvent(Element parent, MyRecord value,
                               Object key, NativeEvent event,
                               ValueUpdater<MyRecord> valueUpdater) {

        // Handle click events          
        if ("change".equals(event.getType())) {
            //In IE7 (when not debugging ONLY), we will come here TWICE for ONE mouse
click
            //The two events will have different IDs
        }
    }

    @Override
    public boolean isEditing(Element parent, MyRecord value,
                             Object key) {
        return false;
    }
}

Workaround if you have one:

This is easy enough to work around, there are better ways of integrating a checkbox
/ boolean view / model than this. The reason I hace raised this issue is to point out
the aparent strangeness of duplicate events in IE release mode.

Use a JavaScript bowser sniff to detect IE, if so, read the checkbox state directly
from the parent element's HTML, rather than just switching the relevant value from
true to false, or vice-versa.

A better option may be to follow the example in CheckBoxCell, and use

      InputElement input = parent.getFirstChild().cast();
      Boolean isChecked = input.isChecked();

to check the checkbox state. Obviously, adjust the parent.get call to match the actual
position of your checkbox.

Reported by AndrewScully on 2010-12-13 09:56:04

dankurka commented 9 years ago

Reported by dankurka@google.com on 2013-05-26 23:33:19