зеркало из https://github.com/mozilla/gecko-dev.git
Bug 674558 - Implement the HTML5 selectionDirection property for text controls (input and textarea); r=bzbarsky
This commit is contained in:
Родитель
58aeddb143
Коммит
5ce917a794
|
@ -49,6 +49,7 @@ class nsIFrame;
|
|||
class nsIPresShell;
|
||||
struct nsTextRangeStyle;
|
||||
struct nsPoint;
|
||||
#include "nsIFrame.h"
|
||||
%}
|
||||
|
||||
[ptr] native nsFrameSelection(nsFrameSelection);
|
||||
|
@ -56,6 +57,7 @@ struct nsPoint;
|
|||
[ptr] native nsIPresShell(nsIPresShell);
|
||||
[ref] native constTextRangeStyleRef(const nsTextRangeStyle);
|
||||
[ref] native nsPointRef(nsPoint);
|
||||
native nsDirection(nsDirection);
|
||||
|
||||
[scriptable, uuid(98552206-ad7a-4d2d-8ce3-b6fa2389298b)]
|
||||
interface nsISelectionPrivate : nsISupports
|
||||
|
@ -128,5 +130,11 @@ interface nsISelectionPrivate : nsISupports
|
|||
*/
|
||||
[noscript] void setTextRangeStyle(in nsIDOMRange range,
|
||||
in constTextRangeStyleRef textRangeStyle);
|
||||
|
||||
/**
|
||||
* Get the direction of the selection.
|
||||
*/
|
||||
[noscript, notxpcom] nsDirection getSelectionDirection();
|
||||
[noscript, notxpcom] void setSelectionDirection(in nsDirection aDirection);
|
||||
};
|
||||
|
||||
|
|
|
@ -2723,7 +2723,8 @@ nsHTMLInputElement::GetTextLength(PRInt32* aTextLength)
|
|||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLInputElement::SetSelectionRange(PRInt32 aSelectionStart,
|
||||
PRInt32 aSelectionEnd)
|
||||
PRInt32 aSelectionEnd,
|
||||
const nsAString& aDirection)
|
||||
{
|
||||
nsresult rv = NS_ERROR_FAILURE;
|
||||
nsIFormControlFrame* formControlFrame = GetFormControlFrame(PR_TRUE);
|
||||
|
@ -2731,7 +2732,15 @@ nsHTMLInputElement::SetSelectionRange(PRInt32 aSelectionStart,
|
|||
if (formControlFrame) {
|
||||
nsITextControlFrame* textControlFrame = do_QueryFrame(formControlFrame);
|
||||
if (textControlFrame) {
|
||||
rv = textControlFrame->SetSelectionRange(aSelectionStart, aSelectionEnd);
|
||||
// Default to forward, even if not specified.
|
||||
// Note that we don't currently support directionless selections, so
|
||||
// "none" is treated like "forward".
|
||||
nsITextControlFrame::SelectionDirection dir = nsITextControlFrame::eForward;
|
||||
if (aDirection.EqualsLiteral("backward")) {
|
||||
dir = nsITextControlFrame::eBackward;
|
||||
}
|
||||
|
||||
rv = textControlFrame->SetSelectionRange(aSelectionStart, aSelectionEnd, dir);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = textControlFrame->ScrollSelectionIntoView();
|
||||
}
|
||||
|
@ -2753,20 +2762,17 @@ nsHTMLInputElement::GetSelectionStart(PRInt32* aSelectionStart)
|
|||
NS_IMETHODIMP
|
||||
nsHTMLInputElement::SetSelectionStart(PRInt32 aSelectionStart)
|
||||
{
|
||||
nsresult rv = NS_ERROR_FAILURE;
|
||||
nsIFormControlFrame* formControlFrame = GetFormControlFrame(PR_TRUE);
|
||||
|
||||
if (formControlFrame) {
|
||||
nsITextControlFrame* textControlFrame = do_QueryFrame(formControlFrame);
|
||||
if (textControlFrame) {
|
||||
rv = textControlFrame->SetSelectionStart(aSelectionStart);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = textControlFrame->ScrollSelectionIntoView();
|
||||
}
|
||||
}
|
||||
nsAutoString direction;
|
||||
nsresult rv = GetSelectionDirection(direction);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
PRInt32 start, end;
|
||||
rv = GetSelectionRange(&start, &end);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
start = aSelectionStart;
|
||||
if (end < start) {
|
||||
end = start;
|
||||
}
|
||||
|
||||
return rv;
|
||||
return SetSelectionRange(start, end, direction);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -2782,20 +2788,17 @@ nsHTMLInputElement::GetSelectionEnd(PRInt32* aSelectionEnd)
|
|||
NS_IMETHODIMP
|
||||
nsHTMLInputElement::SetSelectionEnd(PRInt32 aSelectionEnd)
|
||||
{
|
||||
nsresult rv = NS_ERROR_FAILURE;
|
||||
nsIFormControlFrame* formControlFrame = GetFormControlFrame(PR_TRUE);
|
||||
|
||||
if (formControlFrame) {
|
||||
nsITextControlFrame* textControlFrame = do_QueryFrame(formControlFrame);
|
||||
if (textControlFrame) {
|
||||
rv = textControlFrame->SetSelectionEnd(aSelectionEnd);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = textControlFrame->ScrollSelectionIntoView();
|
||||
}
|
||||
}
|
||||
nsAutoString direction;
|
||||
nsresult rv = GetSelectionDirection(direction);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
PRInt32 start, end;
|
||||
rv = GetSelectionRange(&start, &end);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
end = aSelectionEnd;
|
||||
if (start > end) {
|
||||
start = end;
|
||||
}
|
||||
|
||||
return rv;
|
||||
return SetSelectionRange(start, end, direction);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -2835,6 +2838,45 @@ nsHTMLInputElement::GetSelectionRange(PRInt32* aSelectionStart,
|
|||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLInputElement::GetSelectionDirection(nsAString& aDirection)
|
||||
{
|
||||
nsresult rv = NS_ERROR_FAILURE;
|
||||
nsIFormControlFrame* formControlFrame = GetFormControlFrame(PR_TRUE);
|
||||
|
||||
if (formControlFrame) {
|
||||
nsITextControlFrame* textControlFrame = do_QueryFrame(formControlFrame);
|
||||
if (textControlFrame) {
|
||||
nsITextControlFrame::SelectionDirection dir;
|
||||
rv = textControlFrame->GetSelectionRange(nsnull, nsnull, &dir);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
if (dir == nsITextControlFrame::eNone) {
|
||||
aDirection.AssignLiteral("none");
|
||||
} else if (dir == nsITextControlFrame::eForward) {
|
||||
aDirection.AssignLiteral("forward");
|
||||
} else if (dir == nsITextControlFrame::eBackward) {
|
||||
aDirection.AssignLiteral("backward");
|
||||
} else {
|
||||
NS_NOTREACHED("Invalid SelectionDirection value");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLInputElement::SetSelectionDirection(const nsAString& aDirection) {
|
||||
PRInt32 start, end;
|
||||
nsresult rv = GetSelectionRange(&start, &end);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = SetSelectionRange(start, end, aDirection);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLInputElement::GetPhonetic(nsAString& aPhonetic)
|
||||
{
|
||||
|
|
|
@ -829,20 +829,17 @@ nsHTMLTextAreaElement::GetSelectionStart(PRInt32 *aSelectionStart)
|
|||
NS_IMETHODIMP
|
||||
nsHTMLTextAreaElement::SetSelectionStart(PRInt32 aSelectionStart)
|
||||
{
|
||||
nsresult rv = NS_ERROR_FAILURE;
|
||||
nsIFormControlFrame* formControlFrame = GetFormControlFrame(PR_TRUE);
|
||||
|
||||
if (formControlFrame){
|
||||
nsITextControlFrame* textControlFrame = do_QueryFrame(formControlFrame);
|
||||
if (textControlFrame) {
|
||||
rv = textControlFrame->SetSelectionStart(aSelectionStart);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = textControlFrame->ScrollSelectionIntoView();
|
||||
}
|
||||
}
|
||||
nsAutoString direction;
|
||||
nsresult rv = GetSelectionDirection(direction);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
PRInt32 start, end;
|
||||
rv = GetSelectionRange(&start, &end);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
start = aSelectionStart;
|
||||
if (end < start) {
|
||||
end = start;
|
||||
}
|
||||
|
||||
return rv;
|
||||
return SetSelectionRange(start, end, direction);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -857,20 +854,17 @@ nsHTMLTextAreaElement::GetSelectionEnd(PRInt32 *aSelectionEnd)
|
|||
NS_IMETHODIMP
|
||||
nsHTMLTextAreaElement::SetSelectionEnd(PRInt32 aSelectionEnd)
|
||||
{
|
||||
nsresult rv = NS_ERROR_FAILURE;
|
||||
nsIFormControlFrame* formControlFrame = GetFormControlFrame(PR_TRUE);
|
||||
|
||||
if (formControlFrame) {
|
||||
nsITextControlFrame* textControlFrame = do_QueryFrame(formControlFrame);
|
||||
if (textControlFrame) {
|
||||
rv = textControlFrame->SetSelectionEnd(aSelectionEnd);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = textControlFrame->ScrollSelectionIntoView();
|
||||
}
|
||||
}
|
||||
nsAutoString direction;
|
||||
nsresult rv = GetSelectionDirection(direction);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
PRInt32 start, end;
|
||||
rv = GetSelectionRange(&start, &end);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
end = aSelectionEnd;
|
||||
if (start > end) {
|
||||
start = end;
|
||||
}
|
||||
|
||||
return rv;
|
||||
return SetSelectionRange(start, end, direction);
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
@ -889,8 +883,49 @@ nsHTMLTextAreaElement::GetSelectionRange(PRInt32* aSelectionStart,
|
|||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHTMLTextAreaElement::GetSelectionDirection(nsAString& aDirection)
|
||||
{
|
||||
nsresult rv = NS_ERROR_FAILURE;
|
||||
nsIFormControlFrame* formControlFrame = GetFormControlFrame(PR_TRUE);
|
||||
|
||||
if (formControlFrame) {
|
||||
nsITextControlFrame* textControlFrame = do_QueryFrame(formControlFrame);
|
||||
if (textControlFrame) {
|
||||
nsITextControlFrame::SelectionDirection dir;
|
||||
rv = textControlFrame->GetSelectionRange(nsnull, nsnull, &dir);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
if (dir == nsITextControlFrame::eNone) {
|
||||
aDirection.AssignLiteral("none");
|
||||
} else if (dir == nsITextControlFrame::eForward) {
|
||||
aDirection.AssignLiteral("forward");
|
||||
} else if (dir == nsITextControlFrame::eBackward) {
|
||||
aDirection.AssignLiteral("backward");
|
||||
} else {
|
||||
NS_NOTREACHED("Invalid SelectionDirection value");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLTextAreaElement::SetSelectionRange(PRInt32 aSelectionStart, PRInt32 aSelectionEnd)
|
||||
nsHTMLTextAreaElement::SetSelectionDirection(const nsAString& aDirection) {
|
||||
PRInt32 start, end;
|
||||
nsresult rv = GetSelectionRange(&start, &end);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = SetSelectionRange(start, end, aDirection);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLTextAreaElement::SetSelectionRange(PRInt32 aSelectionStart,
|
||||
PRInt32 aSelectionEnd,
|
||||
const nsAString& aDirection)
|
||||
{
|
||||
nsresult rv = NS_ERROR_FAILURE;
|
||||
nsIFormControlFrame* formControlFrame = GetFormControlFrame(PR_TRUE);
|
||||
|
@ -898,7 +933,15 @@ nsHTMLTextAreaElement::SetSelectionRange(PRInt32 aSelectionStart, PRInt32 aSelec
|
|||
if (formControlFrame) {
|
||||
nsITextControlFrame* textControlFrame = do_QueryFrame(formControlFrame);
|
||||
if (textControlFrame) {
|
||||
rv = textControlFrame->SetSelectionRange(aSelectionStart, aSelectionEnd);
|
||||
// Default to forward, even if not specified.
|
||||
// Note that we don't currently support directionless selections, so
|
||||
// "none" is treated like "forward".
|
||||
nsITextControlFrame::SelectionDirection dir = nsITextControlFrame::eForward;
|
||||
if (aDirection.EqualsLiteral("backward")) {
|
||||
dir = nsITextControlFrame::eBackward;
|
||||
}
|
||||
|
||||
rv = textControlFrame->SetSelectionRange(aSelectionStart, aSelectionEnd, dir);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = textControlFrame->ScrollSelectionIntoView();
|
||||
}
|
||||
|
|
|
@ -277,6 +277,7 @@ _TEST_FILES = \
|
|||
test_bug664299.html \
|
||||
test_bug666200.html \
|
||||
test_bug666666.html \
|
||||
test_bug674558.html \
|
||||
test_restore_from_parser_fragment.html \
|
||||
$(NULL)
|
||||
|
||||
|
|
|
@ -0,0 +1,151 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=674558
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 674558</title>
|
||||
<script type="application/javascript" src="/MochiKit/packed.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=674558">Mozilla Bug 674558</a>
|
||||
<p id="display"></p>
|
||||
<div id="content">
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for Bug 674558 **/
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SimpleTest.waitForFocus(function() {
|
||||
function textAreaCtor() {
|
||||
return document.createElement("textarea");
|
||||
}
|
||||
var ctors = [textAreaCtor];
|
||||
["text", "password", "search"].forEach(function(type) {
|
||||
ctors.push(function inputCtor() {
|
||||
var input = document.createElement("input");
|
||||
input.type = type;
|
||||
return input;
|
||||
});
|
||||
});
|
||||
|
||||
for (var ctor in ctors) {
|
||||
test(ctors[ctor]);
|
||||
}
|
||||
|
||||
SimpleTest.finish();
|
||||
});
|
||||
|
||||
function test(ctor) {
|
||||
var elem = ctor();
|
||||
ok(true, "Testing " + name(elem));
|
||||
|
||||
ok("selectionDirection" in elem, "elem should have the selectionDirection property");
|
||||
|
||||
var content = document.getElementById("content");
|
||||
content.appendChild(elem);
|
||||
|
||||
elem.value = "foobar";
|
||||
|
||||
is(elem.selectionStart, 0, "Default value");
|
||||
is(elem.selectionEnd, 0, "Default value");
|
||||
is(elem.selectionDirection, "forward", "Default value");
|
||||
|
||||
elem.setSelectionRange(1, 3);
|
||||
is(elem.selectionStart, 1, "Correct value");
|
||||
is(elem.selectionEnd, 3, "Correct value");
|
||||
is(elem.selectionDirection, "forward", "If not set, should default to forward");
|
||||
|
||||
// extend to right
|
||||
elem.focus();
|
||||
synthesizeKey("VK_RIGHT", {shiftKey: true});
|
||||
|
||||
is(elem.selectionStart, 1, "Value unchanged");
|
||||
is(elem.selectionEnd, 4, "Correct value");
|
||||
is(elem.selectionDirection, "forward", "Still forward");
|
||||
|
||||
// change the direction
|
||||
elem.selectionDirection = "backward";
|
||||
|
||||
is(elem.selectionStart, 1, "Value unchanged");
|
||||
is(elem.selectionEnd, 4, "Value unchanged");
|
||||
is(elem.selectionDirection, "backward", "Correct value");
|
||||
|
||||
// extend to right again
|
||||
synthesizeKey("VK_RIGHT", {shiftKey: true});
|
||||
|
||||
is(elem.selectionStart, 2, "Correct value");
|
||||
is(elem.selectionEnd, 4, "Value unchanged");
|
||||
is(elem.selectionDirection, "backward", "Still backward");
|
||||
|
||||
elem.selectionEnd = 5;
|
||||
|
||||
is(elem.selectionStart, 2, "Value unchanged");
|
||||
is(elem.selectionEnd, 5, "Correct value");
|
||||
is(elem.selectionDirection, "backward", "Still backward");
|
||||
|
||||
elem.selectionDirection = "none";
|
||||
|
||||
is(elem.selectionStart, 2, "Value unchanged");
|
||||
is(elem.selectionEnd, 5, "Value unchanged");
|
||||
is(elem.selectionDirection, "forward", "none not supported");
|
||||
|
||||
elem.selectionDirection = "backward";
|
||||
|
||||
is(elem.selectionStart, 2, "Value unchanged");
|
||||
is(elem.selectionEnd, 5, "Value unchanged");
|
||||
is(elem.selectionDirection, "backward", "Correct Value");
|
||||
|
||||
elem.selectionDirection = "invalid";
|
||||
|
||||
is(elem.selectionStart, 2, "Value unchanged");
|
||||
is(elem.selectionEnd, 5, "Value unchanged");
|
||||
is(elem.selectionDirection, "forward", "Treated as none");
|
||||
|
||||
elem.selectionDirection = "backward";
|
||||
|
||||
is(elem.selectionStart, 2, "Value unchanged");
|
||||
is(elem.selectionEnd, 5, "Value unchanged");
|
||||
is(elem.selectionDirection, "backward", "Correct Value");
|
||||
|
||||
elem.setSelectionRange(1, 4);
|
||||
|
||||
is(elem.selectionStart, 1, "Correct value");
|
||||
is(elem.selectionEnd, 4, "Correct value");
|
||||
is(elem.selectionDirection, "forward", "Correct value");
|
||||
|
||||
elem.setSelectionRange(1, 1);
|
||||
synthesizeKey("VK_RIGHT", {shiftKey: true});
|
||||
synthesizeKey("VK_RIGHT", {shiftKey: true});
|
||||
synthesizeKey("VK_RIGHT", {shiftKey: true});
|
||||
|
||||
is(elem.selectionStart, 1, "Correct value");
|
||||
is(elem.selectionEnd, 4, "Correct value");
|
||||
is(elem.selectionDirection, "forward", "Correct value");
|
||||
|
||||
elem.setSelectionRange(5, 5);
|
||||
synthesizeKey("VK_LEFT", {shiftKey: true});
|
||||
synthesizeKey("VK_LEFT", {shiftKey: true});
|
||||
synthesizeKey("VK_LEFT", {shiftKey: true});
|
||||
|
||||
is(elem.selectionStart, 2, "Correct value");
|
||||
is(elem.selectionEnd, 5, "Correct value");
|
||||
is(elem.selectionDirection, "backward", "Correct value");
|
||||
}
|
||||
|
||||
function name(elem) {
|
||||
var tag = elem.localName;
|
||||
if (tag == "input") {
|
||||
tag += "[type=" + elem.type + "]";
|
||||
}
|
||||
return tag;
|
||||
}
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -54,7 +54,7 @@ interface nsIDOMValidityState;
|
|||
* http://www.whatwg.org/specs/web-apps/current-work/
|
||||
*/
|
||||
|
||||
[scriptable, uuid(a59ba6b8-6f8b-4003-a8a4-184a51a05050)]
|
||||
[scriptable, uuid(66819eba-89b5-4db4-8d27-6368c70761e8)]
|
||||
interface nsIDOMHTMLInputElement : nsIDOMHTMLElement
|
||||
{
|
||||
attribute DOMString accept;
|
||||
|
@ -107,8 +107,9 @@ interface nsIDOMHTMLInputElement : nsIDOMHTMLElement
|
|||
void select();
|
||||
attribute long selectionStart;
|
||||
attribute long selectionEnd;
|
||||
void setSelectionRange(in long selectionStart, in long selectionEnd);
|
||||
|
||||
void setSelectionRange(in long selectionStart, in long selectionEnd, [optional] in DOMString direction);
|
||||
attribute DOMString selectionDirection;
|
||||
|
||||
|
||||
attribute long tabIndex;
|
||||
attribute DOMString useMap;
|
||||
|
|
|
@ -53,7 +53,7 @@ interface nsIDOMValidityState;
|
|||
* http://www.whatwg.org/specs/web-apps/current-work/
|
||||
*/
|
||||
|
||||
[scriptable, uuid(905edd3e-c0b3-4d54-8a2c-0eaab6ccb3cf)]
|
||||
[scriptable, uuid(43e99aee-e41f-4935-a87d-f2dbafdbfddb)]
|
||||
interface nsIDOMHTMLTextAreaElement : nsIDOMHTMLElement
|
||||
{
|
||||
attribute boolean autofocus;
|
||||
|
@ -89,7 +89,8 @@ interface nsIDOMHTMLTextAreaElement : nsIDOMHTMLElement
|
|||
void select();
|
||||
attribute long selectionStart;
|
||||
attribute long selectionEnd;
|
||||
void setSelectionRange(in long selectionStart, in long selectionEnd);
|
||||
void setSelectionRange(in long selectionStart, in long selectionEnd, [optional] in DOMString direction);
|
||||
attribute DOMString selectionDirection;
|
||||
|
||||
// Defined on HTMLElement in the specification.
|
||||
attribute long tabIndex;
|
||||
|
|
|
@ -258,6 +258,7 @@ members = [
|
|||
'nsIDOMHTMLInputElement.textLength',
|
||||
'nsIDOMHTMLInputElement.selectionStart',
|
||||
'nsIDOMHTMLInputElement.selectionEnd',
|
||||
'nsIDOMHTMLInputElement.selectionDirection',
|
||||
'nsIDOMHTMLInputElement.setSelectionRange',
|
||||
'nsIDOMHTMLLinkElement.disabled',
|
||||
'nsIDOMHTMLOptionElement.index',
|
||||
|
@ -317,6 +318,7 @@ members = [
|
|||
'nsIDOMHTMLTextAreaElement.setSelectionRange',
|
||||
'nsIDOMHTMLTextAreaElement.selectionStart',
|
||||
'nsIDOMHTMLTextAreaElement.selectionEnd',
|
||||
'nsIDOMHTMLTextAreaElement.selectionDirection',
|
||||
'nsIDOMHTMLTextAreaElement.textLength',
|
||||
'nsIDOMHTMLTextAreaElement.wrap',
|
||||
'nsIDOMHTMLTitleElement.text',
|
||||
|
|
|
@ -50,6 +50,12 @@ class nsITextControlFrame : public nsIFormControlFrame
|
|||
public:
|
||||
NS_DECL_QUERYFRAME_TARGET(nsITextControlFrame)
|
||||
|
||||
enum SelectionDirection {
|
||||
eNone,
|
||||
eForward,
|
||||
eBackward
|
||||
};
|
||||
|
||||
NS_IMETHOD GetEditor(nsIEditor **aEditor) = 0;
|
||||
|
||||
NS_IMETHOD GetTextLength(PRInt32* aTextLength) = 0;
|
||||
|
@ -62,8 +68,12 @@ public:
|
|||
NS_IMETHOD SetSelectionStart(PRInt32 aSelectionStart) = 0;
|
||||
NS_IMETHOD SetSelectionEnd(PRInt32 aSelectionEnd) = 0;
|
||||
|
||||
NS_IMETHOD SetSelectionRange(PRInt32 aSelectionStart, PRInt32 aSelectionEnd) = 0;
|
||||
NS_IMETHOD GetSelectionRange(PRInt32* aSelectionStart, PRInt32* aSelectionEnd) = 0;
|
||||
NS_IMETHOD SetSelectionRange(PRInt32 aSelectionStart,
|
||||
PRInt32 aSelectionEnd,
|
||||
SelectionDirection aDirection = eNone) = 0;
|
||||
NS_IMETHOD GetSelectionRange(PRInt32* aSelectionStart,
|
||||
PRInt32* aSelectionEnd,
|
||||
SelectionDirection* aDirection = nsnull) = 0;
|
||||
|
||||
NS_IMETHOD GetOwnedSelectionController(nsISelectionController** aSelCon) = 0;
|
||||
virtual nsFrameSelection* GetOwnedFrameSelection() = 0;
|
||||
|
|
|
@ -805,7 +805,8 @@ nsresult
|
|||
nsTextControlFrame::SetSelectionInternal(nsIDOMNode *aStartNode,
|
||||
PRInt32 aStartOffset,
|
||||
nsIDOMNode *aEndNode,
|
||||
PRInt32 aEndOffset)
|
||||
PRInt32 aEndOffset,
|
||||
nsITextControlFrame::SelectionDirection aDirection)
|
||||
{
|
||||
// Create a new range to represent the new selection.
|
||||
// Note that we use a new range to avoid having to do
|
||||
|
@ -830,10 +831,24 @@ nsTextControlFrame::SetSelectionInternal(nsIDOMNode *aStartNode,
|
|||
selCon->GetSelection(nsISelectionController::SELECTION_NORMAL, getter_AddRefs(selection));
|
||||
NS_ENSURE_TRUE(selection, NS_ERROR_FAILURE);
|
||||
|
||||
nsCOMPtr<nsISelectionPrivate> selPriv = do_QueryInterface(selection, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsDirection direction;
|
||||
if (aDirection == eNone) {
|
||||
// Preserve the direction
|
||||
direction = selPriv->GetSelectionDirection();
|
||||
} else {
|
||||
direction = (aDirection == eBackward) ? eDirPrevious : eDirNext;
|
||||
}
|
||||
|
||||
rv = selection->RemoveAllRanges();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = selection->AddRange(range); // NOTE: can destroy the world
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
selPriv->SetSelectionDirection(direction);
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
@ -906,7 +921,8 @@ nsTextControlFrame::SelectAllOrCollapseToEndOfText(PRBool aSelect)
|
|||
}
|
||||
|
||||
nsresult
|
||||
nsTextControlFrame::SetSelectionEndPoints(PRInt32 aSelStart, PRInt32 aSelEnd)
|
||||
nsTextControlFrame::SetSelectionEndPoints(PRInt32 aSelStart, PRInt32 aSelEnd,
|
||||
nsITextControlFrame::SelectionDirection aDirection)
|
||||
{
|
||||
NS_ASSERTION(aSelStart <= aSelEnd, "Invalid selection offsets!");
|
||||
|
||||
|
@ -936,11 +952,12 @@ nsTextControlFrame::SetSelectionEndPoints(PRInt32 aSelStart, PRInt32 aSelEnd)
|
|||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
return SetSelectionInternal(startNode, startOffset, endNode, endOffset);
|
||||
return SetSelectionInternal(startNode, startOffset, endNode, endOffset, aDirection);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsTextControlFrame::SetSelectionRange(PRInt32 aSelStart, PRInt32 aSelEnd)
|
||||
nsTextControlFrame::SetSelectionRange(PRInt32 aSelStart, PRInt32 aSelEnd,
|
||||
nsITextControlFrame::SelectionDirection aDirection)
|
||||
{
|
||||
nsresult rv = EnsureEditorInitialized();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
@ -952,7 +969,7 @@ nsTextControlFrame::SetSelectionRange(PRInt32 aSelStart, PRInt32 aSelEnd)
|
|||
aSelStart = aSelEnd;
|
||||
}
|
||||
|
||||
return SetSelectionEndPoints(aSelStart, aSelEnd);
|
||||
return SetSelectionEndPoints(aSelStart, aSelEnd, aDirection);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1110,14 +1127,23 @@ nsTextControlFrame::OffsetToDOMPoint(PRInt32 aOffset,
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsTextControlFrame::GetSelectionRange(PRInt32* aSelectionStart, PRInt32* aSelectionEnd)
|
||||
nsTextControlFrame::GetSelectionRange(PRInt32* aSelectionStart,
|
||||
PRInt32* aSelectionEnd,
|
||||
SelectionDirection* aDirection)
|
||||
{
|
||||
// make sure we have an editor
|
||||
nsresult rv = EnsureEditorInitialized();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
*aSelectionStart = 0;
|
||||
*aSelectionEnd = 0;
|
||||
if (aSelectionStart) {
|
||||
*aSelectionStart = 0;
|
||||
}
|
||||
if (aSelectionEnd) {
|
||||
*aSelectionEnd = 0;
|
||||
}
|
||||
if (aDirection) {
|
||||
*aDirection = eNone;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsITextControlElement> txtCtrl = do_QueryInterface(GetContent());
|
||||
NS_ASSERTION(txtCtrl, "Content not a text control element");
|
||||
|
@ -1136,6 +1162,24 @@ nsTextControlFrame::GetSelectionRange(PRInt32* aSelectionStart, PRInt32* aSelect
|
|||
|
||||
// We only operate on the first range in the selection!
|
||||
|
||||
if (aDirection) {
|
||||
nsCOMPtr<nsISelectionPrivate> selPriv = do_QueryInterface(selection);
|
||||
if (selPriv) {
|
||||
nsDirection direction = selPriv->GetSelectionDirection();
|
||||
if (direction == eDirNext) {
|
||||
*aDirection = eForward;
|
||||
} else if (direction == eDirPrevious) {
|
||||
*aDirection = eBackward;
|
||||
} else {
|
||||
NS_NOTREACHED("Invalid nsDirection enum value");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!aSelectionStart || !aSelectionEnd) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMRange> firstRange;
|
||||
rv = selection->GetRangeAt(0, getter_AddRefs(firstRange));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
|
|
@ -145,8 +145,12 @@ public:
|
|||
NS_IMETHOD CheckFireOnChange();
|
||||
NS_IMETHOD SetSelectionStart(PRInt32 aSelectionStart);
|
||||
NS_IMETHOD SetSelectionEnd(PRInt32 aSelectionEnd);
|
||||
NS_IMETHOD SetSelectionRange(PRInt32 aSelectionStart, PRInt32 aSelectionEnd);
|
||||
NS_IMETHOD GetSelectionRange(PRInt32* aSelectionStart, PRInt32* aSelectionEnd);
|
||||
NS_IMETHOD SetSelectionRange(PRInt32 aSelectionStart,
|
||||
PRInt32 aSelectionEnd,
|
||||
SelectionDirection aDirection = eNone);
|
||||
NS_IMETHOD GetSelectionRange(PRInt32* aSelectionStart,
|
||||
PRInt32* aSelectionEnd,
|
||||
SelectionDirection* aDirection = nsnull);
|
||||
NS_IMETHOD GetOwnedSelectionController(nsISelectionController** aSelCon);
|
||||
virtual nsFrameSelection* GetOwnedFrameSelection();
|
||||
|
||||
|
@ -390,9 +394,11 @@ protected:
|
|||
private:
|
||||
//helper methods
|
||||
nsresult SetSelectionInternal(nsIDOMNode *aStartNode, PRInt32 aStartOffset,
|
||||
nsIDOMNode *aEndNode, PRInt32 aEndOffset);
|
||||
nsIDOMNode *aEndNode, PRInt32 aEndOffset,
|
||||
SelectionDirection aDirection = eNone);
|
||||
nsresult SelectAllOrCollapseToEndOfText(PRBool aSelect);
|
||||
nsresult SetSelectionEndPoints(PRInt32 aSelStart, PRInt32 aSelEnd);
|
||||
nsresult SetSelectionEndPoints(PRInt32 aSelStart, PRInt32 aSelEnd,
|
||||
SelectionDirection aDirection = eNone);
|
||||
|
||||
// accessors for the notify on input flag
|
||||
PRBool GetNotifyOnInput() const { return mNotifyOnInput; }
|
||||
|
|
|
@ -5996,6 +5996,16 @@ nsTypedSelection::SelectionLanguageChange(PRBool aLangRTL)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(nsDirection)
|
||||
nsTypedSelection::GetSelectionDirection() {
|
||||
return mDirection;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(void)
|
||||
nsTypedSelection::SetSelectionDirection(nsDirection aDirection) {
|
||||
mDirection = aDirection;
|
||||
}
|
||||
|
||||
|
||||
// nsAutoCopyListener
|
||||
|
||||
|
|
|
@ -491,7 +491,7 @@ NS_IMETHODIMP
|
|||
nsFormFillController::SelectTextRange(PRInt32 aStartIndex, PRInt32 aEndIndex)
|
||||
{
|
||||
if (mFocusedInput)
|
||||
mFocusedInput->SetSelectionRange(aStartIndex, aEndIndex);
|
||||
mFocusedInput->SetSelectionRange(aStartIndex, aEndIndex, EmptyString());
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче