mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-10 03:45:46 +00:00
Bug 1498769 - Also require a frame for an <option> to be interactively selectable. r=enndeakin
This commit is contained in:
parent
e17d968203
commit
4ff1bdbeb2
@ -36,6 +36,7 @@
|
||||
#include <algorithm>
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
|
||||
// Constants
|
||||
const uint32_t kMaxDropDownRows = 20; // This matches the setting for 4.x browsers
|
||||
@ -1147,7 +1148,7 @@ nsListControlFrame::GetNonDisabledOptionFrom(int32_t aFromIndex,
|
||||
if (!node) {
|
||||
break;
|
||||
}
|
||||
if (!selectElement->IsOptionDisabled(node)) {
|
||||
if (IsOptionInteractivelySelectable(selectElement, node)) {
|
||||
if (aFoundIndex) {
|
||||
*aFoundIndex = i;
|
||||
}
|
||||
@ -1549,16 +1550,23 @@ nsListControlFrame::GetBSizeOfARow()
|
||||
return BSizeOfARow();
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsListControlFrame::IsOptionDisabled(int32_t anIndex, bool &aIsDisabled)
|
||||
bool
|
||||
nsListControlFrame::IsOptionInteractivelySelectable(int32_t aIndex) const
|
||||
{
|
||||
RefPtr<dom::HTMLSelectElement> sel =
|
||||
dom::HTMLSelectElement::FromNode(mContent);
|
||||
if (sel) {
|
||||
sel->IsOptionDisabled(anIndex, &aIsDisabled);
|
||||
return NS_OK;
|
||||
if (HTMLSelectElement* sel = HTMLSelectElement::FromNode(mContent)) {
|
||||
if (HTMLOptionElement* item = sel->Item(aIndex)) {
|
||||
return IsOptionInteractivelySelectable(sel, item);
|
||||
}
|
||||
}
|
||||
return NS_ERROR_FAILURE;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
nsListControlFrame::IsOptionInteractivelySelectable(HTMLSelectElement* aSelect,
|
||||
HTMLOptionElement* aOption)
|
||||
{
|
||||
return !aSelect->IsOptionDisabled(aOption) &&
|
||||
aOption->GetPrimaryFrame();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
@ -1664,10 +1672,8 @@ nsListControlFrame::MouseUp(dom::Event* aMouseEvent)
|
||||
|
||||
int32_t selectedIndex;
|
||||
if (NS_SUCCEEDED(GetIndexFromDOMEvent(aMouseEvent, selectedIndex))) {
|
||||
// If it's disabled, disallow the click and leave.
|
||||
bool isDisabled = false;
|
||||
IsOptionDisabled(selectedIndex, isDisabled);
|
||||
if (isDisabled) {
|
||||
// If it's not selectable, disallow the click and leave.
|
||||
if (!IsOptionInteractivelySelectable(selectedIndex)) {
|
||||
aMouseEvent->PreventDefault();
|
||||
aMouseEvent->StopPropagation();
|
||||
CaptureMouseEvents(false);
|
||||
@ -2036,9 +2042,8 @@ nsListControlFrame::AdjustIndexForDisabledOpt(int32_t aStartIndex,
|
||||
}
|
||||
|
||||
while (1) {
|
||||
// if the newIndex isn't disabled, we are golden, bail out
|
||||
bool isDisabled = true;
|
||||
if (NS_SUCCEEDED(IsOptionDisabled(newIndex, isDisabled)) && !isDisabled) {
|
||||
// if the newIndex is selectable, we are golden, bail out
|
||||
if (IsOptionInteractivelySelectable(newIndex)) {
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -36,6 +36,7 @@ namespace mozilla {
|
||||
namespace dom {
|
||||
class Event;
|
||||
class HTMLOptionElement;
|
||||
class HTMLSelectElement;
|
||||
class HTMLOptionsCollection;
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
@ -272,7 +273,17 @@ protected:
|
||||
*/
|
||||
void DropDownToggleKey(mozilla::dom::Event* aKeyEvent);
|
||||
|
||||
nsresult IsOptionDisabled(int32_t anIndex, bool &aIsDisabled);
|
||||
/**
|
||||
* @return true if the <option> at aIndex is selectable by the user.
|
||||
*/
|
||||
bool IsOptionInteractivelySelectable(int32_t aIndex) const;
|
||||
/**
|
||||
* @return true if aOption in aSelect is selectable by the user.
|
||||
*/
|
||||
static bool
|
||||
IsOptionInteractivelySelectable(mozilla::dom::HTMLSelectElement* aSelect,
|
||||
mozilla::dom::HTMLOptionElement* aOption);
|
||||
|
||||
/**
|
||||
* @note This method might destroy the frame, pres shell and other objects.
|
||||
*/
|
||||
|
@ -66,3 +66,4 @@ skip-if = e10s || toolkit == 'android' # Bug 1170129 - vertical <select> popup n
|
||||
skip-if = toolkit == 'android'
|
||||
[test_bug1327129.html]
|
||||
[test_readonly.html]
|
||||
[test_select_key_navigation_bug1498769.html]
|
||||
|
122
layout/forms/test/test_select_key_navigation_bug1498769.html
Normal file
122
layout/forms/test/test_select_key_navigation_bug1498769.html
Normal file
@ -0,0 +1,122 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1498769
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for Bug 1498769</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<script type="application/javascript">
|
||||
/** Test for Bug 1498769 **/
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
function test() {
|
||||
const kIsMac = navigator.platform.indexOf("Mac") == 0;
|
||||
SimpleTest.waitForFocus(function() {
|
||||
[...document.querySelectorAll('select')].forEach(function(e) {
|
||||
e.focus();
|
||||
is(e.selectedIndex, 1, "the 'selected' attribute is respected");
|
||||
if (kIsMac && e.size == "1") {
|
||||
// On OSX, UP/DOWN opens the dropdown menu rather than changing
|
||||
// the value so we skip the rest of this test there in this case.
|
||||
return;
|
||||
}
|
||||
synthesizeKey("VK_DOWN", {});
|
||||
is(e.selectedIndex, 2, "VK_DOWN selected the first option below");
|
||||
synthesizeKey("VK_UP", {});
|
||||
is(e.selectedIndex, 0, "VK_UP skips the display:none/contents option");
|
||||
synthesizeKey("VK_DOWN", {});
|
||||
is(e.selectedIndex, 2, "VK_DOWN skips the display:none/contents option");
|
||||
});
|
||||
SimpleTest.finish();
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body onload="test()">
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1498769">Mozilla Bug 1498769</a>
|
||||
<div>
|
||||
<select size="4">
|
||||
<option>0</option>
|
||||
<option selected style="display:none">1</option>
|
||||
<option>2</option>
|
||||
<option>3</option>
|
||||
</select>
|
||||
<select size="4">
|
||||
<option>0</option>
|
||||
<option selected style="display:contents">1</option>
|
||||
<option>2</option>
|
||||
<option>3</option>
|
||||
</select>
|
||||
<select size="4">
|
||||
<option>0</option>
|
||||
<optgroup label="group" style="display:none">
|
||||
<option selected>1</option>
|
||||
</optgroup>
|
||||
<option>2</option>
|
||||
<option>3</option>
|
||||
</select>
|
||||
<select size="4">
|
||||
<option>0</option>
|
||||
<optgroup label="group" style="display:contents">
|
||||
<option selected>1</option>
|
||||
</optgroup>
|
||||
<option>2</option>
|
||||
<option>3</option>
|
||||
</select>
|
||||
<select size="4">
|
||||
<option>0</option>
|
||||
<optgroup label="group" style="display:contents">
|
||||
<option selected style="display:none">1</option>
|
||||
</optgroup>
|
||||
<option>2</option>
|
||||
<option>3</option>
|
||||
</select>
|
||||
|
||||
<!-- Same as above but with size="1" -->
|
||||
|
||||
<select size="1">
|
||||
<option>0</option>
|
||||
<option selected style="display:none">1</option>
|
||||
<option>2</option>
|
||||
<option>3</option>
|
||||
</select>
|
||||
<select size="1">
|
||||
<option>0</option>
|
||||
<option selected style="display:contents">1</option>
|
||||
<option>2</option>
|
||||
<option>3</option>
|
||||
</select>
|
||||
<select size="1">
|
||||
<option>0</option>
|
||||
<optgroup label="group" style="display:none">
|
||||
<option selected>1</option>
|
||||
</optgroup>
|
||||
<option>2</option>
|
||||
<option>3</option>
|
||||
</select>
|
||||
<select size="1">
|
||||
<option>0</option>
|
||||
<optgroup label="group" style="display:contents">
|
||||
<option selected>1</option>
|
||||
</optgroup>
|
||||
<option>2</option>
|
||||
<option>3</option>
|
||||
</select>
|
||||
<select size="1">
|
||||
<option>0</option>
|
||||
<optgroup label="group" style="display:contents">
|
||||
<option selected style="display:none">1</option>
|
||||
</optgroup>
|
||||
<option>2</option>
|
||||
<option>3</option>
|
||||
</select>
|
||||
</div>
|
||||
<pre id="test">
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
Loading…
Reference in New Issue
Block a user