Skip to content

Commit 67f7af1

Browse files
committedNov 28, 2022
Bug 841942 - Display tick marks for <input type=range> when @list/<datalist> is used r=emilio,credential-management-reviewers,sgalich
Differential Revision: https://phabricator.services.mozilla.com/D162882
1 parent e888fd7 commit 67f7af1

22 files changed

+264
-20
lines changed
 

‎dom/html/HTMLDataListElement.h

+2
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ class HTMLDataListElement final : public nsGenericHTMLElement {
2020
SetFlags(ELEMENT_IS_DATALIST_OR_HAS_DATALIST_ANCESTOR);
2121
}
2222

23+
NS_IMPL_FROMNODE_HTML_WITH_TAG(HTMLDataListElement, datalist)
24+
2325
// nsISupports
2426
NS_DECL_ISUPPORTS_INHERITED
2527

‎dom/html/HTMLInputElement.cpp

+4-7
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636

3737
#include "nsIRadioVisitor.h"
3838

39+
#include "HTMLDataListElement.h"
3940
#include "HTMLFormSubmissionConstants.h"
4041
#include "mozilla/Telemetry.h"
4142
#include "nsBaseCommandController.h"
@@ -1644,7 +1645,7 @@ void HTMLInputElement::SetValue(const nsAString& aValue, CallerType aCallerType,
16441645
}
16451646
}
16461647

