Bug 345822 - Implement required attribute. f=ajvincent r=smaug sr=sicking a2.0=blocking

This commit is contained in:
Mounir Lamouri 2010-08-18 20:30:41 +02:00
Родитель d30156cc14
Коммит da54ee6c6d
10 изменённых файлов: 613 добавлений и 24 удалений

Просмотреть файл

@ -798,6 +798,7 @@ GK_ATOM(removeelement, "removeelement")
GK_ATOM(renderingobserverlist, "renderingobserverlist")
GK_ATOM(repeat, "repeat")
GK_ATOM(replace, "replace")
GK_ATOM(required, "required")
GK_ATOM(reset, "reset")
GK_ATOM(resizeafter, "resizeafter")
GK_ATOM(resizebefore, "resizebefore")

Просмотреть файл

@ -79,6 +79,8 @@ nsConstraintValidation::GetValidationMessage(nsAString & aValidationMessage,
aValidationMessage.Assign(mCustomValidity);
} else if (IsTooLong()) {
GetValidationMessage(aValidationMessage, VALIDATION_MESSAGE_TOO_LONG);
} else if (IsValueMissing()) {
GetValidationMessage(aValidationMessage, VALIDATION_MESSAGE_VALUE_MISSING);
} else {
// TODO: The other messages have not been written
// because related constraint validation are not implemented yet.

Просмотреть файл

@ -538,6 +538,7 @@ NS_IMPL_BOOL_ATTR(nsHTMLInputElement, Multiple, multiple)
NS_IMPL_NON_NEGATIVE_INT_ATTR(nsHTMLInputElement, MaxLength, maxlength)
NS_IMPL_STRING_ATTR(nsHTMLInputElement, Name, name)
NS_IMPL_BOOL_ATTR(nsHTMLInputElement, ReadOnly, readonly)
NS_IMPL_BOOL_ATTR(nsHTMLInputElement, Required, required)
NS_IMPL_URI_ATTR(nsHTMLInputElement, Src, src)
NS_IMPL_INT_ATTR_DEFAULT_VALUE(nsHTMLInputElement, TabIndex, tabindex, 0)
NS_IMPL_STRING_ATTR(nsHTMLInputElement, UseMap, usemap)
@ -1084,17 +1085,7 @@ nsHTMLInputElement::RadioSetChecked(PRBool aNotify)
//
// Find the selected radio button so we can deselect it
//
nsCOMPtr<nsIDOMHTMLInputElement> currentlySelected;
nsCOMPtr<nsIRadioGroupContainer> container = GetRadioGroupContainer();
// This is ONLY INITIALIZED IF container EXISTS
nsAutoString name;
PRBool nameExists = PR_FALSE;
if (container) {
nameExists = GetNameIfExists(name);
if (nameExists) {
container->GetCurrentRadioButton(name, getter_AddRefs(currentlySelected));
}
}
nsCOMPtr<nsIDOMHTMLInputElement> currentlySelected = GetSelectedRadioButton();
//
// Deselect the currently selected radio button
@ -1117,7 +1108,9 @@ nsHTMLInputElement::RadioSetChecked(PRBool aNotify)
// Let the group know that we are now the One True Radio Button
//
NS_ENSURE_SUCCESS(rv, rv);
if (container && nameExists) {
nsCOMPtr<nsIRadioGroupContainer> container = GetRadioGroupContainer();
nsAutoString name;
if (container && GetNameIfExists(name)) {
rv = container->SetCurrentRadioButton(name, this);
}
@ -1139,6 +1132,25 @@ nsHTMLInputElement::GetRadioGroupContainer()
return retval;
}
already_AddRefed<nsIDOMHTMLInputElement>
nsHTMLInputElement::GetSelectedRadioButton()
{
nsIDOMHTMLInputElement* selected;
nsCOMPtr<nsIRadioGroupContainer> container = GetRadioGroupContainer();
if (!container) {
return nsnull;
}
nsAutoString name;
if (!GetNameIfExists(name)) {
return nsnull;
}
container->GetCurrentRadioButton(name, &selected);
return selected;
}
nsresult
nsHTMLInputElement::MaybeSubmitForm(nsPresContext* aPresContext)
{
@ -1502,16 +1514,8 @@ nsHTMLInputElement::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
case NS_FORM_INPUT_RADIO:
{
nsCOMPtr<nsIRadioGroupContainer> container = GetRadioGroupContainer();
if (container) {
nsAutoString name;
if (GetNameIfExists(name)) {
nsCOMPtr<nsIDOMHTMLInputElement> selectedRadioButton;
container->GetCurrentRadioButton(name,
getter_AddRefs(selectedRadioButton));
aVisitor.mItemData = selectedRadioButton;
}
}
nsCOMPtr<nsIDOMHTMLInputElement> selectedRadioButton = GetSelectedRadioButton();
aVisitor.mItemData = selectedRadioButton;
originalCheckedValue = GetChecked();
if (!originalCheckedValue) {
@ -2958,6 +2962,113 @@ nsHTMLInputElement::VisitGroup(nsIRadioVisitor* aVisitor, PRBool aFlushContent)
return rv;
}
nsHTMLInputElement::ValueModeType
nsHTMLInputElement::GetValueMode() const
{
switch (mType)
{
case NS_FORM_INPUT_HIDDEN:
case NS_FORM_INPUT_SUBMIT:
case NS_FORM_INPUT_BUTTON:
case NS_FORM_INPUT_RESET:
case NS_FORM_INPUT_IMAGE:
return VALUE_MODE_DEFAULT;
case NS_FORM_INPUT_CHECKBOX:
case NS_FORM_INPUT_RADIO:
return VALUE_MODE_DEFAULT_ON;
case NS_FORM_INPUT_FILE:
return VALUE_MODE_FILENAME;
#ifdef DEBUG
case NS_FORM_INPUT_TEXT:
case NS_FORM_INPUT_PASSWORD:
case NS_FORM_INPUT_SEARCH:
case NS_FORM_INPUT_TEL:
return VALUE_MODE_VALUE;
default:
NS_NOTYETIMPLEMENTED("Unexpected input type in GetValueMode()");
return VALUE_MODE_VALUE;
#else // DEBUG
default:
return VALUE_MODE_VALUE;
#endif // DEBUG
}
}
PRBool
nsHTMLInputElement::IsMutable() const
{
return !HasAttr(kNameSpaceID_None, nsGkAtoms::disabled) &&
GetCurrentDoc() &&
!(DoesReadOnlyApply() &&
HasAttr(kNameSpaceID_None, nsGkAtoms::readonly));
}
PRBool
nsHTMLInputElement::DoesReadOnlyApply() const
{
switch (mType)
{
case NS_FORM_INPUT_HIDDEN:
case NS_FORM_INPUT_BUTTON:
case NS_FORM_INPUT_IMAGE:
case NS_FORM_INPUT_RESET:
case NS_FORM_INPUT_SUBMIT:
case NS_FORM_INPUT_RADIO:
case NS_FORM_INPUT_FILE:
case NS_FORM_INPUT_CHECKBOX:
// TODO:
// case NS_FORM_INPUT_COLOR:
// case NS_FORM_INPUT_RANGE:
return PR_FALSE;
#ifdef DEBUG
case NS_FORM_INPUT_TEXT:
case NS_FORM_INPUT_PASSWORD:
case NS_FORM_INPUT_SEARCH:
case NS_FORM_INPUT_TEL:
return PR_TRUE;
default:
NS_NOTYETIMPLEMENTED("Unexpected input type in DoesReadOnlyApply()");
return PR_TRUE;
#else // DEBUG
default:
return PR_TRUE;
#endif // DEBUG
}
}
PRBool
nsHTMLInputElement::DoesRequiredApply() const
{
switch (mType)
{
case NS_FORM_INPUT_HIDDEN:
case NS_FORM_INPUT_BUTTON:
case NS_FORM_INPUT_IMAGE:
case NS_FORM_INPUT_RESET:
case NS_FORM_INPUT_SUBMIT:
// TODO:
// case NS_FORM_INPUT_COLOR:
// case NS_FORM_INPUT_RANGE:
return PR_FALSE;
#ifdef DEBUG
case NS_FORM_INPUT_RADIO:
case NS_FORM_INPUT_CHECKBOX:
case NS_FORM_INPUT_FILE:
case NS_FORM_INPUT_TEXT:
case NS_FORM_INPUT_PASSWORD:
case NS_FORM_INPUT_SEARCH:
case NS_FORM_INPUT_TEL:
return PR_TRUE;
default:
NS_NOTYETIMPLEMENTED("Unexpected input type in DoesRequiredApply()");
return PR_TRUE;
#else // DEBUG
default:
return PR_TRUE;
#endif // DEBUG
}
}
// nsConstraintValidation
PRBool
@ -2976,6 +3087,44 @@ nsHTMLInputElement::IsTooLong()
return (maxLength >= 0) && (textLength > maxLength);
}
PRBool
nsHTMLInputElement::IsValueMissing()
{
if (!HasAttr(kNameSpaceID_None, nsGkAtoms::required) ||
!DoesRequiredApply()) {
return PR_FALSE;
}
if (GetValueMode() == VALUE_MODE_VALUE) {
if (!IsMutable()) {
return PR_FALSE;
}
nsAutoString value;
nsresult rv = GetValue(value);
NS_ENSURE_SUCCESS(rv, PR_FALSE);
return value.IsEmpty();
}
if (mType == NS_FORM_INPUT_CHECKBOX) {
return !GetChecked();
}
if (mType == NS_FORM_INPUT_RADIO) {
nsCOMPtr<nsIDOMHTMLInputElement> selected = GetSelectedRadioButton();
return !selected;
}
if (mType == NS_FORM_INPUT_FILE) {
nsCOMArray<nsIFile> files;
GetFileArray(files);
return !files.Count();
}
return PR_FALSE;
}
PRBool
nsHTMLInputElement::IsBarredFromConstraintValidation()
{
@ -3014,6 +3163,29 @@ nsHTMLInputElement::GetValidationMessage(nsAString& aValidationMessage,
aValidationMessage = message;
break;
}
case VALIDATION_MESSAGE_VALUE_MISSING:
{
nsXPIDLString message;
nsCAutoString key;
switch (mType)
{
case NS_FORM_INPUT_FILE:
key.Assign("FileElementSuffersFromBeingMissing");
break;
case NS_FORM_INPUT_CHECKBOX:
key.Assign("CheckboxElementSuffersFromBeingMissing");
break;
case NS_FORM_INPUT_RADIO:
key.Assign("RadioElementSuffersFromBeingMissing");
break;
default:
key.Assign("TextElementSuffersFromBeingMissing");
}
rv = nsContentUtils::GetLocalizedString(nsContentUtils::eDOM_PROPERTIES,
key.get(), message);
aValidationMessage = message;
break;
}
default:
rv = nsConstraintValidation::GetValidationMessage(aValidationMessage, aType);
}

Просмотреть файл

@ -188,6 +188,15 @@ public:
*/
virtual already_AddRefed<nsIRadioGroupContainer> GetRadioGroupContainer();
/**
* Helper function returning the currently selected button in the radio group.
* Returning null if the element is not a button or if there is no selectied
* button in the group.
*
* @return the selected button (or null).
*/
already_AddRefed<nsIDOMHTMLInputElement> GetSelectedRadioButton();
virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
virtual void UpdateEditableState()
@ -204,6 +213,7 @@ public:
// nsConstraintValidation
PRBool IsTooLong();
PRBool IsValueMissing();
PRBool IsBarredFromConstraintValidation();
nsresult GetValidationMessage(nsAString& aValidationMessage,
ValidationMessageType aType);
@ -213,6 +223,29 @@ protected:
// by the nsITextControlElement version.
using nsGenericHTMLFormElement::IsSingleLineTextControl;
/**
* The ValueModeType specifies how the value IDL attribute should behave.
*
* See: http://dev.w3.org/html5/spec/forms.html#dom-input-value
*/
enum ValueModeType
{
// On getting, returns the value.
// On setting, sets value.
VALUE_MODE_VALUE,
// On getting, returns the value if present or the empty string.
// On setting, sets the value.
VALUE_MODE_DEFAULT,
// On getting, returns the value if present or "on".
// On setting, sets the value.
VALUE_MODE_DEFAULT_ON,
// On getting, returns "C:\fakepath\" followed by the file name of the
// first file of the selected files if any.
// On setting the empty string, empties the selected files list, otherwise
// throw the INVALID_STATE_ERR exception.
VALUE_MODE_FILENAME
};
// Helper method
nsresult SetValueInternal(const nsAString& aValue,
PRBool aUserInput,
@ -330,6 +363,30 @@ protected:
*/
PRBool NeedToInitializeEditorForEvent(nsEventChainPreVisitor& aVisitor) const;
/**
* Get the value mode of the element, depending of the type.
*/
ValueModeType GetValueMode() const;
/**
* Get the mutable state of the element.
* When the element isn't mutable (immutable), the value or checkedness
* should not be changed by the user.
*
* See: http://dev.w3.org/html5/spec/forms.html#concept-input-mutable
*/
PRBool IsMutable() const;
/**
* Returns if the readonly attribute applies for the current type.
*/
PRBool DoesReadOnlyApply() const;
/**
* Returns if the required attribute applies for the current type.
*/
PRBool DoesRequiredApply() const;
void FreeData();
nsTextEditorState *GetEditorState() const;

Просмотреть файл

@ -201,6 +201,7 @@ public:
// nsConstraintValidation
PRBool IsTooLong();
PRBool IsValueMissing();
PRBool IsBarredFromConstraintValidation();
nsresult GetValidationMessage(nsAString& aValidationMessage,
ValidationMessageType aType);
@ -251,6 +252,11 @@ protected:
virtual nsresult AfterSetAttr(PRInt32 aNamespaceID, nsIAtom *aName,
const nsAString* aValue, PRBool aNotify);
/**
* Get the mutable state of the element.
*/
PRBool IsMutable() const;
};
@ -409,6 +415,7 @@ NS_IMPL_BOOL_ATTR(nsHTMLTextAreaElement, Disabled, disabled)
NS_IMPL_NON_NEGATIVE_INT_ATTR(nsHTMLTextAreaElement, MaxLength, maxlength)
NS_IMPL_STRING_ATTR(nsHTMLTextAreaElement, Name, name)
NS_IMPL_BOOL_ATTR(nsHTMLTextAreaElement, ReadOnly, readonly)
NS_IMPL_BOOL_ATTR(nsHTMLTextAreaElement, Required, required)
NS_IMPL_INT_ATTR(nsHTMLTextAreaElement, Rows, rows)
NS_IMPL_INT_ATTR_DEFAULT_VALUE(nsHTMLTextAreaElement, TabIndex, tabindex, 0)
NS_IMPL_STRING_ATTR(nsHTMLTextAreaElement, Wrap, wrap)
@ -1044,6 +1051,13 @@ nsHTMLTextAreaElement::CopyInnerTo(nsGenericElement* aDest) const
return NS_OK;
}
PRBool
nsHTMLTextAreaElement::IsMutable() const
{
return (!HasAttr(kNameSpaceID_None, nsGkAtoms::readonly) &&
!HasAttr(kNameSpaceID_None, nsGkAtoms::disabled));
}
// nsConstraintValidation
PRBool
@ -1062,6 +1076,20 @@ nsHTMLTextAreaElement::IsTooLong()
return (maxLength >= 0) && (textLength > maxLength);
}
PRBool
nsHTMLTextAreaElement::IsValueMissing()
{
if (!HasAttr(kNameSpaceID_None, nsGkAtoms::required) || !IsMutable()) {
return PR_FALSE;
}
nsAutoString value;
nsresult rv = GetValue(value);
NS_ENSURE_SUCCESS(rv, PR_FALSE);
return value.IsEmpty();
}
PRBool
nsHTMLTextAreaElement::IsBarredFromConstraintValidation()
{
@ -1097,6 +1125,15 @@ nsHTMLTextAreaElement::GetValidationMessage(nsAString& aValidationMessage,
aValidationMessage = message;
}
break;
case VALIDATION_MESSAGE_VALUE_MISSING:
{
nsXPIDLString message;
rv = nsContentUtils::GetLocalizedString(nsContentUtils::eDOM_PROPERTIES,
"TextElementSuffersFromBeingMissing",
message);
aValidationMessage = message;
}
break;
default:
rv = nsConstraintValidation::GetValidationMessage(aValidationMessage, aType);
}

