exxcellent / echolot

An advanced widget library for the hybrid Java/JavaScript RIA Framework Echo 3 by nextapp
http://exxcellent.github.com/echolot/
9 stars 5 forks source link

KeystrokeListener disapears after textField.setBackground() #12

Open adamb111 opened 13 years ago

adamb111 commented 13 years ago

I tested KeystrokeListener and found small but annoying bug. To reproduce bug, add to class KeystrokeTest call tf1.setBackground() as follows and run server-side demo app.

...... final TextField tf1 = new TextField(); instructLabel.setFormatWhitespace(true);

    final CheckBox cb = new CheckBox("Set Background and disable h-listener");
    cb.addChangeListener(new ChangeListener() {
        @Override
        public void stateChanged(ChangeEvent e) {
            if(cb.isSelected()) {
                tf1.setBackground(Color.CYAN);
            }
            else {
                tf1.setBackground(Color.WHITE);
            }
        }
    });
    cb.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
        }
    });

    layout = new Grid(1);
    layout.add(instructLabel);
    layout.add(new Label(StyleUtil.QUASI_LATIN_TEXT_1));
    layout.add(tf1);
    layout.add(new TextField());
    layout.add(new TextField());
    layout.add(cb);
    layout.add(resultLabel);
    add(layout);

...... Now click CheckBox. H-key listener doesn't work, but ctrl-h listener still works. I found workaround. Unfortunately it isn't simple, doesn't solve all potential problems and needs to change Echo sources. The file SyncTextComponent.js from Echo3 contains class Echo.Sync.TextComponent, and function renderUpdate. I changed this function and add getSupportedPartialProperties():

getSupportedPartialProperties: function() {
    return ["text", "background", "foreground", "editable"];
},

/** @see Echo.Render.ComponentSync#renderUpdate */
renderUpdate: function(update) {
    var fullRender = !Core.Arrays.containsAll(this.getSupportedPartialProperties(), update.getUpdatedPropertyNames(), true);

    if (fullRender) {
        var element = this.container ? this.container : this.input;
        var containerElement = element.parentNode;
        this.renderDispose(update);
        containerElement.removeChild(element);
        this.renderAdd(update, containerElement);
    } else {
        if (update.hasUpdatedProperties()) {
            var textUpdate = update.getUpdatedProperty("text");
            if (textUpdate) {
                var newValue = textUpdate.newValue == null ? "" : textUpdate.newValue;
                if (newValue != this._lastProcessedValue) {
                    this.input.value = newValue;
                    this._lastProcessedValue = newValue;
                }
            }
            var editableUpdate = update.getUpdatedProperty("editable");
            if (editableUpdate != null) {
                this.input.readOnly = !editableUpdate.newValue;
            }
            var propertyBackground = update.getUpdatedProperty("background");
            if (propertyBackground != null) {
                Echo.Sync.Color.renderClear(propertyBackground.newValue, this.input, "backgroundColor");
            }
            var propertyForeground = update.getUpdatedProperty("foreground");
            if (propertyForeground != null) {
                Echo.Sync.Color.renderClear(propertyForeground.newValue, this.input, "foreground");
            }
        }
    }

    return false; // Child elements not supported: safe to return false.
},
bentolor commented 13 years ago

Thanks for your report. adamb111 already pinpointed the problem: The render peer of the TextComponent drops & replaces the HTML DOM element on updates it cannot apply incrementally.

Support for key shortcuts should be part of the core Echo framework. The KeystrokeListener component can only act as workaround. It behaves like a component without any real visible (DOM) element, which modifies / attaches DOM event listener on DOM elements belonging to other (the targeted) components.

The initially attached key event listener on the textbox DOM element gets lost, because Echo replaces its with a new copy and the Keylistener-Component has no clue that it needs to reattach a new event listener to the new component.

Adamb111's change just avoids this an implements an incremental update for background colour changes. So it fixes this special problem but similar will happen on other changes which lead to a "fullRender".