Bug 1020697 - Implement @autocomplete for <select>. r=smaug

This commit is contained in:
Giovanni Sferro 2014-06-17 19:50:00 +02:00
parent 2b00ecc700
commit 3ef149fde8
7 changed files with 68 additions and 28 deletions

View File

@ -2040,8 +2040,11 @@ public:
*
* @return whether aAttr was valid and can be cached.
*/
static AutocompleteAttrState SerializeAutocompleteAttribute(const nsAttrValue* aAttr,
nsAString& aResult);
static AutocompleteAttrState
SerializeAutocompleteAttribute(const nsAttrValue* aAttr,
nsAString& aResult,
AutocompleteAttrState aCachedState =
eAutocompleteAttrState_Unknown);
/**
* This will parse aSource, to extract the value of the pseudo attribute

View File

@ -855,8 +855,26 @@ nsContentUtils::IsAutocompleteEnabled(nsIDOMHTMLInputElement* aInput)
nsContentUtils::AutocompleteAttrState
nsContentUtils::SerializeAutocompleteAttribute(const nsAttrValue* aAttr,
nsAString& aResult)
nsAString& aResult,
AutocompleteAttrState aCachedState)
{
if (!aAttr ||
aCachedState == nsContentUtils::eAutocompleteAttrState_Invalid) {
return aCachedState;
}
if (aCachedState == nsContentUtils::eAutocompleteAttrState_Valid) {
uint32_t atomCount = aAttr->GetAtomCount();
for (uint32_t i = 0; i < atomCount; i++) {
if (i != 0) {
aResult.Append(' ');
}
aResult.Append(nsDependentAtomString(aAttr->AtomAt(i)));
}
nsContentUtils::ASCIIToLower(aResult);
return aCachedState;
}
AutocompleteAttrState state = InternalSerializeAutocompleteAttribute(aAttr, aResult);
if (state == eAutocompleteAttrState_Valid) {
ASCIIToLower(aResult);
@ -873,7 +891,7 @@ nsContentUtils::SerializeAutocompleteAttribute(const nsAttrValue* aAttr,
*/
nsContentUtils::AutocompleteAttrState
nsContentUtils::InternalSerializeAutocompleteAttribute(const nsAttrValue* aAttrVal,
nsAString& aResult)
nsAString& aResult)
{
// No sandbox attribute so we are done
if (!aAttrVal) {

View File

@ -1520,23 +1520,10 @@ HTMLInputElement::GetAutocomplete(nsAString& aValue)
{
aValue.Truncate(0);
const nsAttrValue* attributeVal = GetParsedAttr(nsGkAtoms::autocomplete);
if (!attributeVal ||
mAutocompleteAttrState == nsContentUtils::eAutocompleteAttrState_Invalid) {
return NS_OK;
}
if (mAutocompleteAttrState == nsContentUtils::eAutocompleteAttrState_Valid) {
uint32_t atomCount = attributeVal->GetAtomCount();
for (uint32_t i = 0; i < atomCount; i++) {
if (i != 0) {
aValue.Append(' ');
}
aValue.Append(nsDependentAtomString(attributeVal->AtomAt(i)));
}
nsContentUtils::ASCIIToLower(aValue);
return NS_OK;
}
mAutocompleteAttrState = nsContentUtils::SerializeAutocompleteAttribute(attributeVal, aValue);
mAutocompleteAttrState =
nsContentUtils::SerializeAutocompleteAttribute(attributeVal, aValue,
mAutocompleteAttrState);
return NS_OK;
}

View File

@ -104,6 +104,7 @@ HTMLSelectElement::HTMLSelectElement(already_AddRefed<nsINodeInfo>& aNodeInfo,
FromParser aFromParser)
: nsGenericHTMLFormElementWithState(aNodeInfo),
mOptions(new HTMLOptionsCollection(MOZ_THIS_IN_INITIALIZER_LIST())),
mAutocompleteAttrState(nsContentUtils::eAutocompleteAttrState_Unknown),
mIsDoneAddingChildren(!aFromParser),
mDisabledChanged(false),
mMutating(false),
@ -177,6 +178,16 @@ HTMLSelectElement::SetCustomValidity(const nsAString& aError)
return NS_OK;
}
void
HTMLSelectElement::GetAutocomplete(DOMString& aValue)
{
const nsAttrValue* attributeVal = GetParsedAttr(nsGkAtoms::autocomplete);
mAutocompleteAttrState =
nsContentUtils::SerializeAutocompleteAttribute(attributeVal, aValue,
mAutocompleteAttrState);
}
NS_IMETHODIMP
HTMLSelectElement::GetForm(nsIDOMHTMLFormElement** aForm)
{
@ -1333,6 +1344,9 @@ HTMLSelectElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
UpdateBarredFromConstraintValidation();
} else if (aName == nsGkAtoms::required) {
UpdateValueMissingValidityState();
} else if (aName == nsGkAtoms::autocomplete) {
// Clear the cached @autocomplete attribute state
mAutocompleteAttrState = nsContentUtils::eAutocompleteAttrState_Unknown;
}
UpdateState(aNotify);
@ -1420,8 +1434,13 @@ HTMLSelectElement::ParseAttribute(int32_t aNamespaceID,
const nsAString& aValue,
nsAttrValue& aResult)
{
if (aAttribute == nsGkAtoms::size && kNameSpaceID_None == aNamespaceID) {
return aResult.ParsePositiveIntValue(aValue);
if (kNameSpaceID_None == aNamespaceID) {
if (aAttribute == nsGkAtoms::size) {
return aResult.ParsePositiveIntValue(aValue);
} else if (aAttribute == nsGkAtoms::autocomplete) {
aResult.ParseAtomArray(aValue);
return true;
}
}
return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
aResult);

View File

@ -17,6 +17,7 @@
#include "nsCOMPtr.h"
#include "nsError.h"
#include "mozilla/dom/HTMLFormElement.h"
#include "nsContentUtils.h"
class nsContentList;
class nsIDOMHTMLOptionElement;
@ -159,6 +160,11 @@ public:
{
SetHTMLBoolAttr(nsGkAtoms::autofocus, aVal, aRv);
}
void GetAutocomplete(DOMString& aValue);
void SetAutocomplete(const nsAString& aValue, ErrorResult& aRv)
{
SetHTMLAttr(nsGkAtoms::autocomplete, aValue, aRv);
}
bool Disabled() const
{
return GetBoolAttr(nsGkAtoms::disabled);
@ -605,6 +611,7 @@ protected:
/** The options[] array */
nsRefPtr<HTMLOptionsCollection> mOptions;
nsContentUtils::AutocompleteAttrState mAutocompleteAttrState;
/** false if the parser is in the middle of adding children. */
bool mIsDoneAddingChildren;
/** true if our disabled state has changed from the default **/

View File

@ -13,7 +13,8 @@ Test @autocomplete on <input>
<p id="display"></p>
<div id="content" style="display: none">
<form>
<input id="field" />
<input id="input-field" />
<select id="select-field" />
</form>
</div>
<pre id="test">
@ -69,9 +70,8 @@ var values = [
];
var types = [undefined, "hidden", "text", "search"]; // Valid types for all non-multiline hints.
var field = document.getElementById("field");
function checkAutocompleteValues(type) {
function checkAutocompleteValues(field, type) {
for (var test of values) {
if (typeof(test[0]) === "undefined")
field.removeAttribute("autocomplete");
@ -83,14 +83,18 @@ function checkAutocompleteValues(type) {
}
function start() {
var inputField = document.getElementById("input-field");
for (var type of types) {
// Switch the input type
if (typeof(type) === "undefined")
field.removeAttribute("type");
inputField.removeAttribute("type");
else
field.type = type;
checkAutocompleteValues(type || "");
inputField.type = type;
checkAutocompleteValues(inputField, type || "");
}
var selectField = document.getElementById("select-field");
checkAutocompleteValues(selectField, "select");
SimpleTest.finish();
}

View File

@ -10,6 +10,8 @@
interface HTMLSelectElement : HTMLElement {
[SetterThrows, Pure]
attribute boolean autofocus;
[Pref="dom.forms.autocomplete.experimental", SetterThrows, Pure]
attribute DOMString autocomplete;
[SetterThrows, Pure]
attribute boolean disabled;
[Pure]