Bug 825294 - Add framework for datepicker widgets to input[type=date]. r=smaug

-Add framework for datepicker widgets
-Split date input preference from dom.experimental_forms to dom.forms.date
This commit is contained in:
Jordan
2016-06-20 15:55:00 +02:00
parent e58ba38557
commit 18b6de240e
21 changed files with 546 additions and 19 deletions

View File

@@ -112,12 +112,15 @@
#include <limits>
#include "nsIColorPicker.h"
#include "nsIDatePicker.h"
#include "nsIStringEnumerator.h"
#include "HTMLSplitOnSpacesTokenizer.h"
#include "nsIController.h"
#include "nsIMIMEInfo.h"
#include "nsFrameSelection.h"
#include "nsIConsoleService.h"
// input type=date
#include "js/Date.h"
@@ -938,6 +941,13 @@ GetDOMFileOrDirectoryPath(const OwningFileOrDirectory& aData,
} // namespace
/* static */
bool
HTMLInputElement::ValueAsDateEnabled(JSContext* cx, JSObject* obj)
{
return Preferences::GetBool("dom.experimental_forms", false) ||
Preferences::GetBool("dom.forms.datepicker", false);
}
NS_IMETHODIMP
HTMLInputElement::nsFilePickerShownCallback::Done(int16_t aResult)
@@ -1141,6 +1151,59 @@ nsColorPickerShownCallback::Done(const nsAString& aColor)
NS_IMPL_ISUPPORTS(nsColorPickerShownCallback, nsIColorPickerShownCallback)
class DatePickerShownCallback final : public nsIDatePickerShownCallback
{
~DatePickerShownCallback() {}
public:
DatePickerShownCallback(HTMLInputElement* aInput,
nsIDatePicker* aDatePicker)
: mInput(aInput)
, mDatePicker(aDatePicker)
{}
NS_DECL_ISUPPORTS
NS_IMETHOD Done(const nsAString& aDate) override;
NS_IMETHOD Cancel() override;
private:
RefPtr<HTMLInputElement> mInput;
nsCOMPtr<nsIDatePicker> mDatePicker;
};
NS_IMETHODIMP
DatePickerShownCallback::Cancel()
{
mInput->PickerClosed();
return NS_OK;
}
NS_IMETHODIMP
DatePickerShownCallback::Done(const nsAString& aDate)
{
nsAutoString oldValue;
mInput->PickerClosed();
mInput->GetValue(oldValue);
if(!oldValue.Equals(aDate)){
mInput->SetValue(aDate);
nsContentUtils::DispatchTrustedEvent(mInput->OwnerDoc(),
static_cast<nsIDOMHTMLInputElement*>(mInput.get()),
NS_LITERAL_STRING("input"), true,
false);
return nsContentUtils::DispatchTrustedEvent(mInput->OwnerDoc(),
static_cast<nsIDOMHTMLInputElement*>(mInput.get()),
NS_LITERAL_STRING("change"), true,
false);
}
return NS_OK;
}
NS_IMPL_ISUPPORTS(DatePickerShownCallback, nsIDatePickerShownCallback)
bool
HTMLInputElement::IsPopupBlocked() const
{
@@ -1165,6 +1228,56 @@ HTMLInputElement::IsPopupBlocked() const
return permission == nsIPopupWindowManager::DENY_POPUP;
}
nsresult
HTMLInputElement::InitDatePicker()
{
if (!Preferences::GetBool("dom.forms.datepicker", false)) {
return NS_OK;
}
if (mPickerRunning) {
NS_WARNING("Just one nsIDatePicker is allowed");
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIDocument> doc = OwnerDoc();
nsCOMPtr<nsPIDOMWindowOuter> win = doc->GetWindow();
if (!win) {
return NS_ERROR_FAILURE;
}
if (IsPopupBlocked()) {
win->FirePopupBlockedEvent(doc, nullptr, EmptyString(), EmptyString());
return NS_OK;
}
// Get Loc title
nsXPIDLString title;
nsContentUtils::GetLocalizedString(nsContentUtils::eFORMS_PROPERTIES,
"DatePicker", title);
nsresult rv;
nsCOMPtr<nsIDatePicker> datePicker = do_CreateInstance("@mozilla.org/datepicker;1", &rv);
if (!datePicker) {
return rv;
}
nsAutoString initialValue;
GetValueInternal(initialValue);
rv = datePicker->Init(win, title, initialValue);
nsCOMPtr<nsIDatePickerShownCallback> callback =
new DatePickerShownCallback(this, datePicker);
rv = datePicker->Open(callback);
if (NS_SUCCEEDED(rv)) {
mPickerRunning = true;
}
return rv;
}
nsresult
HTMLInputElement::InitColorPicker()
{
@@ -2020,7 +2133,8 @@ HTMLInputElement::GetValue(nsAString& aValue)
}
// Don't return non-sanitized value for types that are experimental on mobile.
if (IsExperimentalMobileType(mType)) {
// or date types
if (IsExperimentalMobileType(mType) || mType == NS_FORM_INPUT_DATE) {
SanitizeValue(aValue);
}
@@ -2654,6 +2768,15 @@ HTMLInputElement::ApplyStep(int32_t aStep)
return rv;
}
/* static */
bool
HTMLInputElement::IsExperimentalMobileType(uint8_t aType)
{
return aType == NS_FORM_INPUT_TIME ||
(aType == NS_FORM_INPUT_DATE &&
!Preferences::GetBool("dom.forms.datepicker", false));
}
NS_IMETHODIMP
HTMLInputElement::StepDown(int32_t n, uint8_t optional_argc)
{
@@ -2843,7 +2966,7 @@ bool
HTMLInputElement::MozIsTextField(bool aExcludePassword)
{
// TODO: temporary until bug 773205 is fixed.
if (IsExperimentalMobileType(mType)) {
if (IsExperimentalMobileType(mType) || mType == NS_FORM_INPUT_DATE) {
return false;
}
@@ -3875,7 +3998,7 @@ HTMLInputElement::PreHandleEvent(EventChainPreVisitor& aVisitor)
// Experimental mobile types rely on the system UI to prevent users to not
// set invalid values but we have to be extra-careful. Especially if the
// option has been enabled on desktop.
if (IsExperimentalMobileType(mType)) {
if (IsExperimentalMobileType(mType) || mType == NS_FORM_INPUT_DATE) {
nsAutoString aValue;
GetValueInternal(aValue);
nsresult rv =
@@ -4291,6 +4414,10 @@ HTMLInputElement::MaybeInitPickers(EventChainPostVisitor& aVisitor)
if (mType == NS_FORM_INPUT_COLOR) {
return InitColorPicker();
}
if (mType == NS_FORM_INPUT_DATE) {
return InitDatePicker();
}
return NS_OK;
}
@@ -4572,7 +4699,8 @@ HTMLInputElement::PostHandleEvent(EventChainPostVisitor& aVisitor)
keyEvent->mKeyCode == NS_VK_RETURN &&
(IsSingleLineTextControl(false, mType) ||
mType == NS_FORM_INPUT_NUMBER ||
IsExperimentalMobileType(mType))) {
IsExperimentalMobileType(mType) ||
mType == NS_FORM_INPUT_DATE)) {
FireChangeEventIfNeeded();
rv = MaybeSubmitForm(aVisitor.mPresContext);
NS_ENSURE_SUCCESS(rv, rv);