зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1343037 part 13. Implement nsTextEditorState::SetSelectionEnd. r=ehsan
This introduces three behavior changes: 1) Before this change, in cached mode, we did not enforce the "start <= end" invariant. 2) Before this change, in cached mode, we did not fire "select" events on selectionEnd changes. 3) Changes the IDL type of HTMLInputElement's selectionEnd attribute to "unsigned long" to match the spec and HTMLTextareaElement. MozReview-Commit-ID: J3Gkhr8VnbS
This commit is contained in:
Родитель
badbeff5ec
Коммит
e0ef9813e4
|
@ -6459,22 +6459,22 @@ HTMLInputElement::SetSelectionStart(const Nullable<uint32_t>& aSelectionStart,
|
|||
state->SetSelectionStart(aSelectionStart, aRv);
|
||||
}
|
||||
|
||||
Nullable<int32_t>
|
||||
Nullable<uint32_t>
|
||||
HTMLInputElement::GetSelectionEnd(ErrorResult& aRv)
|
||||
{
|
||||
if (!SupportsTextSelection()) {
|
||||
return Nullable<int32_t>();
|
||||
return Nullable<uint32_t>();
|
||||
}
|
||||
|
||||
int32_t selEnd = GetSelectionEndIgnoringType(aRv);
|
||||
uint32_t selEnd = GetSelectionEndIgnoringType(aRv);
|
||||
if (aRv.Failed()) {
|
||||
return Nullable<int32_t>();
|
||||
return Nullable<uint32_t>();
|
||||
}
|
||||
|
||||
return Nullable<int32_t>(selEnd);
|
||||
return Nullable<uint32_t>(selEnd);
|
||||
}
|
||||
|
||||
int32_t
|
||||
uint32_t
|
||||
HTMLInputElement::GetSelectionEndIgnoringType(ErrorResult& aRv)
|
||||
{
|
||||
int32_t selEnd, selStart;
|
||||
|
@ -6483,7 +6483,7 @@ HTMLInputElement::GetSelectionEndIgnoringType(ErrorResult& aRv)
|
|||
}
|
||||
|
||||
void
|
||||
HTMLInputElement::SetSelectionEnd(const Nullable<int32_t>& aSelectionEnd,
|
||||
HTMLInputElement::SetSelectionEnd(const Nullable<uint32_t>& aSelectionEnd,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
if (!SupportsTextSelection()) {
|
||||
|
@ -6491,35 +6491,9 @@ HTMLInputElement::SetSelectionEnd(const Nullable<int32_t>& aSelectionEnd,
|
|||
return;
|
||||
}
|
||||
|
||||
int32_t selEnd = 0;
|
||||
if (!aSelectionEnd.IsNull()) {
|
||||
selEnd = aSelectionEnd.Value();
|
||||
}
|
||||
|
||||
nsTextEditorState* state = GetEditorState();
|
||||
if (state && state->IsSelectionCached()) {
|
||||
state->GetSelectionProperties().SetEnd(selEnd);
|
||||
return;
|
||||
}
|
||||
|
||||
nsAutoString direction;
|
||||
GetSelectionDirection(direction, aRv);
|
||||
if (aRv.Failed()) {
|
||||
return;
|
||||
}
|
||||
|
||||
int32_t start, end;
|
||||
GetSelectionRange(&start, &end, aRv);
|
||||
if (aRv.Failed()) {
|
||||
return;
|
||||
}
|
||||
|
||||
end = selEnd;
|
||||
if (start > end) {
|
||||
start = end;
|
||||
}
|
||||
|
||||
aRv = SetSelectionRange(start, end, direction);
|
||||
MOZ_ASSERT(state, "SupportsTextSelection() returned true!");
|
||||
state->SetSelectionEnd(aSelectionEnd, aRv);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
|
|
@ -247,7 +247,7 @@ public:
|
|||
// Methods for nsFormFillController so it can do selection operations on input
|
||||
// types the HTML spec doesn't support them on, like "email".
|
||||
uint32_t GetSelectionStartIgnoringType(ErrorResult& aRv);
|
||||
int32_t GetSelectionEndIgnoringType(ErrorResult& aRv);
|
||||
uint32_t GetSelectionEndIgnoringType(ErrorResult& aRv);
|
||||
|
||||
void GetDisplayFileName(nsAString& aFileName) const;
|
||||
|
||||
|
@ -720,8 +720,8 @@ public:
|
|||
Nullable<uint32_t> GetSelectionStart(ErrorResult& aRv);
|
||||
void SetSelectionStart(const Nullable<uint32_t>& aValue, ErrorResult& aRv);
|
||||
|
||||
Nullable<int32_t> GetSelectionEnd(ErrorResult& aRv);
|
||||
void SetSelectionEnd(const Nullable<int32_t>& aValue, ErrorResult& aRv);
|
||||
Nullable<uint32_t> GetSelectionEnd(ErrorResult& aRv);
|
||||
void SetSelectionEnd(const Nullable<uint32_t>& aValue, ErrorResult& aRv);
|
||||
|
||||
void GetSelectionDirection(nsAString& aValue, ErrorResult& aRv);
|
||||
void SetSelectionDirection(const nsAString& aValue, ErrorResult& aRv);
|
||||
|
|
|
@ -725,34 +725,7 @@ void
|
|||
HTMLTextAreaElement::SetSelectionEnd(const Nullable<uint32_t>& aSelectionEnd,
|
||||
ErrorResult& aError)
|
||||
{
|
||||
int32_t selEnd = 0;
|
||||
if (!aSelectionEnd.IsNull()) {
|
||||
selEnd = aSelectionEnd.Value();
|
||||
}
|
||||
|
||||
if (mState.IsSelectionCached()) {
|
||||
mState.GetSelectionProperties().SetEnd(selEnd);
|
||||
return;
|
||||
}
|
||||
|
||||
nsAutoString direction;
|
||||
GetSelectionDirection(direction, aError);
|
||||
if (aError.Failed()) {
|
||||
return;
|
||||
}
|
||||
int32_t start, end;
|
||||
GetSelectionRange(&start, &end, aError);
|
||||
if (aError.Failed()) {
|
||||
return;
|
||||
}
|
||||
end = selEnd;
|
||||
if (start > end) {
|
||||
start = end;
|
||||
}
|
||||
nsresult rv = SetSelectionRange(start, end, direction);
|
||||
if (NS_FAILED(rv)) {
|
||||
aError.Throw(rv);
|
||||
}
|
||||
mState.SetSelectionEnd(aSelectionEnd, aError);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -1737,6 +1737,31 @@ nsTextEditorState::SetSelectionStart(const mozilla::dom::Nullable<uint32_t>& aSt
|
|||
SetSelectionRange(start, end, dir, aRv);
|
||||
}
|
||||
|
||||
void
|
||||
nsTextEditorState::SetSelectionEnd(const mozilla::dom::Nullable<uint32_t>& aEnd,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
int32_t end = 0;
|
||||
if (!aEnd.IsNull()) {
|
||||
// XXXbz This will do the wrong thing for input values that are out of the
|
||||
// int32_t range...
|
||||
end = aEnd.Value();
|
||||
}
|
||||
|
||||
int32_t start, ignored;
|
||||
GetSelectionRange(&start, &ignored, aRv);
|
||||
if (aRv.Failed()) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsITextControlFrame::SelectionDirection dir = GetSelectionDirection(aRv);
|
||||
if (aRv.Failed()) {
|
||||
return;
|
||||
}
|
||||
|
||||
SetSelectionRange(start, end, dir, aRv);
|
||||
}
|
||||
|
||||
HTMLInputElement*
|
||||
nsTextEditorState::GetParentNumberControl(nsFrame* aFrame) const
|
||||
{
|
||||
|
|
|
@ -304,6 +304,12 @@ public:
|
|||
void SetSelectionStart(const mozilla::dom::Nullable<uint32_t>& aStart,
|
||||
mozilla::ErrorResult& aRv);
|
||||
|
||||
// Set the selection end. This basically implements the
|
||||
// https://html.spec.whatwg.org/multipage/forms.html#dom-textarea/input-selectionend
|
||||
// setter.
|
||||
void SetSelectionEnd(const mozilla::dom::Nullable<uint32_t>& aEnd,
|
||||
mozilla::ErrorResult& aRv);
|
||||
|
||||
void UpdateEditableState(bool aNotify) {
|
||||
if (mRootNode) {
|
||||
mRootNode->UpdateEditableState(aNotify);
|
||||
|
|
|
@ -119,7 +119,7 @@ interface HTMLInputElement : HTMLElement {
|
|||
[Throws]
|
||||
attribute unsigned long? selectionStart;
|
||||
[Throws]
|
||||
attribute long? selectionEnd;
|
||||
attribute unsigned long? selectionEnd;
|
||||
[Throws]
|
||||
attribute DOMString? selectionDirection;
|
||||
[Throws]
|
||||
|
|
|
@ -53,6 +53,19 @@
|
|||
}
|
||||
}, "onselect should fire when selectionStart is changed");
|
||||
|
||||
test(function() {
|
||||
for (let el of createTestElements(testValue)) {
|
||||
assert_equals(el.selectionEnd, testValue.length,
|
||||
`Initial .value set on ${el.id} should set selectionEnd to end of value`);
|
||||
var t = async_test(`onselect should fire when selectionEnd is changed on ${el.id}`);
|
||||
el.onselect = t.step_func_done(function(e) {
|
||||
assert_equals(e.type, "select");
|
||||
el.remove();
|
||||
});
|
||||
el.selectionEnd = 2;
|
||||
}
|
||||
}, "onselect should fire when selectionEnd is changed");
|
||||
|
||||
test(function() {
|
||||
for (let el of createTestElements(testValue)) {
|
||||
assert_equals(el.selectionStart, testValue.length,
|
||||
|
@ -65,4 +78,18 @@
|
|||
el.remove();
|
||||
}
|
||||
}, "Setting selectionStart to a value larger than selectionEnd should increase selectionEnd");
|
||||
|
||||
test(function() {
|
||||
for (let el of createTestElements(testValue)) {
|
||||
assert_equals(el.selectionStart, testValue.length,
|
||||
`Initial .value set on ${el.id} should set selectionStart to end of value`);
|
||||
assert_equals(el.selectionEnd, testValue.length,
|
||||
`Initial .value set on ${el.id} should set selectionEnd to end of value`);
|
||||
el.selectionStart = 8;
|
||||
el.selectionEnd = 5;
|
||||
assert_equals(el.selectionStart, 5, `selectionStart on ${el.id}`);
|
||||
assert_equals(el.selectionEnd, 5, `selectionEnd on ${el.id}`);
|
||||
el.remove();
|
||||
}
|
||||
}, "Setting selectionEnd to a value smaller than selectionStart should decrease selectionStart");
|
||||
</script>
|
||||
|
|
Загрузка…
Ссылка в новой задаче