Kaynağa Gözat

Implement focus handing in RadioButtonGroup and CheckboxGroup (#10440)

Fixes #10429

* implement focus handing in RadioButtonGroup, fixes #10429

* Merge branch 'master' of https://github.com/vaadin/framework into radiobuttongroup-focus

* merge

* Merge branch 'master' of https://github.com/vaadin/framework into radiobuttongroup-focus

* fix initial focus handling also on CheckBoxGroup and add tests

* add license headers

* Merge branch 'master' of https://github.com/vaadin/framework into radiobuttongroup-focus

* changed client to use lambdas and refactored focus testing to parent class

* made FocusTest abstract

* Merge branch 'master' of https://github.com/vaadin/framework into radiobuttongroup-focus

* don't allow focusing on disabled items & refactor focusing first item
tags/8.4.0.alpha1
Olli Tietäväinen 6 yıl önce
ebeveyn
işleme
c641c7f56f

+ 11
- 0
client/src/main/java/com/vaadin/client/ui/VCheckBoxGroup.java Dosyayı Görüntüle

@@ -23,6 +23,7 @@ import java.util.Map;
import java.util.function.BiConsumer;

import com.google.gwt.aria.client.Roles;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.dom.client.Element;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
@@ -235,4 +236,14 @@ public class VCheckBoxGroup extends FocusableFlowPanelComposite
.remove(selectionChanged);
}

/**
* Set focus to the first check box.
*/
@Override
public void focus() {
// If focus is set on creation, need to wait until options are populated
Scheduler.get().scheduleDeferred(() -> {
getWidget().focusFirstEnabledChild();
});
}
}

+ 25
- 1
client/src/main/java/com/vaadin/client/ui/VRadioButtonGroup.java Dosyayı Görüntüle

@@ -24,6 +24,7 @@ import java.util.Optional;
import java.util.function.Consumer;

import com.google.gwt.aria.client.Roles;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.dom.client.Element;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
@@ -40,6 +41,7 @@ import com.vaadin.client.widgets.FocusableFlowPanelComposite;
import com.vaadin.shared.Registration;
import com.vaadin.shared.data.DataCommunicatorConstants;
import com.vaadin.shared.ui.ListingJsonConstants;

import elemental.json.JsonObject;

/**
@@ -271,9 +273,30 @@ public class VRadioButtonGroup extends FocusableFlowPanelComposite
}
}

/**
* Set focus to the selected radio button (or first radio button if there is
* no selection).
*/
@Override
public void focus() {
// If focus is set on creation, need to wait until options are populated
Scheduler.get().scheduleDeferred(() -> {
// if there's a selected radio button, focus it
for (String key : keyToOptions.keySet()) {
RadioButton radioButton = keyToOptions.get(key);
if (radioButton != null && radioButton.getValue()) {
radioButton.setFocus(true);
return;
}
}
// otherwise focus the first enabled child
getWidget().focusFirstEnabledChild();
});
}

/**
* Updates the selected state of a radio button.
*
*
* @param radioButton
* the radio button to update
* @param value
@@ -282,5 +305,6 @@ public class VRadioButtonGroup extends FocusableFlowPanelComposite
protected void updateItemSelection(RadioButton radioButton, boolean value) {
radioButton.setValue(value);
radioButton.setStyleName(CLASSNAME_OPTION_SELECTED, value);

}
}

+ 20
- 0
client/src/main/java/com/vaadin/client/widgets/ChildFocusAwareFlowPanel.java Dosyayı Görüntüle

@@ -153,6 +153,26 @@ public class ChildFocusAwareFlowPanel extends FocusableFlowPanel
}
}

/**
* Put focus in the first child Widget that can be focused and is not
* disabled.
*/
public void focusFirstEnabledChild() {
for (int i = 0; i < getWidgetCount(); i++) {
Widget widget = getWidget(i);
if (!(widget instanceof FocusWidget)) {
continue;
}
FocusWidget focusableChild = (FocusWidget) widget;
if (focusableChild.isEnabled()) {
focusableChild.setFocus(true);
break;
}

}

}