1647-
nsGenericHTMLElement* HTMLInputElement::GetList() const {
1648+
HTMLDataListElement* HTMLInputElement::GetList() const {
16481649
nsAutoString dataListId;
16491650
GetAttr(kNameSpaceID_None, nsGkAtoms::list_, dataListId);
16501651
if (dataListId.IsEmpty()) {
@@ -1656,12 +1657,8 @@ nsGenericHTMLElement* HTMLInputElement::GetList() const {
16561657
return nullptr;
16571658
}
16581659

1659-
Element* element = docOrShadow->GetElementById(dataListId);
1660-
if (!element || !element->IsHTMLElement(nsGkAtoms::datalist)) {
1661-
return nullptr;
1662-
}
1663-
1664-
return static_cast<nsGenericHTMLElement*>(element);
1660+
return HTMLDataListElement::FromNodeOrNull(
1661+
docOrShadow->GetElementById(dataListId));
16651662
}
16661663

16671664
void HTMLInputElement::SetValue(Decimal aValue, CallerType aCallerType) {

‎dom/html/HTMLInputElement.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -520,7 +520,7 @@ class HTMLInputElement final : public TextControlElement,
520520
bool IsDraggingRange() const { return mIsDraggingRange; }
521521
void SetIndeterminate(bool aValue);
522522

523-
nsGenericHTMLElement* GetList() const;
523+
HTMLDataListElement* GetList() const;
524524

525525
void GetMax(nsAString& aValue) { GetHTMLAttr(nsGkAtoms::max, aValue); }
526526
void SetMax(const nsAString& aValue, ErrorResult& aRv) {

‎dom/webidl/HTMLInputElement.webidl

+1-1
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ interface HTMLInputElement : HTMLElement {
6161
[Pure]
6262
attribute boolean indeterminate;
6363
[Pure]
64-
readonly attribute HTMLElement? list;
64+
readonly attribute HTMLDataListElement? list;
6565
[CEReactions, Pure, SetterThrows]
6666
attribute DOMString max;
6767
[CEReactions, Pure, SetterThrows]

‎layout/forms/nsRangeFrame.cpp

+53-10
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
#include "nsRangeFrame.h"
88

9+
#include "mozilla/Assertions.h"
910
#include "mozilla/PresShell.h"
1011
#include "mozilla/TouchEvents.h"
1112

@@ -19,13 +20,16 @@
1920
#include "mozilla/dom/Document.h"
2021
#include "nsNameSpaceManager.h"
2122
#include "nsGkAtoms.h"
23+
#include "mozilla/dom/HTMLDataListElement.h"
2224
#include "mozilla/dom/HTMLInputElement.h"
25+
#include "mozilla/dom/HTMLOptionElement.h"
2326
#include "nsPresContext.h"
2427
#include "nsPresContextInlines.h"
2528
#include "nsNodeInfoManager.h"
2629
#include "mozilla/dom/Element.h"
2730
#include "mozilla/ServoStyleSet.h"
2831
#include "nsStyleConsts.h"
32+
#include "nsTArray.h"
2933

3034
#ifdef ACCESSIBILITY
3135
# include "nsAccessibilityService.h"
@@ -307,28 +311,29 @@ a11y::AccType nsRangeFrame::AccessibleType() { return a11y::eHTMLRangeType; }
307311
#endif
308312

309313
double nsRangeFrame::GetValueAsFractionOfRange() {
310-
MOZ_ASSERT(mContent->IsHTMLElement(nsGkAtoms::input), "bad cast");
311-
auto* input = static_cast<dom::HTMLInputElement*>(GetContent());
312-
MOZ_ASSERT(input->ControlType() == FormControlType::InputRange);
314+
return GetDoubleAsFractionOfRange(InputElement().GetValueAsDecimal());
315+
}
313316

314-
Decimal value = input->GetValueAsDecimal();
315-
Decimal minimum = input->GetMinimum();
316-
Decimal maximum = input->GetMaximum();
317+
double nsRangeFrame::GetDoubleAsFractionOfRange(const Decimal& aValue) {
318+
auto& input = InputElement();
319+
320+
Decimal minimum = input.GetMinimum();
321+
Decimal maximum = input.GetMaximum();
317322

318-
MOZ_ASSERT(value.isFinite() && minimum.isFinite() && maximum.isFinite(),
323+
MOZ_ASSERT(aValue.isFinite() && minimum.isFinite() && maximum.isFinite(),
319324
"type=range should have a default maximum/minimum");
320325

321326
if (maximum <= minimum) {
322327
// Avoid rounding triggering the assert by checking against an epsilon.
323-
MOZ_ASSERT((value - minimum).abs().toDouble() <
328+
MOZ_ASSERT((aValue - minimum).abs().toDouble() <
324329
std::numeric_limits<float>::epsilon(),
325330
"Unsanitized value");
326331
return 0.0;
327332
}
328333

329-
MOZ_ASSERT(value >= minimum && value <= maximum, "Unsanitized value");
334+
MOZ_ASSERT(aValue >= minimum && aValue <= maximum, "Unsanitized value");
330335

331-
return ((value - minimum) / (maximum - minimum)).toDouble();
336+
return ((aValue - minimum) / (maximum - minimum)).toDouble();
332337
}
333338

334339
Decimal nsRangeFrame::GetValueAtEventPoint(WidgetGUIEvent* aEvent) {
@@ -454,6 +459,44 @@ void nsRangeFrame::UpdateForValueChange() {
454459
SchedulePaint();
455460
}
456461

462+
nsTArray<double> nsRangeFrame::TickMarks() {
463+
nsTArray<double> tickMarks;
464+
auto& input = InputElement();
465+
auto* list = input.GetList();
466+
if (!list) {
467+
return tickMarks;
468+
}
469+
auto min = input.GetMinimumAsDouble();
470+
auto max = input.GetMaximumAsDouble();
471+
auto* options = list->Options();
472+
nsAutoString label;
473+
for (uint32_t i = 0; i < options->Length(); ++i) {
474+
auto* item = options->Item(i);
475+
auto* option = HTMLOptionElement::FromNode(item);
476+
MOZ_ASSERT(option);
477+
if (option->Disabled()) {
478+
continue;
479+
}
480+
nsAutoString str;
481+
option->GetValue(str);
482+
nsresult rv;
483+
double tickMark = str.ToDouble(&rv);
484+
if (NS_FAILED(rv) || tickMark < min || tickMark > max) {
485+
continue;
486+
}
487+
tickMarks.AppendElement(tickMark);
488+
}
489+
tickMarks.Sort();
490+
return tickMarks;
491+
}
492+
493+
mozilla::dom::HTMLInputElement& nsRangeFrame::InputElement() const {
494+
MOZ_ASSERT(mContent->IsHTMLElement(nsGkAtoms::input), "bad cast");
495+
auto& input = *static_cast<dom::HTMLInputElement*>(GetContent());
496+
MOZ_ASSERT(input.ControlType() == FormControlType::InputRange);
497+
return input;
498+
}
499+
457500
void nsRangeFrame::DoUpdateThumbPosition(nsIFrame* aThumbFrame,
458501
const nsSize& aRangeSize) {
459502
MOZ_ASSERT(aThumbFrame);

‎layout/forms/nsRangeFrame.h

+15
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,15 @@
1414
#include "nsIAnonymousContentCreator.h"
1515
#include "nsIDOMEventListener.h"
1616
#include "nsCOMPtr.h"
17+
#include "nsTArray.h"
1718

1819
class nsDisplayRangeFocusRing;
1920

2021
namespace mozilla {
2122
class PresShell;
2223
namespace dom {
2324
class Event;
25+
class HTMLInputElement;
2426
} // namespace dom
2527
} // namespace mozilla
2628

@@ -121,6 +123,14 @@ class nsRangeFrame final : public nsContainerFrame,
121123
*/
122124
double GetValueAsFractionOfRange();
123125

126+
/**
127+
* Returns the given value as a fraction of the difference between the input's
128+
* minimum and its maximum (i.e. returns 0.0 when the value is the same as the
129+
* input's minimum, and returns 1.0 when the value is the same as the input's
130+
* maximum).
131+
*/
132+
double GetDoubleAsFractionOfRange(const mozilla::Decimal& value);
133+
124134
/**
125135
* Returns whether the frame and its child should use the native style.
126136
*/
@@ -137,6 +147,11 @@ class nsRangeFrame final : public nsContainerFrame,
137147
*/
138148
void UpdateForValueChange();
139149

150+
nsTArray<double> TickMarks();
151+
152+
protected:
153+
mozilla::dom::HTMLInputElement& InputElement() const;
154+
140155
private:
141156
// Return our preferred size in the cross-axis (the axis perpendicular
142157
// to the direction of movement of the thumb).
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<!doctype html>
2+
<title>vertical range input with datalist reference</title>
3+
<input type="range" orient="vertical" min="-100" max="100" value="0" step="10" name="power" list="powers">
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<!doctype html>
2+
<title>vertical range input with datalist</title>
3+
<link rel="help" href="https://html.spec.whatwg.org/multipage/input.html#range-state-(type=range)">
4+
<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=841942">
5+
<link rel="author" href="mailto:zach@zrhoffman.net" title="Zach Hoffman">
6+
<link rel="mismatch" href="range-tick-marks-01-notref.html">
7+
<input type="range" orient="vertical" min="-100" max="100" value="0" step="10" name="power" list="powers">
8+
<datalist id="powers">
9+
<option value="0">
10+
<option value="-30">
11+
<option value="30">
12+
<option value="50">
13+
</datalist>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<!doctype html>
2+
<title>max and min attributes applied to vertical range input with datalist reference</title>
3+
<input type="range" orient="vertical" min="-100" max="100" value="0" step="10" name="power" list="powers">
4+
<datalist id="powers">
5+
<option value="0">
6+
<option value="-30">
7+
<option value="30">
8+
<option value="50">
9+
</datalist>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<!doctype html>
2+
<title>max and min attributes applied to vertical range input with datalist</title>
3+
<link rel="help" href="https://html.spec.whatwg.org/multipage/input.html#range-state-(type=range)">
4+
<link rel="help" href="https://html.spec.whatwg.org/multipage/input.html#the-min-and-max-attributes">
5+
<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=841942">
6+
<link rel="author" href="mailto:zach@zrhoffman.net" title="Zach Hoffman">
7+
<link rel="mismatch" href="range-tick-marks-02-notref.html">
8+
<input type="range" orient="vertical" min="-40" max="40" value="0" step="10" name="power" list="powers">
9+
<datalist id="powers">
10+
<option value="0">
11+
<option value="-30">
12+
<option value="30">
13+
<option value="50">
14+
</datalist>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<!doctype html>
2+
<title>no vertical range tick marks for disabled datalist elements reference</title>
3+
<input type="range" orient="vertical" min="-100" max="100" value="0" step="10" name="power" list="powers">
4+
<datalist id="powers">
5+
<option value="-30">
6+
<option value="50">
7+
</datalist>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<!doctype html>
2+
<title>no vertical range tick marks for disabled datalist elements</title>
3+
<link rel="help" href="https://html.spec.whatwg.org/multipage/input.html#range-state-(type=range)">
4+
<link rel="help" href="https://html.spec.whatwg.org/multipage/form-elements.html#htmldatalistelement">
5+
<link rel="help" href="https://html.spec.whatwg.org/multipage/form-elements.html#concept-option-disabled">
6+
<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=841942">
7+
<link rel="author" href="mailto:zach@zrhoffman.net" title="Zach Hoffman">
8+
<link rel="match" href="range-tick-marks-03-ref.html">
9+
<input type="range" orient="vertical" min="-100" max="100" value="0" step="10" name="power" list="powers">
10+
<datalist id="powers">
11+
<option value="0" disabled>
12+
<option value="-30">
13+
<option value="30" disabled>
14+
<option value="50">
15+
</datalist>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<!doctype html>
2+
<title>LTR range input with datalist reference</title>
3+
<input type="range" min="-100" max="100" value="0" step="10" name="power" list="powers">
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<!doctype html>
2+
<title>LTR range input with datalist</title>
3+
<link rel="help" href="https://html.spec.whatwg.org/multipage/input.html#range-state-(type=range)">
4+
<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=841942">
5+
<link rel="author" href="mailto:zach@zrhoffman.net" title="Zach Hoffman">
6+
<link rel="mismatch" href="range-tick-marks-01-notref.html">
7+
<input type="range" min="-100" max="100" value="0" step="10" name="power" list="powers">
8+
<datalist id="powers">
9+
<option value="0">
10+
<option value="-30">
11+
<option value="30">
12+
<option value="50">
13+
</datalist>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<!doctype html>
2+
<title>RTL range input with datalist reference</title>
3+
<style>
4+
input[type=range] {
5+
transform: scaleX(-1);
6+
}
7+
</style>
8+
<input type="range" min="-100" max="100" value="0" step="10" name="power" list="powers">
9+
<datalist id="powers">
10+
<option value="0">
11+
<option value="-30">
12+
<option value="30">
13+
<option value="50">
14+
</datalist>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<!doctype html>
2+
<title>RTL range input with datalist</title>
3+
<link rel="help" href="https://html.spec.whatwg.org/multipage/input.html#range-state-(type=range)">
4+
<link rel="help" href="https://html.spec.whatwg.org/multipage/dom.html#attr-dir-rtl">
5+
<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=841942">
6+
<link rel="author" href="mailto:zach@zrhoffman.net" title="Zach Hoffman">
7+
<link rel="match" href="range-tick-marks-02-ref.html">
8+
<input type="range" min="-100" max="100" value="0" step="10" name="power" list="powers" dir="rtl">
9+
<datalist id="powers">
10+
<option value="0">
11+
<option value="-30">
12+
<option value="30">
13+
<option value="50">
14+
</datalist>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<!doctype html>
2+
<title>max and min attributes applied to range input with datalist reference</title>
3+
<input type="range" min="-100" max="100" value="0" step="10" name="power" list="powers">
4+
<datalist id="powers">
5+
<option value="0">
6+
<option value="-30">
7+
<option value="30">
8+
<option value="50">
9+
</datalist>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<!doctype html>
2+
<title>max and min attributes applied to range input with datalist</title>
3+
<link rel="help" href="https://html.spec.whatwg.org/multipage/input.html#range-state-(type=range)">
4+
<link rel="help" href="https://html.spec.whatwg.org/multipage/input.html#the-min-and-max-attributes">
5+
<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=841942">
6+
<link rel="author" href="mailto:zach@zrhoffman.net" title="Zach Hoffman">
7+
<link rel="mismatch" href="range-tick-marks-03-notref.html">
8+
<input type="range" min="-40" max="40" value="0" step="10" name="power" list="powers">
9+
<datalist id="powers">
10+
<option value="0">
11+
<option value="-30">
12+
<option value="30">
13+
<option value="50">
14+
</datalist>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<!doctype html>
2+
<title>no range tick marks for disabled datalist elements reference</title>
3+
<input type="range" min="-100" max="100" value="0" step="10" name="power" list="powers">
4+
<datalist id="powers">
5+
<option value="-30">
6+
<option value="50">
7+
</datalist>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<!doctype html>
2+
<title>no range tick marks for disabled datalist elements</title>
3+
<link rel="help" href="https://html.spec.whatwg.org/multipage/input.html#range-state-(type=range)">
4+
<link rel="help" href="https://html.spec.whatwg.org/multipage/form-elements.html#htmldatalistelement">
5+
<link rel="help" href="https://html.spec.whatwg.org/multipage/form-elements.html#concept-option-disabled">
6+
<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=841942">
7+
<link rel="author" href="mailto:zach@zrhoffman.net" title="Zach Hoffman">
8+
<link rel="match" href="range-tick-marks-04-ref.html">
9+
<input type="range" min="-100" max="100" value="0" step="10" name="power" list="powers">
10+
<datalist id="powers">
11+
<option value="0" disabled>
12+
<option value="-30">
13+
<option value="30" disabled>
14+
<option value="50">
15+
</datalist>

‎toolkit/components/satchel/nsFormFillController.cpp

+3-1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include "mozilla/dom/Document.h"
1313
#include "mozilla/dom/Element.h"
1414
#include "mozilla/dom/Event.h" // for Event
15+
#include "mozilla/dom/HTMLDataListElement.h"
1516
#include "mozilla/dom/HTMLInputElement.h"
1617
#include "mozilla/dom/KeyboardEvent.h"
1718
#include "mozilla/dom/KeyboardEventBinding.h"
@@ -395,7 +396,8 @@ nsFormFillController::SetPopupOpen(bool aPopupOpen) {
395396
RefPtr<PresShell> presShell = docShell->GetPresShell();
396397
NS_ENSURE_STATE(presShell);
397398
presShell->ScrollContentIntoView(
398-
content, ScrollAxis(WhereToScroll::Nearest, WhenToScroll::IfNotVisible),
399+
content,
400+
ScrollAxis(WhereToScroll::Nearest, WhenToScroll::IfNotVisible),
399401
ScrollAxis(WhereToScroll::Nearest, WhenToScroll::IfNotVisible),
400402
ScrollFlags::ScrollOverflowHidden);
401403
// mFocusedPopup can be destroyed after ScrollContentIntoView, see bug

0 commit comments

Comments
 (0)
Failed to load comments.