summaryrefslogtreecommitdiffstats
path: root/client
diff options
context:
space:
mode:
authorArtem Godin <artem@vaadin.com>2013-10-02 17:07:14 +0300
committerVaadin Code Review <review@vaadin.com>2013-10-03 12:08:42 +0000
commit267a4cae6de31d143c3d8d1d8dd79d4616896603 (patch)
treedacf102c9c4b41221a98a7a0d26852c950e7b929 /client
parent0e9ff32598ed86d5f24a8bce5c5c898d81dc2c84 (diff)
downloadvaadin-framework-267a4cae6de31d143c3d8d1d8dd79d4616896603.tar.gz
vaadin-framework-267a4cae6de31d143c3d8d1d8dd79d4616896603.zip
Fix OptionGroup elements losing focus on value change (#10451)
The misbehavior was caused by VOptionGroup.buildOptions recreating associated panel on every change by removing and adding new elements. With this fix applied it tries to update existing elements, distinguishing them by assigned keys. It will recreate panel though if elements are reordered or new elements were added/removed. Change-Id: I1245b2ff30ce1932614c1eac37bd0131cbd29dd7
Diffstat (limited to 'client')
-rw-r--r--client/src/com/vaadin/client/ui/VOptionGroup.java67
1 files changed, 50 insertions, 17 deletions
diff --git a/client/src/com/vaadin/client/ui/VOptionGroup.java b/client/src/com/vaadin/client/ui/VOptionGroup.java
index a4c8b6733c..455c7669f5 100644
--- a/client/src/com/vaadin/client/ui/VOptionGroup.java
+++ b/client/src/com/vaadin/client/ui/VOptionGroup.java
@@ -95,11 +95,29 @@ public class VOptionGroup extends VOptionGroupBase implements FocusHandler,
}
/*
- * Return true if no elements were changed, false otherwise.
+ * Try to update content of existing elements, rebuild panel entirely
+ * otherwise
*/
@Override
public void buildOptions(UIDL uidl) {
- panel.clear();
+ /*
+ * In order to retain focus, we need to update values rather than
+ * recreate panel from scratch (#10451). However, the panel will be
+ * rebuilt (losing focus) if number of elements or their order is
+ * changed.
+ */
+ HashMap<String, CheckBox> keysToOptions = new HashMap<String, CheckBox>();
+ for (Map.Entry<CheckBox, String> entry : optionsToKeys.entrySet()) {
+ keysToOptions.put(entry.getValue(), entry.getKey());
+ }
+ ArrayList<Widget> existingwidgets = new ArrayList<Widget>();
+ ArrayList<Widget> newwidgets = new ArrayList<Widget>();
+
+ // Get current order of elements
+ for (Widget wid : panel) {
+ existingwidgets.add(wid);
+ }
+
optionsEnabled.clear();
if (isMultiselect()) {
@@ -110,7 +128,6 @@ public class VOptionGroup extends VOptionGroupBase implements FocusHandler,
for (final Iterator<?> it = uidl.getChildIterator(); it.hasNext();) {
final UIDL opUidl = (UIDL) it.next();
- CheckBox op;
String itemHtml = opUidl.getStringAttribute("caption");
if (!htmlContentAllowed) {
@@ -124,32 +141,48 @@ public class VOptionGroup extends VOptionGroupBase implements FocusHandler,
+ Icon.CLASSNAME + "\" alt=\"\" />" + itemHtml;
}
- if (isMultiselect()) {
- op = new VCheckBox();
- op.setHTML(itemHtml);
- } else {
- op = new RadioButton(paintableId, itemHtml, true);
- op.setStyleName("v-radiobutton");
- }
+ String key = opUidl.getStringAttribute("key");
+ CheckBox op = keysToOptions.get(key);
+ if (op == null) {
+ // Create a new element
+ if (isMultiselect()) {
+ op = new VCheckBox();
+ } else {
+ op = new RadioButton(paintableId);
+ op.setStyleName("v-radiobutton");
+ }
+ if (icon != null && icon.length() != 0) {
+ Util.sinkOnloadForImages(op.getElement());
+ op.addHandler(iconLoadHandler, LoadEvent.getType());
+ }
- if (icon != null && icon.length() != 0) {
- Util.sinkOnloadForImages(op.getElement());
- op.addHandler(iconLoadHandler, LoadEvent.getType());
+ op.addStyleName(CLASSNAME_OPTION);
+ op.addClickHandler(this);
+
+ optionsToKeys.put(op, key);
}
- op.addStyleName(CLASSNAME_OPTION);
+ op.setHTML(itemHtml);
op.setValue(opUidl.getBooleanAttribute("selected"));
boolean optionEnabled = !opUidl
.getBooleanAttribute(OptionGroupConstants.ATTRIBUTE_OPTION_DISABLED);
boolean enabled = optionEnabled && !isReadonly() && isEnabled();
op.setEnabled(enabled);
optionsEnabled.add(optionEnabled);
+
setStyleName(op.getElement(),
ApplicationConnection.DISABLED_CLASSNAME,
!(optionEnabled && isEnabled()));
- op.addClickHandler(this);
- optionsToKeys.put(op, opUidl.getStringAttribute("key"));
- panel.add(op);
+
+ newwidgets.add(op);
+ }
+
+ if (!newwidgets.equals(existingwidgets)) {
+ // Rebuild the panel, losing focus
+ panel.clear();
+ for (Widget wid : newwidgets) {
+ panel.add(wid);
+ }
}
}