private void addHandlers(Widget widget) {
if (focusRegistrations.containsKey(widget)) {
assert blurRegistrations.containsKey(widget);

+ 40
- 0
uitest/src/main/java/com/vaadin/tests/components/checkboxgroup/CheckBoxGroupFocus.java Dosyayı Görüntüle

@@ -0,0 +1,40 @@
/*
* Copyright 2000-2016 Vaadin Ltd.
*
* 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.vaadin.tests.components.checkboxgroup;

import com.vaadin.annotations.Widgetset;
import com.vaadin.server.VaadinRequest;
import com.vaadin.tests.components.AbstractTestUIWithLog;
import com.vaadin.ui.Button;
import com.vaadin.ui.CheckBoxGroup;

@Widgetset("com.vaadin.DefaultWidgetSet")
public class CheckBoxGroupFocus extends AbstractTestUIWithLog {

@Override
protected void setup(VaadinRequest request) {
CheckBoxGroup<String> cbg = new CheckBoxGroup<>("CheckBoxes");
cbg.setItems("Test1", "Test2", "Test3");
cbg.select("Test2");
cbg.setItemCaptionGenerator(item -> "Option " + item);
cbg.focus();
CheckBoxGroup<String> cbg2 = new CheckBoxGroup<>("No selection");
cbg2.setItems("Foo1", "Foo2", "Foo3");
Button button = new Button("focus second group", e -> cbg2.focus());
addComponents(cbg, cbg2, button);
}

}

+ 44
- 0
uitest/src/main/java/com/vaadin/tests/components/radiobuttongroup/RadioButtonGroupFocus.java Dosyayı Görüntüle

@@ -0,0 +1,44 @@
/*
* Copyright 2000-2016 Vaadin Ltd.
*
* 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.vaadin.tests.components.radiobuttongroup;

import com.vaadin.annotations.Widgetset;
import com.vaadin.server.VaadinRequest;
import com.vaadin.tests.components.AbstractTestUIWithLog;
import com.vaadin.ui.Button;
import com.vaadin.ui.RadioButtonGroup;

/**
* @author Vaadin Ltd
*
*/
@Widgetset("com.vaadin.DefaultWidgetSet")
public class RadioButtonGroupFocus extends AbstractTestUIWithLog {

@Override
protected void setup(VaadinRequest request) {
RadioButtonGroup<String> rbg = new RadioButtonGroup<>("Radios");
rbg.setItems("Test1", "Test2", "Test3");
rbg.setSelectedItem("Test2");
rbg.setItemCaptionGenerator(item -> "Option " + item);
rbg.focus();
RadioButtonGroup<String> rbg2 = new RadioButtonGroup<>("No selection");
rbg2.setItems("Foo1", "Foo2", "Foo3");
Button button = new Button("focus second group", e -> rbg2.focus());
addComponents(rbg, rbg2, button);
}

}

+ 47
- 0
uitest/src/test/java/com/vaadin/tests/components/FocusTest.java Dosyayı Görüntüle

@@ -0,0 +1,47 @@
/*
* Copyright 2000-2016 Vaadin Ltd.
*
* 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.vaadin.tests.components;

import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;

import java.util.List;

import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.remote.DesiredCapabilities;

import com.vaadin.testbench.TestBenchElement;
import com.vaadin.tests.tb3.MultiBrowserTest;

public abstract class FocusTest extends MultiBrowserTest {

protected boolean isFocusInsideElement(TestBenchElement element) {
WebElement focused = getFocusedElement();
assertNotNull(focused);
String id = focused.getAttribute("id");
assertTrue("Focused element should have a non-empty id",
id != null && !"".equals(id));
return element.isElementPresent(By.id(id));
}

@Override
public List<DesiredCapabilities> getBrowsersToTest() {
// Focus does not move when expected with Selenium/TB and Firefox 45
return getBrowsersExcludingFirefox();
}

}

+ 45
- 0
uitest/src/test/java/com/vaadin/tests/components/checkboxgroup/CheckBoxGroupFocusTest.java Dosyayı Görüntüle

@@ -0,0 +1,45 @@
/*
* Copyright 2000-2016 Vaadin Ltd.
*
* 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.vaadin.tests.components.checkboxgroup;

import static org.junit.Assert.assertTrue;

import org.junit.Test;

import com.vaadin.testbench.elements.ButtonElement;
import com.vaadin.testbench.elements.CheckBoxGroupElement;
import com.vaadin.tests.components.FocusTest;

public class CheckBoxGroupFocusTest extends FocusTest {

@Test
public void focusOnInit() {
openTestURL();
CheckBoxGroupElement checkBoxGroup = $(CheckBoxGroupElement.class)
.first();
assertTrue(isFocusInsideElement(checkBoxGroup));
}

@Test
public void moveFocusAfterClick() {
openTestURL();
$(ButtonElement.class).first().click();
CheckBoxGroupElement checkBoxGroup = $(CheckBoxGroupElement.class)
.last();
assertTrue(isFocusInsideElement(checkBoxGroup));
}

}

+ 45
- 0
uitest/src/test/java/com/vaadin/tests/components/radiobuttongroup/RadioButtonGroupFocusTest.java Dosyayı Görüntüle

@@ -0,0 +1,45 @@
/*
* Copyright 2000-2016 Vaadin Ltd.
*
* 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.vaadin.tests.components.radiobuttongroup;

import static org.junit.Assert.assertTrue;

import org.junit.Test;

import com.vaadin.testbench.elements.ButtonElement;
import com.vaadin.testbench.elements.RadioButtonGroupElement;
import com.vaadin.tests.components.FocusTest;

public class RadioButtonGroupFocusTest extends FocusTest {

@Test
public void focusOnInit() {
openTestURL();
RadioButtonGroupElement radioButtonGroup = $(
RadioButtonGroupElement.class).first();
assertTrue(isFocusInsideElement(radioButtonGroup));
}

@Test
public void moveFocusAfterClick() {
openTestURL();
$(ButtonElement.class).first().click();
RadioButtonGroupElement radioButtonGroup2 = $(
RadioButtonGroupElement.class).last();
assertTrue(isFocusInsideElement(radioButtonGroup2));
}

}

Loading…
İptal
Kaydet