Commit a2a0e4ec authored by tkent@chromium.org's avatar tkent@chromium.org

API to support localized numbers for <input type=number>

https://bugs.webkit.org/show_bug.cgi?id=45730

Reviewed by Dimitri Glazkov.

Introduce platform/text/LocalizedNumber.h, and
LocalizedNumberNone.cpp, which is an empty implementation of the
functions in LocalizedNumber.h.  We use LocalizedNumberNone.cpp in
all platforms for now.

A string in a type=number field is parsed as a localized number
first. If the parsing fails, it is parsed as the HTML5 number.

We introduce HTMLInputElement::visibleValue(). It represents a value
which should be drawn by a renderer. HTMLInputElement::value() always
returns a number formatted for HTML5, and visibleValue() may return a
localized number.

No new tests because this doesn't change any behavior.

* Android.mk: Add LocalizedNumber.h and/or LocalizedNumberNone.cpp.
* CMakeLists.txt: ditto.
* GNUmakefile.am: ditto.
* WebCore.gypi: ditto.
* WebCore.pro: ditto.
* WebCore.vcproj/WebCore.vcproj: ditto.
* WebCore.xcodeproj/project.pbxproj: ditto.
* dom/InputElement.h: Add visibleValue().
* html/HTMLInputElement.cpp:
(WebCore::HTMLInputElement::visibleValue): Added.  Just call InputType::visibleValue().
* html/HTMLInputElement.h: Declare visibleValue().
* html/InputType.cpp:
(WebCore::InputType::visibleValue): Add the default implementation of
  visibleValue(), which returns HTMLInputElement::value().
* html/InputType.h: Add declarations.
* html/NumberInputType.cpp:
(WebCore::isHTMLNumberCharacter): Renamed from isNumberCharacter().
(WebCore::isNumberCharacter): Calls isLocalizedNumberCharacter() and isHTMLNumberCharacter().
(WebCore::NumberInputType::visibleValue):
  Returns a localized number string produced by formatLocalizedNumber().
(WebCore::NumberInputType::isAcceptableValue): Calls parseLocalizedNumber().
(WebCore::NumberInputType::sanitizeValue): Calls parseLocalizedNumber().
* html/NumberInputType.h: Add declarations.
* platform/text/LocalizedNumber.h: Added.
* platform/text/LocalizedNumberNone.cpp: Added.
(WebCore::parseLocalizedNumber):
(WebCore::formatLocalizedNumber):
(WebCore::isLocalizedNumberCharacter):
* rendering/RenderTextControlSingleLine.cpp:
(WebCore::RenderTextControlSingleLine::updateFromElement):
  Calls InputElement::visibleValue() instead of value().