Просмотреть файл

@ -194,6 +194,7 @@ _TEST_FILES = \
test_bug345624-1.html \
test_bug345624-2.html \
test_bug561640.html \
test_bug345822.html \
$(NULL)
libs:: $(_TEST_FILES)

Просмотреть файл

@ -0,0 +1,313 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=345822
-->
<head>
<title>Test for Bug 345822</title>
<script type="application/javascript" src="/MochiKit/packed.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.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=345822">Mozilla Bug 345822</a>
<p id="display"></p>
<div id="content" style="display: none">
<form>
<input name="input" id='i'>
<input name="input" id='r' type='radio'>
<textarea name="textarea" id='t'></textarea>
</form>
</div>
<pre id="test">
<script type="application/javascript">
/** Test for Bug 345822 **/
function checkRequiredAttribute(element)
{
ok('required' in element, "Element should have the required attribute");
ok(!element.required, "Element required attribute should be disabled");
is(element.getAttribute('required'), null,
"Element required attribute should be disabled");
element.required = true;
ok(element.required, "Element required attribute should be enabled");
isnot(element.getAttribute('required'), null,
"Element required attribute should be enabled");
element.removeAttribute('required');
element.setAttribute('required', '');
ok(element.required, "Element required attribute should be enabled");
isnot(element.getAttribute('required'), null,
"Element required attribute should be enabled");
element.removeAttribute('required');
ok(!element.required, "Element required attribute should be disabled");
is(element.getAttribute('required'), null,
"Element required attribute should be disabled");
}
function checkNotSufferingFromBeingMissing(element)
{
ok(!element.validity.valueMissing,
"Element should not suffer from value missing");
ok(element.validity.valid, "Element should be valid");
ok(element.checkValidity(), "Element should be valid");
is(element.validationMessage, "",
"Validation message should be the empty string");
}
function checkSufferingFromBeingMissing(element)
{
ok(element.validity.valueMissing, "Element should suffer from value missing");
ok(!element.validity.valid, "Element should not be valid");
ok(!element.checkValidity(), "Element should not be valid");
if (element.type == 'checkbox')
{
is(element.validationMessage,
"This checkbox is mandatory, you have to check it.",
"Validation message is wrong");
}
else if (element.type == 'radio')
{
is(element.validationMessage,
"You have to select one of these options.",
"Validation message is wrong");
}
else if (input .type == 'file')
{
is(element.validationMessage,
"You have to select a file.",
"Validation message is wrong");
}
else // text fields
{
is(element.validationMessage,
"This field is mandatory, you have to fill it.",
"Validation message is wrong");
}
}
function checkTextareaRequiredValidity(element)
{
element.value = '';
element.required = false;
checkNotSufferingFromBeingMissing(element);
element.required = true;
checkSufferingFromBeingMissing(element);
element.readOnly = true;
checkNotSufferingFromBeingMissing(element);
element.readOnly = false;
checkSufferingFromBeingMissing(element);
element.value = 'foo';
checkNotSufferingFromBeingMissing(element);
element.value = '';
checkSufferingFromBeingMissing(element);
element.required = false;
checkNotSufferingFromBeingMissing(element);
}
function checkInputRequiredNotApply(element)
{
element.value = '';
element.required = false;
checkNotSufferingFromBeingMissing(element);
element.required = true;
checkNotSufferingFromBeingMissing(element);
element.required = false;
}
function checkInputRequiredValidity(element)
{
element.value = '';
element.required = false;
checkNotSufferingFromBeingMissing(element);
element.required = true;
checkSufferingFromBeingMissing(element);
element.readOnly = true;
checkNotSufferingFromBeingMissing(element);
element.readOnly = false;
checkSufferingFromBeingMissing(element);
element.value = 'foo';
checkNotSufferingFromBeingMissing(element);
element.value = '';
checkSufferingFromBeingMissing(element);
element.required = false;
checkNotSufferingFromBeingMissing(element);
}
function checkInputRequiredValidityForCheckbox(element)
{
element.checked = false;
element.required = false;
checkNotSufferingFromBeingMissing(element);
element.required = true;
checkSufferingFromBeingMissing(element);
element.checked = true;
checkNotSufferingFromBeingMissing(element);
element.checked = false;
checkSufferingFromBeingMissing(element);
element.required = false;
checkNotSufferingFromBeingMissing(element);
}
function checkInputRequiredValidityForRadio(element)
{
element.checked = false;
element.required = false;
checkNotSufferingFromBeingMissing(element);
element.required = true;
checkSufferingFromBeingMissing(element);
element.checked = true;
checkNotSufferingFromBeingMissing(element);
element.checked = false;
checkSufferingFromBeingMissing(element);
element.required = false;
checkNotSufferingFromBeingMissing(element);
// A required radio button should not suffer from value missing if another
// radio button from the same group is checked.
var element2 = document.createElement('input');//document.getElementById('r');
document.forms[0].appendChild(element2);
element2.name = 'input';
element2.type = 'radio';
element2.checked = false;
element2.required = false;
element.checked = false;
element.required = true;
checkSufferingFromBeingMissing(element);
element2.checked = true;
checkNotSufferingFromBeingMissing(element);
// The other radio button should not be disabled.
// A disabled checked radio button in the radio group
// is enough to not suffer from value missing.
element2.disabled = true;
checkNotSufferingFromBeingMissing(element);
// If a radio button is not required but another radio button is required in
// the same group, the not required radio button should not suffer from value
// missing.
element2.disabled = false;
element2.checked = false;
element.required = false;
element2.required = true;
checkNotSufferingFromBeingMissing(element);
checkSufferingFromBeingMissing(element2);
}
function checkInputRequiredValidityForFile(element)
{
function createFileWithData(fileName, fileData) {
var dirSvc = Components.classes["@mozilla.org/file/directory_service;1"]
.getService(Components.interfaces.nsIProperties);
var testFile = dirSvc.get("ProfD", Components.interfaces.nsIFile);
testFile.append(fileName);
var outStream = Components.
classes["@mozilla.org/network/file-output-stream;1"].
createInstance(Components.interfaces.nsIFileOutputStream);
outStream.init(testFile, 0x02 | 0x08 | 0x20, // write, create, truncate
0666, 0);
outStream.write(fileData, fileData.length);
outStream.close();
return testFile;
}
// Need privileges to set a filename with .value.
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
var file = createFileWithData("345822_file", "file content");
element.value = "";
element.required = false;
checkNotSufferingFromBeingMissing(element);
element.required = true;
checkSufferingFromBeingMissing(element);
element.value = file.path;
checkNotSufferingFromBeingMissing(element);
element.value = "";
checkSufferingFromBeingMissing(element);
element.required = false;
checkNotSufferingFromBeingMissing(element);
file.remove(false);
}
var textarea = document.getElementById('t');
var input = document.getElementById('i');
checkRequiredAttribute(textarea);
checkTextareaRequiredValidity(textarea);
// Every input element should have the required attribute.
checkRequiredAttribute(input);
// The required attribute behavior depend of the input type.
// First of all, checks for the types which do not use the required attribute.
// TODO: check 'color' and 'range' when they will be implemented.
input.type = 'hidden';
checkInputRequiredNotApply(input);
input.type = 'submit';
checkInputRequiredNotApply(input);
input.type = 'button';
checkInputRequiredNotApply(input);
input.type = 'reset';
checkInputRequiredNotApply(input);
input.type = 'image';
checkInputRequiredNotApply(input);
// Now, checking for all types which accept the required attribute.
// TODO: check 'url', 'email', 'datetime', 'date',
// 'month', 'week', 'time', 'datetime-local' and 'number'
// when they will be implemented.
input.type = 'text';
checkInputRequiredValidity(input);
input.type = 'password';
checkInputRequiredValidity(input);
input.type = 'checkbox';
checkInputRequiredValidityForCheckbox(input);
input.type = 'radio';
checkInputRequiredValidityForRadio(input);
input.type = 'file';
checkInputRequiredValidityForFile(input);
input.type = 'search';
checkInputRequiredValidity(input);
input.type = 'tel';
checkInputRequiredValidity(input);
</script>
</pre>
</body>
</html>

Просмотреть файл

@ -51,7 +51,7 @@ interface nsIDOMValidityState;
* http://www.w3.org/TR/DOM-Level-2-HTML/
*/
[scriptable, uuid(0aac61a3-6cce-4cae-b73c-b0bacd5d3692)]
[scriptable, uuid(ed3f8a4a-9894-4120-a7e6-4a18f3d8effd)]
interface nsIDOMHTMLInputElement : nsIDOMHTMLElement
{
attribute DOMString accept;
@ -74,6 +74,7 @@ interface nsIDOMHTMLInputElement : nsIDOMHTMLElement
attribute DOMString placeholder;
attribute boolean readOnly;
attribute boolean required;
attribute DOMString accessKey;
attribute DOMString align;

Просмотреть файл

@ -42,7 +42,7 @@
interface nsIControllers;
interface nsIDOMValidityState;
[scriptable, uuid(2a7243d5-7958-4394-a063-64c68efa4a32)]
[scriptable, uuid(df5dc23d-cf90-443e-bf56-cd3af021ebc7)]
interface nsIDOMNSHTMLTextAreaElement : nsISupports
{
attribute boolean autofocus;
@ -53,6 +53,7 @@ interface nsIDOMNSHTMLTextAreaElement : nsISupports
attribute long selectionEnd;
attribute long maxLength;
attribute DOMString placeholder;
attribute boolean required;
/**
* Reflects the wrap content attribute. Possible values are "soft, "hard" and

Просмотреть файл

@ -64,4 +64,8 @@ WrongEventPropertyAccessWarning=The '%S' property of a %S event should not be us
SpeculationFailed=An unbalanced tree was written using document.write() causing data from the network to be reparsed. For more information https://developer.mozilla.org/en/Optimizing_Your_Pages_for_Speculative_Parsing
DocumentWriteIgnored=A call to document.write() from an asynchronously-loaded external script was ignored.
ElementSuffersFromBeingTooLong=The text is too long. It is %S characters long and the limit is %S.
TextElementSuffersFromBeingMissing=This field is mandatory, you have to fill it.
CheckboxElementSuffersFromBeingMissing=This checkbox is mandatory, you have to check it.
RadioElementSuffersFromBeingMissing=You have to select one of these options.
FileElementSuffersFromBeingMissing=You have to select a file.