* wml/WMLInputElement.h:
(WebCore::WMLInputElement::visibleValue): Added. It just calls value().

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@76661 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 4faf3917
......@@ -615,6 +615,7 @@ LOCAL_SRC_FILES := $(LOCAL_SRC_FILES) \
platform/text/Base64.cpp \
platform/text/BidiContext.cpp \
platform/text/Hyphenation.cpp \
platform/text/LocalizedNumberNone.cpp \
platform/text/RegularExpression.cpp \
platform/text/SegmentedString.cpp \
platform/text/String.cpp \
......
......@@ -1427,6 +1427,7 @@ SET(WebCore_SOURCES
platform/text/Base64.cpp
platform/text/BidiContext.cpp
platform/text/LineEnding.cpp
platform/text/LocalizedNumberNone.cpp
platform/text/Hyphenation.cpp
platform/text/RegularExpression.cpp
platform/text/SegmentedString.cpp
......
2011-01-25 Kent Tamura <tkent@chromium.org>
Reviewed by Dimitri Glazkov.
API to support localized numbers for <input type=number>
https://bugs.webkit.org/show_bug.cgi?id=45730
Introduce platform/text/LocalizedNumber.h, and
LocalizedNumberNone.cpp, which is an empty implementation of the
functions in LocalizedNumber.h. We use LocalizedNumberNone.cpp in
all platforms for now.
A string in a type=number field is parsed as a localized number
first. If the parsing fails, it is parsed as the HTML5 number.
We introduce HTMLInputElement::visibleValue(). It represents a value
which should be drawn by a renderer. HTMLInputElement::value() always
returns a number formatted for HTML5, and visibleValue() may return a
localized number.
No new tests because this doesn't change any behavior.
* Android.mk: Add LocalizedNumber.h and/or LocalizedNumberNone.cpp.
* CMakeLists.txt: ditto.
* GNUmakefile.am: ditto.
* WebCore.gypi: ditto.
* WebCore.pro: ditto.
* WebCore.vcproj/WebCore.vcproj: ditto.
* WebCore.xcodeproj/project.pbxproj: ditto.
* dom/InputElement.h: Add visibleValue().
* html/HTMLInputElement.cpp:
(WebCore::HTMLInputElement::visibleValue): Added. Just call InputType::visibleValue().
* html/HTMLInputElement.h: Declare visibleValue().
* html/InputType.cpp:
(WebCore::InputType::visibleValue): Add the default implementation of
visibleValue(), which returns HTMLInputElement::value().
* html/InputType.h: Add declarations.
* html/NumberInputType.cpp:
(WebCore::isHTMLNumberCharacter): Renamed from isNumberCharacter().
(WebCore::isNumberCharacter): Calls isLocalizedNumberCharacter() and isHTMLNumberCharacter().
(WebCore::NumberInputType::visibleValue):
Returns a localized number string produced by formatLocalizedNumber().
(WebCore::NumberInputType::isAcceptableValue): Calls parseLocalizedNumber().
(WebCore::NumberInputType::sanitizeValue): Calls parseLocalizedNumber().
* html/NumberInputType.h: Add declarations.
* platform/text/LocalizedNumber.h: Added.
* platform/text/LocalizedNumberNone.cpp: Added.
(WebCore::parseLocalizedNumber):
(WebCore::formatLocalizedNumber):
(WebCore::isLocalizedNumberCharacter):
* rendering/RenderTextControlSingleLine.cpp:
(WebCore::RenderTextControlSingleLine::updateFromElement):
Calls InputElement::visibleValue() instead of value().
* wml/WMLInputElement.h:
(WebCore::WMLInputElement::visibleValue): Added. It just calls value().
2011-01-25 Alexey Proskuryakov <ap@apple.com>
Reviewed by Darin Adler.
......@@ -2618,6 +2618,8 @@ webcore_sources += \
Source/WebCore/platform/text/Hyphenation.h \
Source/WebCore/platform/text/LineEnding.cpp \
Source/WebCore/platform/text/LineEnding.h \
Source/WebCore/platform/text/LocalizedNumber.h \
Source/WebCore/platform/text/LocalizedNumberNone.cpp \
Source/WebCore/platform/text/ParserUtilities.h \
Source/WebCore/platform/text/PlatformString.h \
Source/WebCore/platform/text/RegularExpression.cpp \
......
......@@ -3314,6 +3314,8 @@
'platform/text/Hyphenation.h',
'platform/text/LineEnding.cpp',
'platform/text/LineEnding.h',
'platform/text/LocalizedNumber.h',
'platform/text/LocalizedNumberNone.cpp',
'platform/text/ParserUtilities.h',
'platform/text/PlatformString.h',
'platform/text/RegularExpression.cpp',
......
......@@ -1175,6 +1175,7 @@ SOURCES += \
platform/text/Base64.cpp \
platform/text/BidiContext.cpp \
platform/text/Hyphenation.cpp \
platform/text/LocalizedNumberNone.cpp \
platform/ContentType.cpp \
platform/CrossThreadCopier.cpp \
platform/DeprecatedPtrListImpl.cpp \
......
......@@ -30176,6 +30176,14 @@
RelativePath="..\platform\text\LineEnding.h"
>
</File>
<File
RelativePath="..\platform\text\LocalizedNumber.h"
>
</File>
<File
RelativePath="..\platform\text\LocalizedNumberNone.cpp"
>
</File>
<File
RelativePath="..\platform\text\ParserUtilities.h"
>
......@@ -5634,6 +5634,8 @@
F3F5CF1312ED81B30084C569 /* InspectorDatabaseInstrumentation.h in Headers */ = {isa = PBXBuildFile; fileRef = F3F5CF1212ED81B30084C569 /* InspectorDatabaseInstrumentation.h */; };
F4EAF4AE10C742B1009100D3 /* OpenTypeSanitizer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F4EAF4AC10C742B1009100D3 /* OpenTypeSanitizer.cpp */; };
F4EAF4AF10C742B1009100D3 /* OpenTypeSanitizer.h in Headers */ = {isa = PBXBuildFile; fileRef = F4EAF4AD10C742B1009100D3 /* OpenTypeSanitizer.h */; };
F5142C69123F12B000F5BD4C /* LocalizedNumber.h in Headers */ = {isa = PBXBuildFile; fileRef = F5142C68123F12B000F5BD4C /* LocalizedNumber.h */; };
F5142C6B123F12C500F5BD4C /* LocalizedNumberNone.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F5142C6A123F12C500F5BD4C /* LocalizedNumberNone.cpp */; };
F55B3DAD1251F12D003EF269 /* BaseTextInputType.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F55B3D791251F12D003EF269 /* BaseTextInputType.cpp */; };
F55B3DAE1251F12D003EF269 /* BaseTextInputType.h in Headers */ = {isa = PBXBuildFile; fileRef = F55B3D7A1251F12D003EF269 /* BaseTextInputType.h */; };
F55B3DAF1251F12D003EF269 /* ButtonInputType.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F55B3D7B1251F12D003EF269 /* ButtonInputType.cpp */; };
......@@ -11999,6 +12001,8 @@
F3F5CF1212ED81B30084C569 /* InspectorDatabaseInstrumentation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InspectorDatabaseInstrumentation.h; sourceTree = "<group>"; };
F4EAF4AC10C742B1009100D3 /* OpenTypeSanitizer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = OpenTypeSanitizer.cpp; path = opentype/OpenTypeSanitizer.cpp; sourceTree = "<group>"; };
F4EAF4AD10C742B1009100D3 /* OpenTypeSanitizer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OpenTypeSanitizer.h; path = opentype/OpenTypeSanitizer.h; sourceTree = "<group>"; };
F5142C68123F12B000F5BD4C /* LocalizedNumber.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LocalizedNumber.h; sourceTree = "<group>"; };
F5142C6A123F12C500F5BD4C /* LocalizedNumberNone.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LocalizedNumberNone.cpp; sourceTree = "<group>"; };
F523D23B02DE4396018635CA /* HTMLDocument.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HTMLDocument.cpp; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; };
F523D23C02DE4396018635CA /* HTMLDocument.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = HTMLDocument.h; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; };
F523D23E02DE4396018635CA /* HTMLElement.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HTMLElement.cpp; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; };
......@@ -17563,6 +17567,8 @@
375CD231119D43C800A2A859 /* Hyphenation.h */,
89B5EA9F11E8003D00F2367E /* LineEnding.cpp */,
89B5EAA011E8003D00F2367E /* LineEnding.h */,
F5142C68123F12B000F5BD4C /* LocalizedNumber.h */,
F5142C6A123F12C500F5BD4C /* LocalizedNumberNone.cpp */,
BC76AC110DD7AD5C00415F34 /* ParserUtilities.h */,
B2C3D9FB0D006C1D00EF6F26 /* PlatformString.h */,
B2C3D9FC0D006C1D00EF6F26 /* RegularExpression.cpp */,
......@@ -21464,6 +21470,7 @@
06E81ED70AB5D5E900C87837 /* LocalCurrentGraphicsContext.h in Headers */,
89878568122CA064003AABDA /* LocalFileSystem.h in Headers */,
BC5CFCA911F793320099ED09 /* LocalizationStrategy.h in Headers */,
F5142C69123F12B000F5BD4C /* LocalizedNumber.h in Headers */,
935207BE09BD410A00F2038D /* LocalizedStrings.h in Headers */,
511F23180DC160DA004F0032 /* LocalStorageTask.h in Headers */,
511F231A0DC160DA004F0032 /* LocalStorageThread.h in Headers */,
......@@ -24313,6 +24320,7 @@
7EE6846812D26E3800E79415 /* LoaderRunLoopCF.cpp in Sources */,
06E81EEC0AB5DA9700C87837 /* LocalCurrentGraphicsContext.mm in Sources */,
89878567122CA064003AABDA /* LocalFileSystem.cpp in Sources */,
F5142C6B123F12C500F5BD4C /* LocalizedNumberNone.cpp in Sources */,
C046E1AC1208A9FE00BA2CF7 /* LocalizedStrings.cpp in Sources */,
511F23170DC160DA004F0032 /* LocalStorageTask.cpp in Sources */,
511F23190DC160DA004F0032 /* LocalStorageThread.cpp in Sources */,
......@@ -59,6 +59,8 @@ public:
virtual String value() const = 0;
virtual void setValue(const String&, bool sendChangeEvent = false) = 0;
virtual void setValueForUser(const String&) = 0;
// The value which is drawn by a renderer.
virtual String visibleValue() const = 0;
// Returns true if the specified string can be set as the value of InputElement.
virtual bool isAcceptableValue(const String&) const = 0;
......
......@@ -1121,6 +1121,11 @@ FileList* HTMLInputElement::files()
return m_inputType->files();
}
String HTMLInputElement::visibleValue() const
{
return m_inputType->visibleValue();
}
bool HTMLInputElement::isAcceptableValue(const String& proposedValue) const
{
return m_inputType->isAcceptableValue(proposedValue);
......
......@@ -258,6 +258,7 @@ private:
virtual void cacheSelection(int start, int end);
virtual String visibleValue() const;
virtual bool isAcceptableValue(const String&) const;
virtual String sanitizeValue(const String&) const;
virtual bool hasUnacceptableValue() const;
......
......@@ -506,6 +506,11 @@ void InputType::didDispatchClick(Event*, const ClickHandlingState&)
{
}
String InputType::visibleValue() const
{
return element()->value();
}
bool InputType::isAcceptableValue(const String&)
{
return true;
......
......@@ -148,6 +148,7 @@ public:
virtual String typeMismatchText() const;
virtual String valueMissingText() const;
virtual bool canSetStringValue() const;
virtual String visibleValue() const;
virtual bool isAcceptableValue(const String&);
virtual String sanitizeValue(const String&);
virtual bool hasUnacceptableValue();
......
......@@ -38,6 +38,7 @@
#include "HTMLNames.h"
#include "HTMLParserIdioms.h"
#include "KeyboardEvent.h"
#include "LocalizedNumber.h"
#include "RenderTextControl.h"
#include <limits>
#include <wtf/ASCIICType.h>
......@@ -55,11 +56,18 @@ static const double numberDefaultMaximum = FLT_MAX;
static const double numberDefaultStep = 1.0;
static const double numberStepScaleFactor = 1.0;
static bool isNumberCharacter(UChar ch)
// Returns true if the specified character can be a part of 'valid floating
// point number' of HTML5.
static bool isHTMLNumberCharacter(UChar ch)
{
return ch == '+' || ch == '-' || ch == '.' || ch == 'e' || ch == 'E' || isASCIIDigit(ch);
}
static bool isNumberCharacter(UChar ch)
{
return isLocalizedNumberCharacter(ch) || isHTMLNumberCharacter(ch);
}
PassOwnPtr<InputType> NumberInputType::create(HTMLInputElement* element)
{
return adoptPtr(new NumberInputType(element));
......@@ -248,13 +256,29 @@ void NumberInputType::handleBlurEvent()
element()->renderer()->updateFromElement();
}
String NumberInputType::visibleValue() const
{
String currentValue = element()->value();
if (currentValue.isEmpty())
return currentValue;
double doubleValue = numeric_limits<double>::quiet_NaN();
parseToDoubleForNumberType(currentValue, &doubleValue);
String localized = formatLocalizedNumber(doubleValue);
return localized.isEmpty() ? currentValue : localized;
}
bool NumberInputType::isAcceptableValue(const String& proposedValue)
{
return proposedValue.isEmpty() || parseToDoubleForNumberType(proposedValue, 0);
return proposedValue.isEmpty() || isfinite(parseLocalizedNumber(proposedValue)) || parseToDoubleForNumberType(proposedValue, 0);
}
String NumberInputType::sanitizeValue(const String& proposedValue)
{
// Try to parse the value as a localized number, then try to parse it as
// the standard format.
double parsedValue = parseLocalizedNumber(proposedValue);
if (isfinite(parsedValue))
return serializeForNumberType(parsedValue);
return parseToDoubleForNumberType(proposedValue, 0) ? proposedValue : String();
}
......
......@@ -64,6 +64,7 @@ private:
virtual String serialize(double) const;
virtual double acceptableError(double) const;
virtual void handleBlurEvent();
virtual String visibleValue() const;
virtual bool isAcceptableValue(const String&);
virtual String sanitizeValue(const String&);
virtual bool hasUnacceptableValue();
......
/*
* Copyright (C) 2011 Google Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef LocalizedNumber_h
#define LocalizedNumber_h
#include <wtf/text/WTFString.h>
namespace WebCore {
// Parses a string representation of a floating point number localized
// for the browser's current locale. If the input string is not valid
// or an implementation doesn't support localized numbers, this
// function returns NaN. This function doesn't need to support
// scientific notation, NaN, +Infinity and -Infinity, and doesn't need
// to support the standard representations of ECMAScript and HTML5.
double parseLocalizedNumber(const String&);
// Serializes the specified floating point number for the browser's
// current locale. If an implementation doesn't support localized
// numbers or the input value is NaN or Infinitiy, the function should
// return an empty string.
String formatLocalizedNumber(double);
// Returns true if the input character can be used to represent a
// number in the browser locale. For example, this should return true for 0-9 .
// , + - for en-US locale.
bool isLocalizedNumberCharacter(UChar32);
} // namespace WebCore
#endif // LocalizedNumber_h
/*
* Copyright (C) 2011 Google Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include "LocalizedNumber.h"
#include <limits>
using namespace std;
namespace WebCore {
double parseLocalizedNumber(const String&)
{
return numeric_limits<double>::quiet_NaN();
}
String formatLocalizedNumber(double)
{
return String();
}
bool isLocalizedNumberCharacter(UChar32)
{
return false;
}
} // namespace WebCore
......@@ -680,7 +680,7 @@ void RenderTextControlSingleLine::updateFromElement()
// flag is false. It protects an unacceptable renderer value from
// being overwritten with the DOM value.
if (!static_cast<HTMLInputElement*>(node())->formControlValueMatchesRenderer())
setInnerTextValue(inputElement()->value());
setInnerTextValue(inputElement()->visibleValue());
}
}
......
......@@ -63,6 +63,7 @@ public:
virtual String value() const;
virtual void setValue(const String&, bool sendChangeEvent = false);
virtual void setValueForUser(const String&);
virtual String visibleValue() const { return value(); }
virtual void setValueFromRenderer(const String&);
virtual bool saveFormControlState(String& value) const;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment