2003-03-19 03:47:09 +00:00
|
|
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
2012-05-21 11:12:37 +00:00
|
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
2010-07-14 06:39:48 +00:00
|
|
|
|
2012-12-14 23:58:45 +00:00
|
|
|
#include "mozilla/DebugOnly.h"
|
2011-10-11 05:50:08 +00:00
|
|
|
|
2013-03-28 19:41:32 +00:00
|
|
|
#include "mozilla/dom/HTMLInputElement.h"
|
2013-03-28 19:41:32 +00:00
|
|
|
#include "mozilla/dom/HTMLInputElementBinding.h"
|
2013-04-16 14:20:37 +00:00
|
|
|
#include "nsAsyncDOMEvent.h"
|
2012-09-30 16:40:24 +00:00
|
|
|
#include "nsAttrValueInlines.h"
|
2011-07-15 10:31:34 +00:00
|
|
|
|
1998-09-01 01:27:08 +00:00
|
|
|
#include "nsIDOMHTMLInputElement.h"
|
2001-11-02 07:40:01 +00:00
|
|
|
#include "nsITextControlElement.h"
|
2005-09-21 22:02:26 +00:00
|
|
|
#include "nsIDOMNSEditableElement.h"
|
2002-03-07 20:53:40 +00:00
|
|
|
#include "nsIRadioVisitor.h"
|
2002-12-17 23:38:04 +00:00
|
|
|
#include "nsIPhonetic.h"
|
2002-03-07 20:53:40 +00:00
|
|
|
|
1999-12-01 15:12:49 +00:00
|
|
|
#include "nsIControllers.h"
|
2012-06-06 12:16:58 +00:00
|
|
|
#include "nsIStringBundle.h"
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 18:00:39 +00:00
|
|
|
#include "nsFocusManager.h"
|
2001-04-18 01:41:20 +00:00
|
|
|
#include "nsPIDOMWindow.h"
|
2001-02-22 03:01:34 +00:00
|
|
|
#include "nsContentCID.h"
|
1999-12-01 15:12:49 +00:00
|
|
|
#include "nsIComponentManager.h"
|
1998-09-23 17:16:51 +00:00
|
|
|
#include "nsIDOMHTMLFormElement.h"
|
2006-12-26 17:47:52 +00:00
|
|
|
#include "nsGkAtoms.h"
|
1998-09-01 01:27:08 +00:00
|
|
|
#include "nsStyleConsts.h"
|
2004-07-31 23:15:21 +00:00
|
|
|
#include "nsPresContext.h"
|
2004-01-26 19:22:05 +00:00
|
|
|
#include "nsMappedAttributes.h"
|
1998-09-23 17:16:51 +00:00
|
|
|
#include "nsIFormControl.h"
|
|
|
|
#include "nsIForm.h"
|
2010-05-26 12:49:38 +00:00
|
|
|
#include "nsFormSubmission.h"
|
2010-08-20 17:47:30 +00:00
|
|
|
#include "nsFormSubmissionConstants.h"
|
1999-01-26 23:43:52 +00:00
|
|
|
#include "nsIDocument.h"
|
|
|
|
#include "nsIPresShell.h"
|
|
|
|
#include "nsIFormControlFrame.h"
|
2008-10-28 00:27:55 +00:00
|
|
|
#include "nsITextControlFrame.h"
|
1999-01-26 23:43:52 +00:00
|
|
|
#include "nsIFrame.h"
|
2013-03-08 09:40:12 +00:00
|
|
|
#include "nsRangeFrame.h"
|
2011-04-21 17:35:52 +00:00
|
|
|
#include "nsEventStates.h"
|
2000-02-23 22:34:40 +00:00
|
|
|
#include "nsIServiceManager.h"
|
2012-07-27 14:03:27 +00:00
|
|
|
#include "nsError.h"
|
2000-07-14 23:20:48 +00:00
|
|
|
#include "nsIEditor.h"
|
2001-07-16 02:40:48 +00:00
|
|
|
#include "nsGUIEvent.h"
|
2010-08-18 18:33:37 +00:00
|
|
|
#include "nsIIOService.h"
|
2011-05-04 12:49:59 +00:00
|
|
|
#include "nsDocument.h"
|
2012-02-14 02:00:56 +00:00
|
|
|
#include "nsAttrValueOrString.h"
|
1998-09-01 01:27:08 +00:00
|
|
|
|
2005-01-27 22:52:53 +00:00
|
|
|
#include "nsPresState.h"
|
2000-05-04 13:57:35 +00:00
|
|
|
#include "nsIDOMEvent.h"
|
2000-02-15 23:02:55 +00:00
|
|
|
#include "nsIDOMNodeList.h"
|
|
|
|
#include "nsIDOMHTMLCollection.h"
|
2001-11-02 07:40:01 +00:00
|
|
|
#include "nsLinebreakConverter.h" //to strip out carriage returns
|
|
|
|
#include "nsReadableUtils.h"
|
2002-09-16 06:00:08 +00:00
|
|
|
#include "nsUnicharUtils.h"
|
2006-03-07 17:08:51 +00:00
|
|
|
#include "nsEventDispatcher.h"
|
2005-12-12 23:53:06 +00:00
|
|
|
#include "nsLayoutUtils.h"
|
2000-01-14 09:28:54 +00:00
|
|
|
|
2001-05-11 21:11:38 +00:00
|
|
|
#include "nsIDOMMutationEvent.h"
|
2007-05-14 09:11:38 +00:00
|
|
|
#include "nsIDOMEventTarget.h"
|
2001-05-11 21:11:38 +00:00
|
|
|
#include "nsMutationEvent.h"
|
2011-06-24 02:18:01 +00:00
|
|
|
#include "nsEventListenerManager.h"
|
2001-05-11 21:11:38 +00:00
|
|
|
|
2004-07-20 06:11:27 +00:00
|
|
|
#include "nsRuleData.h"
|
2013-01-15 12:22:03 +00:00
|
|
|
#include <algorithm>
|
2001-05-31 22:19:43 +00:00
|
|
|
|
2010-09-05 18:00:05 +00:00
|
|
|
// input type=radio
|
|
|
|
#include "nsIRadioGroupContainer.h"
|
2002-07-20 23:09:24 +00:00
|
|
|
|
2002-02-16 01:19:24 +00:00
|
|
|
// input type=file
|
2012-06-06 02:08:30 +00:00
|
|
|
#include "nsIFile.h"
|
2002-09-16 06:00:08 +00:00
|
|
|
#include "nsNetUtil.h"
|
2007-07-25 04:29:47 +00:00
|
|
|
#include "nsDOMFile.h"
|
2010-08-27 15:49:06 +00:00
|
|
|
#include "nsDirectoryServiceDefs.h"
|
|
|
|
#include "nsIContentPrefService.h"
|
2012-06-06 12:16:58 +00:00
|
|
|
#include "nsIMIMEService.h"
|
2010-08-27 15:49:06 +00:00
|
|
|
#include "nsIObserverService.h"
|
|
|
|
#include "nsIPopupWindowManager.h"
|
2010-08-27 15:49:08 +00:00
|
|
|
#include "nsGlobalWindow.h"
|
2002-02-16 01:19:24 +00:00
|
|
|
|
2003-03-19 03:47:09 +00:00
|
|
|
// input type=image
|
|
|
|
#include "nsImageLoadingContent.h"
|
2012-10-12 12:43:01 +00:00
|
|
|
#include "imgRequestProxy.h"
|
2003-03-19 03:47:09 +00:00
|
|
|
|
2008-04-11 17:29:06 +00:00
|
|
|
#include "mozAutoDocUpdate.h"
|
2010-06-09 06:45:32 +00:00
|
|
|
#include "nsContentCreatorFunctions.h"
|
2010-08-18 19:26:22 +00:00
|
|
|
#include "nsContentUtils.h"
|
2012-11-21 10:13:57 +00:00
|
|
|
#include "mozilla/dom/DirectionalityUtils.h"
|
2011-04-11 18:31:00 +00:00
|
|
|
#include "nsRadioVisitor.h"
|
2008-04-11 17:29:06 +00:00
|
|
|
|
2011-09-09 02:27:12 +00:00
|
|
|
#include "mozilla/LookAndFeel.h"
|
2011-11-16 07:50:19 +00:00
|
|
|
#include "mozilla/Util.h" // DebugOnly
|
2012-06-23 12:32:54 +00:00
|
|
|
#include "mozilla/Preferences.h"
|
2012-12-22 14:46:19 +00:00
|
|
|
#include "mozilla/MathAlgorithms.h"
|
2011-09-09 02:27:12 +00:00
|
|
|
|
2012-02-29 22:35:47 +00:00
|
|
|
#include "nsIIDNService.h"
|
|
|
|
|
2012-06-22 09:36:24 +00:00
|
|
|
#include <limits>
|
|
|
|
|
2012-12-27 18:55:31 +00:00
|
|
|
// input type=date
|
|
|
|
#include "jsapi.h"
|
|
|
|
|
2013-03-28 19:41:32 +00:00
|
|
|
NS_IMPL_NS_NEW_HTML_ELEMENT_CHECK_PARSER(Input)
|
2010-10-25 12:17:38 +00:00
|
|
|
|
1998-09-01 01:27:08 +00:00
|
|
|
// XXX align=left, hspace, vspace, border? other nav4 attrs
|
|
|
|
|
2000-09-09 05:46:14 +00:00
|
|
|
static NS_DEFINE_CID(kXULControllersCID, NS_XULCONTROLLERS_CID);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 18:00:39 +00:00
|
|
|
|
2013-03-28 19:41:32 +00:00
|
|
|
namespace mozilla {
|
|
|
|
namespace dom {
|
|
|
|
|
2006-03-07 17:08:51 +00:00
|
|
|
// First bits are needed for the control type.
|
|
|
|
#define NS_OUTER_ACTIVATE_EVENT (1 << 9)
|
|
|
|
#define NS_ORIGINAL_CHECKED_VALUE (1 << 10)
|
|
|
|
#define NS_NO_CONTENT_DISPATCH (1 << 11)
|
2009-01-22 00:07:44 +00:00
|
|
|
#define NS_ORIGINAL_INDETERMINATE_VALUE (1 << 12)
|
2006-03-07 17:08:51 +00:00
|
|
|
#define NS_CONTROL_TYPE(bits) ((bits) & ~( \
|
2009-01-22 00:07:44 +00:00
|
|
|
NS_OUTER_ACTIVATE_EVENT | NS_ORIGINAL_CHECKED_VALUE | NS_NO_CONTENT_DISPATCH | \
|
|
|
|
NS_ORIGINAL_INDETERMINATE_VALUE))
|
2006-03-07 17:08:51 +00:00
|
|
|
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 18:00:39 +00:00
|
|
|
// whether textfields should be selected once focused:
|
|
|
|
// -1: no, 1: yes, 0: uninitialized
|
2012-08-22 15:56:38 +00:00
|
|
|
static int32_t gSelectTextFieldOnFocus;
|
2013-03-28 19:41:32 +00:00
|
|
|
UploadLastDir* HTMLInputElement::gUploadLastDir;
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 18:00:39 +00:00
|
|
|
|
2010-04-15 11:03:00 +00:00
|
|
|
static const nsAttrValue::EnumTable kInputTypeTable[] = {
|
|
|
|
{ "button", NS_FORM_INPUT_BUTTON },
|
|
|
|
{ "checkbox", NS_FORM_INPUT_CHECKBOX },
|
2012-12-27 16:06:53 +00:00
|
|
|
{ "date", NS_FORM_INPUT_DATE },
|
2010-08-18 18:31:54 +00:00
|
|
|
{ "email", NS_FORM_INPUT_EMAIL },
|
2010-04-15 11:03:00 +00:00
|
|
|
{ "file", NS_FORM_INPUT_FILE },
|
|
|
|
{ "hidden", NS_FORM_INPUT_HIDDEN },
|
|
|
|
{ "reset", NS_FORM_INPUT_RESET },
|
|
|
|
{ "image", NS_FORM_INPUT_IMAGE },
|
2012-06-10 20:23:17 +00:00
|
|
|
{ "number", NS_FORM_INPUT_NUMBER },
|
2010-04-15 11:03:00 +00:00
|
|
|
{ "password", NS_FORM_INPUT_PASSWORD },
|
|
|
|
{ "radio", NS_FORM_INPUT_RADIO },
|
2013-02-16 12:35:57 +00:00
|
|
|
{ "range", NS_FORM_INPUT_RANGE },
|
2010-05-17 10:20:22 +00:00
|
|
|
{ "search", NS_FORM_INPUT_SEARCH },
|
2010-04-15 11:03:00 +00:00
|
|
|
{ "submit", NS_FORM_INPUT_SUBMIT },
|
2010-05-12 07:17:07 +00:00
|
|
|
{ "tel", NS_FORM_INPUT_TEL },
|
2010-04-15 11:03:00 +00:00
|
|
|
{ "text", NS_FORM_INPUT_TEXT },
|
2013-01-08 17:10:00 +00:00
|
|
|
{ "time", NS_FORM_INPUT_TIME },
|
2010-08-18 18:33:37 +00:00
|
|
|
{ "url", NS_FORM_INPUT_URL },
|
2010-04-15 11:03:00 +00:00
|
|
|
{ 0 }
|
|
|
|
};
|
|
|
|
|
|
|
|
// Default type is 'text'.
|
2013-02-16 12:35:57 +00:00
|
|
|
static const nsAttrValue::EnumTable* kInputDefaultType = &kInputTypeTable[15];
|
2010-04-15 11:03:00 +00:00
|
|
|
|
2012-08-22 15:56:38 +00:00
|
|
|
static const uint8_t NS_INPUT_AUTOCOMPLETE_OFF = 0;
|
|
|
|
static const uint8_t NS_INPUT_AUTOCOMPLETE_ON = 1;
|
|
|
|
static const uint8_t NS_INPUT_AUTOCOMPLETE_DEFAULT = 2;
|
2010-09-14 17:58:34 +00:00
|
|
|
|
|
|
|
static const nsAttrValue::EnumTable kInputAutocompleteTable[] = {
|
|
|
|
{ "", NS_INPUT_AUTOCOMPLETE_DEFAULT },
|
|
|
|
{ "on", NS_INPUT_AUTOCOMPLETE_ON },
|
|
|
|
{ "off", NS_INPUT_AUTOCOMPLETE_OFF },
|
|
|
|
{ 0 }
|
|
|
|
};
|
|
|
|
|
|
|
|
// Default autocomplete value is "".
|
|
|
|
static const nsAttrValue::EnumTable* kInputDefaultAutocomplete = &kInputAutocompleteTable[0];
|
|
|
|
|
2012-08-17 09:53:44 +00:00
|
|
|
static const uint8_t NS_INPUT_INPUTMODE_AUTO = 0;
|
|
|
|
static const uint8_t NS_INPUT_INPUTMODE_NUMERIC = 1;
|
|
|
|
static const uint8_t NS_INPUT_INPUTMODE_DIGIT = 2;
|
|
|
|
static const uint8_t NS_INPUT_INPUTMODE_UPPERCASE = 3;
|
|
|
|
static const uint8_t NS_INPUT_INPUTMODE_LOWERCASE = 4;
|
|
|
|
static const uint8_t NS_INPUT_INPUTMODE_TITLECASE = 5;
|
|
|
|
static const uint8_t NS_INPUT_INPUTMODE_AUTOCAPITALIZED = 6;
|
|
|
|
|
|
|
|
static const nsAttrValue::EnumTable kInputInputmodeTable[] = {
|
|
|
|
{ "auto", NS_INPUT_INPUTMODE_AUTO },
|
|
|
|
{ "numeric", NS_INPUT_INPUTMODE_NUMERIC },
|
|
|
|
{ "digit", NS_INPUT_INPUTMODE_DIGIT },
|
|
|
|
{ "uppercase", NS_INPUT_INPUTMODE_UPPERCASE },
|
|
|
|
{ "lowercase", NS_INPUT_INPUTMODE_LOWERCASE },
|
|
|
|
{ "titlecase", NS_INPUT_INPUTMODE_TITLECASE },
|
|
|
|
{ "autocapitalized", NS_INPUT_INPUTMODE_AUTOCAPITALIZED },
|
|
|
|
{ 0 }
|
|
|
|
};
|
|
|
|
|
|
|
|
// Default inputmode value is "auto".
|
|
|
|
static const nsAttrValue::EnumTable* kInputDefaultInputmode = &kInputInputmodeTable[0];
|
|
|
|
|
2013-03-28 19:41:32 +00:00
|
|
|
const double HTMLInputElement::kStepScaleFactorDate = 86400000;
|
|
|
|
const double HTMLInputElement::kStepScaleFactorNumberRange = 1;
|
|
|
|
const double HTMLInputElement::kStepScaleFactorTime = 1000;
|
|
|
|
const double HTMLInputElement::kDefaultStepBase = 0;
|
|
|
|
const double HTMLInputElement::kDefaultStep = 1;
|
|
|
|
const double HTMLInputElement::kDefaultStepTime = 60;
|
|
|
|
const double HTMLInputElement::kStepAny = 0;
|
2012-06-22 19:02:20 +00:00
|
|
|
|
2008-12-12 19:25:22 +00:00
|
|
|
#define NS_INPUT_ELEMENT_STATE_IID \
|
|
|
|
{ /* dc3b3d14-23e2-4479-b513-7b369343e3a0 */ \
|
|
|
|
0xdc3b3d14, \
|
|
|
|
0x23e2, \
|
|
|
|
0x4479, \
|
|
|
|
{0xb5, 0x13, 0x7b, 0x36, 0x93, 0x43, 0xe3, 0xa0} \
|
|
|
|
}
|
|
|
|
|
2013-03-28 19:41:32 +00:00
|
|
|
class HTMLInputElementState MOZ_FINAL : public nsISupports
|
2008-12-12 19:25:22 +00:00
|
|
|
{
|
|
|
|
public:
|
|
|
|
NS_DECLARE_STATIC_IID_ACCESSOR(NS_INPUT_ELEMENT_STATE_IID)
|
|
|
|
NS_DECL_ISUPPORTS
|
|
|
|
|
2011-09-29 06:19:26 +00:00
|
|
|
bool IsCheckedSet() {
|
2008-12-12 19:25:22 +00:00
|
|
|
return mCheckedSet;
|
|
|
|
}
|
|
|
|
|
2011-09-29 06:19:26 +00:00
|
|
|
bool GetChecked() {
|
2008-12-12 19:25:22 +00:00
|
|
|
return mChecked;
|
|
|
|
}
|
|
|
|
|
2011-09-29 06:19:26 +00:00
|
|
|
void SetChecked(bool aChecked) {
|
2008-12-12 19:25:22 +00:00
|
|
|
mChecked = aChecked;
|
2011-10-17 14:59:28 +00:00
|
|
|
mCheckedSet = true;
|
2008-12-12 19:25:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
const nsString& GetValue() {
|
|
|
|
return mValue;
|
|
|
|
}
|
|
|
|
|
2013-03-28 19:41:32 +00:00
|
|
|
void SetValue(const nsAString& aValue) {
|
2008-12-12 19:25:22 +00:00
|
|
|
mValue = aValue;
|
|
|
|
}
|
|
|
|
|
2010-09-05 18:00:05 +00:00
|
|
|
const nsCOMArray<nsIDOMFile>& GetFiles() {
|
|
|
|
return mFiles;
|
2008-12-12 19:25:22 +00:00
|
|
|
}
|
|
|
|
|
2013-03-28 19:41:32 +00:00
|
|
|
void SetFiles(const nsCOMArray<nsIDOMFile>& aFiles) {
|
2010-09-05 18:00:05 +00:00
|
|
|
mFiles.Clear();
|
|
|
|
mFiles.AppendObjects(aFiles);
|
2008-12-12 19:25:22 +00:00
|
|
|
}
|
|
|
|
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElementState()
|
2008-12-12 19:25:22 +00:00
|
|
|
: mValue()
|
2011-10-17 14:59:28 +00:00
|
|
|
, mChecked(false)
|
|
|
|
, mCheckedSet(false)
|
2008-12-12 19:25:22 +00:00
|
|
|
{};
|
2013-03-28 19:41:32 +00:00
|
|
|
|
2008-12-12 19:25:22 +00:00
|
|
|
protected:
|
|
|
|
nsString mValue;
|
2010-09-05 18:00:05 +00:00
|
|
|
nsCOMArray<nsIDOMFile> mFiles;
|
2011-09-29 06:19:26 +00:00
|
|
|
bool mChecked;
|
|
|
|
bool mCheckedSet;
|
2008-12-12 19:25:22 +00:00
|
|
|
};
|
|
|
|
|
2013-03-28 19:41:32 +00:00
|
|
|
NS_IMPL_ISUPPORTS1(HTMLInputElementState, HTMLInputElementState)
|
|
|
|
NS_DEFINE_STATIC_IID_ACCESSOR(HTMLInputElementState, NS_INPUT_ELEMENT_STATE_IID)
|
2008-12-12 19:25:22 +00:00
|
|
|
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::nsFilePickerShownCallback::nsFilePickerShownCallback(
|
|
|
|
HTMLInputElement* aInput, nsIFilePicker* aFilePicker, bool aMulti)
|
2012-08-17 15:35:01 +00:00
|
|
|
: mFilePicker(aFilePicker)
|
|
|
|
, mInput(aInput)
|
|
|
|
, mMulti(aMulti)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2013-03-30 02:08:57 +00:00
|
|
|
NS_IMPL_ISUPPORTS1(UploadLastDir::ContentPrefCallback, nsIContentPrefCallback2)
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
UploadLastDir::ContentPrefCallback::HandleCompletion(uint16_t aReason)
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsIFile> localFile = do_CreateInstance(NS_LOCAL_FILE_CONTRACTID);
|
|
|
|
NS_ENSURE_STATE(localFile);
|
|
|
|
|
|
|
|
if (aReason == nsIContentPrefCallback2::COMPLETE_ERROR ||
|
|
|
|
!mResult) {
|
|
|
|
// Default to "desktop" directory for each platform
|
|
|
|
nsCOMPtr<nsIFile> homeDir;
|
|
|
|
NS_GetSpecialDirectory(NS_OS_DESKTOP_DIR, getter_AddRefs(homeDir));
|
|
|
|
localFile = do_QueryInterface(homeDir);
|
|
|
|
} else {
|
|
|
|
nsAutoString prefStr;
|
|
|
|
nsCOMPtr<nsIVariant> pref;
|
|
|
|
mResult->GetValue(getter_AddRefs(pref));
|
|
|
|
pref->GetAsAString(prefStr);
|
|
|
|
localFile->InitWithPath(prefStr);
|
|
|
|
}
|
|
|
|
|
|
|
|
mFilePicker->SetDisplayDirectory(localFile);
|
|
|
|
mFilePicker->Open(mFpCallback);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
UploadLastDir::ContentPrefCallback::HandleResult(nsIContentPref* pref)
|
|
|
|
{
|
|
|
|
mResult = pref;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
UploadLastDir::ContentPrefCallback::HandleError(nsresult error)
|
|
|
|
{
|
|
|
|
// HandleCompletion is always called (even with HandleError was called),
|
|
|
|
// so we don't need to do anything special here.
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2012-08-17 15:35:01 +00:00
|
|
|
NS_IMETHODIMP
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::nsFilePickerShownCallback::Done(int16_t aResult)
|
2012-08-17 15:35:01 +00:00
|
|
|
{
|
|
|
|
if (aResult == nsIFilePicker::returnCancel) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Collect new selected filenames
|
|
|
|
nsCOMArray<nsIDOMFile> newFiles;
|
|
|
|
if (mMulti) {
|
|
|
|
nsCOMPtr<nsISimpleEnumerator> iter;
|
2013-03-19 17:49:16 +00:00
|
|
|
nsresult rv = mFilePicker->GetDomfiles(getter_AddRefs(iter));
|
2012-08-17 15:35:01 +00:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
nsCOMPtr<nsISupports> tmp;
|
|
|
|
bool prefSaved = false;
|
|
|
|
bool loop = true;
|
2013-03-19 17:49:16 +00:00
|
|
|
|
2012-08-17 15:35:01 +00:00
|
|
|
while (NS_SUCCEEDED(iter->HasMoreElements(&loop)) && loop) {
|
|
|
|
iter->GetNext(getter_AddRefs(tmp));
|
2013-03-19 17:49:16 +00:00
|
|
|
nsCOMPtr<nsIDOMFile> domFile = do_QueryInterface(tmp);
|
|
|
|
MOZ_ASSERT(domFile);
|
|
|
|
|
2012-08-17 15:35:01 +00:00
|
|
|
newFiles.AppendObject(domFile);
|
2013-03-19 17:49:16 +00:00
|
|
|
|
2012-08-17 15:35:01 +00:00
|
|
|
if (!prefSaved) {
|
|
|
|
// Store the last used directory using the content pref service
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::gUploadLastDir->StoreLastUsedDirectory(
|
2013-03-19 17:49:16 +00:00
|
|
|
mInput->OwnerDoc(), domFile);
|
2012-08-17 15:35:01 +00:00
|
|
|
prefSaved = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
2013-03-19 17:49:16 +00:00
|
|
|
nsCOMPtr<nsIDOMFile> domFile;
|
|
|
|
nsresult rv = mFilePicker->GetDomfile(getter_AddRefs(domFile));
|
2012-08-17 15:35:01 +00:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
2013-03-19 17:49:16 +00:00
|
|
|
if (domFile) {
|
|
|
|
newFiles.AppendObject(domFile);
|
|
|
|
|
|
|
|
// Store the last used directory using the content pref service
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::gUploadLastDir->StoreLastUsedDirectory(
|
2013-03-19 17:49:16 +00:00
|
|
|
mInput->OwnerDoc(), domFile);
|
2010-08-27 15:49:06 +00:00
|
|
|
}
|
2012-08-17 15:35:01 +00:00
|
|
|
}
|
2010-08-27 15:49:06 +00:00
|
|
|
|
2012-08-17 15:35:01 +00:00
|
|
|
if (!newFiles.Count()) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2010-08-27 15:49:06 +00:00
|
|
|
|
2012-08-17 15:35:01 +00:00
|
|
|
// The text control frame (if there is one) isn't going to send a change
|
|
|
|
// event because it will think this is done by a script.
|
|
|
|
// So, we can safely send one by ourself.
|
|
|
|
mInput->SetFiles(newFiles, true);
|
|
|
|
return nsContentUtils::DispatchTrustedEvent(mInput->OwnerDoc(),
|
|
|
|
static_cast<nsIDOMHTMLInputElement*>(mInput.get()),
|
|
|
|
NS_LITERAL_STRING("change"), true,
|
|
|
|
false);
|
|
|
|
}
|
|
|
|
|
2013-03-28 19:41:32 +00:00
|
|
|
NS_IMPL_ISUPPORTS1(HTMLInputElement::nsFilePickerShownCallback,
|
2013-01-10 07:32:03 +00:00
|
|
|
nsIFilePickerShownCallback)
|
2012-08-17 15:35:01 +00:00
|
|
|
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::AsyncClickHandler::AsyncClickHandler(HTMLInputElement* aInput)
|
2012-08-17 15:35:01 +00:00
|
|
|
: mInput(aInput)
|
|
|
|
{
|
|
|
|
nsPIDOMWindow* win = aInput->OwnerDoc()->GetWindow();
|
|
|
|
if (win) {
|
|
|
|
mPopupControlState = win->GetPopupControlState();
|
|
|
|
}
|
|
|
|
}
|
2010-08-27 15:49:06 +00:00
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::AsyncClickHandler::Run()
|
2010-08-27 15:49:06 +00:00
|
|
|
{
|
2011-07-15 10:31:34 +00:00
|
|
|
// Get parent nsPIDOMWindow object.
|
2011-10-18 10:53:36 +00:00
|
|
|
nsCOMPtr<nsIDocument> doc = mInput->OwnerDoc();
|
2010-08-27 15:49:06 +00:00
|
|
|
|
|
|
|
nsPIDOMWindow* win = doc->GetWindow();
|
|
|
|
if (!win) {
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check if page is allowed to open the popup
|
2011-12-21 17:03:52 +00:00
|
|
|
if (mPopupControlState > openControlled) {
|
2010-09-05 18:00:05 +00:00
|
|
|
nsCOMPtr<nsIPopupWindowManager> pm =
|
|
|
|
do_GetService(NS_POPUPWINDOWMANAGER_CONTRACTID);
|
2011-12-21 17:03:52 +00:00
|
|
|
|
2010-09-05 18:00:05 +00:00
|
|
|
if (!pm) {
|
2010-08-27 15:49:06 +00:00
|
|
|
return NS_OK;
|
2010-08-27 15:49:08 +00:00
|
|
|
}
|
2010-09-05 18:00:05 +00:00
|
|
|
|
2012-08-22 15:56:38 +00:00
|
|
|
uint32_t permission;
|
2012-07-16 01:37:31 +00:00
|
|
|
pm->TestPermission(doc->NodePrincipal(), &permission);
|
2010-09-05 18:00:05 +00:00
|
|
|
if (permission == nsIPopupWindowManager::DENY_POPUP) {
|
|
|
|
nsCOMPtr<nsIDOMDocument> domDoc = do_QueryInterface(doc);
|
2012-07-30 14:20:58 +00:00
|
|
|
nsGlobalWindow::FirePopupBlockedEvent(domDoc, win, nullptr, EmptyString(), EmptyString());
|
2010-09-05 18:00:05 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
}
|
2010-08-27 15:49:06 +00:00
|
|
|
|
|
|
|
// Get Loc title
|
|
|
|
nsXPIDLString title;
|
|
|
|
nsContentUtils::GetLocalizedString(nsContentUtils::eFORMS_PROPERTIES,
|
|
|
|
"FileUpload", title);
|
|
|
|
|
|
|
|
nsCOMPtr<nsIFilePicker> filePicker = do_CreateInstance("@mozilla.org/filepicker;1");
|
|
|
|
if (!filePicker)
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
2011-09-29 06:19:26 +00:00
|
|
|
bool multi = mInput->HasAttr(kNameSpaceID_None, nsGkAtoms::multiple);
|
2010-08-27 15:49:06 +00:00
|
|
|
|
2011-11-16 07:50:19 +00:00
|
|
|
nsresult rv = filePicker->Init(win, title,
|
|
|
|
multi
|
2012-08-22 15:56:38 +00:00
|
|
|
? static_cast<int16_t>(nsIFilePicker::modeOpenMultiple)
|
|
|
|
: static_cast<int16_t>(nsIFilePicker::modeOpen));
|
2010-08-27 15:49:06 +00:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
2010-10-08 10:07:20 +00:00
|
|
|
if (mInput->HasAttr(kNameSpaceID_None, nsGkAtoms::accept)) {
|
2012-06-06 12:16:58 +00:00
|
|
|
mInput->SetFilePickerFiltersFromAccept(filePicker);
|
2010-10-08 10:07:20 +00:00
|
|
|
} else {
|
|
|
|
filePicker->AppendFilters(nsIFilePicker::filterAll);
|
2010-08-27 15:49:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Set default directry and filename
|
|
|
|
nsAutoString defaultName;
|
|
|
|
|
2013-03-28 19:41:32 +00:00
|
|
|
const nsCOMArray<nsIDOMFile>& oldFiles = mInput->GetFilesInternal();
|
2010-08-27 15:49:06 +00:00
|
|
|
|
2013-03-30 02:08:57 +00:00
|
|
|
nsCOMPtr<nsIFilePickerShownCallback> callback =
|
|
|
|
new HTMLInputElement::nsFilePickerShownCallback(mInput, filePicker, multi);
|
|
|
|
|
2010-08-27 15:49:06 +00:00
|
|
|
if (oldFiles.Count()) {
|
2010-09-05 18:00:05 +00:00
|
|
|
nsString path;
|
|
|
|
|
|
|
|
oldFiles[0]->GetMozFullPathInternal(path);
|
|
|
|
|
2012-06-06 02:08:30 +00:00
|
|
|
nsCOMPtr<nsIFile> localFile;
|
2011-10-17 14:59:28 +00:00
|
|
|
rv = NS_NewLocalFile(path, false, getter_AddRefs(localFile));
|
2010-09-05 18:00:05 +00:00
|
|
|
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
nsCOMPtr<nsIFile> parentFile;
|
|
|
|
rv = localFile->GetParent(getter_AddRefs(parentFile));
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
2012-06-06 02:08:30 +00:00
|
|
|
filePicker->SetDisplayDirectory(parentFile);
|
2010-08-27 15:49:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Unfortunately nsIFilePicker doesn't allow multiple files to be
|
|
|
|
// default-selected, so only select something by default if exactly
|
|
|
|
// one file was selected before.
|
|
|
|
if (oldFiles.Count() == 1) {
|
|
|
|
nsAutoString leafName;
|
2010-09-05 18:00:05 +00:00
|
|
|
oldFiles[0]->GetName(leafName);
|
2010-08-27 15:49:06 +00:00
|
|
|
if (!leafName.IsEmpty()) {
|
|
|
|
filePicker->SetDefaultString(leafName);
|
|
|
|
}
|
|
|
|
}
|
2013-03-30 02:08:57 +00:00
|
|
|
|
|
|
|
return filePicker->Open(callback);
|
2010-08-27 15:49:06 +00:00
|
|
|
}
|
|
|
|
|
2013-03-30 02:08:57 +00:00
|
|
|
HTMLInputElement::gUploadLastDir->FetchDirectoryAndDisplayPicker(doc, filePicker, callback);
|
|
|
|
return NS_OK;
|
|
|
|
|
2010-08-27 15:49:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#define CPS_PREF_NAME NS_LITERAL_STRING("browser.upload.lastDir")
|
|
|
|
|
|
|
|
NS_IMPL_ISUPPORTS2(UploadLastDir, nsIObserver, nsISupportsWeakReference)
|
|
|
|
|
|
|
|
void
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::InitUploadLastDir() {
|
2010-08-27 15:49:06 +00:00
|
|
|
gUploadLastDir = new UploadLastDir();
|
|
|
|
NS_ADDREF(gUploadLastDir);
|
|
|
|
|
|
|
|
nsCOMPtr<nsIObserverService> observerService =
|
|
|
|
mozilla::services::GetObserverService();
|
|
|
|
if (observerService && gUploadLastDir) {
|
2011-10-17 14:59:28 +00:00
|
|
|
observerService->AddObserver(gUploadLastDir, "browser:purge-session-history", true);
|
2010-08-27 15:49:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-03-28 19:41:32 +00:00
|
|
|
void
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::DestroyUploadLastDir() {
|
2010-08-27 15:49:06 +00:00
|
|
|
NS_IF_RELEASE(gUploadLastDir);
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
2013-03-30 02:08:57 +00:00
|
|
|
UploadLastDir::FetchDirectoryAndDisplayPicker(nsIDocument* aDoc,
|
|
|
|
nsIFilePicker* aFilePicker,
|
|
|
|
nsIFilePickerShownCallback* aFpCallback)
|
2010-08-27 15:49:06 +00:00
|
|
|
{
|
2012-06-30 14:50:07 +00:00
|
|
|
NS_PRECONDITION(aDoc, "aDoc is null");
|
2013-03-30 02:08:57 +00:00
|
|
|
NS_PRECONDITION(aFilePicker, "aFilePicker is null");
|
|
|
|
NS_PRECONDITION(aFpCallback, "aFpCallback is null");
|
2012-06-30 14:50:07 +00:00
|
|
|
|
|
|
|
nsIURI* docURI = aDoc->GetDocumentURI();
|
|
|
|
NS_PRECONDITION(docURI, "docURI is null");
|
|
|
|
|
|
|
|
nsCOMPtr<nsISupports> container = aDoc->GetContainer();
|
|
|
|
nsCOMPtr<nsILoadContext> loadContext = do_QueryInterface(container);
|
|
|
|
|
2013-03-30 02:08:57 +00:00
|
|
|
nsCOMPtr<nsIContentPrefCallback2> prefCallback =
|
|
|
|
new UploadLastDir::ContentPrefCallback(aFilePicker, aFpCallback);
|
|
|
|
|
|
|
|
// Attempt to get the CPS, if it's not present we'll fallback to use the Desktop folder
|
|
|
|
nsCOMPtr<nsIContentPrefService2> contentPrefService =
|
2010-08-27 15:49:06 +00:00
|
|
|
do_GetService(NS_CONTENT_PREF_SERVICE_CONTRACTID);
|
2013-03-30 02:08:57 +00:00
|
|
|
if (!contentPrefService) {
|
|
|
|
prefCallback->HandleCompletion(nsIContentPrefCallback2::COMPLETE_ERROR);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2010-08-27 15:49:06 +00:00
|
|
|
|
2013-03-30 02:08:57 +00:00
|
|
|
nsAutoCString cstrSpec;
|
|
|
|
docURI->GetSpec(cstrSpec);
|
|
|
|
NS_ConvertUTF8toUTF16 spec(cstrSpec);
|
2010-08-27 15:49:06 +00:00
|
|
|
|
2013-03-30 02:08:57 +00:00
|
|
|
contentPrefService->GetByDomainAndName(spec, CPS_PREF_NAME, loadContext, prefCallback);
|
2010-08-27 15:49:06 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
2013-03-19 17:49:16 +00:00
|
|
|
UploadLastDir::StoreLastUsedDirectory(nsIDocument* aDoc, nsIDOMFile* aDomFile)
|
2010-08-27 15:49:06 +00:00
|
|
|
{
|
2012-06-30 14:50:07 +00:00
|
|
|
NS_PRECONDITION(aDoc, "aDoc is null");
|
2013-03-19 17:49:16 +00:00
|
|
|
NS_PRECONDITION(aDomFile, "aDomFile is null");
|
|
|
|
|
|
|
|
nsString path;
|
|
|
|
nsresult rv = aDomFile->GetMozFullPathInternal(path);
|
|
|
|
if (NS_FAILED(rv) || path.IsEmpty()) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsCOMPtr<nsIFile> localFile;
|
|
|
|
rv = NS_NewNativeLocalFile(NS_ConvertUTF16toUTF8(path), true,
|
|
|
|
getter_AddRefs(localFile));
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
2012-06-30 14:50:07 +00:00
|
|
|
|
|
|
|
nsCOMPtr<nsIURI> docURI = aDoc->GetDocumentURI();
|
|
|
|
NS_PRECONDITION(docURI, "docURI is null");
|
|
|
|
|
2010-08-27 15:49:06 +00:00
|
|
|
nsCOMPtr<nsIFile> parentFile;
|
2013-03-19 17:49:16 +00:00
|
|
|
localFile->GetParent(getter_AddRefs(parentFile));
|
2010-11-08 23:16:10 +00:00
|
|
|
if (!parentFile) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2010-08-27 15:49:06 +00:00
|
|
|
|
|
|
|
// Attempt to get the CPS, if it's not present we'll just return
|
2013-03-30 02:08:57 +00:00
|
|
|
nsCOMPtr<nsIContentPrefService2> contentPrefService =
|
2010-08-27 15:49:06 +00:00
|
|
|
do_GetService(NS_CONTENT_PREF_SERVICE_CONTRACTID);
|
|
|
|
if (!contentPrefService)
|
|
|
|
return NS_ERROR_NOT_AVAILABLE;
|
2013-03-30 02:08:57 +00:00
|
|
|
|
|
|
|
nsAutoCString cstrSpec;
|
|
|
|
docURI->GetSpec(cstrSpec);
|
|
|
|
NS_ConvertUTF8toUTF16 spec(cstrSpec);
|
2013-03-28 19:41:32 +00:00
|
|
|
|
2010-08-27 15:49:06 +00:00
|
|
|
// Find the parent of aFile, and store it
|
|
|
|
nsString unicodePath;
|
|
|
|
parentFile->GetPath(unicodePath);
|
|
|
|
if (unicodePath.IsEmpty()) // nothing to do
|
|
|
|
return NS_OK;
|
|
|
|
nsCOMPtr<nsIWritableVariant> prefValue = do_CreateInstance(NS_VARIANT_CONTRACTID);
|
|
|
|
if (!prefValue)
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
prefValue->SetAsAString(unicodePath);
|
2012-06-30 14:50:07 +00:00
|
|
|
|
|
|
|
nsCOMPtr<nsISupports> container = aDoc->GetContainer();
|
|
|
|
nsCOMPtr<nsILoadContext> loadContext = do_QueryInterface(container);
|
2013-03-30 02:08:57 +00:00
|
|
|
return contentPrefService->Set(spec, CPS_PREF_NAME, prefValue, loadContext, nullptr);
|
2010-08-27 15:49:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2013-03-28 19:41:32 +00:00
|
|
|
UploadLastDir::Observe(nsISupports* aSubject, char const* aTopic, PRUnichar const* aData)
|
2010-08-27 15:49:06 +00:00
|
|
|
{
|
bug 679784: let nsIContentPrefService handle private browsing mode; r=ehsan
Manage private browsing mode in content pref service. CPS should be available
in private browsing mode, but should not store informations on disk, and should
clear all informations once the private session ends.
When setting a pref in private mode, it is stored in an in-memory hash table.
When getting a pref, it is retrieved from that hash table if available.
Otherwise, it is retrieved using the standard mechanism. When removing a pref,
it is retrieved from the hash table. The rationale is that in private mode,
it's ok to read a pref from normal database, but not ok to set it.
The in-memory hash table is cleared when leaving the private browsing mode.
When removing a set of preferences (with removeGroupedPrefs or
removePrefsByName), preferences are removed from the in-memory hashtable, *and*
from normal mode database. The rationale is that visiting a website may trigger
setting/getting/removing for a specific preference only. But removing many
prefs at once is the result of an action not associated with a website. For
example, user may wish to delete all its informations. In that case, user
probably expects to not have those informations restored once it leaves private
browsing mode.
2011-09-01 18:13:03 +00:00
|
|
|
if (strcmp(aTopic, "browser:purge-session-history") == 0) {
|
2013-03-30 02:08:57 +00:00
|
|
|
nsCOMPtr<nsIContentPrefService2> contentPrefService =
|
2010-08-27 15:49:06 +00:00
|
|
|
do_GetService(NS_CONTENT_PREF_SERVICE_CONTRACTID);
|
|
|
|
if (contentPrefService)
|
2013-03-30 02:08:57 +00:00
|
|
|
contentPrefService->RemoveByName(CPS_PREF_NAME, nullptr, nullptr);
|
2010-08-27 15:49:06 +00:00
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2006-05-16 03:54:46 +00:00
|
|
|
#ifdef ACCESSIBILITY
|
|
|
|
//Helper method
|
|
|
|
static nsresult FireEventForAccessibility(nsIDOMHTMLInputElement* aTarget,
|
|
|
|
nsPresContext* aPresContext,
|
|
|
|
const nsAString& aEventType);
|
|
|
|
#endif
|
|
|
|
|
2002-02-08 18:23:47 +00:00
|
|
|
//
|
1998-09-23 17:16:51 +00:00
|
|
|
// construction, destruction
|
2002-02-08 18:23:47 +00:00
|
|
|
//
|
1998-09-23 17:16:51 +00:00
|
|
|
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::HTMLInputElement(already_AddRefed<nsINodeInfo> aNodeInfo,
|
|
|
|
FromParser aFromParser)
|
2011-11-16 07:50:19 +00:00
|
|
|
: nsGenericHTMLFormElement(aNodeInfo)
|
|
|
|
, mType(kInputDefaultType->value)
|
|
|
|
, mDisabledChanged(false)
|
|
|
|
, mValueChanged(false)
|
|
|
|
, mCheckedChanged(false)
|
|
|
|
, mChecked(false)
|
|
|
|
, mHandlingSelectEvent(false)
|
|
|
|
, mShouldInitChecked(false)
|
|
|
|
, mParserCreating(aFromParser != NOT_FROM_PARSER)
|
|
|
|
, mInInternalActivate(false)
|
|
|
|
, mCheckedIsToggled(false)
|
|
|
|
, mIndeterminate(false)
|
|
|
|
, mInhibitRestoration(aFromParser & FROM_PARSER_FRAGMENT)
|
|
|
|
, mCanShowValidUI(true)
|
|
|
|
, mCanShowInvalidUI(true)
|
2012-06-22 09:41:32 +00:00
|
|
|
, mHasRange(false)
|
2013-03-08 09:40:12 +00:00
|
|
|
, mIsDraggingRange(false)
|
2011-11-16 07:50:19 +00:00
|
|
|
{
|
2013-03-28 19:41:32 +00:00
|
|
|
SetIsDOMBinding();
|
|
|
|
|
2013-02-12 20:16:58 +00:00
|
|
|
// We are in a type=text so we now we currenty need a nsTextEditorState.
|
2010-04-21 20:17:41 +00:00
|
|
|
mInputData.mState = new nsTextEditorState(this);
|
2012-04-24 04:19:26 +00:00
|
|
|
|
2010-08-27 15:49:06 +00:00
|
|
|
if (!gUploadLastDir)
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::InitUploadLastDir();
|
2011-06-01 01:46:57 +00:00
|
|
|
|
|
|
|
// Set up our default state. By default we're enabled (since we're
|
|
|
|
// a control type that can be disabled but not actually disabled
|
|
|
|
// right now), optional, and valid. We are NOT readwrite by default
|
|
|
|
// until someone calls UpdateEditableState on us, apparently! Also
|
|
|
|
// by default we don't have to show validity UI and so forth.
|
|
|
|
AddStatesSilently(NS_EVENT_STATE_ENABLED |
|
|
|
|
NS_EVENT_STATE_OPTIONAL |
|
|
|
|
NS_EVENT_STATE_VALID);
|
1998-09-01 01:27:08 +00:00
|
|
|
}
|
|
|
|
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::~HTMLInputElement()
|
1998-09-01 01:27:08 +00:00
|
|
|
{
|
2011-08-22 09:14:13 +00:00
|
|
|
if (mFileList) {
|
|
|
|
mFileList->Disconnect();
|
|
|
|
}
|
2006-06-01 18:35:21 +00:00
|
|
|
DestroyImageLoadingContent();
|
2010-04-21 20:17:41 +00:00
|
|
|
FreeData();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::FreeData()
|
2010-04-21 20:17:41 +00:00
|
|
|
{
|
2011-10-17 14:59:28 +00:00
|
|
|
if (!IsSingleLineTextControl(false)) {
|
2010-04-21 20:17:41 +00:00
|
|
|
nsMemory::Free(mInputData.mValue);
|
2012-07-30 14:20:58 +00:00
|
|
|
mInputData.mValue = nullptr;
|
2010-04-21 20:17:41 +00:00
|
|
|
} else {
|
2012-07-30 14:20:58 +00:00
|
|
|
UnbindFromFrame(nullptr);
|
2012-04-24 04:19:26 +00:00
|
|
|
delete mInputData.mState;
|
2012-07-30 14:20:58 +00:00
|
|
|
mInputData.mState = nullptr;
|
2010-04-21 20:17:41 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
nsTextEditorState*
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::GetEditorState() const
|
2010-04-21 20:17:41 +00:00
|
|
|
{
|
2011-10-17 14:59:28 +00:00
|
|
|
if (!IsSingleLineTextControl(false)) {
|
2012-07-30 14:20:58 +00:00
|
|
|
return nullptr;
|
2001-11-02 07:40:01 +00:00
|
|
|
}
|
2010-04-21 20:17:41 +00:00
|
|
|
|
2013-02-12 20:16:58 +00:00
|
|
|
MOZ_ASSERT(mInputData.mState, "Single line text controls need to have a state"
|
|
|
|
" associated with them");
|
2010-04-21 20:17:41 +00:00
|
|
|
|
|
|
|
return mInputData.mState;
|
1998-09-01 01:27:08 +00:00
|
|
|
}
|
|
|
|
|
2000-12-23 10:56:31 +00:00
|
|
|
|
1998-09-23 17:16:51 +00:00
|
|
|
// nsISupports
|
1998-09-01 01:27:08 +00:00
|
|
|
|
2013-03-28 19:41:32 +00:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(HTMLInputElement,
|
2007-03-08 11:17:16 +00:00
|
|
|
nsGenericHTMLFormElement)
|
2013-01-16 18:01:01 +00:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mValidity)
|
2012-11-15 07:32:40 +00:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mControllers)
|
2011-10-17 14:59:28 +00:00
|
|
|
if (tmp->IsSingleLineTextControl(false)) {
|
2012-04-24 04:19:26 +00:00
|
|
|
tmp->mInputData.mState->Traverse(cb);
|
2010-04-21 20:17:41 +00:00
|
|
|
}
|
2012-11-15 07:32:40 +00:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFiles)
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFileList)
|
2007-03-08 11:17:16 +00:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
|
|
|
|
2013-03-28 19:41:32 +00:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(HTMLInputElement,
|
2011-06-21 21:12:50 +00:00
|
|
|
nsGenericHTMLFormElement)
|
2013-01-16 18:01:01 +00:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mValidity)
|
2012-11-15 07:32:40 +00:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mControllers)
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mFiles)
|
2011-08-22 09:14:13 +00:00
|
|
|
if (tmp->mFileList) {
|
|
|
|
tmp->mFileList->Disconnect();
|
2012-07-30 14:20:58 +00:00
|
|
|
tmp->mFileList = nullptr;
|
2011-08-22 09:14:13 +00:00
|
|
|
}
|
2012-04-24 04:19:26 +00:00
|
|
|
if (tmp->IsSingleLineTextControl(false)) {
|
|
|
|
tmp->mInputData.mState->Unlink();
|
|
|
|
}
|
2011-06-21 21:12:50 +00:00
|
|
|
//XXX should unlink more?
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
2013-03-28 19:41:32 +00:00
|
|
|
|
2013-03-28 19:41:32 +00:00
|
|
|
NS_IMPL_ADDREF_INHERITED(HTMLInputElement, Element)
|
|
|
|
NS_IMPL_RELEASE_INHERITED(HTMLInputElement, Element)
|
2000-12-23 10:56:31 +00:00
|
|
|
|
2013-03-28 19:41:32 +00:00
|
|
|
// QueryInterface implementation for HTMLInputElement
|
|
|
|
NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(HTMLInputElement)
|
|
|
|
NS_HTML_CONTENT_INTERFACE_TABLE8(HTMLInputElement,
|
2010-07-14 06:39:48 +00:00
|
|
|
nsIDOMHTMLInputElement,
|
|
|
|
nsITextControlElement,
|
|
|
|
nsIPhonetic,
|
2012-10-12 16:11:22 +00:00
|
|
|
imgINotificationObserver,
|
2010-07-14 06:39:48 +00:00
|
|
|
nsIImageLoadingContent,
|
2012-08-13 22:58:53 +00:00
|
|
|
imgIOnloadBlocker,
|
2010-08-21 18:51:38 +00:00
|
|
|
nsIDOMNSEditableElement,
|
2010-08-21 18:52:49 +00:00
|
|
|
nsIConstraintValidation)
|
2013-03-28 19:41:32 +00:00
|
|
|
NS_HTML_CONTENT_INTERFACE_TABLE_TO_MAP_SEGUE(HTMLInputElement,
|
2008-11-03 10:31:47 +00:00
|
|
|
nsGenericHTMLFormElement)
|
2013-04-13 07:08:49 +00:00
|
|
|
NS_HTML_CONTENT_INTERFACE_MAP_END
|
1998-09-01 01:27:08 +00:00
|
|
|
|
2010-08-21 18:52:49 +00:00
|
|
|
// nsIConstraintValidation
|
2013-03-28 19:41:32 +00:00
|
|
|
NS_IMPL_NSICONSTRAINTVALIDATION_EXCEPT_SETCUSTOMVALIDITY(HTMLInputElement)
|
1998-09-23 17:16:51 +00:00
|
|
|
|
1999-07-28 05:26:55 +00:00
|
|
|
// nsIDOMNode
|
1998-09-23 17:16:51 +00:00
|
|
|
|
1998-09-01 01:27:08 +00:00
|
|
|
nsresult
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::Clone(nsINodeInfo* aNodeInfo, nsINode** aResult) const
|
1998-09-01 01:27:08 +00:00
|
|
|
{
|
2012-07-30 14:20:58 +00:00
|
|
|
*aResult = nullptr;
|
2000-12-23 10:56:31 +00:00
|
|
|
|
2010-07-23 09:49:57 +00:00
|
|
|
nsCOMPtr<nsINodeInfo> ni = aNodeInfo;
|
2013-03-28 19:41:32 +00:00
|
|
|
nsRefPtr<HTMLInputElement> it =
|
|
|
|
new HTMLInputElement(ni.forget(), NOT_FROM_PARSER);
|
2000-12-23 10:56:31 +00:00
|
|
|
|
2013-03-28 19:41:32 +00:00
|
|
|
nsresult rv = const_cast<HTMLInputElement*>(this)->CopyInnerTo(it);
|
2005-09-11 17:15:08 +00:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
2000-12-23 10:56:31 +00:00
|
|
|
|
2003-11-10 23:46:29 +00:00
|
|
|
switch (mType) {
|
2010-08-18 18:31:54 +00:00
|
|
|
case NS_FORM_INPUT_EMAIL:
|
2010-05-17 10:20:22 +00:00
|
|
|
case NS_FORM_INPUT_SEARCH:
|
2003-11-10 23:46:29 +00:00
|
|
|
case NS_FORM_INPUT_TEXT:
|
|
|
|
case NS_FORM_INPUT_PASSWORD:
|
2010-05-12 07:17:07 +00:00
|
|
|
case NS_FORM_INPUT_TEL:
|
2010-08-18 18:33:37 +00:00
|
|
|
case NS_FORM_INPUT_URL:
|
2012-06-10 20:23:17 +00:00
|
|
|
case NS_FORM_INPUT_NUMBER:
|
2012-12-27 16:06:53 +00:00
|
|
|
case NS_FORM_INPUT_DATE:
|
2013-01-08 17:10:00 +00:00
|
|
|
case NS_FORM_INPUT_TIME:
|
2013-02-16 12:35:57 +00:00
|
|
|
case NS_FORM_INPUT_RANGE:
|
2011-11-16 07:50:19 +00:00
|
|
|
if (mValueChanged) {
|
2003-11-10 23:46:29 +00:00
|
|
|
// We don't have our default value anymore. Set our value on
|
|
|
|
// the clone.
|
|
|
|
nsAutoString value;
|
2011-03-09 18:25:20 +00:00
|
|
|
GetValueInternal(value);
|
2003-11-10 23:46:29 +00:00
|
|
|
// SetValueInternal handles setting the VALUE_CHANGED bit for us
|
2011-10-17 14:59:28 +00:00
|
|
|
it->SetValueInternal(value, false, true);
|
2003-11-10 23:46:29 +00:00
|
|
|
}
|
|
|
|
break;
|
2006-04-25 09:18:42 +00:00
|
|
|
case NS_FORM_INPUT_FILE:
|
2011-10-18 10:53:36 +00:00
|
|
|
if (it->OwnerDoc()->IsStaticDocument()) {
|
2010-09-05 18:00:05 +00:00
|
|
|
// We're going to be used in print preview. Since the doc is static
|
|
|
|
// we can just grab the pretty string and use it as wallpaper
|
|
|
|
GetDisplayFileName(it->mStaticDocFileList);
|
|
|
|
} else {
|
|
|
|
it->mFiles.Clear();
|
|
|
|
it->mFiles.AppendObjects(mFiles);
|
|
|
|
}
|
2006-04-25 09:18:42 +00:00
|
|
|
break;
|
2003-11-10 23:46:29 +00:00
|
|
|
case NS_FORM_INPUT_RADIO:
|
|
|
|
case NS_FORM_INPUT_CHECKBOX:
|
2011-11-16 07:50:19 +00:00
|
|
|
if (mCheckedChanged) {
|
2003-11-10 23:46:29 +00:00
|
|
|
// We no longer have our original checked state. Set our
|
|
|
|
// checked state on the clone.
|
2011-11-16 07:50:19 +00:00
|
|
|
it->DoSetChecked(mChecked, false, true);
|
2003-11-10 23:46:29 +00:00
|
|
|
}
|
|
|
|
break;
|
2009-12-11 04:02:13 +00:00
|
|
|
case NS_FORM_INPUT_IMAGE:
|
2011-10-18 10:53:36 +00:00
|
|
|
if (it->OwnerDoc()->IsStaticDocument()) {
|
2009-12-11 04:02:13 +00:00
|
|
|
CreateStaticImageClone(it);
|
|
|
|
}
|
|
|
|
break;
|
2003-11-10 23:46:29 +00:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2005-09-11 17:15:08 +00:00
|
|
|
|
2011-11-16 07:50:19 +00:00
|
|
|
it.forget(aResult);
|
2000-12-23 10:56:31 +00:00
|
|
|
return NS_OK;
|
1999-07-28 05:26:55 +00:00
|
|
|
}
|
|
|
|
|
2005-10-28 02:59:38 +00:00
|
|
|
nsresult
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
|
|
|
|
const nsAttrValueOrString* aValue,
|
|
|
|
bool aNotify)
|
2002-03-07 20:53:40 +00:00
|
|
|
{
|
2005-10-28 02:59:38 +00:00
|
|
|
if (aNameSpaceID == kNameSpaceID_None) {
|
|
|
|
//
|
|
|
|
// When name or type changes, radio should be removed from radio group.
|
|
|
|
// (type changes are handled in the form itself currently)
|
|
|
|
// If the parser is not done creating the radio, we also should not do it.
|
|
|
|
//
|
2006-12-26 17:47:52 +00:00
|
|
|
if ((aName == nsGkAtoms::name ||
|
|
|
|
(aName == nsGkAtoms::type && !mForm)) &&
|
2005-10-28 02:59:38 +00:00
|
|
|
mType == NS_FORM_INPUT_RADIO &&
|
2011-11-16 07:50:19 +00:00
|
|
|
(mForm || !mParserCreating)) {
|
2010-11-11 12:34:27 +00:00
|
|
|
WillRemoveFromRadioGroup();
|
2006-12-26 17:47:52 +00:00
|
|
|
} else if (aNotify && aName == nsGkAtoms::src &&
|
2008-12-12 19:41:11 +00:00
|
|
|
mType == NS_FORM_INPUT_IMAGE) {
|
|
|
|
if (aValue) {
|
2012-02-14 02:00:56 +00:00
|
|
|
LoadImage(aValue->String(), true, aNotify);
|
2008-12-12 19:41:11 +00:00
|
|
|
} else {
|
|
|
|
// Null value means the attr got unset; drop the image
|
|
|
|
CancelImageRequests(aNotify);
|
|
|
|
}
|
2006-12-26 17:47:52 +00:00
|
|
|
} else if (aNotify && aName == nsGkAtoms::disabled) {
|
2011-11-16 07:50:19 +00:00
|
|
|
mDisabledChanged = true;
|
2012-11-21 10:13:57 +00:00
|
|
|
} else if (aName == nsGkAtoms::dir &&
|
|
|
|
AttrValueIs(kNameSpaceID_None, nsGkAtoms::dir,
|
|
|
|
nsGkAtoms::_auto, eIgnoreCase)) {
|
|
|
|
SetDirectionIfAuto(false, aNotify);
|
2005-10-28 02:59:38 +00:00
|
|
|
}
|
2004-02-24 23:55:18 +00:00
|
|
|
}
|
|
|
|
|
2005-10-28 02:59:38 +00:00
|
|
|
return nsGenericHTMLFormElement::BeforeSetAttr(aNameSpaceID, aName,
|
|
|
|
aValue, aNotify);
|
2002-03-07 20:53:40 +00:00
|
|
|
}
|
|
|
|
|
2005-10-28 02:59:38 +00:00
|
|
|
nsresult
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
|
|
|
|
const nsAttrValue* aValue, bool aNotify)
|
2002-03-07 20:53:40 +00:00
|
|
|
{
|
2005-10-28 02:59:38 +00:00
|
|
|
if (aNameSpaceID == kNameSpaceID_None) {
|
|
|
|
//
|
|
|
|
// When name or type changes, radio should be added to radio group.
|
|
|
|
// (type changes are handled in the form itself currently)
|
|
|
|
// If the parser is not done creating the radio, we also should not do it.
|
|
|
|
//
|
2006-12-26 17:47:52 +00:00
|
|
|
if ((aName == nsGkAtoms::name ||
|
|
|
|
(aName == nsGkAtoms::type && !mForm)) &&
|
2005-10-28 02:59:38 +00:00
|
|
|
mType == NS_FORM_INPUT_RADIO &&
|
2011-11-16 07:50:19 +00:00
|
|
|
(mForm || !mParserCreating)) {
|
2005-10-28 02:59:38 +00:00
|
|
|
AddedToRadioGroup();
|
2011-02-25 18:16:04 +00:00
|
|
|
UpdateValueMissingValidityStateForRadio(false);
|
2002-03-31 10:14:01 +00:00
|
|
|
}
|
2002-12-17 13:29:39 +00:00
|
|
|
|
2010-07-21 00:11:19 +00:00
|
|
|
// If @value is changed and BF_VALUE_CHANGED is false, @value is the value
|
2010-09-08 17:42:35 +00:00
|
|
|
// of the element so, if the value of the element is different than @value,
|
|
|
|
// we have to re-set it. This is only the case when GetValueMode() returns
|
|
|
|
// VALUE_MODE_VALUE.
|
2006-12-26 17:47:52 +00:00
|
|
|
if (aName == nsGkAtoms::value &&
|
2011-11-16 07:50:19 +00:00
|
|
|
!mValueChanged && GetValueMode() == VALUE_MODE_VALUE) {
|
2010-07-22 15:10:27 +00:00
|
|
|
SetDefaultValueAsValue();
|
2005-04-05 03:46:12 +00:00
|
|
|
}
|
2010-07-21 00:11:19 +00:00
|
|
|
|
2005-10-28 02:59:38 +00:00
|
|
|
//
|
|
|
|
// Checked must be set no matter what type of control it is, since
|
2011-11-16 07:50:19 +00:00
|
|
|
// mChecked must reflect the new value
|
|
|
|
if (aName == nsGkAtoms::checked && !mCheckedChanged) {
|
2007-07-12 20:05:45 +00:00
|
|
|
// Delay setting checked if the parser is creating this element (wait
|
|
|
|
// until everything is set)
|
2011-11-16 07:50:19 +00:00
|
|
|
if (mParserCreating) {
|
|
|
|
mShouldInitChecked = true;
|
2007-07-12 20:05:45 +00:00
|
|
|
} else {
|
2011-11-16 07:50:19 +00:00
|
|
|
DoSetChecked(DefaultChecked(), true, true);
|
2011-10-17 14:59:28 +00:00
|
|
|
SetCheckedChanged(false);
|
2002-12-17 13:29:39 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-12-26 17:47:52 +00:00
|
|
|
if (aName == nsGkAtoms::type) {
|
2005-10-28 02:59:38 +00:00
|
|
|
if (!aValue) {
|
|
|
|
// We're now a text input. Note that we have to handle this manually,
|
|
|
|
// since removing an attribute (which is what happened, since aValue is
|
|
|
|
// null) doesn't call ParseAttribute.
|
2010-06-09 18:13:56 +00:00
|
|
|
HandleTypeChange(kInputDefaultType->value);
|
2005-10-28 02:59:38 +00:00
|
|
|
}
|
2010-09-10 05:08:56 +00:00
|
|
|
|
|
|
|
UpdateBarredFromConstraintValidation();
|
|
|
|
|
2005-10-28 02:59:38 +00:00
|
|
|
if (mType != NS_FORM_INPUT_IMAGE) {
|
|
|
|
// We're no longer an image input. Cancel our image requests, if we have
|
|
|
|
// any. Note that doing this when we already weren't an image is ok --
|
|
|
|
// just does nothing.
|
|
|
|
CancelImageRequests(aNotify);
|
|
|
|
} else if (aNotify) {
|
|
|
|
// We just got switched to be an image input; we should see
|
|
|
|
// whether we have an image to load;
|
|
|
|
nsAutoString src;
|
2006-12-26 17:47:52 +00:00
|
|
|
if (GetAttr(kNameSpaceID_None, nsGkAtoms::src, src)) {
|
2011-10-17 14:59:28 +00:00
|
|
|
LoadImage(src, false, aNotify);
|
2005-10-28 02:59:38 +00:00
|
|
|
}
|
2003-07-24 17:10:14 +00:00
|
|
|
}
|
2010-08-21 17:52:57 +00:00
|
|
|
}
|
|
|
|
|
2011-02-25 18:12:47 +00:00
|
|
|
if (mType == NS_FORM_INPUT_RADIO && aName == nsGkAtoms::required) {
|
2011-07-19 09:44:55 +00:00
|
|
|
nsCOMPtr<nsIRadioGroupContainer> container = GetRadioGroupContainer();
|
2011-02-25 18:12:47 +00:00
|
|
|
|
2011-05-04 12:49:59 +00:00
|
|
|
if (container) {
|
|
|
|
nsAutoString name;
|
|
|
|
GetAttr(kNameSpaceID_None, nsGkAtoms::name, name);
|
2011-02-25 18:12:47 +00:00
|
|
|
container->RadioRequiredChanged(name, this);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-08-21 17:52:57 +00:00
|
|
|
if (aName == nsGkAtoms::required || aName == nsGkAtoms::disabled ||
|
|
|
|
aName == nsGkAtoms::readonly) {
|
|
|
|
UpdateValueMissingValidityState();
|
2010-09-10 05:08:56 +00:00
|
|
|
|
|
|
|
// This *has* to be called *after* validity has changed.
|
|
|
|
if (aName == nsGkAtoms::readonly || aName == nsGkAtoms::disabled) {
|
|
|
|
UpdateBarredFromConstraintValidation();
|
|
|
|
}
|
2010-10-07 10:01:53 +00:00
|
|
|
} else if (MaxLengthApplies() && aName == nsGkAtoms::maxlength) {
|
2010-08-21 17:52:57 +00:00
|
|
|
UpdateTooLongValidityState();
|
|
|
|
} else if (aName == nsGkAtoms::pattern) {
|
|
|
|
UpdatePatternMismatchValidityState();
|
2011-07-05 22:31:23 +00:00
|
|
|
} else if (aName == nsGkAtoms::multiple) {
|
|
|
|
UpdateTypeMismatchValidityState();
|
2012-06-22 09:36:24 +00:00
|
|
|
} else if (aName == nsGkAtoms::max) {
|
2012-06-22 09:41:32 +00:00
|
|
|
UpdateHasRange();
|
2012-06-22 09:36:24 +00:00
|
|
|
UpdateRangeOverflowValidityState();
|
2013-02-16 12:35:57 +00:00
|
|
|
if (mType == NS_FORM_INPUT_RANGE) {
|
|
|
|
// The value may need to change when @max changes since the value may
|
|
|
|
// have been invalid and can now change to a valid value, or vice
|
|
|
|
// versa. For example, consider:
|
|
|
|
// <input type=range value=-1 max=1 step=3>. The valid range is 0 to 1
|
|
|
|
// while the nearest valid steps are -1 and 2 (the max value having
|
|
|
|
// prevented there being a valid step in range). Changing @max to/from
|
|
|
|
// 1 and a number greater than on equal to 3 should change whether we
|
|
|
|
// have a step mismatch or not.
|
|
|
|
// The value may also need to change between a value that results in
|
|
|
|
// a step mismatch and a value that results in overflow. For example,
|
|
|
|
// if @max in the example above were to change from 1 to -1.
|
|
|
|
nsAutoString value;
|
|
|
|
GetValue(value);
|
|
|
|
SetValueInternal(value, false, false);
|
|
|
|
MOZ_ASSERT(!GetValidityState(VALIDITY_STATE_RANGE_UNDERFLOW),
|
|
|
|
"HTML5 spec does not allow this");
|
|
|
|
}
|
2012-06-22 09:38:20 +00:00
|
|
|
} else if (aName == nsGkAtoms::min) {
|
2012-06-22 09:41:32 +00:00
|
|
|
UpdateHasRange();
|
2012-06-22 09:38:20 +00:00
|
|
|
UpdateRangeUnderflowValidityState();
|
2012-06-22 19:02:20 +00:00
|
|
|
UpdateStepMismatchValidityState();
|
2013-02-16 12:35:57 +00:00
|
|
|
if (mType == NS_FORM_INPUT_RANGE) {
|
|
|
|
// See @max comment
|
|
|
|
nsAutoString value;
|
|
|
|
GetValue(value);
|
|
|
|
SetValueInternal(value, false, false);
|
|
|
|
MOZ_ASSERT(!GetValidityState(VALIDITY_STATE_RANGE_UNDERFLOW),
|
|
|
|
"HTML5 spec does not allow this");
|
|
|
|
}
|
2012-06-22 19:02:20 +00:00
|
|
|
} else if (aName == nsGkAtoms::step) {
|
|
|
|
UpdateStepMismatchValidityState();
|
2013-02-16 12:35:57 +00:00
|
|
|
if (mType == NS_FORM_INPUT_RANGE) {
|
|
|
|
// See @max comment
|
|
|
|
nsAutoString value;
|
|
|
|
GetValue(value);
|
|
|
|
SetValueInternal(value, false, false);
|
|
|
|
MOZ_ASSERT(!GetValidityState(VALIDITY_STATE_RANGE_UNDERFLOW),
|
|
|
|
"HTML5 spec does not allow this");
|
|
|
|
}
|
2012-11-21 10:13:57 +00:00
|
|
|
} else if (aName == nsGkAtoms::dir &&
|
|
|
|
aValue && aValue->Equals(nsGkAtoms::_auto, eIgnoreCase)) {
|
|
|
|
SetDirectionIfAuto(true, aNotify);
|
2010-08-21 17:52:57 +00:00
|
|
|
}
|
|
|
|
|
2011-06-01 01:46:57 +00:00
|
|
|
UpdateState(aNotify);
|
2002-12-16 23:49:16 +00:00
|
|
|
}
|
2005-10-28 02:59:38 +00:00
|
|
|
|
|
|
|
return nsGenericHTMLFormElement::AfterSetAttr(aNameSpaceID, aName,
|
|
|
|
aValue, aNotify);
|
2002-03-07 20:53:40 +00:00
|
|
|
}
|
|
|
|
|
2002-08-06 23:50:08 +00:00
|
|
|
// nsIDOMHTMLInputElement
|
|
|
|
|
1998-09-01 01:27:08 +00:00
|
|
|
NS_IMETHODIMP
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::GetForm(nsIDOMHTMLFormElement** aForm)
|
1998-09-01 01:27:08 +00:00
|
|
|
{
|
2004-02-10 19:36:43 +00:00
|
|
|
return nsGenericHTMLFormElement::GetForm(aForm);
|
1998-09-01 01:27:08 +00:00
|
|
|
}
|
|
|
|
|
2013-03-28 19:41:32 +00:00
|
|
|
NS_IMPL_STRING_ATTR(HTMLInputElement, DefaultValue, value)
|
|
|
|
NS_IMPL_BOOL_ATTR(HTMLInputElement, DefaultChecked, checked)
|
|
|
|
NS_IMPL_STRING_ATTR(HTMLInputElement, Accept, accept)
|
|
|
|
NS_IMPL_STRING_ATTR(HTMLInputElement, Align, align)
|
|
|
|
NS_IMPL_STRING_ATTR(HTMLInputElement, Alt, alt)
|
|
|
|
NS_IMPL_ENUM_ATTR_DEFAULT_VALUE(HTMLInputElement, Autocomplete, autocomplete,
|
2010-09-14 17:58:34 +00:00
|
|
|
kInputDefaultAutocomplete->tag)
|
2013-03-28 19:41:32 +00:00
|
|
|
NS_IMPL_BOOL_ATTR(HTMLInputElement, Autofocus, autofocus)
|
|
|
|
//NS_IMPL_BOOL_ATTR(HTMLInputElement, Checked, checked)
|
|
|
|
NS_IMPL_BOOL_ATTR(HTMLInputElement, Disabled, disabled)
|
|
|
|
NS_IMPL_STRING_ATTR(HTMLInputElement, Max, max)
|
|
|
|
NS_IMPL_STRING_ATTR(HTMLInputElement, Min, min)
|
|
|
|
NS_IMPL_ACTION_ATTR(HTMLInputElement, FormAction, formaction)
|
|
|
|
NS_IMPL_ENUM_ATTR_DEFAULT_MISSING_INVALID_VALUES(HTMLInputElement, FormEnctype, formenctype,
|
2013-01-23 01:35:57 +00:00
|
|
|
"", kFormDefaultEnctype->tag)
|
2013-03-28 19:41:32 +00:00
|
|
|
NS_IMPL_ENUM_ATTR_DEFAULT_MISSING_INVALID_VALUES(HTMLInputElement, FormMethod, formmethod,
|
2013-01-23 01:35:57 +00:00
|
|
|
"", kFormDefaultMethod->tag)
|
2013-03-28 19:41:32 +00:00
|
|
|
NS_IMPL_BOOL_ATTR(HTMLInputElement, FormNoValidate, formnovalidate)
|
|
|
|
NS_IMPL_STRING_ATTR(HTMLInputElement, FormTarget, formtarget)
|
|
|
|
NS_IMPL_ENUM_ATTR_DEFAULT_VALUE(HTMLInputElement, InputMode, inputmode,
|
2012-08-17 09:53:44 +00:00
|
|
|
kInputDefaultInputmode->tag)
|
2013-03-28 19:41:32 +00:00
|
|
|
NS_IMPL_BOOL_ATTR(HTMLInputElement, Multiple, multiple)
|
|
|
|
NS_IMPL_NON_NEGATIVE_INT_ATTR(HTMLInputElement, MaxLength, maxlength)
|
|
|
|
NS_IMPL_STRING_ATTR(HTMLInputElement, Name, name)
|
|
|
|
NS_IMPL_BOOL_ATTR(HTMLInputElement, ReadOnly, readonly)
|
|
|
|
NS_IMPL_BOOL_ATTR(HTMLInputElement, Required, required)
|
|
|
|
NS_IMPL_URI_ATTR(HTMLInputElement, Src, src)
|
|
|
|
NS_IMPL_STRING_ATTR(HTMLInputElement, Step, step)
|
|
|
|
NS_IMPL_STRING_ATTR(HTMLInputElement, UseMap, usemap)
|
|
|
|
//NS_IMPL_STRING_ATTR(HTMLInputElement, Value, value)
|
|
|
|
NS_IMPL_UINT_ATTR_NON_ZERO_DEFAULT_VALUE(HTMLInputElement, Size, size, DEFAULT_COLS)
|
|
|
|
NS_IMPL_STRING_ATTR(HTMLInputElement, Pattern, pattern)
|
|
|
|
NS_IMPL_STRING_ATTR(HTMLInputElement, Placeholder, placeholder)
|
|
|
|
NS_IMPL_ENUM_ATTR_DEFAULT_VALUE(HTMLInputElement, Type, type,
|
2010-04-15 11:03:00 +00:00
|
|
|
kInputDefaultType->tag)
|
2003-11-10 05:52:29 +00:00
|
|
|
|
2012-10-06 07:19:51 +00:00
|
|
|
int32_t
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::TabIndexDefault()
|
2012-10-06 07:19:51 +00:00
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2013-03-28 19:41:32 +00:00
|
|
|
uint32_t
|
|
|
|
HTMLInputElement::Height()
|
|
|
|
{
|
|
|
|
return GetWidthHeightForImage(mCurrentRequest).height;
|
|
|
|
}
|
|
|
|
|
2012-06-27 05:17:31 +00:00
|
|
|
NS_IMETHODIMP
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::GetHeight(uint32_t* aHeight)
|
2012-06-27 05:17:31 +00:00
|
|
|
{
|
2013-03-28 19:41:32 +00:00
|
|
|
*aHeight = Height();
|
2012-06-27 05:17:31 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::SetHeight(uint32_t aHeight)
|
2012-06-27 05:17:31 +00:00
|
|
|
{
|
2013-03-28 19:41:32 +00:00
|
|
|
ErrorResult rv;
|
|
|
|
SetHeight(aHeight, rv);
|
|
|
|
return rv.ErrorCode();
|
2012-06-27 05:17:31 +00:00
|
|
|
}
|
|
|
|
|
2009-01-22 00:07:44 +00:00
|
|
|
NS_IMETHODIMP
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::GetIndeterminate(bool* aValue)
|
2009-01-22 00:07:44 +00:00
|
|
|
{
|
2012-06-03 11:36:51 +00:00
|
|
|
*aValue = Indeterminate();
|
2009-01-22 00:07:44 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2013-03-28 19:41:32 +00:00
|
|
|
void
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::SetIndeterminateInternal(bool aValue,
|
|
|
|
bool aShouldInvalidate)
|
2009-01-22 00:07:44 +00:00
|
|
|
{
|
2011-11-16 07:50:19 +00:00
|
|
|
mIndeterminate = aValue;
|
2009-01-22 00:07:44 +00:00
|
|
|
|
2009-02-11 01:19:37 +00:00
|
|
|
if (aShouldInvalidate) {
|
|
|
|
// Repaint the frame
|
|
|
|
nsIFrame* frame = GetPrimaryFrame();
|
|
|
|
if (frame)
|
2010-08-31 00:49:12 +00:00
|
|
|
frame->InvalidateFrameSubtree();
|
2009-02-11 01:19:37 +00:00
|
|
|
}
|
|
|
|
|
2011-06-01 01:46:57 +00:00
|
|
|
UpdateState(true);
|
2009-01-22 00:07:44 +00:00
|
|
|
}
|
|
|
|
|
2009-02-11 01:19:37 +00:00
|
|
|
NS_IMETHODIMP
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::SetIndeterminate(bool aValue)
|
2009-02-11 01:19:37 +00:00
|
|
|
{
|
2013-03-28 19:41:32 +00:00
|
|
|
SetIndeterminateInternal(aValue, true);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t
|
|
|
|
HTMLInputElement::Width()
|
|
|
|
{
|
|
|
|
return GetWidthHeightForImage(mCurrentRequest).width;
|
2009-02-11 01:19:37 +00:00
|
|
|
}
|
|
|
|
|
2012-06-27 05:17:31 +00:00
|
|
|
NS_IMETHODIMP
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::GetWidth(uint32_t* aWidth)
|
2012-06-27 05:17:31 +00:00
|
|
|
{
|
2013-03-28 19:41:32 +00:00
|
|
|
*aWidth = Width();
|
2012-06-27 05:17:31 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::SetWidth(uint32_t aWidth)
|
2012-06-27 05:17:31 +00:00
|
|
|
{
|
2013-04-04 07:03:50 +00:00
|
|
|
ErrorResult rv;
|
|
|
|
SetWidth(aWidth, rv);
|
|
|
|
return rv.ErrorCode();
|
2012-06-27 05:17:31 +00:00
|
|
|
}
|
|
|
|
|
2011-03-09 18:25:20 +00:00
|
|
|
NS_IMETHODIMP
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::GetValue(nsAString& aValue)
|
2011-03-09 18:25:20 +00:00
|
|
|
{
|
2013-03-28 19:41:32 +00:00
|
|
|
GetValueInternal(aValue);
|
2012-07-05 16:15:46 +00:00
|
|
|
|
2013-01-31 23:05:48 +00:00
|
|
|
// Don't return non-sanitized value for types that are experimental on mobile.
|
|
|
|
if (IsExperimentalMobileType(mType)) {
|
2012-07-05 16:15:46 +00:00
|
|
|
SanitizeValue(aValue);
|
|
|
|
}
|
|
|
|
|
2013-03-28 19:41:32 +00:00
|
|
|
return NS_OK;
|
2011-03-09 18:25:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::GetValueInternal(nsAString& aValue) const
|
1998-10-30 20:41:01 +00:00
|
|
|
{
|
2011-06-22 10:41:00 +00:00
|
|
|
switch (GetValueMode()) {
|
|
|
|
case VALUE_MODE_VALUE:
|
2013-02-12 20:16:58 +00:00
|
|
|
if (IsSingleLineTextControl(false)) {
|
|
|
|
mInputData.mState->GetValue(aValue, true);
|
|
|
|
} else {
|
|
|
|
aValue.Assign(mInputData.mValue);
|
|
|
|
}
|
2011-06-22 10:41:00 +00:00
|
|
|
return NS_OK;
|
2001-02-09 23:45:41 +00:00
|
|
|
|
2011-06-22 10:41:00 +00:00
|
|
|
case VALUE_MODE_FILENAME:
|
2012-10-25 23:10:53 +00:00
|
|
|
if (nsContentUtils::IsCallerChrome()) {
|
2011-06-22 10:41:00 +00:00
|
|
|
if (mFiles.Count()) {
|
|
|
|
return mFiles[0]->GetMozFullPath(aValue);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
aValue.Truncate();
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// Just return the leaf name
|
|
|
|
if (mFiles.Count() == 0 || NS_FAILED(mFiles[0]->GetName(aValue))) {
|
|
|
|
aValue.Truncate();
|
|
|
|
}
|
2007-11-15 06:16:06 +00:00
|
|
|
}
|
2006-04-25 09:18:42 +00:00
|
|
|
|
2011-06-22 10:41:00 +00:00
|
|
|
return NS_OK;
|
|
|
|
|
|
|
|
case VALUE_MODE_DEFAULT:
|
|
|
|
// Treat defaultValue as value.
|
|
|
|
GetAttr(kNameSpaceID_None, nsGkAtoms::value, aValue);
|
|
|
|
return NS_OK;
|
|
|
|
|
|
|
|
case VALUE_MODE_DEFAULT_ON:
|
|
|
|
// Treat default value as value and returns "on" if no value.
|
|
|
|
if (!GetAttr(kNameSpaceID_None, nsGkAtoms::value, aValue)) {
|
|
|
|
aValue.AssignLiteral("on");
|
|
|
|
}
|
|
|
|
return NS_OK;
|
1999-01-28 18:58:11 +00:00
|
|
|
}
|
2001-01-30 04:22:24 +00:00
|
|
|
|
2011-06-22 10:41:00 +00:00
|
|
|
// This return statement is required for some compilers.
|
2005-10-28 11:25:24 +00:00
|
|
|
return NS_OK;
|
1998-10-30 20:41:01 +00:00
|
|
|
}
|
|
|
|
|
2011-03-12 01:07:34 +00:00
|
|
|
bool
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::IsValueEmpty() const
|
2011-03-12 01:07:34 +00:00
|
|
|
{
|
|
|
|
nsAutoString value;
|
|
|
|
GetValueInternal(value);
|
|
|
|
|
|
|
|
return value.IsEmpty();
|
|
|
|
}
|
|
|
|
|
2012-12-27 18:55:31 +00:00
|
|
|
bool
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::ConvertStringToNumber(nsAString& aValue,
|
|
|
|
double& aResultValue) const
|
2012-12-27 18:55:31 +00:00
|
|
|
{
|
2013-01-22 18:22:33 +00:00
|
|
|
MOZ_ASSERT(DoesValueAsNumberApply(),
|
|
|
|
"ConvertStringToNumber only applies if .valueAsNumber applies");
|
|
|
|
|
2012-12-27 18:55:31 +00:00
|
|
|
switch (mType) {
|
|
|
|
case NS_FORM_INPUT_NUMBER:
|
2013-02-16 12:35:57 +00:00
|
|
|
case NS_FORM_INPUT_RANGE:
|
2012-12-27 18:55:31 +00:00
|
|
|
{
|
|
|
|
nsresult ec;
|
|
|
|
aResultValue = PromiseFlatString(aValue).ToDouble(&ec);
|
2013-02-14 17:25:26 +00:00
|
|
|
if (NS_FAILED(ec) || !MOZ_DOUBLE_IS_FINITE(aResultValue)) {
|
2012-12-27 18:55:31 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2013-01-07 15:20:53 +00:00
|
|
|
return true;
|
2012-12-27 18:55:31 +00:00
|
|
|
}
|
|
|
|
case NS_FORM_INPUT_DATE:
|
|
|
|
{
|
2013-01-21 12:38:54 +00:00
|
|
|
SafeAutoJSContext ctx;
|
|
|
|
JSAutoRequest ar(ctx);
|
2012-12-27 18:55:31 +00:00
|
|
|
|
|
|
|
uint32_t year, month, day;
|
2013-01-11 15:02:58 +00:00
|
|
|
if (!GetValueAsDate(aValue, &year, &month, &day)) {
|
2012-12-27 18:55:31 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
JSObject* date = JS_NewDateObjectMsec(ctx, 0);
|
2013-01-07 15:20:53 +00:00
|
|
|
if (!date) {
|
|
|
|
JS_ClearPendingException(ctx);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2013-03-23 05:00:43 +00:00
|
|
|
JS::Value rval;
|
|
|
|
JS::Value fullYear[3];
|
2012-12-27 18:55:31 +00:00
|
|
|
fullYear[0].setInt32(year);
|
2013-01-21 16:44:42 +00:00
|
|
|
fullYear[1].setInt32(month - 1);
|
2012-12-27 18:55:31 +00:00
|
|
|
fullYear[2].setInt32(day);
|
|
|
|
if (!JS::Call(ctx, date, "setUTCFullYear", 3, fullYear, &rval)) {
|
2013-01-07 15:20:53 +00:00
|
|
|
JS_ClearPendingException(ctx);
|
2012-12-27 18:55:31 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2013-03-23 05:00:43 +00:00
|
|
|
JS::Value timestamp;
|
2012-12-27 18:55:31 +00:00
|
|
|
if (!JS::Call(ctx, date, "getTime", 0, nullptr, ×tamp)) {
|
2013-01-07 15:20:53 +00:00
|
|
|
JS_ClearPendingException(ctx);
|
2012-12-27 18:55:31 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2013-01-07 15:20:53 +00:00
|
|
|
if (!timestamp.isNumber() || MOZ_DOUBLE_IS_NaN(timestamp.toNumber())) {
|
2012-12-27 18:55:31 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
aResultValue = timestamp.toNumber();
|
2013-01-07 15:20:53 +00:00
|
|
|
return true;
|
2012-12-27 18:55:31 +00:00
|
|
|
}
|
2013-01-22 18:22:33 +00:00
|
|
|
case NS_FORM_INPUT_TIME:
|
|
|
|
uint32_t milliseconds;
|
|
|
|
if (!ParseTime(aValue, &milliseconds)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
aResultValue = static_cast<double>(milliseconds);
|
|
|
|
return true;
|
2012-12-27 18:55:31 +00:00
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2013-01-07 15:20:53 +00:00
|
|
|
MOZ_NOT_REACHED();
|
|
|
|
return false;
|
2012-12-27 18:55:31 +00:00
|
|
|
}
|
|
|
|
|
2012-06-22 09:36:24 +00:00
|
|
|
double
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::GetValueAsDouble() const
|
2012-06-22 09:36:24 +00:00
|
|
|
{
|
|
|
|
double doubleValue;
|
|
|
|
nsAutoString stringValue;
|
|
|
|
|
|
|
|
GetValueInternal(stringValue);
|
|
|
|
|
2012-12-27 18:55:31 +00:00
|
|
|
return !ConvertStringToNumber(stringValue, doubleValue) ? MOZ_DOUBLE_NaN()
|
|
|
|
: doubleValue;
|
2012-06-22 09:36:24 +00:00
|
|
|
}
|
|
|
|
|
2013-03-28 19:41:32 +00:00
|
|
|
void
|
|
|
|
HTMLInputElement::SetValue(const nsAString& aValue, ErrorResult& aRv)
|
2001-11-02 07:40:01 +00:00
|
|
|
{
|
2004-10-30 18:11:25 +00:00
|
|
|
// check security. Note that setting the value to the empty string is always
|
|
|
|
// OK and gives pages a way to clear a file input if necessary.
|
2006-04-25 09:18:42 +00:00
|
|
|
if (mType == NS_FORM_INPUT_FILE) {
|
|
|
|
if (!aValue.IsEmpty()) {
|
2012-10-25 23:10:53 +00:00
|
|
|
if (!nsContentUtils::IsCallerChrome()) {
|
|
|
|
// setting the value of a "FILE" input widget requires
|
|
|
|
// chrome privilege
|
2013-03-28 19:41:32 +00:00
|
|
|
aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
|
|
|
|
return;
|
2006-04-25 09:18:42 +00:00
|
|
|
}
|
2013-03-28 19:41:32 +00:00
|
|
|
Sequence<nsString> list;
|
|
|
|
list.AppendElement(aValue);
|
|
|
|
MozSetFileNameArray(list);
|
|
|
|
return;
|
2009-10-27 18:14:34 +00:00
|
|
|
}
|
|
|
|
else {
|
2010-11-23 23:45:53 +00:00
|
|
|
ClearFiles(true);
|
2002-12-16 23:49:16 +00:00
|
|
|
}
|
2006-04-25 09:18:42 +00:00
|
|
|
}
|
|
|
|
else {
|
2013-03-16 05:49:41 +00:00
|
|
|
if (MayFireChangeOnBlur()) {
|
2012-09-05 12:39:33 +00:00
|
|
|
// If the value has been set by a script, we basically want to keep the
|
|
|
|
// current change event state. If the element is ready to fire a change
|
|
|
|
// event, we should keep it that way. Otherwise, we should make sure the
|
|
|
|
// element will not fire any event because of the script interaction.
|
|
|
|
//
|
|
|
|
// NOTE: this is currently quite expensive work (too much string
|
|
|
|
// manipulation). We should probably optimize that.
|
|
|
|
nsAutoString currentValue;
|
|
|
|
GetValueInternal(currentValue);
|
|
|
|
|
|
|
|
SetValueInternal(aValue, false, true);
|
|
|
|
|
|
|
|
if (mFocusedValue.Equals(currentValue)) {
|
|
|
|
GetValueInternal(mFocusedValue);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
SetValueInternal(aValue, false, true);
|
2012-05-07 16:27:24 +00:00
|
|
|
}
|
2002-12-16 23:49:16 +00:00
|
|
|
}
|
2001-11-02 07:40:01 +00:00
|
|
|
}
|
|
|
|
|
2010-09-10 05:18:10 +00:00
|
|
|
NS_IMETHODIMP
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::SetValue(const nsAString& aValue)
|
2010-09-10 05:18:10 +00:00
|
|
|
{
|
2013-03-28 19:41:32 +00:00
|
|
|
ErrorResult rv;
|
|
|
|
SetValue(aValue, rv);
|
|
|
|
return rv.ErrorCode();
|
|
|
|
}
|
2011-11-16 07:50:19 +00:00
|
|
|
|
2013-03-28 19:41:32 +00:00
|
|
|
nsGenericHTMLElement*
|
|
|
|
HTMLInputElement::GetList() const
|
|
|
|
{
|
2010-09-10 05:18:10 +00:00
|
|
|
nsAutoString dataListId;
|
|
|
|
GetAttr(kNameSpaceID_None, nsGkAtoms::list, dataListId);
|
2011-11-16 07:50:19 +00:00
|
|
|
if (dataListId.IsEmpty()) {
|
2013-03-28 19:41:32 +00:00
|
|
|
return nullptr;
|
2011-11-16 07:50:19 +00:00
|
|
|
}
|
2010-09-10 05:18:10 +00:00
|
|
|
|
2011-11-16 07:50:19 +00:00
|
|
|
nsIDocument* doc = GetCurrentDoc();
|
|
|
|
if (!doc) {
|
2013-03-28 19:41:32 +00:00
|
|
|
return nullptr;
|
2011-11-16 07:50:19 +00:00
|
|
|
}
|
2010-09-10 05:18:10 +00:00
|
|
|
|
2011-11-16 07:50:19 +00:00
|
|
|
Element* element = doc->GetElementById(dataListId);
|
|
|
|
if (!element || !element->IsHTML(nsGkAtoms::datalist)) {
|
2013-03-28 19:41:32 +00:00
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
return static_cast<nsGenericHTMLElement*>(element);
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
HTMLInputElement::GetList(nsIDOMHTMLElement** aValue)
|
|
|
|
{
|
|
|
|
*aValue = nullptr;
|
|
|
|
|
|
|
|
nsRefPtr<nsGenericHTMLElement> element = GetList();
|
|
|
|
if (!element) {
|
2011-11-16 07:50:19 +00:00
|
|
|
return NS_OK;
|
2010-09-10 05:18:10 +00:00
|
|
|
}
|
|
|
|
|
2011-11-16 07:50:19 +00:00
|
|
|
CallQueryInterface(element, aValue);
|
2010-09-10 05:18:10 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2012-07-05 14:33:47 +00:00
|
|
|
void
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::SetValue(double aValue)
|
2012-07-05 14:33:47 +00:00
|
|
|
{
|
2012-12-28 12:48:41 +00:00
|
|
|
MOZ_ASSERT(!MOZ_DOUBLE_IS_INFINITE(aValue), "aValue must not be Infinity!");
|
|
|
|
|
|
|
|
if (MOZ_DOUBLE_IS_NaN(aValue)) {
|
|
|
|
SetValue(EmptyString());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-07-05 14:33:47 +00:00
|
|
|
nsAutoString value;
|
2012-12-22 14:46:19 +00:00
|
|
|
ConvertNumberToString(aValue, value);
|
|
|
|
SetValue(value);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::ConvertNumberToString(double aValue,
|
|
|
|
nsAString& aResultString) const
|
2012-12-22 14:46:19 +00:00
|
|
|
{
|
2013-01-22 18:22:33 +00:00
|
|
|
MOZ_ASSERT(DoesValueAsNumberApply(),
|
|
|
|
"ConvertNumberToString is only implemented for types implementing .valueAsNumber");
|
2012-12-28 12:48:41 +00:00
|
|
|
MOZ_ASSERT(!MOZ_DOUBLE_IS_NaN(aValue) && !MOZ_DOUBLE_IS_INFINITE(aValue),
|
|
|
|
"aValue must be a valid non-Infinite number.");
|
2012-12-22 14:46:19 +00:00
|
|
|
|
|
|
|
aResultString.Truncate();
|
|
|
|
|
2012-12-27 18:55:31 +00:00
|
|
|
switch (mType) {
|
|
|
|
case NS_FORM_INPUT_NUMBER:
|
2013-02-16 12:35:57 +00:00
|
|
|
case NS_FORM_INPUT_RANGE:
|
2012-12-22 14:46:19 +00:00
|
|
|
aResultString.AppendFloat(aValue);
|
|
|
|
return true;
|
2012-12-27 18:55:31 +00:00
|
|
|
case NS_FORM_INPUT_DATE:
|
2012-12-22 14:46:19 +00:00
|
|
|
{
|
2013-01-21 12:38:54 +00:00
|
|
|
SafeAutoJSContext ctx;
|
|
|
|
JSAutoRequest ar(ctx);
|
2012-12-27 18:55:31 +00:00
|
|
|
|
2012-12-22 14:46:19 +00:00
|
|
|
// The specs require |aValue| to be truncated.
|
|
|
|
aValue = floor(aValue);
|
2012-12-27 18:55:31 +00:00
|
|
|
|
2012-12-22 14:46:19 +00:00
|
|
|
JSObject* date = JS_NewDateObjectMsec(ctx, aValue);
|
|
|
|
if (!date) {
|
2013-01-07 15:20:53 +00:00
|
|
|
JS_ClearPendingException(ctx);
|
2012-12-22 14:46:19 +00:00
|
|
|
return false;
|
|
|
|
}
|
2012-12-27 18:55:31 +00:00
|
|
|
|
2013-03-23 05:00:43 +00:00
|
|
|
JS::Value year, month, day;
|
2012-12-22 14:46:19 +00:00
|
|
|
if (!JS::Call(ctx, date, "getUTCFullYear", 0, nullptr, &year) ||
|
|
|
|
!JS::Call(ctx, date, "getUTCMonth", 0, nullptr, &month) ||
|
|
|
|
!JS::Call(ctx, date, "getUTCDate", 0, nullptr, &day)) {
|
2013-01-07 15:20:53 +00:00
|
|
|
JS_ClearPendingException(ctx);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!year.isNumber() || !month.isNumber() || !day.isNumber() ||
|
|
|
|
MOZ_DOUBLE_IS_NaN(year.toNumber()) ||
|
|
|
|
MOZ_DOUBLE_IS_NaN(month.toNumber()) ||
|
|
|
|
MOZ_DOUBLE_IS_NaN(day.toNumber())) {
|
2012-12-22 14:46:19 +00:00
|
|
|
return false;
|
|
|
|
}
|
2012-12-27 18:55:31 +00:00
|
|
|
|
2012-12-22 14:46:19 +00:00
|
|
|
aResultString.AppendPrintf("%04.0f-%02.0f-%02.0f", year.toNumber(),
|
|
|
|
month.toNumber() + 1, day.toNumber());
|
2012-12-27 18:55:31 +00:00
|
|
|
|
2013-01-31 23:00:08 +00:00
|
|
|
return true;
|
2012-12-22 14:46:19 +00:00
|
|
|
}
|
2013-01-22 18:22:33 +00:00
|
|
|
case NS_FORM_INPUT_TIME:
|
|
|
|
{
|
|
|
|
// Per spec, we need to truncate |aValue| and we should only represent
|
|
|
|
// times inside a day [00:00, 24:00[, which means that we should do a
|
|
|
|
// modulo on |aValue| using the number of milliseconds in a day (86400000).
|
|
|
|
uint32_t value = NS_floorModulo(floor(aValue), 86400000);
|
|
|
|
|
|
|
|
uint16_t milliseconds = value % 1000;
|
|
|
|
value /= 1000;
|
|
|
|
|
|
|
|
uint8_t seconds = value % 60;
|
|
|
|
value /= 60;
|
|
|
|
|
|
|
|
uint8_t minutes = value % 60;
|
|
|
|
value /= 60;
|
|
|
|
|
|
|
|
uint8_t hours = value;
|
|
|
|
|
|
|
|
if (milliseconds != 0) {
|
|
|
|
aResultString.AppendPrintf("%02d:%02d:%02d.%03d",
|
|
|
|
hours, minutes, seconds, milliseconds);
|
|
|
|
} else if (seconds != 0) {
|
|
|
|
aResultString.AppendPrintf("%02d:%02d:%02d",
|
|
|
|
hours, minutes, seconds);
|
|
|
|
} else {
|
|
|
|
aResultString.AppendPrintf("%02d:%02d", hours, minutes);
|
|
|
|
}
|
2013-01-31 23:00:08 +00:00
|
|
|
|
2013-01-22 18:22:33 +00:00
|
|
|
return true;
|
|
|
|
}
|
2012-12-22 14:46:19 +00:00
|
|
|
default:
|
|
|
|
MOZ_NOT_REACHED();
|
|
|
|
return false;
|
2012-12-27 18:55:31 +00:00
|
|
|
}
|
2012-07-05 14:33:47 +00:00
|
|
|
}
|
|
|
|
|
2013-03-28 19:41:32 +00:00
|
|
|
JS::Value
|
|
|
|
HTMLInputElement::GetValueAsDate(JSContext* aCx, ErrorResult& aRv)
|
2012-12-27 18:55:31 +00:00
|
|
|
{
|
2013-01-21 16:44:42 +00:00
|
|
|
if (mType != NS_FORM_INPUT_DATE && mType != NS_FORM_INPUT_TIME) {
|
2013-03-28 19:41:32 +00:00
|
|
|
return JS::NullValue();
|
2012-12-27 18:55:31 +00:00
|
|
|
}
|
|
|
|
|
2013-01-21 16:44:42 +00:00
|
|
|
switch (mType) {
|
|
|
|
case NS_FORM_INPUT_DATE:
|
|
|
|
{
|
|
|
|
uint32_t year, month, day;
|
|
|
|
nsAutoString value;
|
|
|
|
GetValueInternal(value);
|
|
|
|
if (!GetValueAsDate(value, &year, &month, &day)) {
|
2013-03-28 19:41:32 +00:00
|
|
|
return JS::NullValue();
|
2013-01-21 16:44:42 +00:00
|
|
|
}
|
2013-01-21 16:44:42 +00:00
|
|
|
|
2013-03-28 19:41:32 +00:00
|
|
|
JSObject* date = JS_NewDateObjectMsec(aCx, 0);
|
2013-01-21 16:44:42 +00:00
|
|
|
if (!date) {
|
2013-03-28 19:41:32 +00:00
|
|
|
JS_ClearPendingException(aCx);
|
|
|
|
return JS::NullValue();
|
2013-01-21 16:44:42 +00:00
|
|
|
}
|
2013-01-21 16:44:42 +00:00
|
|
|
|
2013-03-23 05:00:43 +00:00
|
|
|
JS::Value rval;
|
|
|
|
JS::Value fullYear[3];
|
2013-01-21 16:44:42 +00:00
|
|
|
fullYear[0].setInt32(year);
|
|
|
|
fullYear[1].setInt32(month - 1);
|
|
|
|
fullYear[2].setInt32(day);
|
2013-03-28 19:41:32 +00:00
|
|
|
if (!JS::Call(aCx, date, "setUTCFullYear", 3, fullYear, &rval)) {
|
|
|
|
JS_ClearPendingException(aCx);
|
|
|
|
return JS::NullValue();
|
2013-01-21 16:44:42 +00:00
|
|
|
}
|
|
|
|
|
2013-03-28 19:41:32 +00:00
|
|
|
return JS::ObjectOrNullValue(date);
|
2013-01-21 16:44:42 +00:00
|
|
|
}
|
|
|
|
case NS_FORM_INPUT_TIME:
|
|
|
|
{
|
|
|
|
uint32_t millisecond;
|
|
|
|
nsAutoString value;
|
|
|
|
GetValueInternal(value);
|
|
|
|
if (!ParseTime(value, &millisecond)) {
|
2013-03-28 19:41:32 +00:00
|
|
|
return JS::NullValue();
|
2013-01-21 16:44:42 +00:00
|
|
|
}
|
|
|
|
|
2013-03-28 19:41:32 +00:00
|
|
|
JSObject* date = JS_NewDateObjectMsec(aCx, millisecond);
|
2013-01-21 16:44:42 +00:00
|
|
|
if (!date) {
|
2013-03-28 19:41:32 +00:00
|
|
|
JS_ClearPendingException(aCx);
|
|
|
|
return JS::NullValue();
|
2013-01-21 16:44:42 +00:00
|
|
|
}
|
|
|
|
|
2013-03-28 19:41:32 +00:00
|
|
|
return JS::ObjectValue(*date);
|
2013-01-21 16:44:42 +00:00
|
|
|
}
|
2012-12-27 18:55:31 +00:00
|
|
|
}
|
|
|
|
|
2013-01-21 16:44:42 +00:00
|
|
|
MOZ_NOT_REACHED();
|
2013-03-28 19:41:32 +00:00
|
|
|
aRv.Throw(NS_ERROR_UNEXPECTED);
|
|
|
|
return JS::NullValue();
|
2012-12-27 18:55:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::GetValueAsDate(JSContext* aCx, JS::Value* aDate)
|
|
|
|
{
|
|
|
|
ErrorResult rv;
|
|
|
|
*aDate = GetValueAsDate(aCx, rv);
|
|
|
|
return rv.ErrorCode();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
HTMLInputElement::SetValueAsDate(JSContext* aCx, JS::Value aDate, ErrorResult& aRv)
|
2012-12-27 18:55:31 +00:00
|
|
|
{
|
2013-01-21 16:44:42 +00:00
|
|
|
if (mType != NS_FORM_INPUT_DATE && mType != NS_FORM_INPUT_TIME) {
|
2013-03-28 19:41:32 +00:00
|
|
|
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
|
|
|
return;
|
2012-12-27 18:55:31 +00:00
|
|
|
}
|
|
|
|
|
2013-01-07 15:20:18 +00:00
|
|
|
if (aDate.isNullOrUndefined()) {
|
2013-03-28 19:41:32 +00:00
|
|
|
aRv = SetValue(EmptyString());
|
|
|
|
return;
|
2013-01-07 15:20:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: return TypeError when HTMLInputElement is converted to WebIDL, see
|
|
|
|
// bug 826302.
|
2013-03-28 19:41:32 +00:00
|
|
|
if (!aDate.isObject() || !JS_ObjectIsDate(aCx, &aDate.toObject())) {
|
2012-12-27 18:55:31 +00:00
|
|
|
SetValue(EmptyString());
|
2013-03-28 19:41:32 +00:00
|
|
|
aRv.Throw(NS_ERROR_INVALID_ARG);
|
|
|
|
return;
|
2012-12-27 18:55:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
JSObject& date = aDate.toObject();
|
2013-03-23 05:00:43 +00:00
|
|
|
JS::Value timestamp;
|
2013-03-28 19:41:32 +00:00
|
|
|
if (!JS::Call(aCx, &date, "getTime", 0, nullptr, ×tamp) ||
|
2013-01-07 15:20:53 +00:00
|
|
|
!timestamp.isNumber() || MOZ_DOUBLE_IS_NaN(timestamp.toNumber())) {
|
2013-03-28 19:41:32 +00:00
|
|
|
JS_ClearPendingException(aCx);
|
2012-12-27 18:55:31 +00:00
|
|
|
SetValue(EmptyString());
|
2013-03-28 19:41:32 +00:00
|
|
|
return;
|
2012-12-27 18:55:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
SetValue(timestamp.toNumber());
|
2013-03-28 19:41:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
HTMLInputElement::SetValueAsDate(JSContext* aCx, const JS::Value& aDate)
|
|
|
|
{
|
|
|
|
ErrorResult rv;
|
|
|
|
SetValueAsDate(aCx, aDate, rv);
|
|
|
|
return rv.ErrorCode();
|
2012-12-27 18:55:31 +00:00
|
|
|
}
|
|
|
|
|
2012-07-05 10:13:41 +00:00
|
|
|
NS_IMETHODIMP
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::GetValueAsNumber(double* aValueAsNumber)
|
2012-07-05 10:13:41 +00:00
|
|
|
{
|
2013-03-28 19:41:32 +00:00
|
|
|
*aValueAsNumber = ValueAsNumber();
|
2012-07-05 10:13:41 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2013-03-28 19:41:32 +00:00
|
|
|
void
|
|
|
|
HTMLInputElement::SetValueAsNumber(double aValueAsNumber, ErrorResult& aRv)
|
2012-07-05 10:13:41 +00:00
|
|
|
{
|
2012-12-28 12:48:41 +00:00
|
|
|
// TODO: return TypeError when HTMLInputElement is converted to WebIDL, see
|
|
|
|
// bug 825197.
|
|
|
|
if (MOZ_DOUBLE_IS_INFINITE(aValueAsNumber)) {
|
2013-03-28 19:41:32 +00:00
|
|
|
aRv.Throw(NS_ERROR_INVALID_ARG);
|
|
|
|
return;
|
2012-12-28 12:48:41 +00:00
|
|
|
}
|
|
|
|
|
2012-07-05 10:13:41 +00:00
|
|
|
if (!DoesValueAsNumberApply()) {
|
2013-03-28 19:41:32 +00:00
|
|
|
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
|
|
|
return;
|
2012-07-05 10:13:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
SetValue(aValueAsNumber);
|
2013-03-28 19:41:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
HTMLInputElement::SetValueAsNumber(double aValueAsNumber)
|
|
|
|
{
|
|
|
|
ErrorResult rv;
|
|
|
|
SetValueAsNumber(aValueAsNumber, rv);
|
|
|
|
return rv.ErrorCode();
|
2012-07-05 10:13:41 +00:00
|
|
|
}
|
|
|
|
|
2012-07-05 14:33:47 +00:00
|
|
|
double
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::GetMinimum() const
|
2012-07-05 14:33:47 +00:00
|
|
|
{
|
2013-01-31 23:00:08 +00:00
|
|
|
MOZ_ASSERT(DoesValueAsNumberApply(),
|
|
|
|
"GetMinAsDouble() should only be used for types that allow .valueAsNumber");
|
2012-07-06 12:40:18 +00:00
|
|
|
|
2013-02-16 12:35:57 +00:00
|
|
|
// Only type=range has a default minimum
|
|
|
|
double defaultMinimum =
|
|
|
|
mType == NS_FORM_INPUT_RANGE ? 0.0 : MOZ_DOUBLE_NaN();
|
2013-01-25 23:51:57 +00:00
|
|
|
|
2012-07-05 14:33:47 +00:00
|
|
|
if (!HasAttr(kNameSpaceID_None, nsGkAtoms::min)) {
|
2013-02-16 12:35:57 +00:00
|
|
|
return defaultMinimum;
|
2012-07-05 14:33:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
nsAutoString minStr;
|
|
|
|
GetAttr(kNameSpaceID_None, nsGkAtoms::min, minStr);
|
|
|
|
|
2012-12-21 17:28:01 +00:00
|
|
|
double min;
|
2013-02-16 12:35:57 +00:00
|
|
|
return ConvertStringToNumber(minStr, min) ? min : defaultMinimum;
|
2012-07-06 12:40:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
double
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::GetMaximum() const
|
2012-07-06 12:40:18 +00:00
|
|
|
{
|
2013-01-31 23:00:08 +00:00
|
|
|
MOZ_ASSERT(DoesValueAsNumberApply(),
|
|
|
|
"GetMaxAsDouble() should only be used for types that allow .valueAsNumber");
|
2012-07-06 12:40:18 +00:00
|
|
|
|
2013-02-16 12:35:57 +00:00
|
|
|
// Only type=range has a default maximum
|
|
|
|
double defaultMaximum =
|
|
|
|
mType == NS_FORM_INPUT_RANGE ? 100.0 : MOZ_DOUBLE_NaN();
|
2013-01-25 23:51:57 +00:00
|
|
|
|
2012-07-06 12:40:18 +00:00
|
|
|
if (!HasAttr(kNameSpaceID_None, nsGkAtoms::max)) {
|
2013-02-16 12:35:57 +00:00
|
|
|
return defaultMaximum;
|
2012-07-06 12:40:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
nsAutoString maxStr;
|
|
|
|
GetAttr(kNameSpaceID_None, nsGkAtoms::max, maxStr);
|
|
|
|
|
2012-12-21 17:26:56 +00:00
|
|
|
double max;
|
2013-02-16 12:35:57 +00:00
|
|
|
return ConvertStringToNumber(maxStr, max) ? max : defaultMaximum;
|
2012-07-06 12:40:18 +00:00
|
|
|
}
|
2012-07-05 14:33:47 +00:00
|
|
|
|
2012-07-06 12:40:18 +00:00
|
|
|
double
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::GetStepBase() const
|
2012-07-06 12:40:18 +00:00
|
|
|
{
|
2013-01-25 23:51:57 +00:00
|
|
|
MOZ_ASSERT(mType == NS_FORM_INPUT_NUMBER ||
|
2013-02-06 22:56:49 +00:00
|
|
|
mType == NS_FORM_INPUT_DATE ||
|
2013-02-16 12:35:57 +00:00
|
|
|
mType == NS_FORM_INPUT_TIME ||
|
|
|
|
mType == NS_FORM_INPUT_RANGE,
|
2013-01-25 23:51:57 +00:00
|
|
|
"Check that kDefaultStepBase is correct for this new type");
|
2012-07-06 12:40:18 +00:00
|
|
|
|
2013-01-25 23:51:57 +00:00
|
|
|
double stepBase;
|
2012-11-26 11:35:26 +00:00
|
|
|
|
2013-01-25 23:51:57 +00:00
|
|
|
// Do NOT use GetMinimum here - the spec says to use "the min content
|
|
|
|
// attribute", not "the minimum".
|
|
|
|
nsAutoString minStr;
|
|
|
|
if (GetAttr(kNameSpaceID_None, nsGkAtoms::min, minStr) &&
|
|
|
|
ConvertStringToNumber(minStr, stepBase)) {
|
|
|
|
return stepBase;
|
|
|
|
}
|
2012-11-26 11:35:26 +00:00
|
|
|
|
2013-01-25 23:51:57 +00:00
|
|
|
// If @min is not a double, we should use @value.
|
|
|
|
nsAutoString valueStr;
|
2013-02-06 18:11:31 +00:00
|
|
|
if (GetAttr(kNameSpaceID_None, nsGkAtoms::value, valueStr) &&
|
|
|
|
ConvertStringToNumber(valueStr, stepBase)) {
|
|
|
|
return stepBase;
|
2012-11-26 11:35:26 +00:00
|
|
|
}
|
|
|
|
|
2013-01-25 23:51:57 +00:00
|
|
|
return kDefaultStepBase;
|
2012-07-05 14:33:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::ApplyStep(int32_t aStep)
|
2012-07-05 14:33:47 +00:00
|
|
|
{
|
|
|
|
if (!DoStepDownStepUpApply()) {
|
|
|
|
return NS_ERROR_DOM_INVALID_STATE_ERR;
|
|
|
|
}
|
|
|
|
|
|
|
|
double step = GetStep();
|
|
|
|
if (step == kStepAny) {
|
|
|
|
return NS_ERROR_DOM_INVALID_STATE_ERR;
|
|
|
|
}
|
|
|
|
|
|
|
|
double value = GetValueAsDouble();
|
2012-07-06 12:41:00 +00:00
|
|
|
if (MOZ_DOUBLE_IS_NaN(value)) {
|
2012-07-05 14:33:47 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2013-01-25 23:51:57 +00:00
|
|
|
double minimum = GetMinimum();
|
2012-07-05 14:33:47 +00:00
|
|
|
|
2013-01-25 23:51:57 +00:00
|
|
|
double maximum = GetMaximum();
|
|
|
|
if (!MOZ_DOUBLE_IS_NaN(maximum)) {
|
2012-07-06 12:40:18 +00:00
|
|
|
// "max - (max - stepBase) % step" is the nearest valid value to max.
|
2013-01-25 23:51:57 +00:00
|
|
|
maximum = maximum - NS_floorModulo(maximum - GetStepBase(), step);
|
2012-07-05 14:33:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Cases where we are clearly going in the wrong way.
|
|
|
|
// We don't use ValidityState because we can be higher than the maximal
|
|
|
|
// allowed value and still not suffer from range overflow in the case of
|
|
|
|
// of the value specified in @max isn't in the step.
|
2013-01-25 23:51:57 +00:00
|
|
|
if ((value <= minimum && aStep < 0) ||
|
|
|
|
(value >= maximum && aStep > 0)) {
|
2012-07-05 14:33:47 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (GetValidityState(VALIDITY_STATE_STEP_MISMATCH) &&
|
2013-01-25 23:51:57 +00:00
|
|
|
value != minimum && value != maximum) {
|
2012-07-05 14:33:47 +00:00
|
|
|
if (aStep > 0) {
|
|
|
|
value -= NS_floorModulo(value - GetStepBase(), step);
|
|
|
|
} else if (aStep < 0) {
|
|
|
|
value -= NS_floorModulo(value - GetStepBase(), step);
|
|
|
|
value += step;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
value += aStep * step;
|
|
|
|
|
2012-12-22 14:46:19 +00:00
|
|
|
// For date inputs, the value can hold a string that is not a day. We do not
|
|
|
|
// want to round it, as it might result in a step mismatch. Instead we want to
|
|
|
|
// clamp to the next valid value.
|
|
|
|
if (mType == NS_FORM_INPUT_DATE &&
|
|
|
|
NS_floorModulo(value - GetStepBase(), GetStepScaleFactor()) != 0) {
|
|
|
|
double validStep = EuclidLCM<uint64_t>(static_cast<uint64_t>(step),
|
|
|
|
static_cast<uint64_t>(GetStepScaleFactor()));
|
|
|
|
if (aStep > 0) {
|
|
|
|
value -= NS_floorModulo(value - GetStepBase(), validStep);
|
|
|
|
value += validStep;
|
|
|
|
} else if (aStep < 0) {
|
|
|
|
value -= NS_floorModulo(value - GetStepBase(), validStep);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-01-25 23:51:57 +00:00
|
|
|
// When stepUp() is called and the value is below minimum, we should clamp on
|
|
|
|
// minimum unless stepUp() moves us higher than minimum.
|
2012-07-05 14:33:47 +00:00
|
|
|
if (GetValidityState(VALIDITY_STATE_RANGE_UNDERFLOW) && aStep > 0 &&
|
2013-01-25 23:51:57 +00:00
|
|
|
value <= minimum) {
|
|
|
|
MOZ_ASSERT(!MOZ_DOUBLE_IS_NaN(minimum), "Can't be NaN if we are here");
|
|
|
|
value = minimum;
|
|
|
|
// Same goes for stepDown() and maximum.
|
2012-07-05 14:33:47 +00:00
|
|
|
} else if (GetValidityState(VALIDITY_STATE_RANGE_OVERFLOW) && aStep < 0 &&
|
2013-01-25 23:51:57 +00:00
|
|
|
value >= maximum) {
|
|
|
|
MOZ_ASSERT(!MOZ_DOUBLE_IS_NaN(maximum), "Can't be NaN if we are here");
|
|
|
|
value = maximum;
|
2012-07-05 14:33:47 +00:00
|
|
|
// If we go down, we want to clamp on min.
|
2013-01-25 23:51:57 +00:00
|
|
|
} else if (aStep < 0 && minimum == minimum) {
|
|
|
|
value = std::max(value, minimum);
|
2012-07-05 14:33:47 +00:00
|
|
|
// If we go up, we want to clamp on max.
|
2013-01-25 23:51:57 +00:00
|
|
|
} else if (aStep > 0 && maximum == maximum) {
|
|
|
|
value = std::min(value, maximum);
|
2012-07-05 14:33:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
SetValue(value);
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::StepDown(int32_t n, uint8_t optional_argc)
|
2012-07-05 14:33:47 +00:00
|
|
|
{
|
|
|
|
return ApplyStep(optional_argc ? -n : -1);
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::StepUp(int32_t n, uint8_t optional_argc)
|
2012-07-05 14:33:47 +00:00
|
|
|
{
|
|
|
|
return ApplyStep(optional_argc ? n : 1);
|
|
|
|
}
|
|
|
|
|
2013-03-28 19:41:32 +00:00
|
|
|
void
|
|
|
|
HTMLInputElement::MozGetFileNameArray(nsTArray< nsString >& aArray)
|
|
|
|
{
|
|
|
|
for (int32_t i = 0; i < mFiles.Count(); i++) {
|
|
|
|
nsString str;
|
|
|
|
mFiles[i]->GetMozFullPathInternal(str);
|
|
|
|
aArray.AppendElement(str);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
HTMLInputElement::MozGetFileNameArray(uint32_t* aLength, PRUnichar*** aFileNames)
|
2009-10-25 04:13:30 +00:00
|
|
|
{
|
2012-10-25 23:10:53 +00:00
|
|
|
if (!nsContentUtils::IsCallerChrome()) {
|
2009-10-25 04:13:30 +00:00
|
|
|
// Since this function returns full paths it's important that normal pages
|
|
|
|
// can't call it.
|
|
|
|
return NS_ERROR_DOM_SECURITY_ERR;
|
|
|
|
}
|
|
|
|
|
2013-03-28 19:41:32 +00:00
|
|
|
nsTArray<nsString> array;
|
|
|
|
MozGetFileNameArray(array);
|
|
|
|
|
|
|
|
*aLength = array.Length();
|
|
|
|
PRUnichar** ret =
|
|
|
|
static_cast<PRUnichar**>(NS_Alloc(*aLength * sizeof(PRUnichar*)));
|
2011-11-16 07:50:19 +00:00
|
|
|
if (!ret) {
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
}
|
|
|
|
|
2013-03-28 19:41:32 +00:00
|
|
|
for (uint32_t i = 0; i < *aLength; ++i) {
|
|
|
|
ret[i] = NS_strdup(array[i].get());
|
2009-10-25 04:13:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
*aFileNames = ret;
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2013-03-28 19:41:32 +00:00
|
|
|
void
|
|
|
|
HTMLInputElement::MozSetFileNameArray(const Sequence< nsString >& aFileNames)
|
2009-10-25 04:13:30 +00:00
|
|
|
{
|
2010-09-05 18:00:05 +00:00
|
|
|
nsCOMArray<nsIDOMFile> files;
|
2013-03-28 19:41:32 +00:00
|
|
|
for (uint32_t i = 0; i < aFileNames.Length(); ++i) {
|
2010-09-05 18:00:05 +00:00
|
|
|
nsCOMPtr<nsIFile> file;
|
2013-03-28 19:41:32 +00:00
|
|
|
|
|
|
|
if (StringBeginsWith(aFileNames[i], NS_LITERAL_STRING("file:"),
|
2010-09-05 18:00:05 +00:00
|
|
|
nsASCIICaseInsensitiveStringComparator())) {
|
|
|
|
// Converts the URL string into the corresponding nsIFile if possible
|
|
|
|
// A local file will be created if the URL string begins with file://
|
|
|
|
NS_GetFileFromURLSpec(NS_ConvertUTF16toUTF8(aFileNames[i]),
|
|
|
|
getter_AddRefs(file));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!file) {
|
|
|
|
// this is no "file://", try as local file
|
2013-03-28 19:41:32 +00:00
|
|
|
NS_NewLocalFile(aFileNames[i], false, getter_AddRefs(file));
|
2010-09-05 18:00:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (file) {
|
2011-07-12 02:41:29 +00:00
|
|
|
nsCOMPtr<nsIDOMFile> domFile = new nsDOMFileFile(file);
|
2010-09-05 18:00:05 +00:00
|
|
|
files.AppendObject(domFile);
|
|
|
|
} else {
|
|
|
|
continue; // Not much we can do if the file doesn't exist
|
|
|
|
}
|
|
|
|
|
2009-10-25 04:13:30 +00:00
|
|
|
}
|
|
|
|
|
2010-11-23 23:45:53 +00:00
|
|
|
SetFiles(files, true);
|
2013-03-28 19:41:32 +00:00
|
|
|
}
|
2009-10-25 04:13:30 +00:00
|
|
|
|
2013-03-28 19:41:32 +00:00
|
|
|
NS_IMETHODIMP
|
|
|
|
HTMLInputElement::MozSetFileNameArray(const PRUnichar** aFileNames, uint32_t aLength)
|
|
|
|
{
|
|
|
|
if (!nsContentUtils::IsCallerChrome()) {
|
|
|
|
// setting the value of a "FILE" input widget requires chrome privilege
|
|
|
|
return NS_ERROR_DOM_SECURITY_ERR;
|
|
|
|
}
|
|
|
|
|
|
|
|
Sequence<nsString> list;
|
|
|
|
for (uint32_t i = 0; i < aLength; ++i) {
|
|
|
|
list.AppendElement(nsDependentString(aFileNames[i]));
|
|
|
|
}
|
|
|
|
|
|
|
|
MozSetFileNameArray(list);
|
2009-10-25 04:13:30 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2013-03-28 19:41:32 +00:00
|
|
|
bool
|
|
|
|
HTMLInputElement::MozIsTextField(bool aExcludePassword)
|
2010-05-12 07:17:07 +00:00
|
|
|
{
|
2012-12-27 16:06:53 +00:00
|
|
|
// TODO: temporary until bug 635240 and 773205 are fixed.
|
2013-01-31 23:01:50 +00:00
|
|
|
if (IsExperimentalMobileType(mType)) {
|
2013-03-28 19:41:32 +00:00
|
|
|
return false;
|
2012-06-10 20:23:17 +00:00
|
|
|
}
|
|
|
|
|
2013-03-28 19:41:32 +00:00
|
|
|
return IsSingleLineTextControl(aExcludePassword);
|
|
|
|
}
|
2010-05-12 07:17:07 +00:00
|
|
|
|
2013-03-28 19:41:32 +00:00
|
|
|
NS_IMETHODIMP
|
|
|
|
HTMLInputElement::MozIsTextField(bool aExcludePassword, bool* aResult)
|
|
|
|
{
|
|
|
|
*aResult = MozIsTextField(aExcludePassword);
|
2010-05-12 07:17:07 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2013-03-28 19:41:32 +00:00
|
|
|
NS_IMETHODIMP
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::SetUserInput(const nsAString& aValue)
|
2007-10-02 16:56:07 +00:00
|
|
|
{
|
2012-10-25 23:10:54 +00:00
|
|
|
if (!nsContentUtils::IsCallerChrome()) {
|
2007-10-02 16:56:07 +00:00
|
|
|
return NS_ERROR_DOM_SECURITY_ERR;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mType == NS_FORM_INPUT_FILE)
|
|
|
|
{
|
2013-03-28 19:41:32 +00:00
|
|
|
Sequence<nsString> list;
|
|
|
|
list.AppendElement(aValue);
|
|
|
|
MozSetFileNameArray(list);
|
|
|
|
return NS_OK;
|
2007-10-02 16:56:07 +00:00
|
|
|
} else {
|
2011-10-17 14:59:28 +00:00
|
|
|
SetValueInternal(aValue, true, true);
|
2007-10-02 16:56:07 +00:00
|
|
|
}
|
2011-01-21 23:06:27 +00:00
|
|
|
|
2011-10-18 10:53:36 +00:00
|
|
|
return nsContentUtils::DispatchTrustedEvent(OwnerDoc(),
|
2011-01-21 23:06:27 +00:00
|
|
|
static_cast<nsIDOMHTMLInputElement*>(this),
|
2011-10-17 14:59:28 +00:00
|
|
|
NS_LITERAL_STRING("input"), true,
|
|
|
|
true);
|
2007-10-02 16:56:07 +00:00
|
|
|
}
|
|
|
|
|
2013-03-28 19:41:32 +00:00
|
|
|
nsIEditor*
|
|
|
|
HTMLInputElement::GetEditor()
|
2010-04-21 20:17:41 +00:00
|
|
|
{
|
2013-03-28 19:41:32 +00:00
|
|
|
nsTextEditorState* state = GetEditorState();
|
2010-04-21 20:17:41 +00:00
|
|
|
if (state) {
|
|
|
|
return state->GetEditor();
|
2010-06-05 20:17:42 +00:00
|
|
|
}
|
2012-07-30 14:20:58 +00:00
|
|
|
return nullptr;
|
2010-04-21 20:17:41 +00:00
|
|
|
}
|
|
|
|
|
2013-03-28 19:41:32 +00:00
|
|
|
NS_IMETHODIMP_(nsIEditor*)
|
|
|
|
HTMLInputElement::GetTextEditor()
|
|
|
|
{
|
|
|
|
return GetEditor();
|
|
|
|
}
|
|
|
|
|
2010-04-21 20:17:41 +00:00
|
|
|
NS_IMETHODIMP_(nsISelectionController*)
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::GetSelectionController()
|
2010-04-21 20:17:41 +00:00
|
|
|
{
|
2013-03-28 19:41:32 +00:00
|
|
|
nsTextEditorState* state = GetEditorState();
|
2010-04-21 20:17:41 +00:00
|
|
|
if (state) {
|
|
|
|
return state->GetSelectionController();
|
2010-06-05 20:17:42 +00:00
|
|
|
}
|
2012-07-30 14:20:58 +00:00
|
|
|
return nullptr;
|
2010-04-21 20:17:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
nsFrameSelection*
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::GetConstFrameSelection()
|
2010-04-21 20:17:41 +00:00
|
|
|
{
|
2013-03-28 19:41:32 +00:00
|
|
|
nsTextEditorState* state = GetEditorState();
|
2010-04-21 20:17:41 +00:00
|
|
|
if (state) {
|
|
|
|
return state->GetConstFrameSelection();
|
2010-06-05 20:17:42 +00:00
|
|
|
}
|
2012-07-30 14:20:58 +00:00
|
|
|
return nullptr;
|
2010-04-21 20:17:41 +00:00
|
|
|
}
|
|
|
|
|
2001-11-19 10:35:52 +00:00
|
|
|
NS_IMETHODIMP
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::BindToFrame(nsTextControlFrame* aFrame)
|
2001-11-19 10:35:52 +00:00
|
|
|
{
|
2013-03-28 19:41:32 +00:00
|
|
|
nsTextEditorState* state = GetEditorState();
|
2010-04-21 20:17:41 +00:00
|
|
|
if (state) {
|
|
|
|
return state->BindToFrame(aFrame);
|
2010-06-05 20:17:42 +00:00
|
|
|
}
|
2010-04-21 20:17:41 +00:00
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP_(void)
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::UnbindFromFrame(nsTextControlFrame* aFrame)
|
2010-04-21 20:17:41 +00:00
|
|
|
{
|
2013-03-28 19:41:32 +00:00
|
|
|
nsTextEditorState* state = GetEditorState();
|
2010-07-22 00:59:25 +00:00
|
|
|
if (state && aFrame) {
|
2010-04-21 20:17:41 +00:00
|
|
|
state->UnbindFromFrame(aFrame);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::CreateEditor()
|
2010-04-21 20:17:41 +00:00
|
|
|
{
|
2013-03-28 19:41:32 +00:00
|
|
|
nsTextEditorState* state = GetEditorState();
|
2010-04-21 20:17:41 +00:00
|
|
|
if (state) {
|
|
|
|
return state->PrepareEditor();
|
2010-06-05 20:17:42 +00:00
|
|
|
}
|
2010-04-21 20:17:41 +00:00
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP_(nsIContent*)
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::GetRootEditorNode()
|
2010-04-21 20:17:41 +00:00
|
|
|
{
|
2013-03-28 19:41:32 +00:00
|
|
|
nsTextEditorState* state = GetEditorState();
|
2010-04-21 20:17:41 +00:00
|
|
|
if (state) {
|
|
|
|
return state->GetRootNode();
|
2010-06-05 20:17:42 +00:00
|
|
|
}
|
2012-07-30 14:20:58 +00:00
|
|
|
return nullptr;
|
2010-04-21 20:17:41 +00:00
|
|
|
}
|
|
|
|
|
2010-10-19 13:11:07 +00:00
|
|
|
NS_IMETHODIMP_(nsIContent*)
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::CreatePlaceholderNode()
|
2010-10-19 13:11:07 +00:00
|
|
|
{
|
2013-03-28 19:41:32 +00:00
|
|
|
nsTextEditorState* state = GetEditorState();
|
2010-10-19 13:11:07 +00:00
|
|
|
if (state) {
|
2012-07-30 14:20:58 +00:00
|
|
|
NS_ENSURE_SUCCESS(state->CreatePlaceholderNode(), nullptr);
|
2010-10-19 13:11:07 +00:00
|
|
|
return state->GetPlaceholderNode();
|
|
|
|
}
|
2012-07-30 14:20:58 +00:00
|
|
|
return nullptr;
|
2010-10-19 13:11:07 +00:00
|
|
|
}
|
|
|
|
|
2010-04-21 20:17:41 +00:00
|
|
|
NS_IMETHODIMP_(nsIContent*)
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::GetPlaceholderNode()
|
2010-04-21 20:17:41 +00:00
|
|
|
{
|
2013-03-28 19:41:32 +00:00
|
|
|
nsTextEditorState* state = GetEditorState();
|
2010-04-21 20:17:41 +00:00
|
|
|
if (state) {
|
|
|
|
return state->GetPlaceholderNode();
|
2010-06-05 20:17:42 +00:00
|
|
|
}
|
2012-07-30 14:20:58 +00:00
|
|
|
return nullptr;
|
2010-04-21 20:17:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP_(void)
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::UpdatePlaceholderVisibility(bool aNotify)
|
2010-04-21 20:17:41 +00:00
|
|
|
{
|
2013-03-28 19:41:32 +00:00
|
|
|
nsTextEditorState* state = GetEditorState();
|
2010-04-21 20:17:41 +00:00
|
|
|
if (state) {
|
2012-11-09 10:31:34 +00:00
|
|
|
state->UpdatePlaceholderVisibility(aNotify);
|
2002-12-16 23:49:16 +00:00
|
|
|
}
|
2001-11-19 10:35:52 +00:00
|
|
|
}
|
|
|
|
|
2012-11-09 10:22:29 +00:00
|
|
|
NS_IMETHODIMP_(bool)
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::GetPlaceholderVisibility()
|
2012-11-09 10:22:29 +00:00
|
|
|
{
|
|
|
|
nsTextEditorState* state = GetEditorState();
|
|
|
|
if (!state) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return state->GetPlaceholderVisibility();
|
|
|
|
}
|
|
|
|
|
2006-04-25 09:18:42 +00:00
|
|
|
void
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::GetDisplayFileName(nsAString& aValue) const
|
2006-04-25 09:18:42 +00:00
|
|
|
{
|
2011-10-18 10:53:36 +00:00
|
|
|
if (OwnerDoc()->IsStaticDocument()) {
|
2010-09-05 18:00:05 +00:00
|
|
|
aValue = mStaticDocFileList;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-02-07 13:58:05 +00:00
|
|
|
if (mFiles.Count() == 1) {
|
|
|
|
mFiles[0]->GetName(aValue);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsXPIDLString value;
|
|
|
|
|
|
|
|
if (mFiles.Count() == 0) {
|
|
|
|
if (HasAttr(kNameSpaceID_None, nsGkAtoms::multiple)) {
|
|
|
|
nsContentUtils::GetLocalizedString(nsContentUtils::eFORMS_PROPERTIES,
|
|
|
|
"NoFilesSelected", value);
|
|
|
|
} else {
|
|
|
|
nsContentUtils::GetLocalizedString(nsContentUtils::eFORMS_PROPERTIES,
|
|
|
|
"NoFileSelected", value);
|
2009-10-25 04:13:30 +00:00
|
|
|
}
|
2013-02-07 13:58:05 +00:00
|
|
|
} else {
|
|
|
|
nsString count;
|
|
|
|
count.AppendInt(mFiles.Count());
|
|
|
|
|
|
|
|
const PRUnichar* params[] = { count.get() };
|
|
|
|
nsContentUtils::FormatLocalizedString(nsContentUtils::eFORMS_PROPERTIES,
|
|
|
|
"XFilesSelected", params, value);
|
2006-04-25 09:18:42 +00:00
|
|
|
}
|
2013-02-07 13:58:05 +00:00
|
|
|
|
|
|
|
aValue = value;
|
2006-04-25 09:18:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::SetFiles(const nsCOMArray<nsIDOMFile>& aFiles,
|
|
|
|
bool aSetValueChanged)
|
2006-04-25 09:18:42 +00:00
|
|
|
{
|
2010-09-05 18:00:05 +00:00
|
|
|
mFiles.Clear();
|
|
|
|
mFiles.AppendObjects(aFiles);
|
|
|
|
|
2011-06-01 06:06:38 +00:00
|
|
|
AfterSetFiles(aSetValueChanged);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::SetFiles(nsIDOMFileList* aFiles,
|
|
|
|
bool aSetValueChanged)
|
2011-06-01 06:06:38 +00:00
|
|
|
{
|
|
|
|
mFiles.Clear();
|
|
|
|
|
|
|
|
if (aFiles) {
|
2012-08-22 15:56:38 +00:00
|
|
|
uint32_t listLength;
|
2011-06-01 06:06:38 +00:00
|
|
|
aFiles->GetLength(&listLength);
|
2012-08-22 15:56:38 +00:00
|
|
|
for (uint32_t i = 0; i < listLength; i++) {
|
2011-06-01 06:06:38 +00:00
|
|
|
nsCOMPtr<nsIDOMFile> file;
|
|
|
|
aFiles->Item(i, getter_AddRefs(file));
|
|
|
|
mFiles.AppendObject(file);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
AfterSetFiles(aSetValueChanged);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::AfterSetFiles(bool aSetValueChanged)
|
2011-06-01 06:06:38 +00:00
|
|
|
{
|
2007-07-14 04:46:09 +00:00
|
|
|
// No need to flush here, if there's no frame at this point we
|
|
|
|
// don't need to force creation of one just to tell it about this
|
|
|
|
// new value. We just want the display to update as needed.
|
2011-10-17 14:59:28 +00:00
|
|
|
nsIFormControlFrame* formControlFrame = GetFormControlFrame(false);
|
2007-07-14 04:46:09 +00:00
|
|
|
if (formControlFrame) {
|
2009-10-25 04:13:30 +00:00
|
|
|
nsAutoString readableValue;
|
|
|
|
GetDisplayFileName(readableValue);
|
|
|
|
formControlFrame->SetFormProperty(nsGkAtoms::value, readableValue);
|
2007-07-14 04:46:09 +00:00
|
|
|
}
|
2007-07-25 04:29:47 +00:00
|
|
|
|
|
|
|
UpdateFileList();
|
2010-08-21 17:52:57 +00:00
|
|
|
|
2010-11-23 23:45:53 +00:00
|
|
|
if (aSetValueChanged) {
|
2011-10-17 14:59:28 +00:00
|
|
|
SetValueChanged(true);
|
2010-11-23 23:45:53 +00:00
|
|
|
}
|
|
|
|
|
2011-10-17 14:59:28 +00:00
|
|
|
UpdateAllValidityStates(true);
|
2006-04-25 09:18:42 +00:00
|
|
|
}
|
|
|
|
|
2012-05-24 13:12:19 +00:00
|
|
|
void
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::FireChangeEventIfNeeded()
|
2012-05-24 13:12:19 +00:00
|
|
|
{
|
|
|
|
nsString value;
|
|
|
|
GetValueInternal(value);
|
|
|
|
|
2013-03-16 05:49:41 +00:00
|
|
|
if (!MayFireChangeOnBlur() || mFocusedValue.Equals(value)) {
|
2012-05-24 13:12:19 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Dispatch the change event.
|
|
|
|
mFocusedValue = value;
|
|
|
|
nsContentUtils::DispatchTrustedEvent(OwnerDoc(),
|
2013-03-28 19:41:32 +00:00
|
|
|
static_cast<nsIContent*>(this),
|
2012-05-24 13:12:19 +00:00
|
|
|
NS_LITERAL_STRING("change"), true,
|
|
|
|
false);
|
2012-05-07 16:27:24 +00:00
|
|
|
}
|
|
|
|
|
2013-03-28 19:41:32 +00:00
|
|
|
nsDOMFileList*
|
|
|
|
HTMLInputElement::GetFiles()
|
2007-07-25 04:29:47 +00:00
|
|
|
{
|
2013-03-28 19:41:32 +00:00
|
|
|
if (mType != NS_FORM_INPUT_FILE) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!mFileList) {
|
|
|
|
mFileList = new nsDOMFileList(static_cast<nsIContent*>(this));
|
|
|
|
UpdateFileList();
|
|
|
|
}
|
|
|
|
|
|
|
|
return mFileList;
|
2007-07-25 04:29:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::UpdateFileList()
|
2007-07-25 04:29:47 +00:00
|
|
|
{
|
|
|
|
if (mFileList) {
|
|
|
|
mFileList->Clear();
|
|
|
|
|
2013-03-28 19:41:32 +00:00
|
|
|
const nsCOMArray<nsIDOMFile>& files = GetFilesInternal();
|
2012-08-22 15:56:38 +00:00
|
|
|
for (int32_t i = 0; i < files.Count(); ++i) {
|
2010-09-05 18:00:05 +00:00
|
|
|
if (!mFileList->Append(files[i])) {
|
|
|
|
return NS_ERROR_FAILURE;
|
2007-07-25 04:29:47 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2002-12-16 23:49:16 +00:00
|
|
|
nsresult
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::SetValueInternal(const nsAString& aValue,
|
|
|
|
bool aUserInput,
|
|
|
|
bool aSetValueChanged)
|
1998-10-30 20:41:01 +00:00
|
|
|
{
|
2011-06-22 10:41:00 +00:00
|
|
|
NS_PRECONDITION(GetValueMode() != VALUE_MODE_FILENAME,
|
2006-04-25 09:18:42 +00:00
|
|
|
"Don't call SetValueInternal for file inputs");
|
|
|
|
|
2011-06-22 10:41:00 +00:00
|
|
|
switch (GetValueMode()) {
|
|
|
|
case VALUE_MODE_VALUE:
|
|
|
|
{
|
|
|
|
// At the moment, only single line text control have to sanitize their value
|
|
|
|
// Because we have to create a new string for that, we should prevent doing
|
|
|
|
// it if it's useless.
|
|
|
|
nsAutoString value(aValue);
|
2010-07-21 00:11:19 +00:00
|
|
|
|
2011-11-16 07:50:19 +00:00
|
|
|
if (!mParserCreating) {
|
2011-06-22 10:41:00 +00:00
|
|
|
SanitizeValue(value);
|
|
|
|
}
|
2010-07-21 00:11:19 +00:00
|
|
|
|
2011-06-22 10:41:00 +00:00
|
|
|
if (aSetValueChanged) {
|
2011-10-17 14:59:28 +00:00
|
|
|
SetValueChanged(true);
|
2011-06-22 10:41:00 +00:00
|
|
|
}
|
|
|
|
|
2013-02-12 20:16:58 +00:00
|
|
|
if (IsSingleLineTextControl(false)) {
|
|
|
|
mInputData.mState->SetValue(value, aUserInput, aSetValueChanged);
|
|
|
|
} else {
|
|
|
|
mInputData.mValue = ToNewUnicode(value);
|
|
|
|
if (aSetValueChanged) {
|
|
|
|
SetValueChanged(true);
|
|
|
|
}
|
|
|
|
OnValueChanged(!mParserCreating);
|
|
|
|
}
|
2011-06-22 10:41:00 +00:00
|
|
|
|
|
|
|
return NS_OK;
|
2010-08-25 04:39:10 +00:00
|
|
|
}
|
|
|
|
|
2011-06-22 10:41:00 +00:00
|
|
|
case VALUE_MODE_DEFAULT:
|
|
|
|
case VALUE_MODE_DEFAULT_ON:
|
|
|
|
// If the value of a hidden input was changed, we mark it changed so that we
|
|
|
|
// will know we need to save / restore the value. Yes, we are overloading
|
|
|
|
// the meaning of ValueChanged just a teensy bit to save a measly byte of
|
2013-03-28 19:41:32 +00:00
|
|
|
// storage space in HTMLInputElement. Yes, you are free to make a new flag,
|
2011-06-22 10:41:00 +00:00
|
|
|
// NEED_TO_SAVE_VALUE, at such time as mBitField becomes a 16-bit value.
|
|
|
|
if (mType == NS_FORM_INPUT_HIDDEN) {
|
2011-10-17 14:59:28 +00:00
|
|
|
SetValueChanged(true);
|
2011-06-22 10:41:00 +00:00
|
|
|
}
|
2002-06-12 06:35:11 +00:00
|
|
|
|
2011-06-22 10:41:00 +00:00
|
|
|
// Treat value == defaultValue for other input elements.
|
|
|
|
return nsGenericHTMLFormElement::SetAttr(kNameSpaceID_None,
|
|
|
|
nsGkAtoms::value, aValue,
|
2011-10-17 14:59:28 +00:00
|
|
|
true);
|
2011-06-22 10:41:00 +00:00
|
|
|
|
|
|
|
case VALUE_MODE_FILENAME:
|
|
|
|
return NS_ERROR_UNEXPECTED;
|
1999-03-03 02:54:25 +00:00
|
|
|
}
|
2000-01-14 09:28:54 +00:00
|
|
|
|
2011-06-22 10:41:00 +00:00
|
|
|
// This return statement is required for some compilers.
|
|
|
|
return NS_OK;
|
1998-10-30 20:41:01 +00:00
|
|
|
}
|
|
|
|
|
2001-11-05 06:50:21 +00:00
|
|
|
NS_IMETHODIMP
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::SetValueChanged(bool aValueChanged)
|
2001-11-05 06:50:21 +00:00
|
|
|
{
|
2011-11-16 07:50:19 +00:00
|
|
|
bool valueChangedBefore = mValueChanged;
|
2010-11-23 23:49:50 +00:00
|
|
|
|
2011-11-16 07:50:19 +00:00
|
|
|
mValueChanged = aValueChanged;
|
2010-11-23 23:49:50 +00:00
|
|
|
|
|
|
|
if (valueChangedBefore != aValueChanged) {
|
2011-06-01 01:46:57 +00:00
|
|
|
UpdateState(true);
|
2010-11-23 23:49:50 +00:00
|
|
|
}
|
|
|
|
|
2001-11-05 06:50:21 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2013-03-28 19:41:32 +00:00
|
|
|
NS_IMETHODIMP
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::GetChecked(bool* aChecked)
|
1998-10-30 20:41:01 +00:00
|
|
|
{
|
2012-06-03 11:36:51 +00:00
|
|
|
*aChecked = Checked();
|
2002-01-24 19:04:55 +00:00
|
|
|
return NS_OK;
|
1998-10-30 20:41:01 +00:00
|
|
|
}
|
|
|
|
|
2010-07-14 06:39:48 +00:00
|
|
|
void
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::SetCheckedChanged(bool aCheckedChanged)
|
2006-02-08 05:56:13 +00:00
|
|
|
{
|
2011-10-17 14:59:28 +00:00
|
|
|
DoSetCheckedChanged(aCheckedChanged, true);
|
2006-02-08 05:56:13 +00:00
|
|
|
}
|
|
|
|
|
2010-07-14 06:39:48 +00:00
|
|
|
void
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::DoSetCheckedChanged(bool aCheckedChanged,
|
|
|
|
bool aNotify)
|
2002-03-07 20:53:40 +00:00
|
|
|
{
|
|
|
|
if (mType == NS_FORM_INPUT_RADIO) {
|
2011-11-16 07:50:19 +00:00
|
|
|
if (mCheckedChanged != aCheckedChanged) {
|
2011-04-11 18:31:00 +00:00
|
|
|
nsCOMPtr<nsIRadioVisitor> visitor =
|
|
|
|
new nsRadioSetCheckedChangedVisitor(aCheckedChanged);
|
2006-02-08 05:56:13 +00:00
|
|
|
VisitGroup(visitor, aNotify);
|
2002-03-07 20:53:40 +00:00
|
|
|
}
|
|
|
|
} else {
|
2010-11-23 23:53:39 +00:00
|
|
|
SetCheckedChangedInternal(aCheckedChanged);
|
2002-03-07 20:53:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-07-14 06:39:48 +00:00
|
|
|
void
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::SetCheckedChangedInternal(bool aCheckedChanged)
|
2002-03-07 20:53:40 +00:00
|
|
|
{
|
2011-11-16 07:50:19 +00:00
|
|
|
bool checkedChangedBefore = mCheckedChanged;
|
2010-11-23 23:49:50 +00:00
|
|
|
|
2011-11-16 07:50:19 +00:00
|
|
|
mCheckedChanged = aCheckedChanged;
|
2010-11-23 23:49:50 +00:00
|
|
|
|
2010-11-23 23:53:39 +00:00
|
|
|
// This method can't be called when we are not authorized to notify
|
|
|
|
// so we do not need a aNotify parameter.
|
|
|
|
if (checkedChangedBefore != aCheckedChanged) {
|
2011-06-01 01:46:57 +00:00
|
|
|
UpdateState(true);
|
2010-11-23 23:49:50 +00:00
|
|
|
}
|
2002-03-07 20:53:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::SetChecked(bool aChecked)
|
2004-01-21 04:28:57 +00:00
|
|
|
{
|
2012-08-03 10:38:52 +00:00
|
|
|
DoSetChecked(aChecked, true, true);
|
|
|
|
return NS_OK;
|
2004-01-21 04:28:57 +00:00
|
|
|
}
|
|
|
|
|
2012-08-03 10:38:52 +00:00
|
|
|
void
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::DoSetChecked(bool aChecked, bool aNotify,
|
|
|
|
bool aSetValueChanged)
|
2002-03-07 20:53:40 +00:00
|
|
|
{
|
|
|
|
// If the user or JS attempts to set checked, whether it actually changes the
|
|
|
|
// value or not, we say the value was changed so that defaultValue don't
|
|
|
|
// affect it no more.
|
2010-07-22 18:27:33 +00:00
|
|
|
if (aSetValueChanged) {
|
2011-10-17 14:59:28 +00:00
|
|
|
DoSetCheckedChanged(true, aNotify);
|
2010-07-22 18:27:33 +00:00
|
|
|
}
|
2002-03-07 20:53:40 +00:00
|
|
|
|
|
|
|
// Don't do anything if we're not changing whether it's checked (it would
|
|
|
|
// screw up state actually, especially when you are setting radio button to
|
|
|
|
// false)
|
2011-11-16 07:50:19 +00:00
|
|
|
if (mChecked == aChecked) {
|
2012-08-03 10:38:52 +00:00
|
|
|
return;
|
2002-03-07 20:53:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Set checked
|
2011-11-16 07:50:19 +00:00
|
|
|
if (mType != NS_FORM_INPUT_RADIO) {
|
2010-08-21 17:52:57 +00:00
|
|
|
SetCheckedInternal(aChecked, aNotify);
|
2012-08-03 10:38:52 +00:00
|
|
|
return;
|
2002-03-07 20:53:40 +00:00
|
|
|
}
|
|
|
|
|
2011-11-16 07:50:19 +00:00
|
|
|
// For radio button, we need to do some extra fun stuff
|
|
|
|
if (aChecked) {
|
2012-08-03 10:38:52 +00:00
|
|
|
RadioSetChecked(aNotify);
|
|
|
|
return;
|
2011-11-16 07:50:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
nsIRadioGroupContainer* container = GetRadioGroupContainer();
|
|
|
|
if (container) {
|
|
|
|
nsAutoString name;
|
|
|
|
GetAttr(kNameSpaceID_None, nsGkAtoms::name, name);
|
2012-07-30 14:20:58 +00:00
|
|
|
container->SetCurrentRadioButton(name, nullptr);
|
2011-11-16 07:50:19 +00:00
|
|
|
}
|
|
|
|
// SetCheckedInternal is going to ask all radios to update their
|
|
|
|
// validity state. We have to be sure the radio group container knows
|
|
|
|
// the currently selected radio.
|
|
|
|
SetCheckedInternal(false, aNotify);
|
2002-03-07 20:53:40 +00:00
|
|
|
}
|
|
|
|
|
2012-08-03 10:38:52 +00:00
|
|
|
void
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::RadioSetChecked(bool aNotify)
|
1998-10-30 20:41:01 +00:00
|
|
|
{
|
2002-03-07 20:53:40 +00:00
|
|
|
// Find the selected radio button so we can deselect it
|
2010-08-18 18:30:41 +00:00
|
|
|
nsCOMPtr<nsIDOMHTMLInputElement> currentlySelected = GetSelectedRadioButton();
|
2002-03-07 20:53:40 +00:00
|
|
|
|
|
|
|
// Deselect the currently selected radio button
|
|
|
|
if (currentlySelected) {
|
2011-10-17 14:59:28 +00:00
|
|
|
// Pass true for the aNotify parameter since the currently selected
|
2004-01-21 04:28:57 +00:00
|
|
|
// button is already in the document.
|
2013-03-28 19:41:32 +00:00
|
|
|
static_cast<HTMLInputElement*>(currentlySelected.get())
|
2011-11-16 07:50:19 +00:00
|
|
|
->SetCheckedInternal(false, true);
|
2002-03-07 20:53:40 +00:00
|
|
|
}
|
|
|
|
|
2002-07-20 23:09:24 +00:00
|
|
|
// Let the group know that we are now the One True Radio Button
|
2011-05-04 12:49:59 +00:00
|
|
|
nsIRadioGroupContainer* container = GetRadioGroupContainer();
|
|
|
|
if (container) {
|
|
|
|
nsAutoString name;
|
|
|
|
GetAttr(kNameSpaceID_None, nsGkAtoms::name, name);
|
2012-08-03 10:38:52 +00:00
|
|
|
container->SetCurrentRadioButton(name, this);
|
2002-03-07 20:53:40 +00:00
|
|
|
}
|
|
|
|
|
2010-08-21 17:52:57 +00:00
|
|
|
// SetCheckedInternal is going to ask all radios to update their
|
2013-03-28 19:41:32 +00:00
|
|
|
// validity state.
|
2012-08-03 10:38:52 +00:00
|
|
|
SetCheckedInternal(true, aNotify);
|
2002-03-07 20:53:40 +00:00
|
|
|
}
|
|
|
|
|
2011-05-04 12:49:59 +00:00
|
|
|
nsIRadioGroupContainer*
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::GetRadioGroupContainer() const
|
2002-07-20 23:09:24 +00:00
|
|
|
{
|
2011-05-04 12:49:59 +00:00
|
|
|
NS_ASSERTION(mType == NS_FORM_INPUT_RADIO,
|
|
|
|
"GetRadioGroupContainer should only be called when type='radio'");
|
|
|
|
|
|
|
|
nsAutoString name;
|
|
|
|
GetAttr(kNameSpaceID_None, nsGkAtoms::name, name);
|
|
|
|
|
|
|
|
if (name.IsEmpty()) {
|
2012-07-30 14:20:58 +00:00
|
|
|
return nullptr;
|
2011-05-04 12:49:59 +00:00
|
|
|
}
|
|
|
|
|
2002-07-20 23:09:24 +00:00
|
|
|
if (mForm) {
|
2011-05-04 12:49:59 +00:00
|
|
|
return mForm;
|
2002-07-20 23:09:24 +00:00
|
|
|
}
|
2011-05-04 12:49:59 +00:00
|
|
|
|
|
|
|
return static_cast<nsDocument*>(GetCurrentDoc());
|
2002-07-20 23:09:24 +00:00
|
|
|
}
|
|
|
|
|
2010-08-18 18:30:41 +00:00
|
|
|
already_AddRefed<nsIDOMHTMLInputElement>
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::GetSelectedRadioButton()
|
2010-08-18 18:30:41 +00:00
|
|
|
{
|
2011-05-04 12:49:59 +00:00
|
|
|
nsIRadioGroupContainer* container = GetRadioGroupContainer();
|
2010-08-18 18:30:41 +00:00
|
|
|
if (!container) {
|
2012-07-30 14:20:58 +00:00
|
|
|
return nullptr;
|
2010-08-18 18:30:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
nsAutoString name;
|
2011-05-04 12:49:59 +00:00
|
|
|
GetAttr(kNameSpaceID_None, nsGkAtoms::name, name);
|
2010-08-18 18:30:41 +00:00
|
|
|
|
2012-08-03 10:38:52 +00:00
|
|
|
nsCOMPtr<nsIDOMHTMLInputElement> selected = container->GetCurrentRadioButton(name);
|
2011-11-16 07:50:19 +00:00
|
|
|
return selected.forget();
|
2010-08-18 18:30:41 +00:00
|
|
|
}
|
|
|
|
|
2004-01-05 23:39:50 +00:00
|
|
|
nsresult
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::MaybeSubmitForm(nsPresContext* aPresContext)
|
2004-01-05 23:39:50 +00:00
|
|
|
{
|
|
|
|
if (!mForm) {
|
|
|
|
// Nothing to do here.
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2013-03-28 19:41:32 +00:00
|
|
|
|
2007-03-26 05:38:22 +00:00
|
|
|
nsCOMPtr<nsIPresShell> shell = aPresContext->GetPresShell();
|
2006-08-16 03:20:19 +00:00
|
|
|
if (!shell) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2004-01-05 23:39:50 +00:00
|
|
|
|
2006-08-16 03:20:19 +00:00
|
|
|
// Get the default submit element
|
|
|
|
nsIFormControl* submitControl = mForm->GetDefaultSubmitElement();
|
|
|
|
if (submitControl) {
|
2011-11-16 07:50:19 +00:00
|
|
|
nsCOMPtr<nsIContent> submitContent = do_QueryInterface(submitControl);
|
2006-08-16 03:20:19 +00:00
|
|
|
NS_ASSERTION(submitContent, "Form control not implementing nsIContent?!");
|
|
|
|
// Fire the button's onclick handler and let the button handle
|
|
|
|
// submitting the form.
|
2012-07-30 14:20:58 +00:00
|
|
|
nsMouseEvent event(true, NS_MOUSE_CLICK, nullptr, nsMouseEvent::eReal);
|
2006-08-16 03:20:19 +00:00
|
|
|
nsEventStatus status = nsEventStatus_eIgnore;
|
|
|
|
shell->HandleDOMEventWithTarget(submitContent, &event, &status);
|
2010-09-11 04:11:58 +00:00
|
|
|
} else if (mForm->HasSingleTextControl() &&
|
|
|
|
(mForm->HasAttr(kNameSpaceID_None, nsGkAtoms::novalidate) ||
|
|
|
|
mForm->CheckValidFormSubmission())) {
|
2010-09-11 04:07:41 +00:00
|
|
|
// TODO: removing this code and have the submit event sent by the form,
|
|
|
|
// bug 592124.
|
2006-09-18 04:53:54 +00:00
|
|
|
// If there's only one text control, just submit the form
|
2009-10-30 01:49:11 +00:00
|
|
|
// Hold strong ref across the event
|
2011-11-16 07:50:19 +00:00
|
|
|
nsRefPtr<nsHTMLFormElement> form = mForm;
|
2011-10-17 14:59:28 +00:00
|
|
|
nsFormEvent event(true, NS_FORM_SUBMIT);
|
2011-11-16 07:50:19 +00:00
|
|
|
nsEventStatus status = nsEventStatus_eIgnore;
|
2009-10-30 01:49:11 +00:00
|
|
|
shell->HandleDOMEventWithTarget(mForm, &event, &status);
|
2004-01-05 23:39:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2010-08-21 17:52:57 +00:00
|
|
|
void
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::SetCheckedInternal(bool aChecked, bool aNotify)
|
2002-03-07 20:53:40 +00:00
|
|
|
{
|
2002-01-24 19:04:55 +00:00
|
|
|
// Set the value
|
2011-11-16 07:50:19 +00:00
|
|
|
mChecked = aChecked;
|
2000-06-22 02:46:53 +00:00
|
|
|
|
2002-01-24 19:04:55 +00:00
|
|
|
// Notify the frame
|
2010-02-09 22:06:37 +00:00
|
|
|
if (mType == NS_FORM_INPUT_CHECKBOX || mType == NS_FORM_INPUT_RADIO) {
|
|
|
|
nsIFrame* frame = GetPrimaryFrame();
|
|
|
|
if (frame) {
|
2010-08-31 00:49:12 +00:00
|
|
|
frame->InvalidateFrameSubtree();
|
2000-01-14 09:57:31 +00:00
|
|
|
}
|
|
|
|
}
|
2002-03-13 10:12:33 +00:00
|
|
|
|
2011-06-01 01:46:57 +00:00
|
|
|
UpdateAllValidityStates(aNotify);
|
|
|
|
|
2002-03-13 10:12:33 +00:00
|
|
|
// Notify the document that the CSS :checked pseudoclass for this element
|
|
|
|
// has changed state.
|
2011-06-01 01:46:57 +00:00
|
|
|
UpdateState(aNotify);
|
2002-01-24 19:04:55 +00:00
|
|
|
}
|
|
|
|
|
2012-10-06 07:19:52 +00:00
|
|
|
void
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::Focus(ErrorResult& aError)
|
1998-09-01 01:27:08 +00:00
|
|
|
{
|
2011-11-16 07:50:19 +00:00
|
|
|
if (mType != NS_FORM_INPUT_FILE) {
|
2012-10-06 07:19:52 +00:00
|
|
|
nsGenericHTMLElement::Focus(aError);
|
|
|
|
return;
|
2011-11-16 07:50:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// For file inputs, focus the button instead.
|
|
|
|
nsIFrame* frame = GetPrimaryFrame();
|
|
|
|
if (frame) {
|
|
|
|
for (nsIFrame* childFrame = frame->GetFirstPrincipalChild();
|
|
|
|
childFrame;
|
|
|
|
childFrame = childFrame->GetNextSibling()) {
|
|
|
|
// See if the child is a button control.
|
|
|
|
nsCOMPtr<nsIFormControl> formCtrl =
|
|
|
|
do_QueryInterface(childFrame->GetContent());
|
2013-03-29 12:32:47 +00:00
|
|
|
if (formCtrl && formCtrl->GetType() == NS_FORM_BUTTON_BUTTON) {
|
2011-11-16 07:50:19 +00:00
|
|
|
nsCOMPtr<nsIDOMElement> element = do_QueryInterface(formCtrl);
|
|
|
|
nsIFocusManager* fm = nsFocusManager::GetFocusManager();
|
|
|
|
if (fm && element) {
|
|
|
|
fm->SetFocus(element, 0);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 18:00:39 +00:00
|
|
|
}
|
2011-11-16 07:50:19 +00:00
|
|
|
break;
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 18:00:39 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-10-06 07:19:52 +00:00
|
|
|
return;
|
1999-03-02 19:19:24 +00:00
|
|
|
}
|
|
|
|
|
1998-09-01 01:27:08 +00:00
|
|
|
NS_IMETHODIMP
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::Select()
|
2000-05-30 02:45:55 +00:00
|
|
|
{
|
2011-10-17 14:59:28 +00:00
|
|
|
if (!IsSingleLineTextControl(false)) {
|
2002-03-16 03:28:23 +00:00
|
|
|
return NS_OK;
|
2008-10-07 18:53:23 +00:00
|
|
|
}
|
2000-05-30 02:45:55 +00:00
|
|
|
|
2008-10-07 18:53:23 +00:00
|
|
|
// XXX Bug? We have to give the input focus before contents can be
|
|
|
|
// selected
|
|
|
|
|
|
|
|
FocusTristate state = FocusState();
|
|
|
|
if (state == eUnfocusable) {
|
2005-10-28 11:25:24 +00:00
|
|
|
return NS_OK;
|
2000-05-30 02:45:55 +00:00
|
|
|
}
|
|
|
|
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 18:00:39 +00:00
|
|
|
nsIFocusManager* fm = nsFocusManager::GetFocusManager();
|
|
|
|
|
2010-03-25 13:17:11 +00:00
|
|
|
nsRefPtr<nsPresContext> presContext = GetPresContext();
|
2008-10-07 18:53:23 +00:00
|
|
|
if (state == eInactiveWindow) {
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 18:00:39 +00:00
|
|
|
if (fm)
|
|
|
|
fm->SetFocus(this, nsIFocusManager::FLAG_NOSCROLL);
|
2008-10-07 18:53:23 +00:00
|
|
|
SelectAll(presContext);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2001-08-18 23:55:01 +00:00
|
|
|
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 18:00:39 +00:00
|
|
|
if (DispatchSelectEvent(presContext) && fm) {
|
|
|
|
fm->SetFocus(this, nsIFocusManager::FLAG_NOSCROLL);
|
|
|
|
|
|
|
|
// ensure that the element is actually focused
|
|
|
|
nsCOMPtr<nsIDOMElement> focusedElement;
|
|
|
|
fm->GetFocusedElement(getter_AddRefs(focusedElement));
|
2013-03-28 19:41:32 +00:00
|
|
|
if (SameCOMIdentity(static_cast<nsIDOMNode*>(this), focusedElement)) {
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 18:00:39 +00:00
|
|
|
// Now Select all the text!
|
|
|
|
SelectAll(presContext);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2011-09-29 06:19:26 +00:00
|
|
|
bool
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::DispatchSelectEvent(nsPresContext* aPresContext)
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 18:00:39 +00:00
|
|
|
{
|
2008-10-07 18:53:23 +00:00
|
|
|
nsEventStatus status = nsEventStatus_eIgnore;
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 18:00:39 +00:00
|
|
|
|
|
|
|
// If already handling select event, don't dispatch a second.
|
2011-11-16 07:50:19 +00:00
|
|
|
if (!mHandlingSelectEvent) {
|
2008-10-07 18:53:23 +00:00
|
|
|
nsEvent event(nsContentUtils::IsCallerChrome(), NS_FORM_SELECTED);
|
|
|
|
|
2011-11-16 07:50:19 +00:00
|
|
|
mHandlingSelectEvent = true;
|
2008-10-07 18:53:23 +00:00
|
|
|
nsEventDispatcher::Dispatch(static_cast<nsIContent*>(this),
|
2012-07-30 14:20:58 +00:00
|
|
|
aPresContext, &event, nullptr, &status);
|
2011-11-16 07:50:19 +00:00
|
|
|
mHandlingSelectEvent = false;
|
2008-10-07 18:53:23 +00:00
|
|
|
}
|
2000-05-30 02:45:55 +00:00
|
|
|
|
2008-10-07 18:53:23 +00:00
|
|
|
// If the DOM event was not canceled (e.g. by a JS event handler
|
|
|
|
// returning false)
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 18:00:39 +00:00
|
|
|
return (status == nsEventStatus_eIgnore);
|
2000-05-30 02:45:55 +00:00
|
|
|
}
|
2013-03-28 19:41:32 +00:00
|
|
|
|
2000-12-23 10:56:31 +00:00
|
|
|
void
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::SelectAll(nsPresContext* aPresContext)
|
1998-09-01 01:27:08 +00:00
|
|
|
{
|
2011-10-17 14:59:28 +00:00
|
|
|
nsIFormControlFrame* formControlFrame = GetFormControlFrame(true);
|
2000-12-23 10:56:31 +00:00
|
|
|
|
|
|
|
if (formControlFrame) {
|
2006-12-26 17:47:52 +00:00
|
|
|
formControlFrame->SetFormProperty(nsGkAtoms::select, EmptyString());
|
1998-09-23 17:16:51 +00:00
|
|
|
}
|
1998-09-01 01:27:08 +00:00
|
|
|
}
|
|
|
|
|
2010-08-27 15:49:06 +00:00
|
|
|
NS_IMETHODIMP
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::FireAsyncClickHandler()
|
2010-08-27 15:49:06 +00:00
|
|
|
{
|
|
|
|
nsCOMPtr<nsIRunnable> event = new AsyncClickHandler(this);
|
|
|
|
return NS_DispatchToMainThread(event);
|
|
|
|
}
|
|
|
|
|
2011-09-29 06:19:26 +00:00
|
|
|
bool
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::NeedToInitializeEditorForEvent(nsEventChainPreVisitor& aVisitor) const
|
2010-02-02 04:00:12 +00:00
|
|
|
{
|
2010-05-13 22:56:24 +00:00
|
|
|
// We only need to initialize the editor for single line input controls because they
|
2010-02-02 04:00:12 +00:00
|
|
|
// are lazily initialized. We don't need to initialize the control for
|
|
|
|
// certain types of events, because we know that those events are safe to be
|
|
|
|
// handled without the editor being initialized. These events include:
|
|
|
|
// mousein/move/out, and DOM mutation events.
|
2011-11-16 07:50:19 +00:00
|
|
|
if (!IsSingleLineTextControl(false) ||
|
|
|
|
aVisitor.mEvent->eventStructType == NS_MUTATION_EVENT) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (aVisitor.mEvent->message) {
|
|
|
|
case NS_MOUSE_MOVE:
|
|
|
|
case NS_MOUSE_ENTER:
|
|
|
|
case NS_MOUSE_EXIT:
|
|
|
|
case NS_MOUSE_ENTER_SYNTH:
|
|
|
|
case NS_MOUSE_EXIT_SYNTH:
|
|
|
|
return false;
|
|
|
|
default:
|
2011-10-17 14:59:28 +00:00
|
|
|
return true;
|
2010-02-02 04:00:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-01-03 15:17:36 +00:00
|
|
|
bool
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::IsDisabledForEvents(uint32_t aMessage)
|
2013-01-03 15:17:36 +00:00
|
|
|
{
|
|
|
|
return IsElementDisabledForEvents(aMessage, GetPrimaryFrame());
|
|
|
|
}
|
|
|
|
|
2004-01-09 23:54:21 +00:00
|
|
|
nsresult
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
|
1998-09-23 17:16:51 +00:00
|
|
|
{
|
1999-12-04 02:22:21 +00:00
|
|
|
// Do not process any DOM events if the element is disabled
|
2011-10-17 14:59:28 +00:00
|
|
|
aVisitor.mCanHandle = false;
|
2013-01-03 15:17:36 +00:00
|
|
|
if (IsDisabledForEvents(aVisitor.mEvent->message)) {
|
2002-12-17 04:31:21 +00:00
|
|
|
return NS_OK;
|
1999-12-04 02:22:21 +00:00
|
|
|
}
|
2010-09-18 21:33:16 +00:00
|
|
|
|
2010-02-02 04:00:12 +00:00
|
|
|
// Initialize the editor if needed.
|
|
|
|
if (NeedToInitializeEditorForEvent(aVisitor)) {
|
|
|
|
nsITextControlFrame* textControlFrame = do_QueryFrame(GetPrimaryFrame());
|
|
|
|
if (textControlFrame)
|
|
|
|
textControlFrame->EnsureEditorInitialized();
|
|
|
|
}
|
|
|
|
|
2007-07-20 23:20:33 +00:00
|
|
|
//FIXME Allow submission etc. also when there is no prescontext, Bug 329509.
|
|
|
|
if (!aVisitor.mPresContext) {
|
|
|
|
return nsGenericHTMLElement::PreHandleEvent(aVisitor);
|
2013-03-28 19:41:32 +00:00
|
|
|
}
|
2000-08-02 22:06:37 +00:00
|
|
|
//
|
2002-12-17 04:31:21 +00:00
|
|
|
// Web pages expect the value of a radio button or checkbox to be set
|
2004-04-30 23:55:16 +00:00
|
|
|
// *before* onclick and DOMActivate fire, and they expect that if they set
|
|
|
|
// the value explicitly during onclick or DOMActivate it will not be toggled
|
|
|
|
// or any such nonsense.
|
2002-12-17 04:31:21 +00:00
|
|
|
// In order to support that (bug 57137 and 58460 are examples) we toggle
|
2004-04-30 23:55:16 +00:00
|
|
|
// the checked attribute *first*, and then fire onclick. If the user
|
|
|
|
// returns false, we reset the control to the old checked value. Otherwise,
|
|
|
|
// we dispatch DOMActivate. If DOMActivate is cancelled, we also reset
|
|
|
|
// the control to the old checked value. We need to keep track of whether
|
|
|
|
// we've already toggled the state from onclick since the user could
|
|
|
|
// explicitly dispatch DOMActivate on the element.
|
2002-12-17 04:31:21 +00:00
|
|
|
//
|
|
|
|
// This is a compatibility hack.
|
2002-03-07 20:53:40 +00:00
|
|
|
//
|
2004-04-30 23:55:16 +00:00
|
|
|
|
2006-03-07 17:08:51 +00:00
|
|
|
// Track whether we're in the outermost Dispatch invocation that will
|
2005-01-11 03:21:23 +00:00
|
|
|
// cause activation of the input. That is, if we're a click event, or a
|
|
|
|
// DOMActivate that was dispatched directly, this will be set, but if we're
|
|
|
|
// a DOMActivate dispatched from click handling, it will not be set.
|
2011-09-29 06:19:26 +00:00
|
|
|
bool outerActivateEvent =
|
2006-11-16 21:35:39 +00:00
|
|
|
(NS_IS_MOUSE_LEFT_CLICK(aVisitor.mEvent) ||
|
2011-11-16 07:50:19 +00:00
|
|
|
(aVisitor.mEvent->message == NS_UI_ACTIVATE && !mInInternalActivate));
|
2004-04-30 23:55:16 +00:00
|
|
|
|
2006-03-07 17:08:51 +00:00
|
|
|
if (outerActivateEvent) {
|
|
|
|
aVisitor.mItemFlags |= NS_OUTER_ACTIVATE_EVENT;
|
|
|
|
}
|
2002-03-07 20:53:40 +00:00
|
|
|
|
2011-09-29 06:19:26 +00:00
|
|
|
bool originalCheckedValue = false;
|
2002-03-07 20:53:40 +00:00
|
|
|
|
2005-01-11 03:21:23 +00:00
|
|
|
if (outerActivateEvent) {
|
2011-11-16 07:50:19 +00:00
|
|
|
mCheckedIsToggled = false;
|
2004-04-30 23:55:16 +00:00
|
|
|
|
2002-12-17 04:31:21 +00:00
|
|
|
switch(mType) {
|
2000-12-10 16:05:29 +00:00
|
|
|
case NS_FORM_INPUT_CHECKBOX:
|
|
|
|
{
|
2011-11-16 07:50:19 +00:00
|
|
|
if (mIndeterminate) {
|
2009-01-22 00:07:44 +00:00
|
|
|
// indeterminate is always set to FALSE when the checkbox is toggled
|
2011-10-17 14:59:28 +00:00
|
|
|
SetIndeterminateInternal(false, false);
|
2009-01-22 00:07:44 +00:00
|
|
|
aVisitor.mItemFlags |= NS_ORIGINAL_INDETERMINATE_VALUE;
|
|
|
|
}
|
|
|
|
|
2002-12-17 04:31:21 +00:00
|
|
|
GetChecked(&originalCheckedValue);
|
2011-10-17 14:59:28 +00:00
|
|
|
DoSetChecked(!originalCheckedValue, true, true);
|
2011-11-16 07:50:19 +00:00
|
|
|
mCheckedIsToggled = true;
|
2000-12-10 16:05:29 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NS_FORM_INPUT_RADIO:
|
|
|
|
{
|
2010-08-18 18:30:41 +00:00
|
|
|
nsCOMPtr<nsIDOMHTMLInputElement> selectedRadioButton = GetSelectedRadioButton();
|
|
|
|
aVisitor.mItemData = selectedRadioButton;
|
2002-03-07 20:53:40 +00:00
|
|
|
|
2011-11-16 07:50:19 +00:00
|
|
|
originalCheckedValue = mChecked;
|
2002-12-17 04:31:21 +00:00
|
|
|
if (!originalCheckedValue) {
|
2011-10-17 14:59:28 +00:00
|
|
|
DoSetChecked(true, true, true);
|
2011-11-16 07:50:19 +00:00
|
|
|
mCheckedIsToggled = true;
|
2000-12-10 16:05:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2002-11-30 00:01:21 +00:00
|
|
|
case NS_FORM_INPUT_SUBMIT:
|
|
|
|
case NS_FORM_INPUT_IMAGE:
|
2013-03-28 19:41:32 +00:00
|
|
|
if (mForm) {
|
2002-11-30 00:01:21 +00:00
|
|
|
// tell the form that we are about to enter a click handler.
|
|
|
|
// that means that if there are scripted submissions, the
|
2013-03-28 19:41:32 +00:00
|
|
|
// latest one will be deferred until after the exit point of the handler.
|
2010-08-19 23:23:59 +00:00
|
|
|
mForm->OnSubmitClickBegin(this);
|
2002-11-30 00:01:21 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2000-12-10 16:05:29 +00:00
|
|
|
default:
|
|
|
|
break;
|
2011-11-16 07:50:19 +00:00
|
|
|
}
|
2000-08-02 22:06:37 +00:00
|
|
|
}
|
|
|
|
|
2006-03-07 17:08:51 +00:00
|
|
|
if (originalCheckedValue) {
|
|
|
|
aVisitor.mItemFlags |= NS_ORIGINAL_CHECKED_VALUE;
|
|
|
|
}
|
|
|
|
|
2012-12-16 01:26:05 +00:00
|
|
|
// If mNoContentDispatch is true we will not allow content to handle
|
2013-03-28 19:41:32 +00:00
|
|
|
// this event. But to allow middle mouse button paste to work we must allow
|
2001-11-07 06:29:29 +00:00
|
|
|
// middle clicks to go to text fields anyway.
|
2012-12-16 01:26:05 +00:00
|
|
|
if (aVisitor.mEvent->mFlags.mNoContentDispatch) {
|
2006-03-07 17:08:51 +00:00
|
|
|
aVisitor.mItemFlags |= NS_NO_CONTENT_DISPATCH;
|
|
|
|
}
|
2011-10-17 14:59:28 +00:00
|
|
|
if (IsSingleLineTextControl(false) &&
|
2006-11-16 21:35:39 +00:00
|
|
|
aVisitor.mEvent->message == NS_MOUSE_CLICK &&
|
|
|
|
aVisitor.mEvent->eventStructType == NS_MOUSE_EVENT &&
|
2007-07-08 07:08:04 +00:00
|
|
|
static_cast<nsMouseEvent*>(aVisitor.mEvent)->button ==
|
2006-11-16 21:35:39 +00:00
|
|
|
nsMouseEvent::eMiddleButton) {
|
2012-12-16 01:26:05 +00:00
|
|
|
aVisitor.mEvent->mFlags.mNoContentDispatch = false;
|
2001-11-07 06:29:29 +00:00
|
|
|
}
|
|
|
|
|
2002-12-17 04:31:21 +00:00
|
|
|
// We must cache type because mType may change during JS event (bug 2369)
|
2010-06-01 13:42:37 +00:00
|
|
|
aVisitor.mItemFlags |= mType;
|
2006-11-28 13:08:23 +00:00
|
|
|
|
|
|
|
// Fire onchange (if necessary), before we do the blur, bug 357684.
|
|
|
|
if (aVisitor.mEvent->message == NS_BLUR_CONTENT) {
|
2013-01-31 23:05:48 +00:00
|
|
|
// 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)) {
|
2012-07-05 16:15:46 +00:00
|
|
|
nsAutoString aValue;
|
|
|
|
GetValueInternal(aValue);
|
|
|
|
SetValueInternal(aValue, false, false);
|
|
|
|
}
|
2012-05-07 16:27:24 +00:00
|
|
|
FireChangeEventIfNeeded();
|
2006-11-28 13:08:23 +00:00
|
|
|
}
|
|
|
|
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 18:00:39 +00:00
|
|
|
return nsGenericHTMLFormElement::PreHandleEvent(aVisitor);
|
|
|
|
}
|
|
|
|
|
2013-03-08 09:40:12 +00:00
|
|
|
void
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::StartRangeThumbDrag(nsGUIEvent* aEvent)
|
2013-03-08 09:40:12 +00:00
|
|
|
{
|
|
|
|
mIsDraggingRange = true;
|
|
|
|
mRangeThumbDragStartValue = GetValueAsDouble();
|
|
|
|
nsIPresShell::SetCapturingContent(this, CAPTURE_IGNOREALLOWED |
|
|
|
|
CAPTURE_RETARGETTOELEMENT);
|
|
|
|
nsRangeFrame* rangeFrame = do_QueryFrame(GetPrimaryFrame());
|
|
|
|
SetValueOfRangeForUserEvent(rangeFrame->GetValueAtEventPoint(aEvent));
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::FinishRangeThumbDrag(nsGUIEvent* aEvent)
|
2013-03-08 09:40:12 +00:00
|
|
|
{
|
|
|
|
MOZ_ASSERT(mIsDraggingRange);
|
2013-03-28 19:41:32 +00:00
|
|
|
|
2013-03-08 09:40:12 +00:00
|
|
|
if (nsIPresShell::GetCapturingContent() == this) {
|
|
|
|
nsIPresShell::SetCapturingContent(nullptr, 0); // cancel capture
|
|
|
|
}
|
|
|
|
if (aEvent) {
|
|
|
|
nsRangeFrame* rangeFrame = do_QueryFrame(GetPrimaryFrame());
|
|
|
|
SetValueOfRangeForUserEvent(rangeFrame->GetValueAtEventPoint(aEvent));
|
|
|
|
}
|
|
|
|
mIsDraggingRange = false;
|
2013-03-16 05:49:41 +00:00
|
|
|
FireChangeEventIfNeeded();
|
2013-03-08 09:40:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::CancelRangeThumbDrag(bool aIsForUserEvent)
|
2013-03-08 09:40:12 +00:00
|
|
|
{
|
|
|
|
MOZ_ASSERT(mIsDraggingRange);
|
|
|
|
|
2013-04-16 14:20:37 +00:00
|
|
|
mIsDraggingRange = false;
|
2013-03-08 09:40:12 +00:00
|
|
|
if (nsIPresShell::GetCapturingContent() == this) {
|
|
|
|
nsIPresShell::SetCapturingContent(nullptr, 0); // cancel capture
|
|
|
|
}
|
2013-03-16 05:49:41 +00:00
|
|
|
if (aIsForUserEvent) {
|
|
|
|
SetValueOfRangeForUserEvent(mRangeThumbDragStartValue);
|
|
|
|
} else {
|
|
|
|
// Don't dispatch an 'input' event - at least not using
|
|
|
|
// DispatchTrustedEvent.
|
|
|
|
// TODO: decide what we should do here - bug 851782.
|
|
|
|
nsAutoString val;
|
|
|
|
ConvertNumberToString(mRangeThumbDragStartValue, val);
|
|
|
|
SetValueInternal(val, true, true);
|
|
|
|
nsRangeFrame* frame = do_QueryFrame(GetPrimaryFrame());
|
|
|
|
if (frame) {
|
2013-03-26 23:04:41 +00:00
|
|
|
frame->UpdateForValueChange();
|
2013-03-16 05:49:41 +00:00
|
|
|
}
|
2013-04-16 14:20:37 +00:00
|
|
|
nsRefPtr<nsAsyncDOMEvent> event =
|
|
|
|
new nsAsyncDOMEvent(this, NS_LITERAL_STRING("input"), true, false);
|
|
|
|
event->RunDOMEventWhenSafe();
|
2013-03-16 05:49:41 +00:00
|
|
|
}
|
2013-03-08 09:40:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::SetValueOfRangeForUserEvent(double aValue)
|
2013-03-08 09:40:12 +00:00
|
|
|
{
|
|
|
|
MOZ_ASSERT(MOZ_DOUBLE_IS_FINITE(aValue));
|
|
|
|
|
|
|
|
nsAutoString val;
|
|
|
|
ConvertNumberToString(aValue, val);
|
|
|
|
SetValueInternal(val, true, true);
|
2013-03-13 11:48:27 +00:00
|
|
|
nsRangeFrame* frame = do_QueryFrame(GetPrimaryFrame());
|
2013-03-08 09:40:12 +00:00
|
|
|
if (frame) {
|
2013-03-26 23:04:41 +00:00
|
|
|
frame->UpdateForValueChange();
|
2013-03-08 09:40:12 +00:00
|
|
|
}
|
2013-03-16 05:49:41 +00:00
|
|
|
nsContentUtils::DispatchTrustedEvent(OwnerDoc(),
|
|
|
|
static_cast<nsIDOMHTMLInputElement*>(this),
|
|
|
|
NS_LITERAL_STRING("input"), true,
|
|
|
|
false);
|
2013-03-08 09:40:12 +00:00
|
|
|
}
|
|
|
|
|
2011-09-29 06:19:26 +00:00
|
|
|
static bool
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 18:00:39 +00:00
|
|
|
SelectTextFieldOnFocus()
|
|
|
|
{
|
|
|
|
if (!gSelectTextFieldOnFocus) {
|
2012-08-22 15:56:38 +00:00
|
|
|
int32_t selectTextfieldsOnKeyFocus = -1;
|
2011-09-09 02:27:12 +00:00
|
|
|
nsresult rv =
|
|
|
|
LookAndFeel::GetInt(LookAndFeel::eIntID_SelectTextfieldsOnKeyFocus,
|
|
|
|
&selectTextfieldsOnKeyFocus);
|
|
|
|
if (NS_FAILED(rv)) {
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 18:00:39 +00:00
|
|
|
gSelectTextFieldOnFocus = -1;
|
2011-09-09 02:27:12 +00:00
|
|
|
} else {
|
|
|
|
gSelectTextFieldOnFocus = selectTextfieldsOnKeyFocus != 0 ? 1 : -1;
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 18:00:39 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return gSelectTextFieldOnFocus == 1;
|
2006-03-07 17:08:51 +00:00
|
|
|
}
|
2001-11-07 06:29:29 +00:00
|
|
|
|
2013-03-01 15:34:06 +00:00
|
|
|
static bool
|
|
|
|
IsLTR(Element* aElement)
|
|
|
|
{
|
2013-03-28 19:41:32 +00:00
|
|
|
nsIFrame* frame = aElement->GetPrimaryFrame();
|
2013-03-01 15:34:06 +00:00
|
|
|
if (frame) {
|
|
|
|
return frame->StyleVisibility()->mDirection == NS_STYLE_DIRECTION_LTR;
|
|
|
|
}
|
|
|
|
// at least for HTML, directionality is exclusively LTR or RTL
|
|
|
|
return aElement->GetDirectionality() == eDir_LTR;
|
|
|
|
}
|
|
|
|
|
2013-03-27 11:32:00 +00:00
|
|
|
bool
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::ShouldPreventDOMActivateDispatch(nsIDOMEventTarget* aOriginalTarget)
|
2013-03-27 11:32:00 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* For the moment, there is only one situation where we actually want to
|
|
|
|
* prevent firing a DOMActivate event:
|
|
|
|
* - we are a <input type='file'> that just got a click event,
|
|
|
|
* - the event was targeted to our button which should have sent a
|
|
|
|
* DOMActivate event.
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (mType != NS_FORM_INPUT_FILE) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsCOMPtr<nsIContent> target = do_QueryInterface(aOriginalTarget);
|
|
|
|
if (!target) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return target->GetParent() == this &&
|
|
|
|
target->IsRootOfNativeAnonymousSubtree() &&
|
|
|
|
target->AttrValueIs(kNameSpaceID_None, nsGkAtoms::type,
|
|
|
|
nsGkAtoms::button, eCaseMatters);
|
|
|
|
}
|
|
|
|
|
2006-03-07 17:08:51 +00:00
|
|
|
nsresult
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::PostHandleEvent(nsEventChainPostVisitor& aVisitor)
|
2006-03-07 17:08:51 +00:00
|
|
|
{
|
|
|
|
if (!aVisitor.mPresContext) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2009-11-25 02:12:00 +00:00
|
|
|
|
2010-11-23 23:50:53 +00:00
|
|
|
if (aVisitor.mEvent->message == NS_FOCUS_CONTENT ||
|
|
|
|
aVisitor.mEvent->message == NS_BLUR_CONTENT) {
|
2013-03-28 19:41:32 +00:00
|
|
|
if (aVisitor.mEvent->message == NS_FOCUS_CONTENT &&
|
2013-03-16 05:49:41 +00:00
|
|
|
MayFireChangeOnBlur()) {
|
2012-05-07 16:27:24 +00:00
|
|
|
GetValueInternal(mFocusedValue);
|
|
|
|
}
|
2010-11-23 23:56:24 +00:00
|
|
|
|
2013-03-08 09:40:12 +00:00
|
|
|
if (mIsDraggingRange &&
|
|
|
|
aVisitor.mEvent->message == NS_BLUR_CONTENT) {
|
|
|
|
FinishRangeThumbDrag();
|
|
|
|
}
|
|
|
|
|
2011-06-01 01:46:57 +00:00
|
|
|
UpdateValidityUIBits(aVisitor.mEvent->message == NS_FOCUS_CONTENT);
|
2010-11-23 23:50:53 +00:00
|
|
|
|
2011-06-01 01:46:57 +00:00
|
|
|
UpdateState(true);
|
2010-08-25 04:39:10 +00:00
|
|
|
}
|
|
|
|
|
2006-03-07 17:08:51 +00:00
|
|
|
nsresult rv = NS_OK;
|
2011-09-29 06:19:26 +00:00
|
|
|
bool outerActivateEvent = !!(aVisitor.mItemFlags & NS_OUTER_ACTIVATE_EVENT);
|
|
|
|
bool originalCheckedValue =
|
2008-02-10 06:16:30 +00:00
|
|
|
!!(aVisitor.mItemFlags & NS_ORIGINAL_CHECKED_VALUE);
|
2011-09-29 06:19:26 +00:00
|
|
|
bool noContentDispatch = !!(aVisitor.mItemFlags & NS_NO_CONTENT_DISPATCH);
|
2012-08-22 15:56:38 +00:00
|
|
|
uint8_t oldType = NS_CONTROL_TYPE(aVisitor.mItemFlags);
|
2013-03-27 11:32:00 +00:00
|
|
|
|
2004-04-30 23:55:16 +00:00
|
|
|
// Ideally we would make the default action for click and space just dispatch
|
|
|
|
// DOMActivate, and the default action for DOMActivate flip the checkbox/
|
|
|
|
// radio state and fire onchange. However, for backwards compatibility, we
|
|
|
|
// need to flip the state before firing click, and we need to fire click
|
|
|
|
// when space is pressed. So, we just nest the firing of DOMActivate inside
|
|
|
|
// the click event handling, and allow cancellation of DOMActivate to cancel
|
|
|
|
// the click.
|
2006-03-07 17:08:51 +00:00
|
|
|
if (aVisitor.mEventStatus != nsEventStatus_eConsumeNoDefault &&
|
2011-10-17 14:59:28 +00:00
|
|
|
!IsSingleLineTextControl(true) &&
|
2013-03-27 11:32:00 +00:00
|
|
|
NS_IS_MOUSE_LEFT_CLICK(aVisitor.mEvent) &&
|
|
|
|
!ShouldPreventDOMActivateDispatch(aVisitor.mEvent->originalTarget)) {
|
2012-12-16 01:26:03 +00:00
|
|
|
nsUIEvent actEvent(aVisitor.mEvent->mFlags.mIsTrusted, NS_UI_ACTIVATE, 1);
|
2004-04-30 23:55:16 +00:00
|
|
|
|
2007-03-26 05:38:22 +00:00
|
|
|
nsCOMPtr<nsIPresShell> shell = aVisitor.mPresContext->GetPresShell();
|
2004-04-30 23:55:16 +00:00
|
|
|
if (shell) {
|
|
|
|
nsEventStatus status = nsEventStatus_eIgnore;
|
2011-11-16 07:50:19 +00:00
|
|
|
mInInternalActivate = true;
|
2004-04-30 23:55:16 +00:00
|
|
|
rv = shell->HandleDOMEventWithTarget(this, &actEvent, &status);
|
2011-11-16 07:50:19 +00:00
|
|
|
mInInternalActivate = false;
|
2004-04-30 23:55:16 +00:00
|
|
|
|
|
|
|
// If activate is cancelled, we must do the same as when click is
|
|
|
|
// cancelled (revert the checkbox to its original value).
|
|
|
|
if (status == nsEventStatus_eConsumeNoDefault)
|
2006-03-07 17:08:51 +00:00
|
|
|
aVisitor.mEventStatus = status;
|
2004-04-30 23:55:16 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-01-11 03:21:23 +00:00
|
|
|
if (outerActivateEvent) {
|
2002-12-17 04:31:21 +00:00
|
|
|
switch(oldType) {
|
2002-11-30 00:01:21 +00:00
|
|
|
case NS_FORM_INPUT_SUBMIT:
|
|
|
|
case NS_FORM_INPUT_IMAGE:
|
2013-03-28 19:41:32 +00:00
|
|
|
if (mForm) {
|
2002-11-30 00:01:21 +00:00
|
|
|
// tell the form that we are about to exit a click handler
|
|
|
|
// so the form knows not to defer subsequent submissions
|
|
|
|
// the pending ones that were created during the handler
|
|
|
|
// will be flushed or forgoten.
|
|
|
|
mForm->OnSubmitClickEnd();
|
|
|
|
}
|
|
|
|
break;
|
2011-11-16 07:50:19 +00:00
|
|
|
}
|
2002-11-30 00:01:21 +00:00
|
|
|
}
|
|
|
|
|
2001-11-07 06:29:29 +00:00
|
|
|
// Reset the flag for other content besides this text field
|
2012-12-16 01:26:05 +00:00
|
|
|
aVisitor.mEvent->mFlags.mNoContentDispatch = noContentDispatch;
|
2001-11-07 06:29:29 +00:00
|
|
|
|
2000-12-10 16:05:29 +00:00
|
|
|
// now check to see if the event was "cancelled"
|
2011-11-16 07:50:19 +00:00
|
|
|
if (mCheckedIsToggled && outerActivateEvent) {
|
2006-03-07 17:08:51 +00:00
|
|
|
if (aVisitor.mEventStatus == nsEventStatus_eConsumeNoDefault) {
|
2002-12-17 04:31:21 +00:00
|
|
|
// if it was cancelled and a radio button, then set the old
|
|
|
|
// selected btn to TRUE. if it is a checkbox then set it to its
|
|
|
|
// original value
|
2011-11-22 12:38:37 +00:00
|
|
|
if (oldType == NS_FORM_INPUT_RADIO) {
|
|
|
|
nsCOMPtr<nsIDOMHTMLInputElement> selectedRadioButton =
|
|
|
|
do_QueryInterface(aVisitor.mItemData);
|
|
|
|
if (selectedRadioButton) {
|
|
|
|
selectedRadioButton->SetChecked(true);
|
|
|
|
}
|
|
|
|
// If there was no checked radio button or this one is no longer a
|
|
|
|
// radio button we must reset it back to false to cancel the action.
|
|
|
|
// See how the web of hack grows?
|
|
|
|
if (!selectedRadioButton || mType != NS_FORM_INPUT_RADIO) {
|
2011-10-17 14:59:28 +00:00
|
|
|
DoSetChecked(false, true, true);
|
2002-12-17 04:31:21 +00:00
|
|
|
}
|
|
|
|
} else if (oldType == NS_FORM_INPUT_CHECKBOX) {
|
2011-09-29 06:19:26 +00:00
|
|
|
bool originalIndeterminateValue =
|
2009-01-22 00:07:44 +00:00
|
|
|
!!(aVisitor.mItemFlags & NS_ORIGINAL_INDETERMINATE_VALUE);
|
2011-10-17 14:59:28 +00:00
|
|
|
SetIndeterminateInternal(originalIndeterminateValue, false);
|
|
|
|
DoSetChecked(originalCheckedValue, true, true);
|
2002-12-17 04:31:21 +00:00
|
|
|
}
|
|
|
|
} else {
|
2011-10-18 10:53:36 +00:00
|
|
|
nsContentUtils::DispatchTrustedEvent(OwnerDoc(),
|
2010-12-17 17:45:46 +00:00
|
|
|
static_cast<nsIDOMHTMLInputElement*>(this),
|
2011-10-17 14:59:28 +00:00
|
|
|
NS_LITERAL_STRING("change"), true,
|
|
|
|
false);
|
2002-12-17 04:31:21 +00:00
|
|
|
#ifdef ACCESSIBILITY
|
|
|
|
// Fire an event to notify accessibility
|
|
|
|
if (mType == NS_FORM_INPUT_CHECKBOX) {
|
2006-05-16 03:54:46 +00:00
|
|
|
FireEventForAccessibility(this, aVisitor.mPresContext,
|
2002-12-17 04:31:21 +00:00
|
|
|
NS_LITERAL_STRING("CheckboxStateChange"));
|
|
|
|
} else {
|
2006-05-16 03:54:46 +00:00
|
|
|
FireEventForAccessibility(this, aVisitor.mPresContext,
|
|
|
|
NS_LITERAL_STRING("RadioStateChange"));
|
|
|
|
// Fire event for the previous selected radio.
|
|
|
|
nsCOMPtr<nsIDOMHTMLInputElement> previous =
|
|
|
|
do_QueryInterface(aVisitor.mItemData);
|
2013-03-28 19:41:32 +00:00
|
|
|
if (previous) {
|
2006-10-12 13:30:07 +00:00
|
|
|
FireEventForAccessibility(previous, aVisitor.mPresContext,
|
|
|
|
NS_LITERAL_STRING("RadioStateChange"));
|
|
|
|
}
|
2002-12-17 04:31:21 +00:00
|
|
|
}
|
|
|
|
#endif
|
2000-12-10 16:05:29 +00:00
|
|
|
}
|
|
|
|
}
|
2000-10-24 01:41:07 +00:00
|
|
|
|
2006-03-07 17:08:51 +00:00
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
if (nsEventStatus_eIgnore == aVisitor.mEventStatus) {
|
|
|
|
switch (aVisitor.mEvent->message) {
|
2002-11-30 00:01:21 +00:00
|
|
|
|
|
|
|
case NS_FOCUS_CONTENT:
|
|
|
|
{
|
2009-10-01 17:53:10 +00:00
|
|
|
// see if we should select the contents of the textbox. This happens
|
|
|
|
// for text and password fields when the field was focused by the
|
|
|
|
// keyboard or a navigation, the platform allows it, and it wasn't
|
|
|
|
// just because we raised a window.
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 18:00:39 +00:00
|
|
|
nsIFocusManager* fm = nsFocusManager::GetFocusManager();
|
2011-10-17 14:59:28 +00:00
|
|
|
if (fm && IsSingleLineTextControl(false) &&
|
2013-03-28 19:41:32 +00:00
|
|
|
!(static_cast<nsFocusEvent*>(aVisitor.mEvent))->fromRaise &&
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 18:00:39 +00:00
|
|
|
SelectTextFieldOnFocus()) {
|
|
|
|
nsIDocument* document = GetCurrentDoc();
|
|
|
|
if (document) {
|
2012-08-22 15:56:38 +00:00
|
|
|
uint32_t lastFocusMethod;
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 18:00:39 +00:00
|
|
|
fm->GetLastFocusMethod(document->GetWindow(), &lastFocusMethod);
|
2009-08-26 16:19:41 +00:00
|
|
|
if (lastFocusMethod &
|
|
|
|
(nsIFocusManager::FLAG_BYKEY | nsIFocusManager::FLAG_BYMOVEFOCUS)) {
|
2010-03-25 13:17:11 +00:00
|
|
|
nsRefPtr<nsPresContext> presContext = GetPresContext();
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 18:00:39 +00:00
|
|
|
if (DispatchSelectEvent(presContext)) {
|
|
|
|
SelectAll(presContext);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2006-03-07 17:08:51 +00:00
|
|
|
}
|
2002-11-30 00:01:21 +00:00
|
|
|
|
|
|
|
case NS_KEY_PRESS:
|
|
|
|
case NS_KEY_UP:
|
|
|
|
{
|
|
|
|
// For backwards compat, trigger checks/radios/buttons with
|
|
|
|
// space or enter (bug 25300)
|
2013-03-28 19:41:32 +00:00
|
|
|
nsKeyEvent* keyEvent = (nsKeyEvent*)aVisitor.mEvent;
|
2002-11-30 00:01:21 +00:00
|
|
|
|
2006-03-07 17:08:51 +00:00
|
|
|
if ((aVisitor.mEvent->message == NS_KEY_PRESS &&
|
2002-11-30 00:01:21 +00:00
|
|
|
keyEvent->keyCode == NS_VK_RETURN) ||
|
2006-03-07 17:08:51 +00:00
|
|
|
(aVisitor.mEvent->message == NS_KEY_UP &&
|
2002-11-30 00:01:21 +00:00
|
|
|
keyEvent->keyCode == NS_VK_SPACE)) {
|
2002-12-17 04:31:21 +00:00
|
|
|
switch(mType) {
|
2002-11-30 00:01:21 +00:00
|
|
|
case NS_FORM_INPUT_CHECKBOX:
|
|
|
|
case NS_FORM_INPUT_RADIO:
|
|
|
|
{
|
|
|
|
// Checkbox and Radio try to submit on Enter press
|
|
|
|
if (keyEvent->keyCode != NS_VK_SPACE) {
|
2006-03-07 17:08:51 +00:00
|
|
|
MaybeSubmitForm(aVisitor.mPresContext);
|
2004-01-05 23:39:50 +00:00
|
|
|
|
2002-11-30 00:01:21 +00:00
|
|
|
break; // If we are submitting, do not send click event
|
2001-08-16 07:38:47 +00:00
|
|
|
}
|
2002-11-30 00:01:21 +00:00
|
|
|
// else fall through and treat Space like click...
|
2001-08-16 07:38:47 +00:00
|
|
|
}
|
2002-11-30 00:01:21 +00:00
|
|
|
case NS_FORM_INPUT_BUTTON:
|
|
|
|
case NS_FORM_INPUT_RESET:
|
|
|
|
case NS_FORM_INPUT_SUBMIT:
|
|
|
|
case NS_FORM_INPUT_IMAGE: // Bug 34418
|
|
|
|
{
|
2012-12-16 01:26:03 +00:00
|
|
|
nsMouseEvent event(aVisitor.mEvent->mFlags.mIsTrusted,
|
2012-07-30 14:20:58 +00:00
|
|
|
NS_MOUSE_CLICK, nullptr, nsMouseEvent::eReal);
|
2011-08-26 07:43:56 +00:00
|
|
|
event.inputSource = nsIDOMMouseEvent::MOZ_SOURCE_KEYBOARD;
|
2002-11-30 00:01:21 +00:00
|
|
|
nsEventStatus status = nsEventStatus_eIgnore;
|
2005-04-28 23:48:28 +00:00
|
|
|
|
2007-07-08 07:08:04 +00:00
|
|
|
nsEventDispatcher::Dispatch(static_cast<nsIContent*>(this),
|
2006-03-07 17:08:51 +00:00
|
|
|
aVisitor.mPresContext, &event,
|
2012-07-30 14:20:58 +00:00
|
|
|
nullptr, &status);
|
2010-12-27 20:42:10 +00:00
|
|
|
aVisitor.mEventStatus = nsEventStatus_eConsumeNoDefault;
|
2002-11-30 00:01:21 +00:00
|
|
|
} // case
|
|
|
|
} // switch
|
|
|
|
}
|
2006-03-07 17:08:51 +00:00
|
|
|
if (aVisitor.mEvent->message == NS_KEY_PRESS &&
|
2012-04-25 03:00:02 +00:00
|
|
|
mType == NS_FORM_INPUT_RADIO && !keyEvent->IsAlt() &&
|
|
|
|
!keyEvent->IsControl() && !keyEvent->IsMeta()) {
|
2011-09-29 06:19:26 +00:00
|
|
|
bool isMovingBack = false;
|
2004-07-05 01:31:30 +00:00
|
|
|
switch (keyEvent->keyCode) {
|
2013-03-28 19:41:32 +00:00
|
|
|
case NS_VK_UP:
|
2004-07-05 01:31:30 +00:00
|
|
|
case NS_VK_LEFT:
|
2011-10-17 14:59:28 +00:00
|
|
|
isMovingBack = true;
|
2010-12-20 03:44:00 +00:00
|
|
|
// FALLTHROUGH
|
2004-07-05 01:31:30 +00:00
|
|
|
case NS_VK_DOWN:
|
|
|
|
case NS_VK_RIGHT:
|
|
|
|
// Arrow key pressed, focus+select prev/next radio button
|
2011-05-04 12:49:59 +00:00
|
|
|
nsIRadioGroupContainer* container = GetRadioGroupContainer();
|
2004-07-05 01:31:30 +00:00
|
|
|
if (container) {
|
|
|
|
nsAutoString name;
|
2011-05-04 12:49:59 +00:00
|
|
|
GetAttr(kNameSpaceID_None, nsGkAtoms::name, name);
|
|
|
|
nsCOMPtr<nsIDOMHTMLInputElement> selectedRadioButton;
|
|
|
|
container->GetNextRadioButton(name, isMovingBack, this,
|
|
|
|
getter_AddRefs(selectedRadioButton));
|
|
|
|
nsCOMPtr<nsIContent> radioContent =
|
|
|
|
do_QueryInterface(selectedRadioButton);
|
|
|
|
if (radioContent) {
|
2012-11-10 23:30:15 +00:00
|
|
|
rv = selectedRadioButton->Focus();
|
2011-05-04 12:49:59 +00:00
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
nsEventStatus status = nsEventStatus_eIgnore;
|
2012-12-16 01:26:03 +00:00
|
|
|
nsMouseEvent event(aVisitor.mEvent->mFlags.mIsTrusted,
|
2012-07-30 14:20:58 +00:00
|
|
|
NS_MOUSE_CLICK, nullptr,
|
2011-05-04 12:49:59 +00:00
|
|
|
nsMouseEvent::eReal);
|
2011-08-26 07:43:56 +00:00
|
|
|
event.inputSource = nsIDOMMouseEvent::MOZ_SOURCE_KEYBOARD;
|
2011-05-04 12:49:59 +00:00
|
|
|
rv = nsEventDispatcher::Dispatch(radioContent,
|
|
|
|
aVisitor.mPresContext,
|
2012-07-30 14:20:58 +00:00
|
|
|
&event, nullptr, &status);
|
2004-07-05 01:31:30 +00:00
|
|
|
if (NS_SUCCEEDED(rv)) {
|
2011-05-04 12:49:59 +00:00
|
|
|
aVisitor.mEventStatus = nsEventStatus_eConsumeNoDefault;
|
2004-07-05 01:31:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2002-06-04 00:44:04 +00:00
|
|
|
|
2002-11-30 00:01:21 +00:00
|
|
|
/*
|
2011-04-13 19:43:34 +00:00
|
|
|
* For some input types, if the user hits enter, the form is submitted.
|
2002-11-30 00:01:21 +00:00
|
|
|
*
|
|
|
|
* Bug 99920, bug 109463 and bug 147850:
|
2002-12-17 04:31:21 +00:00
|
|
|
* (a) if there is a submit control in the form, click the first
|
|
|
|
* submit control in the form.
|
|
|
|
* (b) if there is just one text control in the form, submit by
|
|
|
|
* sending a submit event directly to the form
|
2002-11-30 00:01:21 +00:00
|
|
|
* (c) if there is more than one text input and no submit buttons, do
|
|
|
|
* not submit, period.
|
|
|
|
*/
|
|
|
|
|
2006-03-07 17:08:51 +00:00
|
|
|
if (aVisitor.mEvent->message == NS_KEY_PRESS &&
|
2002-11-30 00:01:21 +00:00
|
|
|
(keyEvent->keyCode == NS_VK_RETURN ||
|
|
|
|
keyEvent->keyCode == NS_VK_ENTER) &&
|
2012-06-10 20:23:17 +00:00
|
|
|
(IsSingleLineTextControl(false, mType) ||
|
2013-01-31 23:01:50 +00:00
|
|
|
IsExperimentalMobileType(mType))) {
|
2013-01-31 23:05:48 +00:00
|
|
|
FireChangeEventIfNeeded();
|
2011-04-13 19:43:34 +00:00
|
|
|
rv = MaybeSubmitForm(aVisitor.mPresContext);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
2002-06-04 00:44:04 +00:00
|
|
|
}
|
|
|
|
|
2013-03-01 15:34:06 +00:00
|
|
|
if (aVisitor.mEvent->message == NS_KEY_PRESS &&
|
|
|
|
mType == NS_FORM_INPUT_RANGE && !keyEvent->IsAlt() &&
|
|
|
|
!keyEvent->IsControl() && !keyEvent->IsMeta() &&
|
|
|
|
(keyEvent->keyCode == NS_VK_LEFT ||
|
|
|
|
keyEvent->keyCode == NS_VK_RIGHT ||
|
|
|
|
keyEvent->keyCode == NS_VK_UP ||
|
|
|
|
keyEvent->keyCode == NS_VK_DOWN ||
|
|
|
|
keyEvent->keyCode == NS_VK_PAGE_UP ||
|
|
|
|
keyEvent->keyCode == NS_VK_PAGE_DOWN ||
|
|
|
|
keyEvent->keyCode == NS_VK_HOME ||
|
|
|
|
keyEvent->keyCode == NS_VK_END)) {
|
|
|
|
double minimum = GetMinimum();
|
|
|
|
double maximum = GetMaximum();
|
|
|
|
MOZ_ASSERT(MOZ_DOUBLE_IS_FINITE(minimum) &&
|
|
|
|
MOZ_DOUBLE_IS_FINITE(maximum));
|
|
|
|
if (minimum < maximum) { // else the value is locked to the minimum
|
|
|
|
double value = GetValueAsDouble();
|
|
|
|
double step = GetStep();
|
|
|
|
if (step == kStepAny) {
|
|
|
|
step = GetDefaultStep();
|
|
|
|
}
|
|
|
|
MOZ_ASSERT(MOZ_DOUBLE_IS_FINITE(value) &&
|
|
|
|
MOZ_DOUBLE_IS_FINITE(step));
|
|
|
|
double newValue;
|
|
|
|
switch (keyEvent->keyCode) {
|
|
|
|
case NS_VK_LEFT:
|
|
|
|
newValue = value + (IsLTR(this) ? -step : step);
|
|
|
|
break;
|
|
|
|
case NS_VK_RIGHT:
|
|
|
|
newValue = value + (IsLTR(this) ? step : -step);
|
|
|
|
break;
|
|
|
|
case NS_VK_UP:
|
|
|
|
// Even for horizontal range, "up" means "increase"
|
|
|
|
newValue = value + step;
|
|
|
|
break;
|
|
|
|
case NS_VK_DOWN:
|
|
|
|
// Even for horizontal range, "down" means "decrease"
|
|
|
|
newValue = value - step;
|
|
|
|
break;
|
|
|
|
case NS_VK_HOME:
|
|
|
|
newValue = minimum;
|
|
|
|
break;
|
|
|
|
case NS_VK_END:
|
|
|
|
newValue = maximum;
|
|
|
|
break;
|
|
|
|
case NS_VK_PAGE_UP:
|
|
|
|
// For PgUp/PgDn we jump 10% of the total range, unless step
|
|
|
|
// requires us to jump more.
|
|
|
|
newValue = value + std::max(step, 0.1 * (maximum - minimum));
|
|
|
|
break;
|
|
|
|
case NS_VK_PAGE_DOWN:
|
|
|
|
newValue = value - std::max(step, 0.1 * (maximum - minimum));
|
|
|
|
break;
|
|
|
|
}
|
2013-03-09 14:12:06 +00:00
|
|
|
SetValueOfRangeForUserEvent(newValue);
|
2013-03-01 15:34:06 +00:00
|
|
|
aVisitor.mEventStatus = nsEventStatus_eConsumeNoDefault;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-11-30 00:01:21 +00:00
|
|
|
} break; // NS_KEY_PRESS || NS_KEY_UP
|
|
|
|
|
2006-11-16 21:35:39 +00:00
|
|
|
case NS_MOUSE_BUTTON_DOWN:
|
|
|
|
case NS_MOUSE_BUTTON_UP:
|
|
|
|
case NS_MOUSE_DOUBLECLICK:
|
2002-11-30 00:01:21 +00:00
|
|
|
{
|
2006-11-16 21:35:39 +00:00
|
|
|
// cancel all of these events for buttons
|
|
|
|
//XXXsmaug Why?
|
|
|
|
if (aVisitor.mEvent->eventStructType == NS_MOUSE_EVENT &&
|
2007-07-08 07:08:04 +00:00
|
|
|
(static_cast<nsMouseEvent*>(aVisitor.mEvent)->button ==
|
2006-11-16 21:35:39 +00:00
|
|
|
nsMouseEvent::eMiddleButton ||
|
2007-07-08 07:08:04 +00:00
|
|
|
static_cast<nsMouseEvent*>(aVisitor.mEvent)->button ==
|
2006-11-16 21:35:39 +00:00
|
|
|
nsMouseEvent::eRightButton)) {
|
|
|
|
if (mType == NS_FORM_INPUT_BUTTON ||
|
|
|
|
mType == NS_FORM_INPUT_RESET ||
|
|
|
|
mType == NS_FORM_INPUT_SUBMIT) {
|
|
|
|
if (aVisitor.mDOMEvent) {
|
|
|
|
aVisitor.mDOMEvent->StopPropagation();
|
|
|
|
} else {
|
|
|
|
rv = NS_ERROR_FAILURE;
|
|
|
|
}
|
2002-11-30 00:01:21 +00:00
|
|
|
}
|
2000-05-04 13:57:35 +00:00
|
|
|
|
2006-11-16 21:35:39 +00:00
|
|
|
}
|
2002-11-30 00:01:21 +00:00
|
|
|
break;
|
|
|
|
}
|
2006-03-07 17:08:51 +00:00
|
|
|
default:
|
|
|
|
break;
|
2004-05-17 22:05:41 +00:00
|
|
|
}
|
|
|
|
|
2005-01-11 03:21:23 +00:00
|
|
|
if (outerActivateEvent) {
|
2004-05-17 22:05:41 +00:00
|
|
|
if (mForm && (oldType == NS_FORM_INPUT_SUBMIT ||
|
|
|
|
oldType == NS_FORM_INPUT_IMAGE)) {
|
|
|
|
if (mType != NS_FORM_INPUT_SUBMIT && mType != NS_FORM_INPUT_IMAGE) {
|
|
|
|
// If the type has changed to a non-submit type, then we want to
|
|
|
|
// flush the stored submission if there is one (as if the submit()
|
|
|
|
// was allowed to succeed)
|
|
|
|
mForm->FlushPendingSubmission();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
switch(mType) {
|
|
|
|
case NS_FORM_INPUT_RESET:
|
|
|
|
case NS_FORM_INPUT_SUBMIT:
|
|
|
|
case NS_FORM_INPUT_IMAGE:
|
|
|
|
if (mForm) {
|
2011-10-17 14:59:28 +00:00
|
|
|
nsFormEvent event(true, (mType == NS_FORM_INPUT_RESET) ?
|
2004-05-17 22:05:41 +00:00
|
|
|
NS_FORM_RESET : NS_FORM_SUBMIT);
|
|
|
|
event.originator = this;
|
|
|
|
nsEventStatus status = nsEventStatus_eIgnore;
|
|
|
|
|
2007-03-26 05:38:22 +00:00
|
|
|
nsCOMPtr<nsIPresShell> presShell =
|
|
|
|
aVisitor.mPresContext->GetPresShell();
|
2004-05-17 22:05:41 +00:00
|
|
|
|
|
|
|
// If |nsIPresShell::Destroy| has been called due to
|
2006-03-07 17:08:51 +00:00
|
|
|
// handling the event the pres context will return a null
|
|
|
|
// pres shell. See bug 125624.
|
2010-09-11 04:07:41 +00:00
|
|
|
// TODO: removing this code and have the submit event sent by the
|
|
|
|
// form, see bug 592124.
|
|
|
|
if (presShell && (event.message != NS_FORM_SUBMIT ||
|
2010-09-11 04:11:58 +00:00
|
|
|
mForm->HasAttr(kNameSpaceID_None, nsGkAtoms::novalidate) ||
|
2010-09-14 23:38:07 +00:00
|
|
|
// We know the element is a submit control, if this check is moved,
|
|
|
|
// make sure formnovalidate is used only if it's a submit control.
|
|
|
|
HasAttr(kNameSpaceID_None, nsGkAtoms::formnovalidate) ||
|
2010-09-11 04:07:41 +00:00
|
|
|
mForm->CheckValidFormSubmission())) {
|
2009-10-30 01:49:11 +00:00
|
|
|
// Hold a strong ref while dispatching
|
|
|
|
nsRefPtr<nsHTMLFormElement> form(mForm);
|
|
|
|
presShell->HandleDOMEventWithTarget(mForm, &event, &status);
|
2010-12-27 20:42:10 +00:00
|
|
|
aVisitor.mEventStatus = nsEventStatus_eConsumeNoDefault;
|
2002-12-17 04:31:21 +00:00
|
|
|
}
|
|
|
|
}
|
2004-05-17 22:05:41 +00:00
|
|
|
break;
|
2000-05-30 02:45:55 +00:00
|
|
|
|
2004-05-17 22:05:41 +00:00
|
|
|
default:
|
|
|
|
break;
|
2013-03-28 19:41:32 +00:00
|
|
|
} //switch
|
2004-05-17 22:05:41 +00:00
|
|
|
} //click or outer activate event
|
2006-03-07 17:08:51 +00:00
|
|
|
} else if (outerActivateEvent &&
|
|
|
|
(oldType == NS_FORM_INPUT_SUBMIT ||
|
|
|
|
oldType == NS_FORM_INPUT_IMAGE) &&
|
|
|
|
mForm) {
|
|
|
|
// tell the form to flush a possible pending submission.
|
|
|
|
// the reason is that the script returned false (the event was
|
|
|
|
// not ignored) so if there is a stored submission, it needs to
|
|
|
|
// be submitted immediately.
|
|
|
|
mForm->FlushPendingSubmission();
|
|
|
|
}
|
2000-01-11 20:33:36 +00:00
|
|
|
} // if
|
1999-07-26 15:02:19 +00:00
|
|
|
|
2013-03-08 09:40:12 +00:00
|
|
|
if (NS_SUCCEEDED(rv) && mType == NS_FORM_INPUT_RANGE) {
|
|
|
|
PostHandleEventForRangeThumb(aVisitor);
|
|
|
|
}
|
|
|
|
|
2013-03-27 11:32:00 +00:00
|
|
|
// Open a file picker when we receive a click on a <input type='file'>.
|
|
|
|
// A click is handled in the following cases:
|
|
|
|
// - preventDefault() has not been called (or something similar);
|
|
|
|
// - it's the left mouse button.
|
|
|
|
// We do not prevent non-trusted click because authors can already use
|
|
|
|
// .click(). However, the file picker will follow the rules of popup-blocking.
|
|
|
|
if (mType == NS_FORM_INPUT_FILE && NS_IS_MOUSE_LEFT_CLICK(aVisitor.mEvent) &&
|
|
|
|
!aVisitor.mEvent->mFlags.mDefaultPrevented) {
|
|
|
|
return FireAsyncClickHandler();
|
|
|
|
}
|
|
|
|
|
2000-12-23 10:56:31 +00:00
|
|
|
return rv;
|
1998-09-01 01:27:08 +00:00
|
|
|
}
|
|
|
|
|
2013-03-08 09:40:12 +00:00
|
|
|
void
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::PostHandleEventForRangeThumb(nsEventChainPostVisitor& aVisitor)
|
2013-03-08 09:40:12 +00:00
|
|
|
{
|
|
|
|
MOZ_ASSERT(mType == NS_FORM_INPUT_RANGE);
|
|
|
|
|
|
|
|
if (nsEventStatus_eConsumeNoDefault == aVisitor.mEventStatus ||
|
|
|
|
!(aVisitor.mEvent->eventStructType == NS_MOUSE_EVENT ||
|
|
|
|
aVisitor.mEvent->eventStructType == NS_TOUCH_EVENT ||
|
|
|
|
aVisitor.mEvent->eventStructType == NS_KEY_EVENT)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsRangeFrame* rangeFrame = do_QueryFrame(GetPrimaryFrame());
|
|
|
|
if (!rangeFrame && mIsDraggingRange) {
|
|
|
|
CancelRangeThumbDrag();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (aVisitor.mEvent->message)
|
|
|
|
{
|
|
|
|
case NS_MOUSE_BUTTON_DOWN:
|
|
|
|
case NS_TOUCH_START: {
|
|
|
|
if (mIsDraggingRange) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (nsIPresShell::GetCapturingContent()) {
|
|
|
|
break; // don't start drag if someone else is already capturing
|
|
|
|
}
|
|
|
|
nsInputEvent* inputEvent = static_cast<nsInputEvent*>(aVisitor.mEvent);
|
|
|
|
if (inputEvent->IsShift() || inputEvent->IsControl() ||
|
|
|
|
inputEvent->IsAlt() || inputEvent->IsMeta() ||
|
|
|
|
inputEvent->IsAltGraph() || inputEvent->IsFn() ||
|
|
|
|
inputEvent->IsOS()) {
|
|
|
|
break; // ignore
|
|
|
|
}
|
|
|
|
if (aVisitor.mEvent->message == NS_MOUSE_BUTTON_DOWN) {
|
|
|
|
nsMouseEvent* mouseEvent = static_cast<nsMouseEvent*>(aVisitor.mEvent);
|
|
|
|
if (mouseEvent->buttons == nsMouseEvent::eLeftButtonFlag) {
|
|
|
|
StartRangeThumbDrag(inputEvent);
|
|
|
|
} else if (mIsDraggingRange) {
|
|
|
|
CancelRangeThumbDrag();
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
nsTouchEvent* touchEvent = static_cast<nsTouchEvent*>(aVisitor.mEvent);
|
|
|
|
if (touchEvent->touches.Length() == 1) {
|
|
|
|
StartRangeThumbDrag(inputEvent);
|
|
|
|
} else if (mIsDraggingRange) {
|
|
|
|
CancelRangeThumbDrag();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
aVisitor.mEvent->mFlags.mMultipleActionsPrevented = true;
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case NS_MOUSE_MOVE:
|
|
|
|
case NS_TOUCH_MOVE:
|
|
|
|
if (!mIsDraggingRange) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (nsIPresShell::GetCapturingContent() != this) {
|
|
|
|
// Someone else grabbed capture.
|
|
|
|
CancelRangeThumbDrag();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
SetValueOfRangeForUserEvent(rangeFrame->GetValueAtEventPoint(
|
|
|
|
static_cast<nsInputEvent*>(aVisitor.mEvent)));
|
|
|
|
aVisitor.mEvent->mFlags.mMultipleActionsPrevented = true;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NS_MOUSE_BUTTON_UP:
|
|
|
|
case NS_TOUCH_END:
|
|
|
|
if (!mIsDraggingRange) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
// We don't check to see whether we are the capturing content here and
|
|
|
|
// call CancelRangeThumbDrag() if that is the case. We just finish off
|
|
|
|
// the drag and set our final value (unless someone has called
|
|
|
|
// preventDefault() and prevents us getting here).
|
|
|
|
FinishRangeThumbDrag(static_cast<nsInputEvent*>(aVisitor.mEvent));
|
|
|
|
aVisitor.mEvent->mFlags.mMultipleActionsPrevented = true;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NS_KEY_PRESS:
|
|
|
|
if (mIsDraggingRange &&
|
|
|
|
static_cast<nsKeyEvent*>(aVisitor.mEvent)->keyCode == NS_VK_ESCAPE) {
|
|
|
|
CancelRangeThumbDrag();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NS_TOUCH_CANCEL:
|
|
|
|
if (mIsDraggingRange) {
|
|
|
|
CancelRangeThumbDrag();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-05-20 08:00:04 +00:00
|
|
|
void
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::MaybeLoadImage()
|
2009-05-20 08:00:04 +00:00
|
|
|
{
|
|
|
|
// Our base URI may have changed; claim that our URI changed, and the
|
|
|
|
// nsImageLoadingContent will decide whether a new image load is warranted.
|
|
|
|
nsAutoString uri;
|
|
|
|
if (mType == NS_FORM_INPUT_IMAGE &&
|
|
|
|
GetAttr(kNameSpaceID_None, nsGkAtoms::src, uri) &&
|
2011-10-17 14:59:28 +00:00
|
|
|
(NS_FAILED(LoadImage(uri, false, true)) ||
|
2009-05-20 08:00:04 +00:00
|
|
|
!LoadingEnabled())) {
|
2011-10-17 14:59:28 +00:00
|
|
|
CancelImageRequests(true);
|
2009-05-20 08:00:04 +00:00
|
|
|
}
|
|
|
|
}
|
1999-07-26 15:02:19 +00:00
|
|
|
|
2005-04-05 23:54:35 +00:00
|
|
|
nsresult
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
|
|
|
|
nsIContent* aBindingParent,
|
|
|
|
bool aCompileEventHandlers)
|
2002-07-20 23:09:24 +00:00
|
|
|
{
|
2005-04-05 23:54:35 +00:00
|
|
|
nsresult rv = nsGenericHTMLFormElement::BindToTree(aDocument, aParent,
|
|
|
|
aBindingParent,
|
|
|
|
aCompileEventHandlers);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
2003-07-24 17:10:14 +00:00
|
|
|
|
2012-08-13 22:11:50 +00:00
|
|
|
nsImageLoadingContent::BindToTree(aDocument, aParent, aBindingParent,
|
|
|
|
aCompileEventHandlers);
|
|
|
|
|
2005-04-05 23:54:35 +00:00
|
|
|
if (mType == NS_FORM_INPUT_IMAGE) {
|
2003-07-24 17:10:14 +00:00
|
|
|
// Our base URI may have changed; claim that our URI changed, and the
|
|
|
|
// nsImageLoadingContent will decide whether a new image load is warranted.
|
2009-05-20 08:00:04 +00:00
|
|
|
if (HasAttr(kNameSpaceID_None, nsGkAtoms::src)) {
|
2011-06-01 01:46:57 +00:00
|
|
|
// FIXME: Bug 660963 it would be nice if we could just have
|
|
|
|
// ClearBrokenState update our state and do it fast...
|
2009-05-20 08:00:04 +00:00
|
|
|
ClearBrokenState();
|
2011-06-01 01:46:57 +00:00
|
|
|
RemoveStatesSilently(NS_EVENT_STATE_BROKEN);
|
2009-05-20 08:00:04 +00:00
|
|
|
nsContentUtils::AddScriptRunner(
|
2013-03-28 19:41:32 +00:00
|
|
|
NS_NewRunnableMethod(this, &HTMLInputElement::MaybeLoadImage));
|
2003-07-24 17:10:14 +00:00
|
|
|
}
|
|
|
|
}
|
2005-04-05 23:54:35 +00:00
|
|
|
|
2002-07-20 23:09:24 +00:00
|
|
|
// Add radio to document if we don't have a form already (if we do it's
|
|
|
|
// already been added into that group)
|
|
|
|
if (aDocument && !mForm && mType == NS_FORM_INPUT_RADIO) {
|
|
|
|
AddedToRadioGroup();
|
|
|
|
}
|
2005-04-05 23:54:35 +00:00
|
|
|
|
2012-11-21 10:13:57 +00:00
|
|
|
// Set direction based on value if dir=auto
|
|
|
|
SetDirectionIfAuto(HasDirAuto(), false);
|
|
|
|
|
2010-08-21 17:52:57 +00:00
|
|
|
// An element can't suffer from value missing if it is not in a document.
|
|
|
|
// We have to check if we suffer from that as we are now in a document.
|
|
|
|
UpdateValueMissingValidityState();
|
|
|
|
|
2010-09-18 21:33:16 +00:00
|
|
|
// If there is a disabled fieldset in the parent chain, the element is now
|
|
|
|
// barred from constraint validation and can't suffer from value missing
|
|
|
|
// (call done before).
|
|
|
|
UpdateBarredFromConstraintValidation();
|
|
|
|
|
2011-06-01 01:46:57 +00:00
|
|
|
// And now make sure our state is up to date
|
|
|
|
UpdateState(false);
|
|
|
|
|
2005-04-05 23:54:35 +00:00
|
|
|
return rv;
|
2002-07-20 23:09:24 +00:00
|
|
|
}
|
|
|
|
|
2004-01-09 23:54:21 +00:00
|
|
|
void
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::UnbindFromTree(bool aDeep, bool aNullParent)
|
2003-07-24 17:10:14 +00:00
|
|
|
{
|
2005-04-05 23:54:35 +00:00
|
|
|
// If we have a form and are unbound from it,
|
2005-05-03 15:56:18 +00:00
|
|
|
// nsGenericHTMLFormElement::UnbindFromTree() will unset the form and
|
2005-04-05 23:54:35 +00:00
|
|
|
// that takes care of form's WillRemove so we just have to take care
|
|
|
|
// of the case where we're removing from the document and we don't
|
|
|
|
// have a form
|
|
|
|
if (!mForm && mType == NS_FORM_INPUT_RADIO) {
|
2010-11-11 12:34:27 +00:00
|
|
|
WillRemoveFromRadioGroup();
|
2003-07-24 17:10:14 +00:00
|
|
|
}
|
2005-04-05 23:54:35 +00:00
|
|
|
|
2012-08-13 22:11:50 +00:00
|
|
|
nsImageLoadingContent::UnbindFromTree(aDeep, aNullParent);
|
2005-04-05 23:54:35 +00:00
|
|
|
nsGenericHTMLFormElement::UnbindFromTree(aDeep, aNullParent);
|
2010-08-21 17:52:57 +00:00
|
|
|
|
2012-07-30 14:20:58 +00:00
|
|
|
// GetCurrentDoc is returning nullptr so we can update the value
|
2010-08-21 17:52:57 +00:00
|
|
|
// missing validity state to reflect we are no longer into a doc.
|
|
|
|
UpdateValueMissingValidityState();
|
2010-09-18 21:33:16 +00:00
|
|
|
// We might be no longer disabled because of parent chain changed.
|
|
|
|
UpdateBarredFromConstraintValidation();
|
2011-06-01 01:46:57 +00:00
|
|
|
|
|
|
|
// And now make sure our state is up to date
|
|
|
|
UpdateState(false);
|
2003-07-24 17:10:14 +00:00
|
|
|
}
|
|
|
|
|
2010-06-09 18:13:56 +00:00
|
|
|
void
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::HandleTypeChange(uint8_t aNewType)
|
2010-06-09 18:13:56 +00:00
|
|
|
{
|
2013-03-08 09:40:12 +00:00
|
|
|
if (mType == NS_FORM_INPUT_RANGE && mIsDraggingRange) {
|
2013-03-16 05:49:41 +00:00
|
|
|
CancelRangeThumbDrag(false);
|
2013-03-08 09:40:12 +00:00
|
|
|
}
|
|
|
|
|
2010-09-14 00:23:03 +00:00
|
|
|
ValueModeType aOldValueMode = GetValueMode();
|
2013-02-12 20:16:58 +00:00
|
|
|
uint8_t oldType = mType;
|
2010-09-14 00:23:03 +00:00
|
|
|
nsAutoString aOldValue;
|
2010-09-20 20:33:17 +00:00
|
|
|
|
2013-02-12 20:16:58 +00:00
|
|
|
if (aOldValueMode == VALUE_MODE_VALUE) {
|
2010-09-20 20:33:17 +00:00
|
|
|
GetValue(aOldValue);
|
|
|
|
}
|
2010-09-14 00:23:03 +00:00
|
|
|
|
2013-02-12 20:16:58 +00:00
|
|
|
// We already have a copy of the value, lets free it and changes the type.
|
|
|
|
FreeData();
|
|
|
|
mType = aNewType;
|
2011-03-24 16:06:58 +00:00
|
|
|
|
2013-02-12 20:16:58 +00:00
|
|
|
if (IsSingleLineTextControl()) {
|
2010-06-09 18:13:56 +00:00
|
|
|
mInputData.mState = new nsTextEditorState(this);
|
|
|
|
}
|
|
|
|
|
2013-02-12 20:16:58 +00:00
|
|
|
/**
|
|
|
|
* The following code is trying to reproduce the algorithm described here:
|
|
|
|
* http://www.whatwg.org/specs/web-apps/current-work/complete.html#input-type-change
|
|
|
|
*/
|
|
|
|
switch (GetValueMode()) {
|
|
|
|
case VALUE_MODE_DEFAULT:
|
|
|
|
case VALUE_MODE_DEFAULT_ON:
|
|
|
|
// If the previous value mode was value, we need to set the value content
|
|
|
|
// attribute to the previous value.
|
|
|
|
// There is no value sanitizing algorithm for elements in this mode.
|
|
|
|
if (aOldValueMode == VALUE_MODE_VALUE && !aOldValue.IsEmpty()) {
|
|
|
|
SetAttr(kNameSpaceID_None, nsGkAtoms::value, aOldValue, true);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case VALUE_MODE_VALUE:
|
|
|
|
// If the previous value mode wasn't value, we have to set the value to
|
|
|
|
// the value content attribute.
|
|
|
|
// SetValueInternal is going to sanitize the value.
|
|
|
|
{
|
|
|
|
nsAutoString value;
|
|
|
|
if (aOldValueMode != VALUE_MODE_VALUE) {
|
|
|
|
GetAttr(kNameSpaceID_None, nsGkAtoms::value, value);
|
|
|
|
} else {
|
|
|
|
value = aOldValue;
|
2010-09-20 20:33:17 +00:00
|
|
|
}
|
2013-02-12 20:16:58 +00:00
|
|
|
SetValueInternal(value, false, false);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case VALUE_MODE_FILENAME:
|
|
|
|
default:
|
|
|
|
// We don't care about the value.
|
|
|
|
// There is no value sanitizing algorithm for elements in this mode.
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Updating mFocusedValue in consequence:
|
2013-03-16 05:49:41 +00:00
|
|
|
// If the new type fires a change event on blur, but the previous type
|
|
|
|
// doesn't, we should set mFocusedValue to the current value.
|
|
|
|
// Otherwise, if the new type doesn't fire a change event on blur, but the
|
|
|
|
// previous type does, we should clear out mFocusedValue.
|
|
|
|
if (MayFireChangeOnBlur(mType) && !MayFireChangeOnBlur(oldType)) {
|
2013-02-12 20:16:58 +00:00
|
|
|
GetValueInternal(mFocusedValue);
|
|
|
|
} else if (!IsSingleLineTextControl(mType, false) &&
|
|
|
|
IsSingleLineTextControl(oldType, false)) {
|
|
|
|
mFocusedValue.Truncate();
|
2010-07-21 00:11:19 +00:00
|
|
|
}
|
2010-08-21 17:52:57 +00:00
|
|
|
|
2012-06-22 09:41:32 +00:00
|
|
|
UpdateHasRange();
|
|
|
|
|
2010-08-21 17:52:57 +00:00
|
|
|
// Do not notify, it will be done after if needed.
|
2011-10-17 14:59:28 +00:00
|
|
|
UpdateAllValidityStates(false);
|
2010-07-21 00:11:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::SanitizeValue(nsAString& aValue)
|
2010-07-21 00:11:19 +00:00
|
|
|
{
|
2011-11-16 07:50:19 +00:00
|
|
|
NS_ASSERTION(!mParserCreating, "The element parsing should be finished!");
|
2010-09-20 20:33:17 +00:00
|
|
|
|
2010-07-21 00:11:19 +00:00
|
|
|
switch (mType) {
|
|
|
|
case NS_FORM_INPUT_TEXT:
|
|
|
|
case NS_FORM_INPUT_SEARCH:
|
|
|
|
case NS_FORM_INPUT_TEL:
|
|
|
|
case NS_FORM_INPUT_PASSWORD:
|
|
|
|
{
|
|
|
|
PRUnichar crlf[] = { PRUnichar('\r'), PRUnichar('\n'), 0 };
|
|
|
|
aValue.StripChars(crlf);
|
|
|
|
}
|
|
|
|
break;
|
2011-08-22 12:58:01 +00:00
|
|
|
case NS_FORM_INPUT_EMAIL:
|
2010-08-18 18:34:14 +00:00
|
|
|
case NS_FORM_INPUT_URL:
|
|
|
|
{
|
|
|
|
PRUnichar crlf[] = { PRUnichar('\r'), PRUnichar('\n'), 0 };
|
|
|
|
aValue.StripChars(crlf);
|
|
|
|
|
|
|
|
aValue = nsContentUtils::TrimWhitespace<nsContentUtils::IsHTMLWhitespace>(aValue);
|
|
|
|
}
|
|
|
|
break;
|
2012-06-10 20:24:03 +00:00
|
|
|
case NS_FORM_INPUT_NUMBER:
|
|
|
|
{
|
2012-07-27 13:59:29 +00:00
|
|
|
nsresult ec;
|
2013-02-14 17:25:26 +00:00
|
|
|
double val = PromiseFlatString(aValue).ToDouble(&ec);
|
|
|
|
if (NS_FAILED(ec) || !MOZ_DOUBLE_IS_FINITE(val)) {
|
2012-06-10 20:24:03 +00:00
|
|
|
aValue.Truncate();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2013-02-16 12:35:57 +00:00
|
|
|
case NS_FORM_INPUT_RANGE:
|
|
|
|
{
|
|
|
|
double minimum = GetMinimum();
|
|
|
|
double maximum = GetMaximum();
|
|
|
|
MOZ_ASSERT(MOZ_DOUBLE_IS_FINITE(minimum) &&
|
|
|
|
MOZ_DOUBLE_IS_FINITE(maximum),
|
|
|
|
"type=range should have a default maximum/minimum");
|
|
|
|
|
|
|
|
// We use this to avoid modifying the string unnecessarily, since that
|
|
|
|
// may introduce rounding. This is set to true only if the value we
|
|
|
|
// parse out from aValue needs to be sanitized.
|
|
|
|
bool needSanitization = false;
|
|
|
|
|
|
|
|
double value;
|
|
|
|
bool ok = ConvertStringToNumber(aValue, value);
|
|
|
|
if (!ok) {
|
|
|
|
needSanitization = true;
|
|
|
|
// Set value to midway between minimum and maximum.
|
|
|
|
value = maximum <= minimum ? minimum : minimum + (maximum - minimum)/2.0;
|
|
|
|
} else if (value < minimum || maximum < minimum) {
|
|
|
|
needSanitization = true;
|
|
|
|
value = minimum;
|
|
|
|
} else if (value > maximum) {
|
|
|
|
needSanitization = true;
|
|
|
|
value = maximum;
|
|
|
|
}
|
|
|
|
|
|
|
|
double step = GetStep();
|
|
|
|
if (step != kStepAny) {
|
|
|
|
double stepBase = GetStepBase();
|
|
|
|
// There could be rounding issues below when dealing with fractional
|
|
|
|
// numbers, but let's ignore that until ECMAScript supplies us with a
|
|
|
|
// decimal number type.
|
|
|
|
double deltaToStep = NS_floorModulo(value - stepBase, step);
|
|
|
|
if (deltaToStep != 0) {
|
|
|
|
// "suffering from a step mismatch"
|
|
|
|
// Round the element's value to the nearest number for which the
|
|
|
|
// element would not suffer from a step mismatch, and which is
|
|
|
|
// greater than or equal to the minimum, and, if the maximum is not
|
|
|
|
// less than the minimum, which is less than or equal to the
|
|
|
|
// maximum, if there is a number that matches these constraints:
|
|
|
|
MOZ_ASSERT(deltaToStep > 0, "stepBelow/stepAbove will be wrong");
|
|
|
|
double stepBelow = value - deltaToStep;
|
|
|
|
double stepAbove = value - deltaToStep + step;
|
|
|
|
double halfStep = step / 2;
|
|
|
|
bool stepAboveIsClosest = (stepAbove - value) <= halfStep;
|
|
|
|
bool stepAboveInRange = stepAbove >= minimum &&
|
|
|
|
stepAbove <= maximum;
|
|
|
|
bool stepBelowInRange = stepBelow >= minimum &&
|
|
|
|
stepBelow <= maximum;
|
|
|
|
|
|
|
|
if ((stepAboveIsClosest || !stepBelowInRange) && stepAboveInRange) {
|
|
|
|
needSanitization = true;
|
|
|
|
value = stepAbove;
|
|
|
|
} else if ((!stepAboveIsClosest || !stepAboveInRange) && stepBelowInRange) {
|
|
|
|
needSanitization = true;
|
|
|
|
value = stepBelow;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (needSanitization) {
|
|
|
|
aValue.Truncate();
|
|
|
|
aValue.AppendFloat(value);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2012-12-27 18:48:13 +00:00
|
|
|
case NS_FORM_INPUT_DATE:
|
|
|
|
{
|
|
|
|
if (!aValue.IsEmpty() && !IsValidDate(aValue)) {
|
|
|
|
aValue.Truncate();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2013-01-11 15:00:52 +00:00
|
|
|
case NS_FORM_INPUT_TIME:
|
|
|
|
{
|
|
|
|
if (!aValue.IsEmpty() && !IsValidTime(aValue)) {
|
|
|
|
aValue.Truncate();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2012-12-27 18:48:13 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::IsValidDate(const nsAString& aValue) const
|
2012-12-27 18:48:13 +00:00
|
|
|
{
|
2012-12-27 18:55:31 +00:00
|
|
|
uint32_t year, month, day;
|
2013-01-11 15:02:58 +00:00
|
|
|
return GetValueAsDate(aValue, &year, &month, &day);
|
2012-12-27 18:55:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::GetValueAsDate(const nsAString& aValue,
|
|
|
|
uint32_t* aYear,
|
|
|
|
uint32_t* aMonth,
|
|
|
|
uint32_t* aDay) const
|
2012-12-27 18:55:31 +00:00
|
|
|
{
|
|
|
|
|
2012-12-27 18:48:13 +00:00
|
|
|
/*
|
2013-01-11 15:02:58 +00:00
|
|
|
* Parse the year, month, day values out a date string formatted as 'yyyy-mm-dd'.
|
2012-12-27 18:48:13 +00:00
|
|
|
* -The year must be 4 or more digits long, and year > 0
|
|
|
|
* -The month must be exactly 2 digits long, and 01 <= month <= 12
|
|
|
|
* -The day must be exactly 2 digit long, and 01 <= day <= maxday
|
|
|
|
* Where maxday is the number of days in the month 'month' and year 'year'
|
|
|
|
*/
|
|
|
|
|
2013-01-11 15:02:58 +00:00
|
|
|
if (aValue.Length() < 10) {
|
2012-12-27 18:48:13 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2013-01-11 15:02:58 +00:00
|
|
|
uint32_t endOfYearOffset = 0;
|
|
|
|
for (; NS_IsAsciiDigit(aValue[endOfYearOffset]); ++endOfYearOffset);
|
2012-12-27 18:48:13 +00:00
|
|
|
|
2013-01-11 15:02:58 +00:00
|
|
|
// The year must be at least 4 digits long.
|
|
|
|
if (aValue[endOfYearOffset] != '-' || endOfYearOffset < 4) {
|
|
|
|
return false;
|
|
|
|
}
|
2012-12-27 18:48:13 +00:00
|
|
|
|
2013-01-11 15:02:58 +00:00
|
|
|
// Now, we know where is the next '-' and what should be the size of the
|
|
|
|
// string.
|
|
|
|
if (aValue[endOfYearOffset + 3] != '-' ||
|
|
|
|
aValue.Length() != 10 + (endOfYearOffset - 4)) {
|
|
|
|
return false;
|
|
|
|
}
|
2012-12-27 18:48:13 +00:00
|
|
|
|
2013-01-11 15:02:58 +00:00
|
|
|
nsresult ec;
|
|
|
|
*aYear = PromiseFlatString(StringHead(aValue, endOfYearOffset)).ToInteger(&ec);
|
|
|
|
if (NS_FAILED(ec) || *aYear == 0) {
|
|
|
|
return false;
|
|
|
|
}
|
2012-12-27 18:48:13 +00:00
|
|
|
|
2013-01-11 15:02:58 +00:00
|
|
|
if (!DigitSubStringToNumber(aValue, endOfYearOffset + 1, 2, aMonth) ||
|
|
|
|
*aMonth < 1 || *aMonth > 12) {
|
|
|
|
return false;
|
2010-07-21 00:11:19 +00:00
|
|
|
}
|
2012-12-27 18:48:13 +00:00
|
|
|
|
2013-01-11 15:02:58 +00:00
|
|
|
return DigitSubStringToNumber(aValue, endOfYearOffset + 4, 2, aDay) &&
|
|
|
|
*aDay > 0 && *aDay <= NumberOfDaysInMonth(*aMonth, *aYear);
|
2010-06-09 18:13:56 +00:00
|
|
|
}
|
|
|
|
|
2012-12-27 18:48:13 +00:00
|
|
|
uint32_t
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::NumberOfDaysInMonth(uint32_t aMonth, uint32_t aYear) const
|
2012-12-27 18:48:13 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Returns the number of days in a month.
|
|
|
|
* Months that are |longMonths| always have 31 days.
|
|
|
|
* Months that are not |longMonths| have 30 days except February (month 2).
|
|
|
|
* February has 29 days during leap years which are years that are divisible by 400.
|
|
|
|
* or divisible by 100 and 4. February has 28 days otherwise.
|
|
|
|
*/
|
|
|
|
|
|
|
|
static const bool longMonths[] = { true, false, true, false, true, false,
|
|
|
|
true, true, false, true, false, true };
|
|
|
|
MOZ_ASSERT(aMonth <= 12 && aMonth > 0);
|
|
|
|
|
|
|
|
if (longMonths[aMonth-1]) {
|
|
|
|
return 31;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (aMonth != 2) {
|
|
|
|
return 30;
|
|
|
|
}
|
|
|
|
|
|
|
|
return (aYear % 400 == 0 || (aYear % 100 != 0 && aYear % 4 == 0))
|
|
|
|
? 29 : 28;
|
|
|
|
}
|
2013-01-11 15:00:52 +00:00
|
|
|
|
|
|
|
/* static */ bool
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::DigitSubStringToNumber(const nsAString& aStr,
|
|
|
|
uint32_t aStart, uint32_t aLen,
|
|
|
|
uint32_t* aRetVal)
|
2013-01-11 15:00:52 +00:00
|
|
|
{
|
|
|
|
MOZ_ASSERT(aStr.Length() > (aStart + aLen - 1));
|
|
|
|
|
|
|
|
for (uint32_t offset = 0; offset < aLen; ++offset) {
|
|
|
|
if (!NS_IsAsciiDigit(aStr[aStart + offset])) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult ec;
|
|
|
|
*aRetVal = static_cast<uint32_t>(PromiseFlatString(Substring(aStr, aStart, aLen)).ToInteger(&ec));
|
|
|
|
|
|
|
|
return NS_SUCCEEDED(ec);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::IsValidTime(const nsAString& aValue) const
|
2013-01-22 18:22:33 +00:00
|
|
|
{
|
|
|
|
return ParseTime(aValue, nullptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* static */ bool
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::ParseTime(const nsAString& aValue, uint32_t* aResult)
|
2013-01-11 15:00:52 +00:00
|
|
|
{
|
|
|
|
/* The string must have the following parts:
|
|
|
|
* - HOURS: two digits, value being in [0, 23];
|
|
|
|
* - Colon (:);
|
|
|
|
* - MINUTES: two digits, value being in [0, 59];
|
|
|
|
* - Optional:
|
|
|
|
* - Colon (:);
|
|
|
|
* - SECONDS: two digits, value being in [0, 59];
|
|
|
|
* - Optional:
|
|
|
|
* - DOT (.);
|
|
|
|
* - FRACTIONAL SECONDS: one to three digits, no value range.
|
|
|
|
*/
|
|
|
|
|
|
|
|
// The following format is the shorter one allowed: "HH:MM".
|
|
|
|
if (aValue.Length() < 5) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t hours;
|
|
|
|
if (!DigitSubStringToNumber(aValue, 0, 2, &hours) || hours > 23) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Hours/minutes separator.
|
|
|
|
if (aValue[2] != ':') {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t minutes;
|
|
|
|
if (!DigitSubStringToNumber(aValue, 3, 2, &minutes) || minutes > 59) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (aValue.Length() == 5) {
|
2013-01-22 18:22:33 +00:00
|
|
|
if (aResult) {
|
|
|
|
*aResult = ((hours * 60) + minutes) * 60000;
|
|
|
|
}
|
2013-01-11 15:00:52 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// The following format is the next shorter one: "HH:MM:SS".
|
|
|
|
if (aValue.Length() < 8 || aValue[5] != ':') {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t seconds;
|
|
|
|
if (!DigitSubStringToNumber(aValue, 6, 2, &seconds) || seconds > 59) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (aValue.Length() == 8) {
|
2013-01-22 18:22:33 +00:00
|
|
|
if (aResult) {
|
|
|
|
*aResult = (((hours * 60) + minutes) * 60 + seconds) * 1000;
|
|
|
|
}
|
2013-01-11 15:00:52 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// The string must follow this format now: "HH:MM:SS.{s,ss,sss}".
|
|
|
|
// There can be 1 to 3 digits for the fractions of seconds.
|
|
|
|
if (aValue.Length() == 9 || aValue.Length() > 12 || aValue[8] != '.') {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t fractionsSeconds;
|
2013-01-22 18:22:33 +00:00
|
|
|
if (!DigitSubStringToNumber(aValue, 9, aValue.Length() - 9, &fractionsSeconds)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (aResult) {
|
|
|
|
*aResult = (((hours * 60) + minutes) * 60 + seconds) * 1000 +
|
|
|
|
// NOTE: there is 10.0 instead of 10 and static_cast<int> because
|
|
|
|
// some old [and stupid] compilers can't just do the right thing.
|
|
|
|
fractionsSeconds * pow(10.0, static_cast<int>(3 - (aValue.Length() - 9)));
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
2013-01-11 15:00:52 +00:00
|
|
|
}
|
2013-03-28 19:41:32 +00:00
|
|
|
|
2011-09-29 06:19:26 +00:00
|
|
|
bool
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::ParseAttribute(int32_t aNamespaceID,
|
|
|
|
nsIAtom* aAttribute,
|
|
|
|
const nsAString& aValue,
|
|
|
|
nsAttrValue& aResult)
|
1998-09-01 01:27:08 +00:00
|
|
|
{
|
2005-11-29 16:37:15 +00:00
|
|
|
if (aNamespaceID == kNameSpaceID_None) {
|
2006-12-26 17:47:52 +00:00
|
|
|
if (aAttribute == nsGkAtoms::type) {
|
2005-11-29 16:37:15 +00:00
|
|
|
// XXX ARG!! This is major evilness. ParseAttribute
|
|
|
|
// shouldn't set members. Override SetAttr instead
|
2012-08-22 15:56:38 +00:00
|
|
|
int32_t newType;
|
2011-09-29 06:19:26 +00:00
|
|
|
bool success = aResult.ParseEnumValue(aValue, kInputTypeTable, false);
|
2010-04-15 11:03:00 +00:00
|
|
|
if (success) {
|
2007-07-25 04:29:47 +00:00
|
|
|
newType = aResult.GetEnumValue();
|
2013-02-16 12:35:57 +00:00
|
|
|
if ((IsExperimentalMobileType(newType) &&
|
|
|
|
!Preferences::GetBool("dom.experimental_forms", false)) ||
|
|
|
|
(newType == NS_FORM_INPUT_RANGE &&
|
|
|
|
!Preferences::GetBool("dom.experimental_forms_range", false))) {
|
2012-06-23 12:32:54 +00:00
|
|
|
newType = kInputDefaultType->value;
|
2013-01-21 10:48:48 +00:00
|
|
|
aResult.SetTo(newType, &aValue);
|
|
|
|
}
|
2007-07-25 04:29:47 +00:00
|
|
|
} else {
|
2010-04-15 11:03:00 +00:00
|
|
|
newType = kInputDefaultType->value;
|
2005-11-29 16:37:15 +00:00
|
|
|
}
|
2004-03-04 02:06:28 +00:00
|
|
|
|
2008-08-25 17:21:28 +00:00
|
|
|
if (newType != mType) {
|
|
|
|
// Make sure to do the check for newType being NS_FORM_INPUT_FILE and
|
|
|
|
// the corresponding SetValueInternal() call _before_ we set mType.
|
|
|
|
// That way the logic in SetValueInternal() will work right (that logic
|
|
|
|
// makes assumptions about our frame based on mType, but we won't have
|
|
|
|
// had time to recreate frames yet -- that happens later in the
|
|
|
|
// SetAttr() process).
|
2009-10-27 18:14:34 +00:00
|
|
|
if (newType == NS_FORM_INPUT_FILE || mType == NS_FORM_INPUT_FILE) {
|
|
|
|
// This call isn't strictly needed any more since we'll never
|
|
|
|
// confuse values and filenames. However it's there for backwards
|
2008-08-25 17:21:28 +00:00
|
|
|
// compat.
|
2010-11-23 23:45:53 +00:00
|
|
|
ClearFiles(false);
|
2008-08-25 17:21:28 +00:00
|
|
|
}
|
2004-03-04 02:06:28 +00:00
|
|
|
|
2010-06-09 18:13:56 +00:00
|
|
|
HandleTypeChange(newType);
|
2008-08-25 17:21:28 +00:00
|
|
|
}
|
2006-02-09 16:34:06 +00:00
|
|
|
|
2007-07-25 04:29:47 +00:00
|
|
|
return success;
|
2005-11-29 16:37:15 +00:00
|
|
|
}
|
2006-12-26 17:47:52 +00:00
|
|
|
if (aAttribute == nsGkAtoms::width) {
|
2011-02-04 19:46:16 +00:00
|
|
|
return aResult.ParseSpecialIntValue(aValue);
|
2005-11-29 16:37:15 +00:00
|
|
|
}
|
2006-12-26 17:47:52 +00:00
|
|
|
if (aAttribute == nsGkAtoms::height) {
|
2011-02-04 19:46:16 +00:00
|
|
|
return aResult.ParseSpecialIntValue(aValue);
|
2005-11-29 16:37:15 +00:00
|
|
|
}
|
2006-12-26 17:47:52 +00:00
|
|
|
if (aAttribute == nsGkAtoms::maxlength) {
|
2010-03-05 19:38:26 +00:00
|
|
|
return aResult.ParseNonNegativeIntValue(aValue);
|
2005-11-29 16:37:15 +00:00
|
|
|
}
|
2006-12-26 17:47:52 +00:00
|
|
|
if (aAttribute == nsGkAtoms::size) {
|
2010-11-06 09:30:27 +00:00
|
|
|
return aResult.ParsePositiveIntValue(aValue);
|
2005-11-29 16:37:15 +00:00
|
|
|
}
|
2006-12-26 17:47:52 +00:00
|
|
|
if (aAttribute == nsGkAtoms::border) {
|
2005-11-29 16:37:15 +00:00
|
|
|
return aResult.ParseIntWithBounds(aValue, 0);
|
|
|
|
}
|
2006-12-26 17:47:52 +00:00
|
|
|
if (aAttribute == nsGkAtoms::align) {
|
2005-11-29 16:37:15 +00:00
|
|
|
return ParseAlignValue(aValue, aResult);
|
|
|
|
}
|
2010-08-20 17:47:30 +00:00
|
|
|
if (aAttribute == nsGkAtoms::formmethod) {
|
2011-10-17 14:59:28 +00:00
|
|
|
return aResult.ParseEnumValue(aValue, kFormMethodTable, false);
|
2010-08-20 17:47:30 +00:00
|
|
|
}
|
|
|
|
if (aAttribute == nsGkAtoms::formenctype) {
|
2011-10-17 14:59:28 +00:00
|
|
|
return aResult.ParseEnumValue(aValue, kFormEnctypeTable, false);
|
2010-08-20 17:47:30 +00:00
|
|
|
}
|
2010-09-14 17:58:34 +00:00
|
|
|
if (aAttribute == nsGkAtoms::autocomplete) {
|
2011-10-17 14:59:28 +00:00
|
|
|
return aResult.ParseEnumValue(aValue, kInputAutocompleteTable, false);
|
2010-09-14 17:58:34 +00:00
|
|
|
}
|
2012-08-17 09:53:44 +00:00
|
|
|
if (aAttribute == nsGkAtoms::inputmode) {
|
|
|
|
return aResult.ParseEnumValue(aValue, kInputInputmodeTable, false);
|
|
|
|
}
|
2005-11-29 16:37:15 +00:00
|
|
|
if (ParseImageAttribute(aAttribute, aValue, aResult)) {
|
|
|
|
// We have to call |ParseImageAttribute| unconditionally since we
|
|
|
|
// don't know if we're going to have a type="image" attribute yet,
|
|
|
|
// (or could have it set dynamically in the future). See bug
|
|
|
|
// 214077.
|
2011-10-17 14:59:28 +00:00
|
|
|
return true;
|
2005-11-29 16:37:15 +00:00
|
|
|
}
|
1998-11-07 05:27:39 +00:00
|
|
|
}
|
2000-12-23 10:56:31 +00:00
|
|
|
|
2005-11-29 16:37:15 +00:00
|
|
|
return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
|
|
|
|
aResult);
|
1998-09-01 01:27:08 +00:00
|
|
|
}
|
|
|
|
|
1998-09-05 04:00:06 +00:00
|
|
|
static void
|
2004-01-26 19:22:05 +00:00
|
|
|
MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
|
2001-05-31 22:19:43 +00:00
|
|
|
nsRuleData* aData)
|
1998-09-01 01:27:08 +00:00
|
|
|
{
|
2006-12-26 17:47:52 +00:00
|
|
|
const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::type);
|
2004-04-13 16:45:59 +00:00
|
|
|
if (value && value->Type() == nsAttrValue::eEnum &&
|
|
|
|
value->GetEnumValue() == NS_FORM_INPUT_IMAGE) {
|
2004-02-10 19:36:43 +00:00
|
|
|
nsGenericHTMLFormElement::MapImageBorderAttributeInto(aAttributes, aData);
|
|
|
|
nsGenericHTMLFormElement::MapImageMarginAttributeInto(aAttributes, aData);
|
|
|
|
nsGenericHTMLFormElement::MapImageSizeAttributesInto(aAttributes, aData);
|
2002-12-27 00:41:52 +00:00
|
|
|
// Images treat align as "float"
|
2004-02-10 19:36:43 +00:00
|
|
|
nsGenericHTMLFormElement::MapImageAlignAttributeInto(aAttributes, aData);
|
2013-03-28 19:41:32 +00:00
|
|
|
}
|
2000-12-23 10:56:31 +00:00
|
|
|
|
2004-02-10 19:36:43 +00:00
|
|
|
nsGenericHTMLFormElement::MapCommonAttributesInto(aAttributes, aData);
|
1998-09-01 01:27:08 +00:00
|
|
|
}
|
|
|
|
|
2004-10-24 17:10:32 +00:00
|
|
|
nsChangeHint
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::GetAttributeChangeHint(const nsIAtom* aAttribute,
|
|
|
|
int32_t aModType) const
|
1999-07-07 01:24:40 +00:00
|
|
|
{
|
2004-10-24 17:10:32 +00:00
|
|
|
nsChangeHint retval =
|
|
|
|
nsGenericHTMLFormElement::GetAttributeChangeHint(aAttribute, aModType);
|
2006-12-26 17:47:52 +00:00
|
|
|
if (aAttribute == nsGkAtoms::type) {
|
2004-10-24 17:10:32 +00:00
|
|
|
NS_UpdateHint(retval, NS_STYLE_HINT_FRAMECHANGE);
|
2007-12-19 17:46:54 +00:00
|
|
|
} else if (mType == NS_FORM_INPUT_IMAGE &&
|
|
|
|
(aAttribute == nsGkAtoms::alt ||
|
|
|
|
aAttribute == nsGkAtoms::value)) {
|
|
|
|
// We might need to rebuild our alt text. Just go ahead and
|
|
|
|
// reconstruct our frame. This should be quite rare..
|
|
|
|
NS_UpdateHint(retval, NS_STYLE_HINT_FRAMECHANGE);
|
2006-12-26 17:47:52 +00:00
|
|
|
} else if (aAttribute == nsGkAtoms::value) {
|
2004-10-24 17:10:32 +00:00
|
|
|
NS_UpdateHint(retval, NS_STYLE_HINT_REFLOW);
|
2006-12-26 17:47:52 +00:00
|
|
|
} else if (aAttribute == nsGkAtoms::size &&
|
2011-10-17 14:59:28 +00:00
|
|
|
IsSingleLineTextControl(false)) {
|
2004-10-24 17:10:32 +00:00
|
|
|
NS_UpdateHint(retval, NS_STYLE_HINT_REFLOW);
|
2010-10-19 13:11:07 +00:00
|
|
|
} else if (PlaceholderApplies() && aAttribute == nsGkAtoms::placeholder) {
|
|
|
|
NS_UpdateHint(retval, NS_STYLE_HINT_FRAMECHANGE);
|
2003-07-11 21:16:12 +00:00
|
|
|
}
|
2004-10-24 17:10:32 +00:00
|
|
|
return retval;
|
2003-07-11 21:16:12 +00:00
|
|
|
}
|
|
|
|
|
2011-09-29 06:19:26 +00:00
|
|
|
NS_IMETHODIMP_(bool)
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::IsAttributeMapped(const nsIAtom* aAttribute) const
|
2003-07-11 21:16:12 +00:00
|
|
|
{
|
2004-02-25 21:04:50 +00:00
|
|
|
static const MappedAttributeEntry attributes[] = {
|
2006-12-26 17:47:52 +00:00
|
|
|
{ &nsGkAtoms::align },
|
|
|
|
{ &nsGkAtoms::type },
|
2012-07-30 14:20:58 +00:00
|
|
|
{ nullptr },
|
2003-04-16 20:54:20 +00:00
|
|
|
};
|
|
|
|
|
2004-02-25 21:04:50 +00:00
|
|
|
static const MappedAttributeEntry* const map[] = {
|
2003-04-16 20:54:20 +00:00
|
|
|
attributes,
|
|
|
|
sCommonAttributeMap,
|
2003-07-11 21:16:12 +00:00
|
|
|
sImageMarginSizeAttributeMap,
|
2003-04-16 20:54:20 +00:00
|
|
|
sImageBorderAttributeMap,
|
|
|
|
};
|
|
|
|
|
2011-12-18 10:09:27 +00:00
|
|
|
return FindAttributeDependence(aAttribute, map);
|
1999-07-07 01:24:40 +00:00
|
|
|
}
|
|
|
|
|
2005-01-12 19:45:38 +00:00
|
|
|
nsMapRuleToAttributesFunc
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::GetAttributeMappingFunction() const
|
1998-09-05 04:00:06 +00:00
|
|
|
{
|
2005-01-12 19:45:38 +00:00
|
|
|
return &MapAttributesIntoRule;
|
1998-09-05 04:00:06 +00:00
|
|
|
}
|
|
|
|
|
2000-06-23 14:12:24 +00:00
|
|
|
|
1999-12-01 15:12:49 +00:00
|
|
|
// Controllers Methods
|
2000-12-23 10:56:31 +00:00
|
|
|
|
2013-03-28 19:41:32 +00:00
|
|
|
nsIControllers*
|
|
|
|
HTMLInputElement::GetControllers(ErrorResult& aRv)
|
1999-12-01 15:12:49 +00:00
|
|
|
{
|
|
|
|
//XXX: what about type "file"?
|
2011-10-17 14:59:28 +00:00
|
|
|
if (IsSingleLineTextControl(false))
|
1999-12-01 15:12:49 +00:00
|
|
|
{
|
|
|
|
if (!mControllers)
|
|
|
|
{
|
2000-02-16 01:41:17 +00:00
|
|
|
nsresult rv;
|
2002-12-17 13:29:39 +00:00
|
|
|
mControllers = do_CreateInstance(kXULControllersCID, &rv);
|
2013-03-28 19:41:32 +00:00
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
aRv.Throw(rv);
|
|
|
|
return nullptr;
|
|
|
|
}
|
2002-12-17 13:29:39 +00:00
|
|
|
|
2000-12-23 10:56:31 +00:00
|
|
|
nsCOMPtr<nsIController>
|
|
|
|
controller(do_CreateInstance("@mozilla.org/editor/editorcontroller;1",
|
|
|
|
&rv));
|
2013-03-28 19:41:32 +00:00
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
aRv.Throw(rv);
|
|
|
|
return nullptr;
|
|
|
|
}
|
2002-12-17 13:29:39 +00:00
|
|
|
|
1999-12-15 03:54:52 +00:00
|
|
|
mControllers->AppendController(controller);
|
2011-12-24 00:11:30 +00:00
|
|
|
|
|
|
|
controller = do_CreateInstance("@mozilla.org/editor/editingcontroller;1",
|
|
|
|
&rv);
|
2013-03-28 19:41:32 +00:00
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
aRv.Throw(rv);
|
|
|
|
return nullptr;
|
|
|
|
}
|
2011-12-24 00:11:30 +00:00
|
|
|
|
|
|
|
mControllers->AppendController(controller);
|
1999-12-01 15:12:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-03-28 19:41:32 +00:00
|
|
|
return mControllers;
|
1999-12-01 15:12:49 +00:00
|
|
|
}
|
2000-04-13 05:15:59 +00:00
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::GetControllers(nsIControllers** aResult)
|
2000-04-13 05:15:59 +00:00
|
|
|
{
|
2013-03-28 19:41:32 +00:00
|
|
|
NS_ENSURE_ARG_POINTER(aResult);
|
2000-12-23 10:56:31 +00:00
|
|
|
|
2013-03-28 19:41:32 +00:00
|
|
|
ErrorResult rv;
|
|
|
|
nsRefPtr<nsIControllers> controller = GetControllers(rv);
|
|
|
|
controller.forget(aResult);
|
|
|
|
return rv.ErrorCode();
|
|
|
|
}
|
2000-12-23 10:56:31 +00:00
|
|
|
|
2013-03-28 19:41:32 +00:00
|
|
|
int32_t
|
|
|
|
HTMLInputElement::GetTextLength(ErrorResult& aRv)
|
|
|
|
{
|
|
|
|
nsAutoString val;
|
|
|
|
GetValue(val);
|
|
|
|
return val.Length();
|
2000-04-13 05:15:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::GetTextLength(int32_t* aTextLength)
|
|
|
|
{
|
|
|
|
ErrorResult rv;
|
|
|
|
*aTextLength = GetTextLength(rv);
|
|
|
|
return rv.ErrorCode();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::SetSelectionRange(int32_t aSelectionStart,
|
|
|
|
int32_t aSelectionEnd,
|
2013-03-28 19:41:32 +00:00
|
|
|
const Optional<nsAString>& aDirection,
|
|
|
|
ErrorResult& aRv)
|
2000-04-13 05:15:59 +00:00
|
|
|
{
|
2011-10-17 14:59:28 +00:00
|
|
|
nsIFormControlFrame* formControlFrame = GetFormControlFrame(true);
|
2000-12-23 10:56:31 +00:00
|
|
|
|
|
|
|
if (formControlFrame) {
|
2009-01-12 19:20:59 +00:00
|
|
|
nsITextControlFrame* textControlFrame = do_QueryFrame(formControlFrame);
|
2011-02-05 00:29:29 +00:00
|
|
|
if (textControlFrame) {
|
2011-07-28 17:51:22 +00:00
|
|
|
// 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;
|
2013-03-28 19:41:32 +00:00
|
|
|
if (aDirection.WasPassed() && aDirection.Value().EqualsLiteral("backward")) {
|
2011-07-28 17:51:22 +00:00
|
|
|
dir = nsITextControlFrame::eBackward;
|
|
|
|
}
|
|
|
|
|
2013-03-28 19:41:32 +00:00
|
|
|
aRv = textControlFrame->SetSelectionRange(aSelectionStart, aSelectionEnd, dir);
|
|
|
|
if (!aRv.Failed()) {
|
|
|
|
aRv = textControlFrame->ScrollSelectionIntoView();
|
2011-02-05 00:29:29 +00:00
|
|
|
}
|
|
|
|
}
|
2000-04-13 05:15:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::SetSelectionRange(int32_t aSelectionStart,
|
|
|
|
int32_t aSelectionEnd,
|
|
|
|
const nsAString& aDirection)
|
2000-04-13 05:15:59 +00:00
|
|
|
{
|
2013-03-28 19:41:32 +00:00
|
|
|
ErrorResult rv;
|
|
|
|
Optional<nsAString> direction;
|
|
|
|
direction = &aDirection;
|
2011-07-29 21:31:57 +00:00
|
|
|
|
2013-03-28 19:41:32 +00:00
|
|
|
SetSelectionRange(aSelectionStart, aSelectionEnd, direction, rv);
|
|
|
|
return rv.ErrorCode();
|
|
|
|
}
|
2011-10-07 13:40:11 +00:00
|
|
|
|
2013-03-28 19:41:32 +00:00
|
|
|
int32_t
|
|
|
|
HTMLInputElement::GetSelectionStart(ErrorResult& aRv)
|
|
|
|
{
|
|
|
|
int32_t selEnd, selStart;
|
|
|
|
aRv = GetSelectionRange(&selStart, &selEnd);
|
|
|
|
|
|
|
|
if (aRv.Failed()) {
|
|
|
|
nsTextEditorState* state = GetEditorState();
|
2011-10-07 13:40:11 +00:00
|
|
|
if (state && state->IsSelectionCached()) {
|
2013-03-28 19:41:32 +00:00
|
|
|
aRv = NS_OK;
|
|
|
|
return state->GetSelectionProperties().mStart;
|
2011-10-07 13:40:11 +00:00
|
|
|
}
|
|
|
|
}
|
2013-03-28 19:41:32 +00:00
|
|
|
|
|
|
|
return selStart;
|
2000-04-13 05:15:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::GetSelectionStart(int32_t* aSelectionStart)
|
2000-04-13 05:15:59 +00:00
|
|
|
{
|
2013-03-28 19:41:32 +00:00
|
|
|
NS_ENSURE_ARG_POINTER(aSelectionStart);
|
|
|
|
|
|
|
|
ErrorResult rv;
|
|
|
|
*aSelectionStart = GetSelectionStart(rv);
|
|
|
|
return rv.ErrorCode();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
HTMLInputElement::SetSelectionStart(int32_t aSelectionStart, ErrorResult& aRv)
|
|
|
|
{
|
|
|
|
nsTextEditorState* state = GetEditorState();
|
2011-07-29 21:31:57 +00:00
|
|
|
if (state && state->IsSelectionCached()) {
|
|
|
|
state->GetSelectionProperties().mStart = aSelectionStart;
|
2013-03-28 19:41:32 +00:00
|
|
|
return;
|
2011-07-29 21:31:57 +00:00
|
|
|
}
|
|
|
|
|
2011-07-28 17:51:22 +00:00
|
|
|
nsAutoString direction;
|
2013-03-28 19:41:32 +00:00
|
|
|
aRv = GetSelectionDirection(direction);
|
|
|
|
if (aRv.Failed()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-08-22 15:56:38 +00:00
|
|
|
int32_t start, end;
|
2013-03-28 19:41:32 +00:00
|
|
|
aRv = GetSelectionRange(&start, &end);
|
|
|
|
if (aRv.Failed()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2011-07-28 17:51:22 +00:00
|
|
|
start = aSelectionStart;
|
|
|
|
if (end < start) {
|
|
|
|
end = start;
|
2000-04-13 05:15:59 +00:00
|
|
|
}
|
2013-03-28 19:41:32 +00:00
|
|
|
|
|
|
|
aRv = SetSelectionRange(start, end, direction);
|
2000-04-13 05:15:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::SetSelectionStart(int32_t aSelectionStart)
|
2000-04-13 05:15:59 +00:00
|
|
|
{
|
2013-03-28 19:41:32 +00:00
|
|
|
ErrorResult rv;
|
|
|
|
SetSelectionStart(aSelectionStart, rv);
|
|
|
|
return rv.ErrorCode();
|
|
|
|
}
|
2011-07-29 21:31:57 +00:00
|
|
|
|
2013-03-28 19:41:32 +00:00
|
|
|
int32_t
|
|
|
|
HTMLInputElement::GetSelectionEnd(ErrorResult& aRv)
|
|
|
|
{
|
|
|
|
int32_t selStart, selEnd;
|
|
|
|
aRv = GetSelectionRange(&selStart, &selEnd);
|
2011-10-07 13:40:11 +00:00
|
|
|
|
2013-03-28 19:41:32 +00:00
|
|
|
if (aRv.Failed()) {
|
|
|
|
nsTextEditorState* state = GetEditorState();
|
2011-10-07 13:40:11 +00:00
|
|
|
if (state && state->IsSelectionCached()) {
|
2013-03-28 19:41:32 +00:00
|
|
|
aRv = NS_OK;
|
|
|
|
return state->GetSelectionProperties().mEnd;
|
2011-10-07 13:40:11 +00:00
|
|
|
}
|
|
|
|
}
|
2000-04-13 05:15:59 +00:00
|
|
|
|
2013-03-28 19:41:32 +00:00
|
|
|
return selEnd;
|
|
|
|
}
|
2000-04-13 05:15:59 +00:00
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::GetSelectionEnd(int32_t* aSelectionEnd)
|
2000-04-13 05:15:59 +00:00
|
|
|
{
|
2013-03-28 19:41:32 +00:00
|
|
|
NS_ENSURE_ARG_POINTER(aSelectionEnd);
|
|
|
|
|
|
|
|
ErrorResult rv;
|
|
|
|
*aSelectionEnd = GetSelectionEnd(rv);
|
|
|
|
return rv.ErrorCode();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
HTMLInputElement::SetSelectionEnd(int32_t aSelectionEnd, ErrorResult& aRv)
|
|
|
|
{
|
|
|
|
nsTextEditorState* state = GetEditorState();
|
2011-07-29 21:31:57 +00:00
|
|
|
if (state && state->IsSelectionCached()) {
|
|
|
|
state->GetSelectionProperties().mEnd = aSelectionEnd;
|
2013-03-28 19:41:32 +00:00
|
|
|
return;
|
2011-07-29 21:31:57 +00:00
|
|
|
}
|
|
|
|
|
2011-07-28 17:51:22 +00:00
|
|
|
nsAutoString direction;
|
2013-03-28 19:41:32 +00:00
|
|
|
aRv = GetSelectionDirection(direction);
|
|
|
|
if (aRv.Failed()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-08-22 15:56:38 +00:00
|
|
|
int32_t start, end;
|
2013-03-28 19:41:32 +00:00
|
|
|
aRv = GetSelectionRange(&start, &end);
|
|
|
|
if (aRv.Failed()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2011-07-28 17:51:22 +00:00
|
|
|
end = aSelectionEnd;
|
|
|
|
if (start > end) {
|
|
|
|
start = end;
|
2000-04-13 05:15:59 +00:00
|
|
|
}
|
2013-03-28 19:41:32 +00:00
|
|
|
|
|
|
|
aRv = SetSelectionRange(start, end, direction);
|
2000-04-13 05:15:59 +00:00
|
|
|
}
|
|
|
|
|
2007-07-25 04:29:47 +00:00
|
|
|
NS_IMETHODIMP
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::SetSelectionEnd(int32_t aSelectionEnd)
|
2007-07-25 04:29:47 +00:00
|
|
|
{
|
2013-03-28 19:41:32 +00:00
|
|
|
ErrorResult rv;
|
|
|
|
SetSelectionEnd(aSelectionEnd, rv);
|
|
|
|
return rv.ErrorCode();
|
|
|
|
}
|
2007-07-25 04:29:47 +00:00
|
|
|
|
2013-03-28 19:41:32 +00:00
|
|
|
NS_IMETHODIMP
|
|
|
|
HTMLInputElement::GetFiles(nsIDOMFileList** aFileList)
|
|
|
|
{
|
|
|
|
nsRefPtr<nsDOMFileList> list = GetFiles();
|
|
|
|
list.forget(aFileList);
|
2007-07-25 04:29:47 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2000-04-13 05:15:59 +00:00
|
|
|
nsresult
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::GetSelectionRange(int32_t* aSelectionStart,
|
|
|
|
int32_t* aSelectionEnd)
|
2000-04-13 05:15:59 +00:00
|
|
|
{
|
2003-01-09 06:06:17 +00:00
|
|
|
nsresult rv = NS_ERROR_FAILURE;
|
2011-10-17 14:59:28 +00:00
|
|
|
nsIFormControlFrame* formControlFrame = GetFormControlFrame(true);
|
2000-12-23 10:56:31 +00:00
|
|
|
|
|
|
|
if (formControlFrame) {
|
2009-01-12 19:20:59 +00:00
|
|
|
nsITextControlFrame* textControlFrame = do_QueryFrame(formControlFrame);
|
2000-04-13 05:15:59 +00:00
|
|
|
if (textControlFrame)
|
2003-01-09 06:06:17 +00:00
|
|
|
rv = textControlFrame->GetSelectionRange(aSelectionStart, aSelectionEnd);
|
2000-04-13 05:15:59 +00:00
|
|
|
}
|
2000-12-23 10:56:31 +00:00
|
|
|
|
2003-01-09 06:06:17 +00:00
|
|
|
return rv;
|
2000-04-13 05:15:59 +00:00
|
|
|
}
|
|
|
|
|
2011-07-29 21:31:57 +00:00
|
|
|
static void
|
|
|
|
DirectionToName(nsITextControlFrame::SelectionDirection dir, nsAString& aDirection)
|
|
|
|
{
|
|
|
|
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");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-03-28 19:41:32 +00:00
|
|
|
void
|
|
|
|
HTMLInputElement::GetSelectionDirection(nsAString& aDirection, ErrorResult& aRv)
|
2011-07-28 17:51:22 +00:00
|
|
|
{
|
|
|
|
nsresult rv = NS_ERROR_FAILURE;
|
2011-10-17 14:59:28 +00:00
|
|
|
nsIFormControlFrame* formControlFrame = GetFormControlFrame(true);
|
2011-07-28 17:51:22 +00:00
|
|
|
|
|
|
|
if (formControlFrame) {
|
|
|
|
nsITextControlFrame* textControlFrame = do_QueryFrame(formControlFrame);
|
|
|
|
if (textControlFrame) {
|
|
|
|
nsITextControlFrame::SelectionDirection dir;
|
2012-07-30 14:20:58 +00:00
|
|
|
rv = textControlFrame->GetSelectionRange(nullptr, nullptr, &dir);
|
2011-07-28 17:51:22 +00:00
|
|
|
if (NS_SUCCEEDED(rv)) {
|
2011-07-29 21:31:57 +00:00
|
|
|
DirectionToName(dir, aDirection);
|
2011-07-28 17:51:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-10-07 13:40:11 +00:00
|
|
|
if (NS_FAILED(rv)) {
|
2013-03-28 19:41:32 +00:00
|
|
|
nsTextEditorState* state = GetEditorState();
|
2011-10-07 13:40:11 +00:00
|
|
|
if (state && state->IsSelectionCached()) {
|
|
|
|
DirectionToName(state->GetSelectionProperties().mDirection, aDirection);
|
2013-03-28 19:41:32 +00:00
|
|
|
return;
|
2011-10-07 13:40:11 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-03-28 19:41:32 +00:00
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
aRv.Throw(rv);
|
|
|
|
}
|
2011-07-28 17:51:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::GetSelectionDirection(nsAString& aDirection)
|
2013-03-28 19:41:32 +00:00
|
|
|
{
|
2013-03-28 19:41:32 +00:00
|
|
|
ErrorResult rv;
|
|
|
|
GetSelectionDirection(aDirection, rv);
|
|
|
|
return rv.ErrorCode();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
HTMLInputElement::SetSelectionDirection(const nsAString& aDirection, ErrorResult& aRv)
|
|
|
|
{
|
|
|
|
nsTextEditorState* state = GetEditorState();
|
2011-07-29 21:31:57 +00:00
|
|
|
if (state && state->IsSelectionCached()) {
|
|
|
|
nsITextControlFrame::SelectionDirection dir = nsITextControlFrame::eNone;
|
|
|
|
if (aDirection.EqualsLiteral("forward")) {
|
|
|
|
dir = nsITextControlFrame::eForward;
|
|
|
|
} else if (aDirection.EqualsLiteral("backward")) {
|
|
|
|
dir = nsITextControlFrame::eBackward;
|
|
|
|
}
|
|
|
|
state->GetSelectionProperties().mDirection = dir;
|
2013-03-28 19:41:32 +00:00
|
|
|
return;
|
2011-07-29 21:31:57 +00:00
|
|
|
}
|
|
|
|
|
2012-08-22 15:56:38 +00:00
|
|
|
int32_t start, end;
|
2013-03-28 19:41:32 +00:00
|
|
|
aRv = GetSelectionRange(&start, &end);
|
|
|
|
if (!aRv.Failed()) {
|
|
|
|
aRv = SetSelectionRange(start, end, aDirection);
|
2011-07-28 17:51:22 +00:00
|
|
|
}
|
2013-03-28 19:41:32 +00:00
|
|
|
}
|
2011-07-28 17:51:22 +00:00
|
|
|
|
2013-03-28 19:41:32 +00:00
|
|
|
NS_IMETHODIMP
|
|
|
|
HTMLInputElement::SetSelectionDirection(const nsAString& aDirection)
|
|
|
|
{
|
|
|
|
ErrorResult rv;
|
|
|
|
SetSelectionDirection(aDirection, rv);
|
|
|
|
return rv.ErrorCode();
|
2011-07-28 17:51:22 +00:00
|
|
|
}
|
|
|
|
|
2002-12-17 23:38:04 +00:00
|
|
|
NS_IMETHODIMP
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::GetPhonetic(nsAString& aPhonetic)
|
2002-12-17 23:38:04 +00:00
|
|
|
{
|
2011-11-16 07:50:19 +00:00
|
|
|
aPhonetic.Truncate();
|
2011-10-17 14:59:28 +00:00
|
|
|
nsIFormControlFrame* formControlFrame = GetFormControlFrame(true);
|
2002-12-17 23:38:04 +00:00
|
|
|
|
|
|
|
if (formControlFrame) {
|
2009-01-12 19:20:59 +00:00
|
|
|
nsITextControlFrame* textControlFrame = do_QueryFrame(formControlFrame);
|
2008-10-28 00:27:55 +00:00
|
|
|
if (textControlFrame)
|
|
|
|
textControlFrame->GetPhonetic(aPhonetic);
|
2002-12-17 23:38:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2001-08-17 03:13:07 +00:00
|
|
|
#ifdef ACCESSIBILITY
|
2006-05-16 03:54:46 +00:00
|
|
|
/*static*/ nsresult
|
|
|
|
FireEventForAccessibility(nsIDOMHTMLInputElement* aTarget,
|
|
|
|
nsPresContext* aPresContext,
|
|
|
|
const nsAString& aEventType)
|
2001-05-11 21:11:38 +00:00
|
|
|
{
|
2003-03-05 03:20:17 +00:00
|
|
|
nsCOMPtr<nsIDOMEvent> event;
|
2013-03-09 11:34:29 +00:00
|
|
|
nsCOMPtr<mozilla::dom::Element> element = do_QueryInterface(aTarget);
|
|
|
|
if (NS_SUCCEEDED(nsEventDispatcher::CreateEvent(element, aPresContext, nullptr,
|
2006-03-07 17:08:51 +00:00
|
|
|
NS_LITERAL_STRING("Events"),
|
|
|
|
getter_AddRefs(event)))) {
|
2011-10-17 14:59:28 +00:00
|
|
|
event->InitEvent(aEventType, true, true);
|
2012-06-10 23:44:50 +00:00
|
|
|
event->SetTrusted(true);
|
2005-04-28 23:48:28 +00:00
|
|
|
|
2012-07-30 14:20:58 +00:00
|
|
|
nsEventDispatcher::DispatchDOMEvent(aTarget, nullptr, event, aPresContext, nullptr);
|
2003-03-05 03:20:17 +00:00
|
|
|
}
|
2001-05-11 21:11:38 +00:00
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2001-08-17 03:13:07 +00:00
|
|
|
#endif
|
2001-11-02 07:40:01 +00:00
|
|
|
|
2010-07-22 15:10:27 +00:00
|
|
|
nsresult
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::SetDefaultValueAsValue()
|
2001-11-02 07:40:01 +00:00
|
|
|
{
|
2010-09-08 17:42:35 +00:00
|
|
|
NS_ASSERTION(GetValueMode() == VALUE_MODE_VALUE,
|
|
|
|
"GetValueMode() should return VALUE_MODE_VALUE!");
|
2001-11-05 06:50:21 +00:00
|
|
|
|
2010-09-08 17:42:35 +00:00
|
|
|
// The element has a content attribute value different from it's value when
|
|
|
|
// it's in the value mode value.
|
|
|
|
nsAutoString resetVal;
|
|
|
|
GetDefaultValue(resetVal);
|
|
|
|
|
|
|
|
// SetValueInternal is going to sanitize the value.
|
2011-10-17 14:59:28 +00:00
|
|
|
return SetValueInternal(resetVal, false, false);
|
2010-07-22 15:10:27 +00:00
|
|
|
}
|
|
|
|
|
2012-11-21 10:13:57 +00:00
|
|
|
void
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::SetDirectionIfAuto(bool aAuto, bool aNotify)
|
2012-11-21 10:13:57 +00:00
|
|
|
{
|
|
|
|
if (aAuto) {
|
|
|
|
SetHasDirAuto();
|
|
|
|
if (IsSingleLineTextControl(true)) {
|
|
|
|
nsAutoString value;
|
|
|
|
GetValue(value);
|
|
|
|
SetDirectionalityFromValue(this, value, aNotify);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
ClearHasDirAuto();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-07-22 15:10:27 +00:00
|
|
|
NS_IMETHODIMP
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::Reset()
|
2010-07-22 15:10:27 +00:00
|
|
|
{
|
2010-09-08 17:42:35 +00:00
|
|
|
// We should be able to reset all dirty flags regardless of the type.
|
2011-10-17 14:59:28 +00:00
|
|
|
SetCheckedChanged(false);
|
|
|
|
SetValueChanged(false);
|
2010-07-22 15:10:27 +00:00
|
|
|
|
2010-09-08 17:42:35 +00:00
|
|
|
switch (GetValueMode()) {
|
|
|
|
case VALUE_MODE_VALUE:
|
|
|
|
return SetDefaultValueAsValue();
|
|
|
|
case VALUE_MODE_DEFAULT_ON:
|
2012-08-03 10:38:52 +00:00
|
|
|
DoSetChecked(DefaultChecked(), true, false);
|
|
|
|
return NS_OK;
|
2010-09-08 17:42:35 +00:00
|
|
|
case VALUE_MODE_FILENAME:
|
2010-11-23 23:45:53 +00:00
|
|
|
ClearFiles(false);
|
2010-09-08 17:42:35 +00:00
|
|
|
return NS_OK;
|
|
|
|
case VALUE_MODE_DEFAULT:
|
2010-07-22 15:10:27 +00:00
|
|
|
default:
|
2010-09-08 17:42:35 +00:00
|
|
|
return NS_OK;
|
2010-07-22 15:10:27 +00:00
|
|
|
}
|
2001-11-02 07:40:01 +00:00
|
|
|
}
|
|
|
|
|
2002-02-16 01:19:24 +00:00
|
|
|
NS_IMETHODIMP
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::SubmitNamesValues(nsFormSubmission* aFormSubmission)
|
2001-11-02 07:40:01 +00:00
|
|
|
{
|
2002-02-16 01:19:24 +00:00
|
|
|
// Disabled elements don't submit
|
|
|
|
// For type=reset, and type=button, we just never submit, period.
|
|
|
|
// For type=image and type=button, we only submit if we were the button
|
|
|
|
// pressed
|
|
|
|
// For type=radio and type=checkbox, we only submit if checked=true
|
2010-09-18 21:33:16 +00:00
|
|
|
if (IsDisabled() || mType == NS_FORM_INPUT_RESET ||
|
2010-02-25 05:58:16 +00:00
|
|
|
mType == NS_FORM_INPUT_BUTTON ||
|
|
|
|
((mType == NS_FORM_INPUT_SUBMIT || mType == NS_FORM_INPUT_IMAGE) &&
|
2010-08-19 21:58:20 +00:00
|
|
|
aFormSubmission->GetOriginatingElement() != this) ||
|
2010-02-25 05:58:16 +00:00
|
|
|
((mType == NS_FORM_INPUT_RADIO || mType == NS_FORM_INPUT_CHECKBOX) &&
|
2011-11-16 07:50:19 +00:00
|
|
|
!mChecked)) {
|
2010-02-25 05:58:16 +00:00
|
|
|
return NS_OK;
|
2002-01-24 19:08:57 +00:00
|
|
|
}
|
2001-11-02 07:40:01 +00:00
|
|
|
|
2002-02-16 01:19:24 +00:00
|
|
|
// Get the name
|
|
|
|
nsAutoString name;
|
2011-05-04 12:46:09 +00:00
|
|
|
GetAttr(kNameSpaceID_None, nsGkAtoms::name, name);
|
2001-11-02 07:40:01 +00:00
|
|
|
|
2002-02-16 01:19:24 +00:00
|
|
|
// Submit .x, .y for input type=image
|
2002-12-18 23:38:09 +00:00
|
|
|
if (mType == NS_FORM_INPUT_IMAGE) {
|
2007-02-18 16:49:54 +00:00
|
|
|
// Get a property set by the frame to find out where it was clicked.
|
|
|
|
nsIntPoint* lastClickedPoint =
|
2007-07-08 07:08:04 +00:00
|
|
|
static_cast<nsIntPoint*>(GetProperty(nsGkAtoms::imageClickedPoint));
|
2012-08-22 15:56:38 +00:00
|
|
|
int32_t x, y;
|
2007-02-18 16:49:54 +00:00
|
|
|
if (lastClickedPoint) {
|
2004-01-22 03:26:17 +00:00
|
|
|
// Convert the values to strings for submission
|
2008-11-03 02:25:11 +00:00
|
|
|
x = lastClickedPoint->x;
|
|
|
|
y = lastClickedPoint->y;
|
|
|
|
} else {
|
|
|
|
x = y = 0;
|
2004-01-22 03:26:17 +00:00
|
|
|
}
|
2007-02-18 16:49:54 +00:00
|
|
|
|
2008-11-03 02:25:11 +00:00
|
|
|
nsAutoString xVal, yVal;
|
|
|
|
xVal.AppendInt(x);
|
|
|
|
yVal.AppendInt(y);
|
|
|
|
|
2004-01-22 03:26:17 +00:00
|
|
|
if (!name.IsEmpty()) {
|
2010-02-25 05:58:16 +00:00
|
|
|
aFormSubmission->AddNameValuePair(name + NS_LITERAL_STRING(".x"), xVal);
|
|
|
|
aFormSubmission->AddNameValuePair(name + NS_LITERAL_STRING(".y"), yVal);
|
2004-01-22 03:26:17 +00:00
|
|
|
} else {
|
|
|
|
// If the Image Element has no name, simply return x and y
|
2007-02-18 16:49:54 +00:00
|
|
|
// to Nav and IE compatibility.
|
2010-02-25 05:58:16 +00:00
|
|
|
aFormSubmission->AddNameValuePair(NS_LITERAL_STRING("x"), xVal);
|
|
|
|
aFormSubmission->AddNameValuePair(NS_LITERAL_STRING("y"), yVal);
|
2001-11-02 07:40:01 +00:00
|
|
|
}
|
2010-02-25 05:57:54 +00:00
|
|
|
|
|
|
|
return NS_OK;
|
2002-02-16 01:19:24 +00:00
|
|
|
}
|
2001-11-02 07:40:01 +00:00
|
|
|
|
2002-02-16 01:19:24 +00:00
|
|
|
//
|
|
|
|
// Submit name=value
|
|
|
|
//
|
|
|
|
|
|
|
|
// If name not there, don't submit
|
2011-05-04 12:46:09 +00:00
|
|
|
if (name.IsEmpty()) {
|
2010-02-25 05:58:16 +00:00
|
|
|
return NS_OK;
|
2002-02-16 01:19:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Get the value
|
|
|
|
nsAutoString value;
|
2011-11-16 07:50:19 +00:00
|
|
|
nsresult rv = GetValue(value);
|
2002-02-16 01:19:24 +00:00
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2005-01-20 16:47:25 +00:00
|
|
|
if (mType == NS_FORM_INPUT_SUBMIT && value.IsEmpty() &&
|
2006-12-26 17:47:52 +00:00
|
|
|
!HasAttr(kNameSpaceID_None, nsGkAtoms::value)) {
|
2005-01-20 16:47:25 +00:00
|
|
|
// Get our default value, which is the same as our default label
|
2005-01-20 17:07:51 +00:00
|
|
|
nsXPIDLString defaultValue;
|
2005-01-20 16:47:25 +00:00
|
|
|
nsContentUtils::GetLocalizedString(nsContentUtils::eFORMS_PROPERTIES,
|
2005-01-20 17:07:51 +00:00
|
|
|
"Submit", defaultValue);
|
|
|
|
value = defaultValue;
|
2005-01-20 16:47:25 +00:00
|
|
|
}
|
2013-03-03 18:30:13 +00:00
|
|
|
|
2002-02-16 01:19:24 +00:00
|
|
|
//
|
2009-01-23 09:02:09 +00:00
|
|
|
// Submit file if its input type=file and this encoding method accepts files
|
2002-02-16 01:19:24 +00:00
|
|
|
//
|
2002-12-18 23:38:09 +00:00
|
|
|
if (mType == NS_FORM_INPUT_FILE) {
|
2009-10-25 04:13:30 +00:00
|
|
|
// Submit files
|
2002-02-16 01:19:24 +00:00
|
|
|
|
2013-03-28 19:41:32 +00:00
|
|
|
const nsCOMArray<nsIDOMFile>& files = GetFilesInternal();
|
2009-10-25 04:13:30 +00:00
|
|
|
|
2012-08-22 15:56:38 +00:00
|
|
|
for (int32_t i = 0; i < files.Count(); ++i) {
|
2013-03-03 18:30:13 +00:00
|
|
|
aFormSubmission->AddNameFilePair(name, files[i], NullString());
|
2001-11-02 07:40:01 +00:00
|
|
|
}
|
2009-10-25 04:13:30 +00:00
|
|
|
|
2009-11-19 20:58:46 +00:00
|
|
|
if (files.Count() == 0) {
|
|
|
|
// If no file was selected, pretend we had an empty file with an
|
|
|
|
// empty filename.
|
2013-03-03 18:30:13 +00:00
|
|
|
aFormSubmission->AddNameFilePair(name, nullptr, NullString());
|
2009-11-19 20:58:46 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2009-10-25 04:13:30 +00:00
|
|
|
return NS_OK;
|
2002-02-16 01:19:24 +00:00
|
|
|
}
|
2001-11-02 07:40:01 +00:00
|
|
|
|
2010-02-25 05:58:16 +00:00
|
|
|
if (mType == NS_FORM_INPUT_HIDDEN && name.EqualsLiteral("_charset_")) {
|
|
|
|
nsCString charset;
|
|
|
|
aFormSubmission->GetCharset(charset);
|
2011-11-16 07:50:19 +00:00
|
|
|
return aFormSubmission->AddNameValuePair(name,
|
|
|
|
NS_ConvertASCIItoUTF16(charset));
|
2010-03-11 12:29:51 +00:00
|
|
|
}
|
2011-11-16 07:50:19 +00:00
|
|
|
if (IsSingleLineTextControl(true) &&
|
|
|
|
name.EqualsLiteral("isindex") &&
|
|
|
|
aFormSubmission->SupportsIsindexSubmission()) {
|
|
|
|
return aFormSubmission->AddIsindex(value);
|
2001-11-02 07:40:01 +00:00
|
|
|
}
|
2011-11-16 07:50:19 +00:00
|
|
|
return aFormSubmission->AddNameValuePair(name, value);
|
2001-11-02 07:40:01 +00:00
|
|
|
}
|
|
|
|
|
2002-02-16 01:19:24 +00:00
|
|
|
|
2001-11-02 07:40:01 +00:00
|
|
|
NS_IMETHODIMP
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::SaveState()
|
2001-11-02 07:40:01 +00:00
|
|
|
{
|
2013-03-28 19:41:32 +00:00
|
|
|
nsRefPtr<HTMLInputElementState> inputState;
|
2002-12-18 23:38:09 +00:00
|
|
|
switch (mType) {
|
2002-03-07 20:53:40 +00:00
|
|
|
case NS_FORM_INPUT_CHECKBOX:
|
|
|
|
case NS_FORM_INPUT_RADIO:
|
|
|
|
{
|
2011-11-16 07:50:19 +00:00
|
|
|
if (mCheckedChanged) {
|
2013-03-28 19:41:32 +00:00
|
|
|
inputState = new HTMLInputElementState();
|
2011-11-16 07:50:19 +00:00
|
|
|
inputState->SetChecked(mChecked);
|
2002-03-07 20:53:40 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2001-11-02 07:40:01 +00:00
|
|
|
// Never save passwords in session history
|
|
|
|
case NS_FORM_INPUT_PASSWORD:
|
|
|
|
break;
|
2010-08-18 18:31:54 +00:00
|
|
|
case NS_FORM_INPUT_EMAIL:
|
2010-05-17 10:20:22 +00:00
|
|
|
case NS_FORM_INPUT_SEARCH:
|
2001-11-02 07:40:01 +00:00
|
|
|
case NS_FORM_INPUT_TEXT:
|
2010-05-12 07:17:07 +00:00
|
|
|
case NS_FORM_INPUT_TEL:
|
2010-08-18 18:33:37 +00:00
|
|
|
case NS_FORM_INPUT_URL:
|
2002-06-12 06:35:11 +00:00
|
|
|
case NS_FORM_INPUT_HIDDEN:
|
2012-06-10 20:23:17 +00:00
|
|
|
case NS_FORM_INPUT_NUMBER:
|
2012-12-27 16:06:53 +00:00
|
|
|
case NS_FORM_INPUT_DATE:
|
2013-01-08 17:10:00 +00:00
|
|
|
case NS_FORM_INPUT_TIME:
|
2013-02-16 12:35:57 +00:00
|
|
|
case NS_FORM_INPUT_RANGE:
|
2002-03-07 20:53:40 +00:00
|
|
|
{
|
2011-11-16 07:50:19 +00:00
|
|
|
if (mValueChanged) {
|
2013-03-28 19:41:32 +00:00
|
|
|
inputState = new HTMLInputElementState();
|
2008-12-12 19:25:22 +00:00
|
|
|
nsAutoString value;
|
|
|
|
GetValue(value);
|
2011-11-16 07:50:19 +00:00
|
|
|
DebugOnly<nsresult> rv =
|
|
|
|
nsLinebreakConverter::ConvertStringLineBreaks(
|
2008-12-12 19:25:22 +00:00
|
|
|
value,
|
|
|
|
nsLinebreakConverter::eLinebreakPlatform,
|
|
|
|
nsLinebreakConverter::eLinebreakContent);
|
|
|
|
NS_ASSERTION(NS_SUCCEEDED(rv), "Converting linebreaks failed!");
|
|
|
|
inputState->SetValue(value);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2006-04-25 09:18:42 +00:00
|
|
|
case NS_FORM_INPUT_FILE:
|
|
|
|
{
|
2010-09-05 18:00:05 +00:00
|
|
|
if (mFiles.Count()) {
|
2013-03-28 19:41:32 +00:00
|
|
|
inputState = new HTMLInputElementState();
|
2010-09-05 18:00:05 +00:00
|
|
|
inputState->SetFiles(mFiles);
|
2006-04-25 09:18:42 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2001-11-02 07:40:01 +00:00
|
|
|
}
|
2013-03-28 19:41:32 +00:00
|
|
|
|
2011-11-16 07:50:19 +00:00
|
|
|
nsresult rv = NS_OK;
|
2012-07-30 14:20:58 +00:00
|
|
|
nsPresState* state = nullptr;
|
2008-12-12 19:25:22 +00:00
|
|
|
if (inputState) {
|
|
|
|
rv = GetPrimaryPresState(this, &state);
|
|
|
|
if (state) {
|
|
|
|
state->SetStateProperty(inputState);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-11-16 07:50:19 +00:00
|
|
|
if (mDisabledChanged) {
|
2012-07-27 14:03:08 +00:00
|
|
|
nsresult tmp = GetPrimaryPresState(this, &state);
|
|
|
|
if (NS_FAILED(tmp)) {
|
|
|
|
rv = tmp;
|
|
|
|
}
|
2003-11-10 05:52:29 +00:00
|
|
|
if (state) {
|
2010-09-18 21:33:16 +00:00
|
|
|
// We do not want to save the real disabled state but the disabled
|
|
|
|
// attribute.
|
|
|
|
state->SetDisabled(HasAttr(kNameSpaceID_None, nsGkAtoms::disabled));
|
2003-11-10 05:52:29 +00:00
|
|
|
}
|
|
|
|
}
|
2001-11-02 07:40:01 +00:00
|
|
|
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2004-01-09 23:54:21 +00:00
|
|
|
void
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::DoneCreatingElement()
|
2002-03-31 10:14:01 +00:00
|
|
|
{
|
2011-11-16 07:50:19 +00:00
|
|
|
mParserCreating = false;
|
2002-03-31 10:14:01 +00:00
|
|
|
|
|
|
|
//
|
2005-09-01 18:58:31 +00:00
|
|
|
// Restore state as needed. Note that disabled state applies to all control
|
|
|
|
// types.
|
2002-03-31 10:14:01 +00:00
|
|
|
//
|
2011-09-29 06:19:26 +00:00
|
|
|
bool restoredCheckedState =
|
2011-11-16 07:50:19 +00:00
|
|
|
!mInhibitRestoration && RestoreFormControlState(this, this);
|
2002-03-31 10:14:01 +00:00
|
|
|
|
|
|
|
//
|
|
|
|
// If restore does not occur, we initialize .checked using the CHECKED
|
|
|
|
// property.
|
|
|
|
//
|
2011-11-16 07:50:19 +00:00
|
|
|
if (!restoredCheckedState && mShouldInitChecked) {
|
2011-11-16 07:50:19 +00:00
|
|
|
DoSetChecked(DefaultChecked(), false, true);
|
2011-10-17 14:59:28 +00:00
|
|
|
DoSetCheckedChanged(false, false);
|
2002-03-31 10:14:01 +00:00
|
|
|
}
|
|
|
|
|
2010-09-20 20:33:17 +00:00
|
|
|
// Sanitize the value.
|
|
|
|
if (GetValueMode() == VALUE_MODE_VALUE) {
|
|
|
|
nsAutoString aValue;
|
|
|
|
GetValue(aValue);
|
2011-10-17 14:59:28 +00:00
|
|
|
SetValueInternal(aValue, false, false);
|
2010-09-20 20:33:17 +00:00
|
|
|
}
|
|
|
|
|
2011-11-16 07:50:19 +00:00
|
|
|
mShouldInitChecked = false;
|
2002-03-31 10:14:01 +00:00
|
|
|
}
|
|
|
|
|
2010-10-20 11:26:32 +00:00
|
|
|
nsEventStates
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::IntrinsicState() const
|
2005-06-03 02:02:45 +00:00
|
|
|
{
|
2007-02-09 06:20:47 +00:00
|
|
|
// If you add states here, and they're type-dependent, you need to add them
|
|
|
|
// to the type case in AfterSetAttr.
|
2013-03-28 19:41:32 +00:00
|
|
|
|
2010-10-20 11:26:32 +00:00
|
|
|
nsEventStates state = nsGenericHTMLFormElement::IntrinsicState();
|
2006-08-16 03:20:19 +00:00
|
|
|
if (mType == NS_FORM_INPUT_CHECKBOX || mType == NS_FORM_INPUT_RADIO) {
|
|
|
|
// Check current checked state (:checked)
|
2011-11-16 07:50:19 +00:00
|
|
|
if (mChecked) {
|
2006-08-16 03:20:19 +00:00
|
|
|
state |= NS_EVENT_STATE_CHECKED;
|
|
|
|
}
|
|
|
|
|
2009-02-11 01:19:37 +00:00
|
|
|
// Check current indeterminate state (:indeterminate)
|
2011-11-16 07:50:19 +00:00
|
|
|
if (mType == NS_FORM_INPUT_CHECKBOX && mIndeterminate) {
|
2009-02-11 01:19:37 +00:00
|
|
|
state |= NS_EVENT_STATE_INDETERMINATE;
|
|
|
|
}
|
|
|
|
|
2006-08-16 03:20:19 +00:00
|
|
|
// Check whether we are the default checked element (:default)
|
2011-11-16 07:50:19 +00:00
|
|
|
if (DefaultChecked()) {
|
2006-08-16 03:20:19 +00:00
|
|
|
state |= NS_EVENT_STATE_DEFAULT;
|
|
|
|
}
|
2005-09-18 18:05:40 +00:00
|
|
|
} else if (mType == NS_FORM_INPUT_IMAGE) {
|
|
|
|
state |= nsImageLoadingContent::ImageState();
|
2005-06-03 02:02:45 +00:00
|
|
|
}
|
2006-08-16 03:20:19 +00:00
|
|
|
|
2010-08-19 00:03:20 +00:00
|
|
|
if (DoesRequiredApply() && HasAttr(kNameSpaceID_None, nsGkAtoms::required)) {
|
|
|
|
state |= NS_EVENT_STATE_REQUIRED;
|
|
|
|
} else {
|
|
|
|
state |= NS_EVENT_STATE_OPTIONAL;
|
|
|
|
}
|
|
|
|
|
2010-08-21 18:51:38 +00:00
|
|
|
if (IsCandidateForConstraintValidation()) {
|
2010-11-23 23:49:50 +00:00
|
|
|
if (IsValid()) {
|
2010-11-23 23:55:22 +00:00
|
|
|
state |= NS_EVENT_STATE_VALID;
|
2010-11-23 23:49:50 +00:00
|
|
|
} else {
|
|
|
|
state |= NS_EVENT_STATE_INVALID;
|
2010-11-23 23:50:53 +00:00
|
|
|
|
2011-01-27 13:51:45 +00:00
|
|
|
if ((!mForm || !mForm->HasAttr(kNameSpaceID_None, nsGkAtoms::novalidate)) &&
|
|
|
|
(GetValidityState(VALIDITY_STATE_CUSTOM_ERROR) ||
|
2011-11-16 07:50:19 +00:00
|
|
|
(mCanShowInvalidUI && ShouldShowValidityUI()))) {
|
2010-11-23 23:49:50 +00:00
|
|
|
state |= NS_EVENT_STATE_MOZ_UI_INVALID;
|
|
|
|
}
|
|
|
|
}
|
2010-11-23 23:56:24 +00:00
|
|
|
|
|
|
|
// :-moz-ui-valid applies if all of the following conditions are true:
|
|
|
|
// 1. The element is not focused, or had either :-moz-ui-valid or
|
|
|
|
// :-moz-ui-invalid applying before it was focused ;
|
|
|
|
// 2. The element is either valid or isn't allowed to have
|
|
|
|
// :-moz-ui-invalid applying ;
|
2011-01-27 13:51:45 +00:00
|
|
|
// 3. The element has no form owner or its form owner doesn't have the
|
|
|
|
// novalidate attribute set ;
|
|
|
|
// 4. The element has already been modified or the user tried to submit the
|
|
|
|
// form owner while invalid.
|
|
|
|
if ((!mForm || !mForm->HasAttr(kNameSpaceID_None, nsGkAtoms::novalidate)) &&
|
2011-11-16 07:50:19 +00:00
|
|
|
(mCanShowValidUI && ShouldShowValidityUI() &&
|
2011-01-27 13:51:45 +00:00
|
|
|
(IsValid() || (!state.HasState(NS_EVENT_STATE_MOZ_UI_INVALID) &&
|
2011-11-16 07:50:19 +00:00
|
|
|
!mCanShowInvalidUI)))) {
|
2010-11-23 23:56:24 +00:00
|
|
|
state |= NS_EVENT_STATE_MOZ_UI_VALID;
|
|
|
|
}
|
2010-08-21 17:52:57 +00:00
|
|
|
}
|
|
|
|
|
2010-09-10 05:08:56 +00:00
|
|
|
if (mForm && !mForm->GetValidity() && IsSubmitControl()) {
|
|
|
|
state |= NS_EVENT_STATE_MOZ_SUBMITINVALID;
|
|
|
|
}
|
|
|
|
|
2012-06-09 17:44:47 +00:00
|
|
|
// :in-range and :out-of-range only apply if the element currently has a range.
|
|
|
|
if (mHasRange) {
|
|
|
|
state |= (GetValidityState(VALIDITY_STATE_RANGE_OVERFLOW) ||
|
|
|
|
GetValidityState(VALIDITY_STATE_RANGE_UNDERFLOW))
|
|
|
|
? NS_EVENT_STATE_OUTOFRANGE
|
|
|
|
: NS_EVENT_STATE_INRANGE;
|
|
|
|
}
|
|
|
|
|
2005-06-03 02:02:45 +00:00
|
|
|
return state;
|
|
|
|
}
|
|
|
|
|
2011-09-29 06:19:26 +00:00
|
|
|
bool
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::RestoreState(nsPresState* aState)
|
2001-11-02 07:40:01 +00:00
|
|
|
{
|
2011-09-29 06:19:26 +00:00
|
|
|
bool restoredCheckedState = false;
|
2001-11-02 07:40:01 +00:00
|
|
|
|
2013-03-28 19:41:32 +00:00
|
|
|
nsCOMPtr<HTMLInputElementState> inputState
|
2008-12-12 19:25:22 +00:00
|
|
|
(do_QueryInterface(aState->GetStateProperty()));
|
|
|
|
|
|
|
|
if (inputState) {
|
|
|
|
switch (mType) {
|
|
|
|
case NS_FORM_INPUT_CHECKBOX:
|
|
|
|
case NS_FORM_INPUT_RADIO:
|
|
|
|
{
|
|
|
|
if (inputState->IsCheckedSet()) {
|
2011-10-17 14:59:28 +00:00
|
|
|
restoredCheckedState = true;
|
|
|
|
DoSetChecked(inputState->GetChecked(), true, true);
|
2008-12-12 19:25:22 +00:00
|
|
|
}
|
|
|
|
break;
|
2003-11-10 05:52:29 +00:00
|
|
|
}
|
2002-03-07 20:53:40 +00:00
|
|
|
|
2010-08-18 18:31:54 +00:00
|
|
|
case NS_FORM_INPUT_EMAIL:
|
2010-05-17 10:20:22 +00:00
|
|
|
case NS_FORM_INPUT_SEARCH:
|
2008-12-12 19:25:22 +00:00
|
|
|
case NS_FORM_INPUT_TEXT:
|
2010-05-12 07:17:07 +00:00
|
|
|
case NS_FORM_INPUT_TEL:
|
2010-08-18 18:33:37 +00:00
|
|
|
case NS_FORM_INPUT_URL:
|
2008-12-12 19:25:22 +00:00
|
|
|
case NS_FORM_INPUT_HIDDEN:
|
2012-06-10 20:23:17 +00:00
|
|
|
case NS_FORM_INPUT_NUMBER:
|
2012-12-27 16:06:53 +00:00
|
|
|
case NS_FORM_INPUT_DATE:
|
2013-01-08 17:10:00 +00:00
|
|
|
case NS_FORM_INPUT_TIME:
|
2013-02-16 12:35:57 +00:00
|
|
|
case NS_FORM_INPUT_RANGE:
|
2008-12-12 19:25:22 +00:00
|
|
|
{
|
2011-10-17 14:59:28 +00:00
|
|
|
SetValueInternal(inputState->GetValue(), false, true);
|
2008-12-12 19:25:22 +00:00
|
|
|
break;
|
2007-10-10 03:39:16 +00:00
|
|
|
}
|
2008-12-12 19:25:22 +00:00
|
|
|
case NS_FORM_INPUT_FILE:
|
|
|
|
{
|
2010-09-05 18:00:05 +00:00
|
|
|
const nsCOMArray<nsIDOMFile>& files = inputState->GetFiles();
|
2010-11-23 23:45:53 +00:00
|
|
|
SetFiles(files, true);
|
2008-12-12 19:25:22 +00:00
|
|
|
break;
|
2007-10-10 03:39:16 +00:00
|
|
|
}
|
2008-12-12 19:25:22 +00:00
|
|
|
}
|
2002-03-07 20:53:40 +00:00
|
|
|
}
|
2008-12-12 19:25:22 +00:00
|
|
|
|
|
|
|
if (aState->IsDisabledSet()) {
|
|
|
|
SetDisabled(aState->GetDisabled());
|
2003-11-10 05:52:29 +00:00
|
|
|
}
|
2002-03-07 20:53:40 +00:00
|
|
|
|
2004-09-21 18:04:47 +00:00
|
|
|
return restoredCheckedState;
|
2002-03-07 20:53:40 +00:00
|
|
|
}
|
|
|
|
|
2011-09-29 06:19:26 +00:00
|
|
|
bool
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::AllowDrop()
|
2004-02-11 21:31:53 +00:00
|
|
|
{
|
|
|
|
// Allow drop on anything other than file inputs.
|
|
|
|
|
|
|
|
return mType != NS_FORM_INPUT_FILE;
|
|
|
|
}
|
2002-03-07 20:53:40 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Radio group stuff
|
|
|
|
*/
|
|
|
|
|
2010-07-14 06:39:48 +00:00
|
|
|
void
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::AddedToRadioGroup()
|
2002-03-07 20:53:40 +00:00
|
|
|
{
|
2012-05-14 20:32:39 +00:00
|
|
|
// If the element is neither in a form nor a document, there is no group so we
|
|
|
|
// should just stop here.
|
|
|
|
if (!mForm && !IsInDoc()) {
|
2010-07-14 06:39:48 +00:00
|
|
|
return;
|
2002-03-07 20:53:40 +00:00
|
|
|
}
|
|
|
|
|
2012-05-14 20:32:39 +00:00
|
|
|
// Make sure not to notify if we're still being created by the parser
|
|
|
|
bool notify = !mParserCreating;
|
|
|
|
|
2002-03-07 20:53:40 +00:00
|
|
|
//
|
|
|
|
// If the input element is checked, and we add it to the group, it will
|
|
|
|
// deselect whatever is currently selected in that group
|
|
|
|
//
|
2011-11-16 07:50:19 +00:00
|
|
|
if (mChecked) {
|
2002-03-07 20:53:40 +00:00
|
|
|
//
|
|
|
|
// If it is checked, call "RadioSetChecked" to perform the selection/
|
|
|
|
// deselection ritual. This has the side effect of repainting the
|
|
|
|
// radio button, but as adding a checked radio button into the group
|
|
|
|
// should not be that common an occurrence, I think we can live with
|
|
|
|
// that.
|
|
|
|
//
|
2010-11-23 23:53:39 +00:00
|
|
|
RadioSetChecked(notify);
|
2002-03-07 20:53:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// For integrity purposes, we have to ensure that "checkedChanged" is
|
|
|
|
// the same for this new element as for all the others in the group
|
|
|
|
//
|
2011-11-16 07:50:19 +00:00
|
|
|
bool checkedChanged = mCheckedChanged;
|
2011-04-11 18:31:00 +00:00
|
|
|
|
|
|
|
nsCOMPtr<nsIRadioVisitor> visitor =
|
|
|
|
new nsRadioGetCheckedChangedVisitor(&checkedChanged, this);
|
2010-11-23 23:53:39 +00:00
|
|
|
VisitGroup(visitor, notify);
|
2011-04-11 18:31:00 +00:00
|
|
|
|
2010-11-23 23:53:39 +00:00
|
|
|
SetCheckedChangedInternal(checkedChanged);
|
2011-04-11 18:31:00 +00:00
|
|
|
|
2002-07-20 23:09:24 +00:00
|
|
|
//
|
|
|
|
// Add the radio to the radio group container.
|
|
|
|
//
|
|
|
|
nsCOMPtr<nsIRadioGroupContainer> container = GetRadioGroupContainer();
|
|
|
|
if (container) {
|
|
|
|
nsAutoString name;
|
2011-05-04 12:49:59 +00:00
|
|
|
GetAttr(kNameSpaceID_None, nsGkAtoms::name, name);
|
|
|
|
container->AddToRadioGroup(name, static_cast<nsIFormControl*>(this));
|
2011-02-25 18:16:04 +00:00
|
|
|
|
2011-05-04 12:49:59 +00:00
|
|
|
// We initialize the validity of the element to the validity of the group
|
|
|
|
// because we assume UpdateValueMissingState() will be called after.
|
|
|
|
SetValidityState(VALIDITY_STATE_VALUE_MISSING,
|
2011-07-19 09:44:55 +00:00
|
|
|
container->GetValueMissingState(name));
|
2002-07-20 23:09:24 +00:00
|
|
|
}
|
2002-03-07 20:53:40 +00:00
|
|
|
}
|
|
|
|
|
2010-07-14 06:39:48 +00:00
|
|
|
void
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::WillRemoveFromRadioGroup()
|
2002-03-07 20:53:40 +00:00
|
|
|
{
|
2011-05-04 12:49:59 +00:00
|
|
|
nsIRadioGroupContainer* container = GetRadioGroupContainer();
|
|
|
|
if (!container) {
|
2010-07-14 06:39:48 +00:00
|
|
|
return;
|
2002-03-07 20:53:40 +00:00
|
|
|
}
|
|
|
|
|
2011-05-04 12:49:59 +00:00
|
|
|
nsAutoString name;
|
|
|
|
GetAttr(kNameSpaceID_None, nsGkAtoms::name, name);
|
|
|
|
|
2002-03-07 20:53:40 +00:00
|
|
|
// If this button was checked, we need to notify the group that there is no
|
|
|
|
// longer a selected radio button
|
2011-11-16 07:50:19 +00:00
|
|
|
if (mChecked) {
|
2012-07-30 14:20:58 +00:00
|
|
|
container->SetCurrentRadioButton(name, nullptr);
|
2002-07-20 23:09:24 +00:00
|
|
|
}
|
2010-12-16 19:51:59 +00:00
|
|
|
|
2011-05-04 12:49:59 +00:00
|
|
|
// Remove this radio from its group in the container.
|
|
|
|
// We need to call UpdateValueMissingValidityStateForRadio before to make sure
|
|
|
|
// the group validity is updated (with this element being ignored).
|
|
|
|
UpdateValueMissingValidityStateForRadio(true);
|
|
|
|
container->RemoveFromRadioGroup(name, static_cast<nsIFormControl*>(this));
|
2002-03-07 20:53:40 +00:00
|
|
|
}
|
|
|
|
|
2011-09-29 06:19:26 +00:00
|
|
|
bool
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::IsHTMLFocusable(bool aWithMouse, bool* aIsFocusable, int32_t* aTabIndex)
|
2004-07-05 01:31:30 +00:00
|
|
|
{
|
2011-01-05 13:23:37 +00:00
|
|
|
if (nsGenericHTMLFormElement::IsHTMLFocusable(aWithMouse, aIsFocusable, aTabIndex)) {
|
2011-10-17 14:59:28 +00:00
|
|
|
return true;
|
2004-07-24 21:12:43 +00:00
|
|
|
}
|
2004-07-05 01:31:30 +00:00
|
|
|
|
2010-09-18 21:33:16 +00:00
|
|
|
if (IsDisabled()) {
|
2011-10-17 14:59:28 +00:00
|
|
|
*aIsFocusable = false;
|
|
|
|
return true;
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 18:00:39 +00:00
|
|
|
}
|
|
|
|
|
2013-03-01 15:34:06 +00:00
|
|
|
if (IsSingleLineTextControl(false) ||
|
|
|
|
mType == NS_FORM_INPUT_RANGE) {
|
2011-10-17 14:59:28 +00:00
|
|
|
*aIsFocusable = true;
|
|
|
|
return false;
|
2004-07-24 21:12:43 +00:00
|
|
|
}
|
2004-07-05 01:31:30 +00:00
|
|
|
|
2010-06-21 12:37:34 +00:00
|
|
|
#ifdef XP_MACOSX
|
2011-09-29 06:19:26 +00:00
|
|
|
const bool defaultFocusable = !aWithMouse || nsFocusManager::sMouseFocusesFormControl;
|
2010-06-21 12:37:34 +00:00
|
|
|
#else
|
2011-09-29 06:19:26 +00:00
|
|
|
const bool defaultFocusable = true;
|
2010-06-21 12:37:34 +00:00
|
|
|
#endif
|
|
|
|
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 18:00:39 +00:00
|
|
|
if (mType == NS_FORM_INPUT_FILE) {
|
|
|
|
if (aTabIndex) {
|
|
|
|
*aTabIndex = -1;
|
|
|
|
}
|
2010-06-21 12:37:34 +00:00
|
|
|
*aIsFocusable = defaultFocusable;
|
2011-10-17 14:59:28 +00:00
|
|
|
return true;
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 18:00:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (mType == NS_FORM_INPUT_HIDDEN) {
|
2004-07-24 21:12:43 +00:00
|
|
|
if (aTabIndex) {
|
|
|
|
*aTabIndex = -1;
|
|
|
|
}
|
2011-10-17 14:59:28 +00:00
|
|
|
*aIsFocusable = false;
|
|
|
|
return false;
|
2004-07-05 01:31:30 +00:00
|
|
|
}
|
|
|
|
|
2004-07-24 21:12:43 +00:00
|
|
|
if (!aTabIndex) {
|
|
|
|
// The other controls are all focusable
|
2010-06-21 12:37:34 +00:00
|
|
|
*aIsFocusable = defaultFocusable;
|
2011-10-17 14:59:28 +00:00
|
|
|
return false;
|
2004-07-24 21:12:43 +00:00
|
|
|
}
|
|
|
|
|
2004-07-05 01:31:30 +00:00
|
|
|
if (mType != NS_FORM_INPUT_RADIO) {
|
2010-06-21 12:37:34 +00:00
|
|
|
*aIsFocusable = defaultFocusable;
|
2011-10-17 14:59:28 +00:00
|
|
|
return false;
|
2004-07-05 01:31:30 +00:00
|
|
|
}
|
|
|
|
|
2011-11-16 07:50:19 +00:00
|
|
|
if (mChecked) {
|
2004-07-05 01:31:30 +00:00
|
|
|
// Selected radio buttons are tabbable
|
2010-06-21 12:37:34 +00:00
|
|
|
*aIsFocusable = defaultFocusable;
|
2011-10-17 14:59:28 +00:00
|
|
|
return false;
|
2004-07-05 01:31:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Current radio button is not selected.
|
|
|
|
// But make it tabbable if nothing in group is selected.
|
2011-05-04 12:49:59 +00:00
|
|
|
nsIRadioGroupContainer* container = GetRadioGroupContainer();
|
|
|
|
if (!container) {
|
2010-06-21 12:37:34 +00:00
|
|
|
*aIsFocusable = defaultFocusable;
|
2011-10-17 14:59:28 +00:00
|
|
|
return false;
|
2004-07-05 01:31:30 +00:00
|
|
|
}
|
|
|
|
|
2011-05-04 12:49:59 +00:00
|
|
|
nsAutoString name;
|
|
|
|
GetAttr(kNameSpaceID_None, nsGkAtoms::name, name);
|
|
|
|
|
2012-08-03 10:38:52 +00:00
|
|
|
nsCOMPtr<nsIDOMHTMLInputElement> currentRadio = container->GetCurrentRadioButton(name);
|
2004-07-05 01:31:30 +00:00
|
|
|
if (currentRadio) {
|
2004-07-24 21:12:43 +00:00
|
|
|
*aTabIndex = -1;
|
2004-07-05 01:31:30 +00:00
|
|
|
}
|
2010-06-21 12:37:34 +00:00
|
|
|
*aIsFocusable = defaultFocusable;
|
2011-10-17 14:59:28 +00:00
|
|
|
return false;
|
2004-07-05 01:31:30 +00:00
|
|
|
}
|
|
|
|
|
2002-03-07 20:53:40 +00:00
|
|
|
nsresult
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::VisitGroup(nsIRadioVisitor* aVisitor, bool aFlushContent)
|
2002-03-07 20:53:40 +00:00
|
|
|
{
|
2011-05-04 12:49:59 +00:00
|
|
|
nsIRadioGroupContainer* container = GetRadioGroupContainer();
|
2002-07-20 23:09:24 +00:00
|
|
|
if (container) {
|
2002-03-07 20:53:40 +00:00
|
|
|
nsAutoString name;
|
2011-05-04 12:49:59 +00:00
|
|
|
GetAttr(kNameSpaceID_None, nsGkAtoms::name, name);
|
|
|
|
return container->WalkRadioGroup(name, aVisitor, aFlushContent);
|
2002-03-07 20:53:40 +00:00
|
|
|
}
|
2011-05-04 12:49:59 +00:00
|
|
|
|
|
|
|
aVisitor->Visit(this);
|
|
|
|
return NS_OK;
|
2001-11-02 07:40:01 +00:00
|
|
|
}
|
2002-03-07 20:53:40 +00:00
|
|
|
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::ValueModeType
|
|
|
|
HTMLInputElement::GetValueMode() const
|
2010-08-18 18:30:41 +00:00
|
|
|
{
|
|
|
|
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:
|
2010-08-18 18:31:54 +00:00
|
|
|
case NS_FORM_INPUT_EMAIL:
|
2010-08-18 18:33:37 +00:00
|
|
|
case NS_FORM_INPUT_URL:
|
2012-06-10 20:23:17 +00:00
|
|
|
case NS_FORM_INPUT_NUMBER:
|
2013-02-16 12:35:57 +00:00
|
|
|
case NS_FORM_INPUT_RANGE:
|
2012-12-27 16:06:53 +00:00
|
|
|
case NS_FORM_INPUT_DATE:
|
2013-01-08 17:10:00 +00:00
|
|
|
case NS_FORM_INPUT_TIME:
|
2010-08-18 18:30:41 +00:00
|
|
|
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
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-09-29 06:19:26 +00:00
|
|
|
bool
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::IsMutable() const
|
2010-08-18 18:30:41 +00:00
|
|
|
{
|
2010-09-18 21:33:16 +00:00
|
|
|
return !IsDisabled() && GetCurrentDoc() &&
|
2010-08-18 18:30:41 +00:00
|
|
|
!(DoesReadOnlyApply() &&
|
|
|
|
HasAttr(kNameSpaceID_None, nsGkAtoms::readonly));
|
|
|
|
}
|
|
|
|
|
2011-09-29 06:19:26 +00:00
|
|
|
bool
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::DoesReadOnlyApply() const
|
2010-08-18 18:30:41 +00:00
|
|
|
{
|
|
|
|
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:
|
2013-02-16 12:35:57 +00:00
|
|
|
case NS_FORM_INPUT_RANGE:
|
2010-08-18 18:30:41 +00:00
|
|
|
// TODO:
|
|
|
|
// case NS_FORM_INPUT_COLOR:
|
2011-10-17 14:59:28 +00:00
|
|
|
return false;
|
2010-08-18 18:30:41 +00:00
|
|
|
#ifdef DEBUG
|
|
|
|
case NS_FORM_INPUT_TEXT:
|
|
|
|
case NS_FORM_INPUT_PASSWORD:
|
|
|
|
case NS_FORM_INPUT_SEARCH:
|
|
|
|
case NS_FORM_INPUT_TEL:
|
2010-08-18 18:31:54 +00:00
|
|
|
case NS_FORM_INPUT_EMAIL:
|
2010-08-18 18:33:37 +00:00
|
|
|
case NS_FORM_INPUT_URL:
|
2012-06-10 20:23:17 +00:00
|
|
|
case NS_FORM_INPUT_NUMBER:
|
2012-12-27 16:06:53 +00:00
|
|
|
case NS_FORM_INPUT_DATE:
|
2013-01-08 17:10:00 +00:00
|
|
|
case NS_FORM_INPUT_TIME:
|
2011-10-17 14:59:28 +00:00
|
|
|
return true;
|
2010-08-18 18:30:41 +00:00
|
|
|
default:
|
|
|
|
NS_NOTYETIMPLEMENTED("Unexpected input type in DoesReadOnlyApply()");
|
2011-10-17 14:59:28 +00:00
|
|
|
return true;
|
2010-08-18 18:30:41 +00:00
|
|
|
#else // DEBUG
|
|
|
|
default:
|
2011-10-17 14:59:28 +00:00
|
|
|
return true;
|
2010-08-18 18:30:41 +00:00
|
|
|
#endif // DEBUG
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-09-29 06:19:26 +00:00
|
|
|
bool
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::DoesRequiredApply() const
|
2010-08-18 18:30:41 +00:00
|
|
|
{
|
|
|
|
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:
|
2013-02-16 12:35:57 +00:00
|
|
|
case NS_FORM_INPUT_RANGE:
|
2010-08-18 18:30:41 +00:00
|
|
|
// TODO:
|
|
|
|
// case NS_FORM_INPUT_COLOR:
|
2011-10-17 14:59:28 +00:00
|
|
|
return false;
|
2010-08-18 18:30:41 +00:00
|
|
|
#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:
|
2010-08-18 18:31:54 +00:00
|
|
|
case NS_FORM_INPUT_EMAIL:
|
2010-08-18 18:33:37 +00:00
|
|
|
case NS_FORM_INPUT_URL:
|
2012-06-10 20:23:17 +00:00
|
|
|
case NS_FORM_INPUT_NUMBER:
|
2012-12-27 16:06:53 +00:00
|
|
|
case NS_FORM_INPUT_DATE:
|
2013-01-08 17:10:00 +00:00
|
|
|
case NS_FORM_INPUT_TIME:
|
2011-10-17 14:59:28 +00:00
|
|
|
return true;
|
2010-08-18 18:30:41 +00:00
|
|
|
default:
|
|
|
|
NS_NOTYETIMPLEMENTED("Unexpected input type in DoesRequiredApply()");
|
2011-10-17 14:59:28 +00:00
|
|
|
return true;
|
2010-08-18 18:30:41 +00:00
|
|
|
#else // DEBUG
|
|
|
|
default:
|
2011-10-17 14:59:28 +00:00
|
|
|
return true;
|
2010-08-18 18:30:41 +00:00
|
|
|
#endif // DEBUG
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-12-27 16:06:53 +00:00
|
|
|
bool
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::PlaceholderApplies() const
|
2012-12-27 16:06:53 +00:00
|
|
|
{
|
2013-01-08 17:10:00 +00:00
|
|
|
if (mType == NS_FORM_INPUT_DATE ||
|
|
|
|
mType == NS_FORM_INPUT_TIME) {
|
2012-12-27 16:06:53 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return IsSingleLineTextControl(false);
|
|
|
|
}
|
|
|
|
|
2011-09-29 06:19:26 +00:00
|
|
|
bool
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::DoesPatternApply() const
|
2010-08-18 19:26:22 +00:00
|
|
|
{
|
2013-01-08 17:10:00 +00:00
|
|
|
// TODO: temporary until bug 635240 and bug 773205 are fixed.
|
2013-01-31 23:01:50 +00:00
|
|
|
if (IsExperimentalMobileType(mType)) {
|
2012-06-10 20:23:17 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2011-10-17 14:59:28 +00:00
|
|
|
return IsSingleLineTextControl(false);
|
2010-08-18 19:26:22 +00:00
|
|
|
}
|
|
|
|
|
2012-06-22 09:36:24 +00:00
|
|
|
bool
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::DoesMinMaxApply() const
|
2012-06-22 09:36:24 +00:00
|
|
|
{
|
|
|
|
switch (mType)
|
|
|
|
{
|
|
|
|
case NS_FORM_INPUT_NUMBER:
|
2012-12-27 16:06:53 +00:00
|
|
|
case NS_FORM_INPUT_DATE:
|
2013-01-31 23:00:08 +00:00
|
|
|
case NS_FORM_INPUT_TIME:
|
2013-02-16 12:35:57 +00:00
|
|
|
case NS_FORM_INPUT_RANGE:
|
2012-06-22 09:36:24 +00:00
|
|
|
// TODO:
|
|
|
|
// All date/time types.
|
|
|
|
return true;
|
|
|
|
#ifdef DEBUG
|
|
|
|
case NS_FORM_INPUT_RESET:
|
|
|
|
case NS_FORM_INPUT_SUBMIT:
|
|
|
|
case NS_FORM_INPUT_IMAGE:
|
|
|
|
case NS_FORM_INPUT_BUTTON:
|
|
|
|
case NS_FORM_INPUT_HIDDEN:
|
|
|
|
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:
|
|
|
|
case NS_FORM_INPUT_EMAIL:
|
|
|
|
case NS_FORM_INPUT_URL:
|
|
|
|
return false;
|
|
|
|
default:
|
|
|
|
NS_NOTYETIMPLEMENTED("Unexpected input type in DoesRequiredApply()");
|
|
|
|
return false;
|
|
|
|
#else // DEBUG
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
#endif // DEBUG
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-06-22 19:02:20 +00:00
|
|
|
double
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::GetStep() const
|
2012-06-22 19:02:20 +00:00
|
|
|
{
|
2013-01-31 23:00:08 +00:00
|
|
|
MOZ_ASSERT(DoesStepApply(), "GetStep() can only be called if @step applies");
|
2012-06-22 19:02:20 +00:00
|
|
|
|
2013-02-06 22:56:49 +00:00
|
|
|
if (!HasAttr(kNameSpaceID_None, nsGkAtoms::step)) {
|
|
|
|
return GetDefaultStep() * GetStepScaleFactor();
|
|
|
|
}
|
2012-06-22 19:02:20 +00:00
|
|
|
|
2013-02-06 22:56:49 +00:00
|
|
|
nsAutoString stepStr;
|
|
|
|
GetAttr(kNameSpaceID_None, nsGkAtoms::step, stepStr);
|
2012-06-22 19:02:20 +00:00
|
|
|
|
2013-02-06 22:56:49 +00:00
|
|
|
if (stepStr.LowerCaseEqualsLiteral("any")) {
|
|
|
|
// The element can't suffer from step mismatch if there is no step.
|
|
|
|
return kStepAny;
|
|
|
|
}
|
2012-06-22 19:02:20 +00:00
|
|
|
|
2013-02-06 22:56:49 +00:00
|
|
|
nsresult ec;
|
|
|
|
double step = stepStr.ToDouble(&ec);
|
2013-02-14 17:25:26 +00:00
|
|
|
if (NS_FAILED(ec) || !MOZ_DOUBLE_IS_FINITE(step) || step <= 0) {
|
2013-02-06 22:56:49 +00:00
|
|
|
step = GetDefaultStep();
|
2012-06-22 19:02:20 +00:00
|
|
|
}
|
|
|
|
|
2012-12-22 14:46:19 +00:00
|
|
|
// TODO: This multiplication can lead to inexact results, we should use a
|
|
|
|
// type that supports a better precision than double. Bug 783607.
|
|
|
|
return step * GetStepScaleFactor();
|
2012-06-22 19:02:20 +00:00
|
|
|
}
|
|
|
|
|
2010-08-21 18:52:49 +00:00
|
|
|
// nsIConstraintValidation
|
2010-08-18 18:28:08 +00:00
|
|
|
|
2010-08-21 17:52:57 +00:00
|
|
|
NS_IMETHODIMP
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::SetCustomValidity(const nsAString& aError)
|
2010-08-21 17:52:57 +00:00
|
|
|
{
|
2010-08-21 18:52:49 +00:00
|
|
|
nsIConstraintValidation::SetCustomValidity(aError);
|
2010-08-21 17:52:57 +00:00
|
|
|
|
2011-06-01 01:46:57 +00:00
|
|
|
UpdateState(true);
|
2010-08-21 17:52:57 +00:00
|
|
|
|
2010-08-21 18:51:38 +00:00
|
|
|
return NS_OK;
|
2010-08-21 17:52:57 +00:00
|
|
|
}
|
|
|
|
|
2011-09-29 06:19:26 +00:00
|
|
|
bool
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::IsTooLong()
|
2010-08-18 18:28:08 +00:00
|
|
|
{
|
2010-10-07 10:01:53 +00:00
|
|
|
if (!MaxLengthApplies() ||
|
|
|
|
!HasAttr(kNameSpaceID_None, nsGkAtoms::maxlength) ||
|
2011-11-16 07:50:19 +00:00
|
|
|
!mValueChanged) {
|
2011-10-17 14:59:28 +00:00
|
|
|
return false;
|
2010-08-18 18:29:20 +00:00
|
|
|
}
|
|
|
|
|
2013-03-28 19:41:32 +00:00
|
|
|
int32_t maxLength = MaxLength();
|
2010-10-07 10:02:29 +00:00
|
|
|
|
|
|
|
// Maxlength of -1 means parsing error.
|
|
|
|
if (maxLength == -1) {
|
2011-10-17 14:59:28 +00:00
|
|
|
return false;
|
2010-10-07 10:02:29 +00:00
|
|
|
}
|
|
|
|
|
2012-08-22 15:56:38 +00:00
|
|
|
int32_t textLength = -1;
|
2010-08-18 18:28:08 +00:00
|
|
|
GetTextLength(&textLength);
|
|
|
|
|
2010-10-07 10:02:29 +00:00
|
|
|
return textLength > maxLength;
|
2010-08-18 18:28:08 +00:00
|
|
|
}
|
|
|
|
|
2011-09-29 06:19:26 +00:00
|
|
|
bool
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::IsValueMissing() const
|
2010-08-18 18:30:41 +00:00
|
|
|
{
|
2012-05-16 10:43:20 +00:00
|
|
|
// Should use UpdateValueMissingValidityStateForRadio() for type radio.
|
|
|
|
MOZ_ASSERT(mType != NS_FORM_INPUT_RADIO);
|
|
|
|
|
2010-08-18 18:30:41 +00:00
|
|
|
if (!HasAttr(kNameSpaceID_None, nsGkAtoms::required) ||
|
|
|
|
!DoesRequiredApply()) {
|
2011-10-17 14:59:28 +00:00
|
|
|
return false;
|
2010-08-18 18:30:41 +00:00
|
|
|
}
|
|
|
|
|
2012-05-16 10:43:20 +00:00
|
|
|
if (!IsMutable()) {
|
|
|
|
return false;
|
2010-08-18 18:30:41 +00:00
|
|
|
}
|
|
|
|
|
2012-05-16 10:43:20 +00:00
|
|
|
switch (GetValueMode()) {
|
|
|
|
case VALUE_MODE_VALUE:
|
|
|
|
return IsValueEmpty();
|
|
|
|
case VALUE_MODE_FILENAME:
|
|
|
|
{
|
2013-03-28 19:41:32 +00:00
|
|
|
const nsCOMArray<nsIDOMFile>& files = GetFilesInternal();
|
2012-05-16 10:43:20 +00:00
|
|
|
return !files.Count();
|
|
|
|
}
|
|
|
|
case VALUE_MODE_DEFAULT_ON:
|
|
|
|
// This should not be used for type radio.
|
|
|
|
// See the MOZ_ASSERT at the beginning of the method.
|
2011-11-16 07:50:19 +00:00
|
|
|
return !mChecked;
|
2012-05-16 10:43:20 +00:00
|
|
|
case VALUE_MODE_DEFAULT:
|
2010-08-21 17:52:57 +00:00
|
|
|
default:
|
2011-10-17 14:59:28 +00:00
|
|
|
return false;
|
2010-08-18 18:30:41 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-09-29 06:19:26 +00:00
|
|
|
bool
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::HasTypeMismatch() const
|
2010-08-18 18:31:54 +00:00
|
|
|
{
|
2010-08-21 17:52:57 +00:00
|
|
|
if (mType != NS_FORM_INPUT_EMAIL && mType != NS_FORM_INPUT_URL) {
|
2011-10-17 14:59:28 +00:00
|
|
|
return false;
|
2010-08-21 17:52:57 +00:00
|
|
|
}
|
2010-08-18 18:31:54 +00:00
|
|
|
|
2010-08-21 17:52:57 +00:00
|
|
|
nsAutoString value;
|
2011-10-17 14:59:28 +00:00
|
|
|
NS_ENSURE_SUCCESS(GetValueInternal(value), false);
|
2010-08-18 18:33:37 +00:00
|
|
|
|
2010-08-21 17:52:57 +00:00
|
|
|
if (value.IsEmpty()) {
|
2011-10-17 14:59:28 +00:00
|
|
|
return false;
|
2010-08-21 17:52:57 +00:00
|
|
|
}
|
2010-08-18 18:33:37 +00:00
|
|
|
|
2010-08-21 17:52:57 +00:00
|
|
|
if (mType == NS_FORM_INPUT_EMAIL) {
|
|
|
|
return HasAttr(kNameSpaceID_None, nsGkAtoms::multiple)
|
|
|
|
? !IsValidEmailAddressList(value) : !IsValidEmailAddress(value);
|
|
|
|
} else if (mType == NS_FORM_INPUT_URL) {
|
2010-08-18 18:33:37 +00:00
|
|
|
/**
|
|
|
|
* TODO:
|
|
|
|
* The URL is not checked as the HTML5 specifications want it to be because
|
|
|
|
* there is no code to check for a valid URI/IRI according to 3986 and 3987
|
|
|
|
* RFC's at the moment, see bug 561586.
|
|
|
|
*
|
|
|
|
* RFC 3987 (IRI) implementation: bug 42899
|
|
|
|
*
|
|
|
|
* HTML5 specifications:
|
|
|
|
* http://dev.w3.org/html5/spec/infrastructure.html#valid-url
|
|
|
|
*/
|
|
|
|
nsCOMPtr<nsIIOService> ioService = do_GetIOService();
|
|
|
|
nsCOMPtr<nsIURI> uri;
|
|
|
|
|
2012-07-30 14:20:58 +00:00
|
|
|
return !NS_SUCCEEDED(ioService->NewURI(NS_ConvertUTF16toUTF8(value), nullptr,
|
|
|
|
nullptr, getter_AddRefs(uri)));
|
2010-08-18 18:31:54 +00:00
|
|
|
}
|
|
|
|
|
2011-10-17 14:59:28 +00:00
|
|
|
return false;
|
2010-08-18 18:31:54 +00:00
|
|
|
}
|
|
|
|
|
2011-09-29 06:19:26 +00:00
|
|
|
bool
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::HasPatternMismatch() const
|
2010-08-18 19:26:22 +00:00
|
|
|
{
|
2010-08-21 17:52:57 +00:00
|
|
|
if (!DoesPatternApply() ||
|
2012-07-05 10:03:19 +00:00
|
|
|
!HasAttr(kNameSpaceID_None, nsGkAtoms::pattern)) {
|
2011-10-17 14:59:28 +00:00
|
|
|
return false;
|
2010-08-18 19:26:22 +00:00
|
|
|
}
|
|
|
|
|
2012-07-05 10:03:19 +00:00
|
|
|
nsAutoString pattern;
|
|
|
|
GetAttr(kNameSpaceID_None, nsGkAtoms::pattern, pattern);
|
|
|
|
|
2010-08-18 19:26:22 +00:00
|
|
|
nsAutoString value;
|
2011-10-17 14:59:28 +00:00
|
|
|
NS_ENSURE_SUCCESS(GetValueInternal(value), false);
|
2010-08-18 19:26:22 +00:00
|
|
|
|
|
|
|
if (value.IsEmpty()) {
|
2011-10-17 14:59:28 +00:00
|
|
|
return false;
|
2010-08-18 19:26:22 +00:00
|
|
|
}
|
|
|
|
|
2011-10-18 10:53:36 +00:00
|
|
|
nsIDocument* doc = OwnerDoc();
|
2010-08-18 19:26:22 +00:00
|
|
|
|
2011-04-28 17:21:37 +00:00
|
|
|
return !nsContentUtils::IsPatternMatching(value, pattern, doc);
|
2010-08-18 19:26:22 +00:00
|
|
|
}
|
|
|
|
|
2012-06-22 09:36:24 +00:00
|
|
|
bool
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::IsRangeOverflow() const
|
2012-06-22 09:36:24 +00:00
|
|
|
{
|
2013-01-31 23:00:08 +00:00
|
|
|
if (!DoesMinMaxApply()) {
|
2012-06-22 09:36:24 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2013-01-25 23:51:57 +00:00
|
|
|
double maximum = GetMaximum();
|
|
|
|
if (MOZ_DOUBLE_IS_NaN(maximum)) {
|
2012-06-22 09:36:24 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
double value = GetValueAsDouble();
|
2012-07-06 12:41:00 +00:00
|
|
|
if (MOZ_DOUBLE_IS_NaN(value)) {
|
2012-06-22 09:36:24 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2013-01-25 23:51:57 +00:00
|
|
|
return value > maximum;
|
2012-06-22 09:36:24 +00:00
|
|
|
}
|
|
|
|
|
2012-06-22 09:38:20 +00:00
|
|
|
bool
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::IsRangeUnderflow() const
|
2012-06-22 09:38:20 +00:00
|
|
|
{
|
2012-12-21 17:28:01 +00:00
|
|
|
if (!DoesMinMaxApply()) {
|
2012-06-22 09:38:20 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2013-01-25 23:51:57 +00:00
|
|
|
double minimum = GetMinimum();
|
|
|
|
if (MOZ_DOUBLE_IS_NaN(minimum)) {
|
2012-06-22 09:38:20 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
double value = GetValueAsDouble();
|
2012-07-06 12:41:00 +00:00
|
|
|
if (MOZ_DOUBLE_IS_NaN(value)) {
|
2012-06-22 09:38:20 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2013-01-25 23:51:57 +00:00
|
|
|
return value < minimum;
|
2012-06-22 09:38:20 +00:00
|
|
|
}
|
|
|
|
|
2012-06-22 19:02:20 +00:00
|
|
|
bool
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::HasStepMismatch() const
|
2012-06-22 19:02:20 +00:00
|
|
|
{
|
|
|
|
if (!DoesStepApply()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
double value = GetValueAsDouble();
|
2012-07-06 12:41:00 +00:00
|
|
|
if (MOZ_DOUBLE_IS_NaN(value)) {
|
2012-06-22 19:02:20 +00:00
|
|
|
// The element can't suffer from step mismatch if it's value isn't a number.
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
double step = GetStep();
|
|
|
|
if (step == kStepAny) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2012-12-22 14:46:19 +00:00
|
|
|
if (mType == NS_FORM_INPUT_DATE) {
|
|
|
|
// The multiplication by the stepScaleFactor for date can easily lead
|
|
|
|
// to precision loss, since in most use cases this value should be
|
|
|
|
// an integer (millisecond precision), we can get rid of the precision
|
|
|
|
// loss by rounding step. This will however lead to erroneous results
|
|
|
|
// when step was intented to have a precision superior to a millisecond.
|
|
|
|
step = NS_round(step);
|
|
|
|
}
|
|
|
|
|
2012-06-22 19:02:20 +00:00
|
|
|
// Value has to be an integral multiple of step.
|
2012-07-06 12:41:23 +00:00
|
|
|
return NS_floorModulo(value - GetStepBase(), step) != 0;
|
2012-06-22 19:02:20 +00:00
|
|
|
}
|
|
|
|
|
2010-08-21 17:52:57 +00:00
|
|
|
void
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::UpdateTooLongValidityState()
|
2010-08-21 17:52:57 +00:00
|
|
|
{
|
2010-11-23 14:17:12 +00:00
|
|
|
// TODO: this code will be re-enabled with bug 613016 and bug 613019.
|
|
|
|
#if 0
|
2010-08-21 17:52:57 +00:00
|
|
|
SetValidityState(VALIDITY_STATE_TOO_LONG, IsTooLong());
|
2010-11-23 14:17:12 +00:00
|
|
|
#endif
|
2010-08-21 17:52:57 +00:00
|
|
|
}
|
|
|
|
|
2010-12-16 19:51:59 +00:00
|
|
|
void
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::UpdateValueMissingValidityStateForRadio(bool aIgnoreSelf)
|
2010-12-16 19:51:59 +00:00
|
|
|
{
|
2011-11-16 07:50:19 +00:00
|
|
|
bool notify = !mParserCreating;
|
2010-12-16 19:51:59 +00:00
|
|
|
nsCOMPtr<nsIDOMHTMLInputElement> selection = GetSelectedRadioButton();
|
2011-02-25 18:12:47 +00:00
|
|
|
|
2010-12-16 19:51:59 +00:00
|
|
|
// If there is no selection, that might mean the radio is not in a group.
|
|
|
|
// In that case, we can look for the checked state of the radio.
|
2011-11-16 07:50:19 +00:00
|
|
|
bool selected = selection || (!aIgnoreSelf && mChecked);
|
2011-11-16 07:50:19 +00:00
|
|
|
bool required = !aIgnoreSelf && HasAttr(kNameSpaceID_None, nsGkAtoms::required);
|
2010-12-16 19:51:59 +00:00
|
|
|
bool valueMissing = false;
|
|
|
|
|
2011-07-19 09:44:55 +00:00
|
|
|
nsCOMPtr<nsIRadioGroupContainer> container = GetRadioGroupContainer();
|
2011-05-04 12:49:59 +00:00
|
|
|
|
|
|
|
if (!container) {
|
2012-05-16 10:43:20 +00:00
|
|
|
SetValidityState(VALIDITY_STATE_VALUE_MISSING,
|
|
|
|
IsMutable() && required && !selected);
|
2011-05-04 12:49:59 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2011-02-25 18:12:47 +00:00
|
|
|
nsAutoString name;
|
2011-05-04 12:49:59 +00:00
|
|
|
GetAttr(kNameSpaceID_None, nsGkAtoms::name, name);
|
2011-02-25 18:12:47 +00:00
|
|
|
|
|
|
|
// If the current radio is required and not ignored, we can assume the entire
|
|
|
|
// group is required.
|
2011-05-04 12:49:59 +00:00
|
|
|
if (!required) {
|
2011-02-25 18:12:47 +00:00
|
|
|
required = (aIgnoreSelf && HasAttr(kNameSpaceID_None, nsGkAtoms::required))
|
|
|
|
? container->GetRequiredRadioCount(name) - 1
|
|
|
|
: container->GetRequiredRadioCount(name);
|
2010-12-16 19:51:59 +00:00
|
|
|
}
|
|
|
|
|
2012-05-16 10:43:20 +00:00
|
|
|
valueMissing = IsMutable() && required && !selected;
|
2010-12-16 19:51:59 +00:00
|
|
|
|
2011-05-04 12:49:59 +00:00
|
|
|
if (container->GetValueMissingState(name) != valueMissing) {
|
|
|
|
container->SetValueMissingState(name, valueMissing);
|
2011-05-04 12:45:47 +00:00
|
|
|
|
2011-05-04 12:53:06 +00:00
|
|
|
SetValidityState(VALIDITY_STATE_VALUE_MISSING, valueMissing);
|
2011-05-04 12:49:59 +00:00
|
|
|
|
2011-06-01 00:21:24 +00:00
|
|
|
// nsRadioSetValueMissingState will call ContentStateChanged while visiting.
|
|
|
|
nsAutoScriptBlocker scriptBlocker;
|
2011-05-04 12:49:59 +00:00
|
|
|
nsCOMPtr<nsIRadioVisitor> visitor =
|
|
|
|
new nsRadioSetValueMissingState(this, valueMissing, notify);
|
|
|
|
VisitGroup(visitor, notify);
|
2011-02-25 18:16:04 +00:00
|
|
|
}
|
2010-12-16 19:51:59 +00:00
|
|
|
}
|
|
|
|
|
2010-08-21 17:52:57 +00:00
|
|
|
void
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::UpdateValueMissingValidityState()
|
2010-08-21 17:52:57 +00:00
|
|
|
{
|
2010-12-16 19:51:59 +00:00
|
|
|
if (mType == NS_FORM_INPUT_RADIO) {
|
|
|
|
UpdateValueMissingValidityStateForRadio(false);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2010-08-21 17:52:57 +00:00
|
|
|
SetValidityState(VALIDITY_STATE_VALUE_MISSING, IsValueMissing());
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::UpdateTypeMismatchValidityState()
|
2010-08-21 17:52:57 +00:00
|
|
|
{
|
|
|
|
SetValidityState(VALIDITY_STATE_TYPE_MISMATCH, HasTypeMismatch());
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::UpdatePatternMismatchValidityState()
|
2010-08-21 17:52:57 +00:00
|
|
|
{
|
|
|
|
SetValidityState(VALIDITY_STATE_PATTERN_MISMATCH, HasPatternMismatch());
|
|
|
|
}
|
|
|
|
|
2012-06-22 09:36:24 +00:00
|
|
|
void
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::UpdateRangeOverflowValidityState()
|
2012-06-22 09:36:24 +00:00
|
|
|
{
|
|
|
|
SetValidityState(VALIDITY_STATE_RANGE_OVERFLOW, IsRangeOverflow());
|
|
|
|
}
|
|
|
|
|
2012-06-22 09:38:20 +00:00
|
|
|
void
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::UpdateRangeUnderflowValidityState()
|
2012-06-22 09:38:20 +00:00
|
|
|
{
|
|
|
|
SetValidityState(VALIDITY_STATE_RANGE_UNDERFLOW, IsRangeUnderflow());
|
|
|
|
}
|
|
|
|
|
2012-06-22 19:02:20 +00:00
|
|
|
void
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::UpdateStepMismatchValidityState()
|
2012-06-22 19:02:20 +00:00
|
|
|
{
|
|
|
|
SetValidityState(VALIDITY_STATE_STEP_MISMATCH, HasStepMismatch());
|
|
|
|
}
|
|
|
|
|
2010-08-21 17:52:57 +00:00
|
|
|
void
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::UpdateAllValidityStates(bool aNotify)
|
2010-08-21 17:52:57 +00:00
|
|
|
{
|
2011-09-29 06:19:26 +00:00
|
|
|
bool validBefore = IsValid();
|
2010-08-21 17:52:57 +00:00
|
|
|
UpdateTooLongValidityState();
|
|
|
|
UpdateValueMissingValidityState();
|
|
|
|
UpdateTypeMismatchValidityState();
|
|
|
|
UpdatePatternMismatchValidityState();
|
2012-06-22 09:36:24 +00:00
|
|
|
UpdateRangeOverflowValidityState();
|
2012-06-22 09:38:20 +00:00
|
|
|
UpdateRangeUnderflowValidityState();
|
2012-06-22 19:02:20 +00:00
|
|
|
UpdateStepMismatchValidityState();
|
2010-08-21 17:52:57 +00:00
|
|
|
|
2011-06-01 01:46:57 +00:00
|
|
|
if (validBefore != IsValid()) {
|
|
|
|
UpdateState(aNotify);
|
2010-08-21 17:52:57 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-09-10 05:08:56 +00:00
|
|
|
void
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::UpdateBarredFromConstraintValidation()
|
2010-08-18 18:28:08 +00:00
|
|
|
{
|
2010-09-10 05:08:56 +00:00
|
|
|
SetBarredFromConstraintValidation(mType == NS_FORM_INPUT_HIDDEN ||
|
|
|
|
mType == NS_FORM_INPUT_BUTTON ||
|
|
|
|
mType == NS_FORM_INPUT_RESET ||
|
2011-01-20 11:05:57 +00:00
|
|
|
mType == NS_FORM_INPUT_SUBMIT ||
|
|
|
|
mType == NS_FORM_INPUT_IMAGE ||
|
2010-09-10 05:08:56 +00:00
|
|
|
HasAttr(kNameSpaceID_None, nsGkAtoms::readonly) ||
|
2010-09-18 21:33:16 +00:00
|
|
|
IsDisabled());
|
2010-08-18 18:28:08 +00:00
|
|
|
}
|
|
|
|
|
2013-03-28 19:41:32 +00:00
|
|
|
void
|
|
|
|
HTMLInputElement::GetValidationMessage(nsAString& aValidationMessage,
|
|
|
|
ErrorResult& aRv)
|
|
|
|
{
|
|
|
|
aRv = GetValidationMessage(aValidationMessage);
|
|
|
|
}
|
|
|
|
|
2010-08-18 18:28:08 +00:00
|
|
|
nsresult
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::GetValidationMessage(nsAString& aValidationMessage,
|
2013-03-28 19:41:32 +00:00
|
|
|
ValidityStateType aType)
|
2010-08-18 18:28:08 +00:00
|
|
|
{
|
|
|
|
nsresult rv = NS_OK;
|
|
|
|
|
|
|
|
switch (aType)
|
|
|
|
{
|
2010-08-21 17:52:57 +00:00
|
|
|
case VALIDITY_STATE_TOO_LONG:
|
2010-08-18 18:28:08 +00:00
|
|
|
{
|
|
|
|
nsXPIDLString message;
|
2013-03-28 19:41:32 +00:00
|
|
|
int32_t maxLength = MaxLength();
|
2012-08-22 15:56:38 +00:00
|
|
|
int32_t textLength = -1;
|
2010-08-18 18:28:08 +00:00
|
|
|
nsAutoString strMaxLength;
|
|
|
|
nsAutoString strTextLength;
|
|
|
|
|
|
|
|
GetTextLength(&textLength);
|
|
|
|
|
|
|
|
strMaxLength.AppendInt(maxLength);
|
|
|
|
strTextLength.AppendInt(textLength);
|
|
|
|
|
2010-09-23 01:44:13 +00:00
|
|
|
const PRUnichar* params[] = { strMaxLength.get(), strTextLength.get() };
|
2010-08-18 18:28:08 +00:00
|
|
|
rv = nsContentUtils::FormatLocalizedString(nsContentUtils::eDOM_PROPERTIES,
|
2010-09-23 01:44:13 +00:00
|
|
|
"FormValidationTextTooLong",
|
2012-03-09 02:22:57 +00:00
|
|
|
params, message);
|
2010-08-18 18:28:08 +00:00
|
|
|
aValidationMessage = message;
|
|
|
|
break;
|
|
|
|
}
|
2010-08-21 17:52:57 +00:00
|
|
|
case VALIDITY_STATE_VALUE_MISSING:
|
2010-08-18 18:30:41 +00:00
|
|
|
{
|
|
|
|
nsXPIDLString message;
|
2012-09-02 02:35:17 +00:00
|
|
|
nsAutoCString key;
|
2010-08-18 18:30:41 +00:00
|
|
|
switch (mType)
|
|
|
|
{
|
|
|
|
case NS_FORM_INPUT_FILE:
|
2010-09-23 01:44:13 +00:00
|
|
|
key.Assign("FormValidationFileMissing");
|
2010-08-18 18:30:41 +00:00
|
|
|
break;
|
|
|
|
case NS_FORM_INPUT_CHECKBOX:
|
2010-09-23 01:44:13 +00:00
|
|
|
key.Assign("FormValidationCheckboxMissing");
|
2010-08-18 18:30:41 +00:00
|
|
|
break;
|
|
|
|
case NS_FORM_INPUT_RADIO:
|
2010-09-23 01:44:13 +00:00
|
|
|
key.Assign("FormValidationRadioMissing");
|
2010-08-18 18:30:41 +00:00
|
|
|
break;
|
|
|
|
default:
|
2010-09-23 01:44:13 +00:00
|
|
|
key.Assign("FormValidationValueMissing");
|
2010-08-18 18:30:41 +00:00
|
|
|
}
|
|
|
|
rv = nsContentUtils::GetLocalizedString(nsContentUtils::eDOM_PROPERTIES,
|
|
|
|
key.get(), message);
|
|
|
|
aValidationMessage = message;
|
|
|
|
break;
|
|
|
|
}
|
2010-08-21 17:52:57 +00:00
|
|
|
case VALIDITY_STATE_TYPE_MISMATCH:
|
2010-08-18 18:31:54 +00:00
|
|
|
{
|
|
|
|
nsXPIDLString message;
|
2012-09-02 02:35:17 +00:00
|
|
|
nsAutoCString key;
|
2010-08-18 18:33:37 +00:00
|
|
|
if (mType == NS_FORM_INPUT_EMAIL) {
|
2010-09-23 01:44:13 +00:00
|
|
|
key.AssignLiteral("FormValidationInvalidEmail");
|
2010-08-18 18:33:37 +00:00
|
|
|
} else if (mType == NS_FORM_INPUT_URL) {
|
2010-09-23 01:44:13 +00:00
|
|
|
key.AssignLiteral("FormValidationInvalidURL");
|
2010-08-18 18:33:37 +00:00
|
|
|
} else {
|
|
|
|
return NS_ERROR_UNEXPECTED;
|
|
|
|
}
|
2010-08-18 18:31:54 +00:00
|
|
|
rv = nsContentUtils::GetLocalizedString(nsContentUtils::eDOM_PROPERTIES,
|
2010-08-18 18:33:37 +00:00
|
|
|
key.get(), message);
|
2010-08-18 18:31:54 +00:00
|
|
|
aValidationMessage = message;
|
|
|
|
break;
|
|
|
|
}
|
2010-08-21 17:52:57 +00:00
|
|
|
case VALIDITY_STATE_PATTERN_MISMATCH:
|
2010-08-18 19:26:22 +00:00
|
|
|
{
|
|
|
|
nsXPIDLString message;
|
|
|
|
nsAutoString title;
|
|
|
|
GetAttr(kNameSpaceID_None, nsGkAtoms::title, title);
|
|
|
|
if (title.IsEmpty()) {
|
|
|
|
rv = nsContentUtils::GetLocalizedString(nsContentUtils::eDOM_PROPERTIES,
|
2010-09-23 01:44:13 +00:00
|
|
|
"FormValidationPatternMismatch",
|
2010-08-18 19:26:22 +00:00
|
|
|
message);
|
|
|
|
} else {
|
2010-10-25 22:02:24 +00:00
|
|
|
if (title.Length() > nsIConstraintValidation::sContentSpecifiedMaxLengthMessage) {
|
|
|
|
title.Truncate(nsIConstraintValidation::sContentSpecifiedMaxLengthMessage);
|
|
|
|
}
|
2010-08-18 19:26:22 +00:00
|
|
|
const PRUnichar* params[] = { title.get() };
|
|
|
|
rv = nsContentUtils::FormatLocalizedString(nsContentUtils::eDOM_PROPERTIES,
|
2010-09-23 01:44:13 +00:00
|
|
|
"FormValidationPatternMismatchWithTitle",
|
2012-03-09 02:22:57 +00:00
|
|
|
params, message);
|
2010-08-18 19:26:22 +00:00
|
|
|
}
|
|
|
|
aValidationMessage = message;
|
|
|
|
break;
|
|
|
|
}
|
2012-06-22 09:36:24 +00:00
|
|
|
case VALIDITY_STATE_RANGE_OVERFLOW:
|
|
|
|
{
|
|
|
|
nsXPIDLString message;
|
|
|
|
|
2012-07-06 12:40:18 +00:00
|
|
|
nsAutoString maxStr;
|
2013-02-16 12:35:57 +00:00
|
|
|
if (mType == NS_FORM_INPUT_NUMBER ||
|
|
|
|
mType == NS_FORM_INPUT_RANGE) {
|
2012-12-21 17:26:56 +00:00
|
|
|
//We want to show the value as parsed when it's a number
|
2013-01-25 23:51:57 +00:00
|
|
|
double maximum = GetMaximum();
|
|
|
|
MOZ_ASSERT(!MOZ_DOUBLE_IS_NaN(maximum));
|
2012-12-21 17:26:56 +00:00
|
|
|
|
2013-01-25 23:51:57 +00:00
|
|
|
maxStr.AppendFloat(maximum);
|
2013-01-31 23:00:08 +00:00
|
|
|
} else if (mType == NS_FORM_INPUT_DATE || mType == NS_FORM_INPUT_TIME) {
|
2012-12-21 17:26:56 +00:00
|
|
|
GetAttr(kNameSpaceID_None, nsGkAtoms::max, maxStr);
|
|
|
|
} else {
|
|
|
|
NS_NOTREACHED("Unexpected input type");
|
|
|
|
}
|
2012-06-22 09:36:24 +00:00
|
|
|
|
|
|
|
const PRUnichar* params[] = { maxStr.get() };
|
|
|
|
rv = nsContentUtils::FormatLocalizedString(nsContentUtils::eDOM_PROPERTIES,
|
|
|
|
"FormValidationRangeOverflow",
|
|
|
|
params, message);
|
|
|
|
aValidationMessage = message;
|
|
|
|
break;
|
|
|
|
}
|
2012-06-22 09:38:20 +00:00
|
|
|
case VALIDITY_STATE_RANGE_UNDERFLOW:
|
|
|
|
{
|
|
|
|
nsXPIDLString message;
|
|
|
|
|
2012-07-06 12:40:18 +00:00
|
|
|
nsAutoString minStr;
|
2013-02-16 12:35:57 +00:00
|
|
|
if (mType == NS_FORM_INPUT_NUMBER ||
|
|
|
|
mType == NS_FORM_INPUT_RANGE) {
|
2013-01-25 23:51:57 +00:00
|
|
|
double minimum = GetMinimum();
|
|
|
|
MOZ_ASSERT(!MOZ_DOUBLE_IS_NaN(minimum));
|
2012-12-21 17:28:01 +00:00
|
|
|
|
2013-01-25 23:51:57 +00:00
|
|
|
minStr.AppendFloat(minimum);
|
2013-01-31 23:00:08 +00:00
|
|
|
} else if (mType == NS_FORM_INPUT_DATE || mType == NS_FORM_INPUT_TIME) {
|
2012-12-21 17:28:01 +00:00
|
|
|
GetAttr(kNameSpaceID_None, nsGkAtoms::min, minStr);
|
|
|
|
} else {
|
|
|
|
NS_NOTREACHED("Unexpected input type");
|
|
|
|
}
|
2012-06-22 09:38:20 +00:00
|
|
|
|
|
|
|
const PRUnichar* params[] = { minStr.get() };
|
|
|
|
rv = nsContentUtils::FormatLocalizedString(nsContentUtils::eDOM_PROPERTIES,
|
|
|
|
"FormValidationRangeUnderflow",
|
|
|
|
params, message);
|
|
|
|
aValidationMessage = message;
|
|
|
|
break;
|
|
|
|
}
|
2012-06-22 19:02:20 +00:00
|
|
|
case VALIDITY_STATE_STEP_MISMATCH:
|
|
|
|
{
|
|
|
|
nsXPIDLString message;
|
|
|
|
|
|
|
|
double value = GetValueAsDouble();
|
2012-07-06 12:41:00 +00:00
|
|
|
MOZ_ASSERT(!MOZ_DOUBLE_IS_NaN(value));
|
2012-06-22 19:02:20 +00:00
|
|
|
|
|
|
|
double step = GetStep();
|
2012-07-06 12:41:00 +00:00
|
|
|
MOZ_ASSERT(step != kStepAny);
|
2012-06-22 19:02:20 +00:00
|
|
|
|
2012-12-22 14:46:19 +00:00
|
|
|
// In case this is a date and the step is not an integer, we don't want to
|
|
|
|
// display the dates corresponding to the truncated timestamps of valueLow
|
|
|
|
// and valueHigh because they might suffer from a step mismatch as well.
|
|
|
|
// Instead we want the timestamps to correspond to a rounded day. That is,
|
|
|
|
// we want a multiple of the step scale factor (1 day) as well as of step.
|
|
|
|
if (mType == NS_FORM_INPUT_DATE) {
|
|
|
|
step = EuclidLCM<uint64_t>(static_cast<uint64_t>(step),
|
|
|
|
static_cast<uint64_t>(GetStepScaleFactor()));
|
|
|
|
}
|
|
|
|
|
2012-07-06 12:41:23 +00:00
|
|
|
double stepBase = GetStepBase();
|
2012-06-22 19:02:20 +00:00
|
|
|
|
2012-07-06 12:41:23 +00:00
|
|
|
double valueLow = value - NS_floorModulo(value - stepBase, step);
|
|
|
|
double valueHigh = value + step - NS_floorModulo(value - stepBase, step);
|
2012-06-22 19:02:20 +00:00
|
|
|
|
2013-01-25 23:51:57 +00:00
|
|
|
double maximum = GetMaximum();
|
2012-06-22 19:02:20 +00:00
|
|
|
|
2013-01-25 23:51:57 +00:00
|
|
|
if (MOZ_DOUBLE_IS_NaN(maximum) || valueHigh <= maximum) {
|
2012-06-22 19:02:20 +00:00
|
|
|
nsAutoString valueLowStr, valueHighStr;
|
2012-12-22 14:46:19 +00:00
|
|
|
ConvertNumberToString(valueLow, valueLowStr);
|
|
|
|
ConvertNumberToString(valueHigh, valueHighStr);
|
2012-06-22 19:02:20 +00:00
|
|
|
|
2013-02-06 22:56:49 +00:00
|
|
|
if (valueLowStr.Equals(valueHighStr)) {
|
|
|
|
const PRUnichar* params[] = { valueLowStr.get() };
|
|
|
|
rv = nsContentUtils::FormatLocalizedString(nsContentUtils::eDOM_PROPERTIES,
|
|
|
|
"FormValidationStepMismatchOneValue",
|
|
|
|
params, message);
|
|
|
|
} else {
|
|
|
|
const PRUnichar* params[] = { valueLowStr.get(), valueHighStr.get() };
|
|
|
|
rv = nsContentUtils::FormatLocalizedString(nsContentUtils::eDOM_PROPERTIES,
|
|
|
|
"FormValidationStepMismatch",
|
|
|
|
params, message);
|
|
|
|
}
|
2012-06-22 19:02:20 +00:00
|
|
|
} else {
|
|
|
|
nsAutoString valueLowStr;
|
2012-12-22 14:46:19 +00:00
|
|
|
ConvertNumberToString(valueLow, valueLowStr);
|
2012-06-22 19:02:20 +00:00
|
|
|
|
|
|
|
const PRUnichar* params[] = { valueLowStr.get() };
|
|
|
|
rv = nsContentUtils::FormatLocalizedString(nsContentUtils::eDOM_PROPERTIES,
|
2013-02-06 22:56:49 +00:00
|
|
|
"FormValidationStepMismatchOneValue",
|
2012-06-22 19:02:20 +00:00
|
|
|
params, message);
|
|
|
|
}
|
|
|
|
|
|
|
|
aValidationMessage = message;
|
|
|
|
break;
|
|
|
|
}
|
2010-08-18 18:28:08 +00:00
|
|
|
default:
|
2010-08-21 18:52:49 +00:00
|
|
|
rv = nsIConstraintValidation::GetValidationMessage(aValidationMessage, aType);
|
2010-08-18 18:28:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return rv;
|
|
|
|
}
|
2002-03-07 20:53:40 +00:00
|
|
|
|
2010-08-18 18:31:54 +00:00
|
|
|
//static
|
2011-09-29 06:19:26 +00:00
|
|
|
bool
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::IsValidEmailAddressList(const nsAString& aValue)
|
2010-08-18 18:31:54 +00:00
|
|
|
{
|
2012-01-04 10:08:00 +00:00
|
|
|
HTMLSplitOnSpacesTokenizer tokenizer(aValue, ',');
|
2010-08-18 18:31:54 +00:00
|
|
|
|
|
|
|
while (tokenizer.hasMoreTokens()) {
|
|
|
|
if (!IsValidEmailAddress(tokenizer.nextToken())) {
|
2011-10-17 14:59:28 +00:00
|
|
|
return false;
|
2010-08-18 18:31:54 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return !tokenizer.lastTokenEndedWithSeparator();
|
|
|
|
}
|
|
|
|
|
|
|
|
//static
|
2011-09-29 06:19:26 +00:00
|
|
|
bool
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::IsValidEmailAddress(const nsAString& aValue)
|
2010-08-18 18:31:54 +00:00
|
|
|
{
|
2012-09-02 02:35:17 +00:00
|
|
|
nsAutoCString value = NS_ConvertUTF16toUTF8(aValue);
|
2012-08-22 15:56:38 +00:00
|
|
|
uint32_t i = 0;
|
|
|
|
uint32_t length = value.Length();
|
2012-02-29 22:35:47 +00:00
|
|
|
|
|
|
|
// Puny-encode the string if needed before running the validation algorithm.
|
|
|
|
nsCOMPtr<nsIIDNService> idnSrv = do_GetService(NS_IDNSERVICE_CONTRACTID);
|
|
|
|
if (idnSrv) {
|
|
|
|
bool ace;
|
|
|
|
if (NS_SUCCEEDED(idnSrv->IsACE(value, &ace)) && !ace) {
|
2012-09-02 02:35:17 +00:00
|
|
|
nsAutoCString punyCodedValue;
|
2012-02-29 22:35:47 +00:00
|
|
|
if (NS_SUCCEEDED(idnSrv->ConvertUTF8toACE(value, punyCodedValue))) {
|
|
|
|
value = punyCodedValue;
|
|
|
|
length = value.Length();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
NS_ERROR("nsIIDNService isn't present!");
|
|
|
|
}
|
2010-08-18 18:31:54 +00:00
|
|
|
|
2013-04-10 22:05:07 +00:00
|
|
|
// If the email address is empty, begins with an '@'
|
|
|
|
// or ends with a '.' or '-', we know it's invalid.
|
|
|
|
if (length == 0 || value[0] == '@' || value[length-1] == '.' ||
|
|
|
|
value[length-1] == '-') {
|
2011-10-17 14:59:28 +00:00
|
|
|
return false;
|
2010-08-18 18:31:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Parsing the username.
|
2012-02-29 22:35:47 +00:00
|
|
|
for (; i < length && value[i] != '@'; ++i) {
|
|
|
|
PRUnichar c = value[i];
|
2010-08-18 18:31:54 +00:00
|
|
|
|
|
|
|
// The username characters have to be in this list to be valid.
|
|
|
|
if (!(nsCRT::IsAsciiAlpha(c) || nsCRT::IsAsciiDigit(c) ||
|
|
|
|
c == '.' || c == '!' || c == '#' || c == '$' || c == '%' ||
|
|
|
|
c == '&' || c == '\''|| c == '*' || c == '+' || c == '-' ||
|
|
|
|
c == '/' || c == '=' || c == '?' || c == '^' || c == '_' ||
|
|
|
|
c == '`' || c == '{' || c == '|' || c == '}' || c == '~' )) {
|
2011-10-17 14:59:28 +00:00
|
|
|
return false;
|
2010-08-18 18:31:54 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-04-10 22:05:07 +00:00
|
|
|
// If there is no domain name, that's not a valid email address.
|
2010-08-18 18:31:54 +00:00
|
|
|
if (++i >= length) {
|
2011-10-17 14:59:28 +00:00
|
|
|
return false;
|
2010-08-18 18:31:54 +00:00
|
|
|
}
|
|
|
|
|
2013-04-10 22:05:07 +00:00
|
|
|
// The domain name can't begin with a dot or a dash.
|
|
|
|
if (value[i] == '.' || value[i] == '-') {
|
2011-10-17 14:59:28 +00:00
|
|
|
return false;
|
2010-08-18 18:31:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Parsing the domain name.
|
|
|
|
for (; i < length; ++i) {
|
2012-02-29 22:35:47 +00:00
|
|
|
PRUnichar c = value[i];
|
2010-08-18 18:31:54 +00:00
|
|
|
|
|
|
|
if (c == '.') {
|
2013-04-10 22:05:07 +00:00
|
|
|
// A dot can't follow a dot or a dash.
|
|
|
|
if (value[i-1] == '.' || value[i-1] == '-') {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
} else if (c == '-'){
|
|
|
|
// A dash can't follow a dot.
|
2012-02-29 22:35:47 +00:00
|
|
|
if (value[i-1] == '.') {
|
2011-10-17 14:59:28 +00:00
|
|
|
return false;
|
2010-08-18 18:31:54 +00:00
|
|
|
}
|
|
|
|
} else if (!(nsCRT::IsAsciiAlpha(c) || nsCRT::IsAsciiDigit(c) ||
|
|
|
|
c == '-')) {
|
|
|
|
// The domain characters have to be in this list to be valid.
|
2011-10-17 14:59:28 +00:00
|
|
|
return false;
|
2010-08-18 18:31:54 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-10-17 14:59:28 +00:00
|
|
|
return true;
|
2010-08-18 18:31:54 +00:00
|
|
|
}
|
|
|
|
|
2011-09-29 06:19:26 +00:00
|
|
|
NS_IMETHODIMP_(bool)
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::IsSingleLineTextControl() const
|
2010-04-21 20:17:41 +00:00
|
|
|
{
|
2011-10-17 14:59:28 +00:00
|
|
|
return IsSingleLineTextControl(false);
|
2010-04-21 20:17:41 +00:00
|
|
|
}
|
|
|
|
|
2011-09-29 06:19:26 +00:00
|
|
|
NS_IMETHODIMP_(bool)
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::IsTextArea() const
|
2010-04-21 20:17:41 +00:00
|
|
|
{
|
2011-10-17 14:59:28 +00:00
|
|
|
return false;
|
2010-04-21 20:17:41 +00:00
|
|
|
}
|
|
|
|
|
2011-09-29 06:19:26 +00:00
|
|
|
NS_IMETHODIMP_(bool)
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::IsPlainTextControl() const
|
2010-04-21 20:17:41 +00:00
|
|
|
{
|
|
|
|
// need to check our HTML attribute and/or CSS.
|
2011-10-17 14:59:28 +00:00
|
|
|
return true;
|
2010-04-21 20:17:41 +00:00
|
|
|
}
|
|
|
|
|
2011-09-29 06:19:26 +00:00
|
|
|
NS_IMETHODIMP_(bool)
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::IsPasswordTextControl() const
|
2010-04-21 20:17:41 +00:00
|
|
|
{
|
|
|
|
return mType == NS_FORM_INPUT_PASSWORD;
|
|
|
|
}
|
|
|
|
|
2012-08-22 15:56:38 +00:00
|
|
|
NS_IMETHODIMP_(int32_t)
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::GetCols()
|
2010-04-21 20:17:41 +00:00
|
|
|
{
|
|
|
|
// Else we know (assume) it is an input with size attr
|
|
|
|
const nsAttrValue* attr = GetParsedAttr(nsGkAtoms::size);
|
|
|
|
if (attr && attr->Type() == nsAttrValue::eInteger) {
|
2012-08-22 15:56:38 +00:00
|
|
|
int32_t cols = attr->GetIntegerValue();
|
2010-04-21 20:17:41 +00:00
|
|
|
if (cols > 0) {
|
|
|
|
return cols;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return DEFAULT_COLS;
|
|
|
|
}
|
|
|
|
|
2012-08-22 15:56:38 +00:00
|
|
|
NS_IMETHODIMP_(int32_t)
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::GetWrapCols()
|
2010-04-21 20:17:41 +00:00
|
|
|
{
|
|
|
|
return -1; // only textarea's can have wrap cols
|
|
|
|
}
|
|
|
|
|
2012-08-22 15:56:38 +00:00
|
|
|
NS_IMETHODIMP_(int32_t)
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::GetRows()
|
2010-04-21 20:17:41 +00:00
|
|
|
{
|
|
|
|
return DEFAULT_ROWS;
|
|
|
|
}
|
|
|
|
|
2013-03-25 19:35:55 +00:00
|
|
|
NS_IMETHODIMP_(void)
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::GetDefaultValueFromContent(nsAString& aValue)
|
2013-03-25 19:35:55 +00:00
|
|
|
{
|
|
|
|
nsTextEditorState *state = GetEditorState();
|
|
|
|
if (state) {
|
|
|
|
GetDefaultValue(aValue);
|
|
|
|
// This is called by the frame to show the value.
|
|
|
|
// We have to sanitize it when needed.
|
|
|
|
if (!mParserCreating) {
|
|
|
|
SanitizeValue(aValue);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-09-29 06:19:26 +00:00
|
|
|
NS_IMETHODIMP_(bool)
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::ValueChanged() const
|
2010-04-21 20:17:41 +00:00
|
|
|
{
|
2011-11-16 07:50:19 +00:00
|
|
|
return mValueChanged;
|
2010-04-21 20:17:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP_(void)
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::GetTextEditorValue(nsAString& aValue,
|
|
|
|
bool aIgnoreWrap) const
|
2010-04-21 20:17:41 +00:00
|
|
|
{
|
2013-03-28 19:41:32 +00:00
|
|
|
nsTextEditorState* state = GetEditorState();
|
2010-04-21 20:17:41 +00:00
|
|
|
if (state) {
|
|
|
|
state->GetValue(aValue, aIgnoreWrap);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP_(void)
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::InitializeKeyboardEventListeners()
|
2010-04-21 20:17:41 +00:00
|
|
|
{
|
2013-03-28 19:41:32 +00:00
|
|
|
nsTextEditorState* state = GetEditorState();
|
2010-04-21 20:17:41 +00:00
|
|
|
if (state) {
|
|
|
|
state->InitializeKeyboardEventListeners();
|
|
|
|
}
|
|
|
|
}
|
2010-08-21 17:52:57 +00:00
|
|
|
|
|
|
|
NS_IMETHODIMP_(void)
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::OnValueChanged(bool aNotify)
|
2010-08-21 17:52:57 +00:00
|
|
|
{
|
|
|
|
UpdateAllValidityStates(aNotify);
|
2012-11-21 10:13:57 +00:00
|
|
|
|
|
|
|
if (HasDirAuto()) {
|
|
|
|
SetDirectionIfAuto(true, aNotify);
|
|
|
|
}
|
2010-08-21 17:52:57 +00:00
|
|
|
}
|
|
|
|
|
2011-09-29 06:19:26 +00:00
|
|
|
NS_IMETHODIMP_(bool)
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::HasCachedSelection()
|
2011-07-29 21:31:57 +00:00
|
|
|
{
|
2011-09-29 06:19:26 +00:00
|
|
|
bool isCached = false;
|
2013-03-28 19:41:32 +00:00
|
|
|
nsTextEditorState* state = GetEditorState();
|
2011-07-29 21:31:57 +00:00
|
|
|
if (state) {
|
|
|
|
isCached = state->IsSelectionCached() &&
|
|
|
|
state->HasNeverInitializedBefore() &&
|
|
|
|
!state->GetSelectionProperties().IsDefault();
|
|
|
|
if (isCached) {
|
|
|
|
state->WillInitEagerly();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return isCached;
|
|
|
|
}
|
|
|
|
|
2010-09-18 21:33:16 +00:00
|
|
|
void
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::FieldSetDisabledChanged(bool aNotify)
|
2010-09-18 21:33:16 +00:00
|
|
|
{
|
|
|
|
UpdateValueMissingValidityState();
|
|
|
|
UpdateBarredFromConstraintValidation();
|
|
|
|
|
2011-06-01 01:46:57 +00:00
|
|
|
nsGenericHTMLFormElement::FieldSetDisabledChanged(aNotify);
|
2010-09-18 21:33:16 +00:00
|
|
|
}
|
|
|
|
|
2012-06-06 12:16:58 +00:00
|
|
|
void
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::SetFilePickerFiltersFromAccept(nsIFilePicker* filePicker)
|
2012-06-06 12:16:58 +00:00
|
|
|
{
|
|
|
|
// We always add |filterAll|
|
|
|
|
filePicker->AppendFilters(nsIFilePicker::filterAll);
|
|
|
|
|
|
|
|
NS_ASSERTION(HasAttr(kNameSpaceID_None, nsGkAtoms::accept),
|
|
|
|
"You should not call SetFilePickerFiltersFromAccept if the"
|
|
|
|
" element has no accept attribute!");
|
|
|
|
|
|
|
|
// Services to retrieve image/*, audio/*, video/* filters
|
|
|
|
nsCOMPtr<nsIStringBundleService> stringService =
|
|
|
|
mozilla::services::GetStringBundleService();
|
|
|
|
if (!stringService) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
nsCOMPtr<nsIStringBundle> filterBundle;
|
|
|
|
if (NS_FAILED(stringService->CreateBundle("chrome://global/content/filepicker.properties",
|
|
|
|
getter_AddRefs(filterBundle)))) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Service to retrieve mime type information for mime types filters
|
|
|
|
nsCOMPtr<nsIMIMEService> mimeService = do_GetService("@mozilla.org/mime;1");
|
|
|
|
if (!mimeService) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsAutoString accept;
|
|
|
|
GetAttr(kNameSpaceID_None, nsGkAtoms::accept, accept);
|
|
|
|
|
|
|
|
HTMLSplitOnSpacesTokenizer tokenizer(accept, ',');
|
|
|
|
|
|
|
|
nsTArray<nsFilePickerFilter> filters;
|
|
|
|
nsString allExtensionsList;
|
|
|
|
|
|
|
|
// Retrieve all filters
|
|
|
|
while (tokenizer.hasMoreTokens()) {
|
|
|
|
const nsDependentSubstring& token = tokenizer.nextToken();
|
|
|
|
|
|
|
|
if (token.IsEmpty()) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2012-08-22 15:56:38 +00:00
|
|
|
int32_t filterMask = 0;
|
2012-06-06 12:16:58 +00:00
|
|
|
nsString filterName;
|
|
|
|
nsString extensionListStr;
|
|
|
|
|
|
|
|
// First, check for image/audio/video filters...
|
|
|
|
if (token.EqualsLiteral("image/*")) {
|
|
|
|
filterMask = nsIFilePicker::filterImages;
|
|
|
|
filterBundle->GetStringFromName(NS_LITERAL_STRING("imageFilter").get(),
|
|
|
|
getter_Copies(extensionListStr));
|
|
|
|
} else if (token.EqualsLiteral("audio/*")) {
|
|
|
|
filterMask = nsIFilePicker::filterAudio;
|
|
|
|
filterBundle->GetStringFromName(NS_LITERAL_STRING("audioFilter").get(),
|
|
|
|
getter_Copies(extensionListStr));
|
|
|
|
} else if (token.EqualsLiteral("video/*")) {
|
|
|
|
filterMask = nsIFilePicker::filterVideo;
|
|
|
|
filterBundle->GetStringFromName(NS_LITERAL_STRING("videoFilter").get(),
|
|
|
|
getter_Copies(extensionListStr));
|
|
|
|
} else {
|
|
|
|
//... if no image/audio/video filter is found, check mime types filters
|
|
|
|
nsCOMPtr<nsIMIMEInfo> mimeInfo;
|
|
|
|
if (NS_FAILED(mimeService->GetFromTypeAndExtension(
|
|
|
|
NS_ConvertUTF16toUTF8(token),
|
|
|
|
EmptyCString(), // No extension
|
|
|
|
getter_AddRefs(mimeInfo))) ||
|
|
|
|
!mimeInfo) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get mime type name
|
|
|
|
nsCString mimeTypeName;
|
|
|
|
mimeInfo->GetType(mimeTypeName);
|
|
|
|
CopyUTF8toUTF16(mimeTypeName, filterName);
|
|
|
|
|
|
|
|
// Get extension list
|
|
|
|
nsCOMPtr<nsIUTF8StringEnumerator> extensions;
|
|
|
|
mimeInfo->GetFileExtensions(getter_AddRefs(extensions));
|
|
|
|
|
|
|
|
bool hasMore;
|
|
|
|
while (NS_SUCCEEDED(extensions->HasMore(&hasMore)) && hasMore) {
|
|
|
|
nsCString extension;
|
|
|
|
if (NS_FAILED(extensions->GetNext(extension))) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (!extensionListStr.IsEmpty()) {
|
|
|
|
extensionListStr.AppendLiteral("; ");
|
|
|
|
}
|
|
|
|
extensionListStr += NS_LITERAL_STRING("*.") +
|
|
|
|
NS_ConvertUTF8toUTF16(extension);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!filterMask && (extensionListStr.IsEmpty() || filterName.IsEmpty())) {
|
|
|
|
// No valid filter found
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If we arrived here, that means we have a valid filter: let's create it
|
|
|
|
// and add it to our list, if no similar filter is already present
|
|
|
|
nsFilePickerFilter filter;
|
|
|
|
if (filterMask) {
|
|
|
|
filter = nsFilePickerFilter(filterMask);
|
|
|
|
} else {
|
|
|
|
filter = nsFilePickerFilter(filterName, extensionListStr);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!filters.Contains(filter)) {
|
|
|
|
if (!allExtensionsList.IsEmpty()) {
|
|
|
|
allExtensionsList.AppendLiteral("; ");
|
|
|
|
}
|
|
|
|
allExtensionsList += extensionListStr;
|
|
|
|
filters.AppendElement(filter);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Add "All Supported Types" filter
|
|
|
|
if (filters.Length() > 1) {
|
|
|
|
nsXPIDLString title;
|
|
|
|
nsContentUtils::GetLocalizedString(nsContentUtils::eFORMS_PROPERTIES,
|
|
|
|
"AllSupportedTypes", title);
|
|
|
|
filePicker->AppendFilter(title, allExtensionsList);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Add each filter, and check if all filters are trusted
|
|
|
|
bool allFilterAreTrusted = true;
|
2012-08-22 15:56:38 +00:00
|
|
|
for (uint32_t i = 0; i < filters.Length(); ++i) {
|
2012-06-06 12:16:58 +00:00
|
|
|
const nsFilePickerFilter& filter = filters[i];
|
|
|
|
if (filter.mFilterMask) {
|
|
|
|
filePicker->AppendFilters(filter.mFilterMask);
|
|
|
|
} else {
|
|
|
|
filePicker->AppendFilter(filter.mTitle, filter.mFilter);
|
|
|
|
}
|
|
|
|
allFilterAreTrusted &= filter.mIsTrusted;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If all filters are trusted, select the first filter as default;
|
|
|
|
// otherwise filterAll will remain the default filter
|
|
|
|
if (filters.Length() >= 1 && allFilterAreTrusted) {
|
|
|
|
// |filterAll| will always use index=0 so we need to set index=1 as the
|
|
|
|
// current filter.
|
|
|
|
filePicker->SetFilterIndex(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-08-22 15:56:38 +00:00
|
|
|
int32_t
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::GetFilterFromAccept()
|
2010-10-08 10:07:20 +00:00
|
|
|
{
|
|
|
|
NS_ASSERTION(HasAttr(kNameSpaceID_None, nsGkAtoms::accept),
|
|
|
|
"You should not call GetFileFiltersFromAccept if the element"
|
|
|
|
" has no accept attribute!");
|
|
|
|
|
2012-08-22 15:56:38 +00:00
|
|
|
int32_t filter = 0;
|
2010-10-08 10:07:20 +00:00
|
|
|
nsAutoString accept;
|
|
|
|
GetAttr(kNameSpaceID_None, nsGkAtoms::accept, accept);
|
|
|
|
|
2012-01-04 10:08:00 +00:00
|
|
|
HTMLSplitOnSpacesTokenizer tokenizer(accept, ',');
|
2010-10-08 10:07:20 +00:00
|
|
|
|
|
|
|
while (tokenizer.hasMoreTokens()) {
|
|
|
|
const nsDependentSubstring token = tokenizer.nextToken();
|
|
|
|
|
2012-08-22 15:56:38 +00:00
|
|
|
int32_t tokenFilter = 0;
|
2010-10-08 10:07:20 +00:00
|
|
|
if (token.EqualsLiteral("image/*")) {
|
2010-10-08 10:13:08 +00:00
|
|
|
tokenFilter = nsIFilePicker::filterImages;
|
2010-10-08 10:07:20 +00:00
|
|
|
} else if (token.EqualsLiteral("audio/*")) {
|
2010-10-08 10:13:08 +00:00
|
|
|
tokenFilter = nsIFilePicker::filterAudio;
|
2010-10-08 10:07:20 +00:00
|
|
|
} else if (token.EqualsLiteral("video/*")) {
|
2010-10-08 10:13:08 +00:00
|
|
|
tokenFilter = nsIFilePicker::filterVideo;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (tokenFilter) {
|
|
|
|
// We do not want to set more than one filter so if we found two different
|
|
|
|
// kwown tokens, we will return 0 (no filter).
|
|
|
|
if (filter && filter != tokenFilter) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
filter = tokenFilter;
|
2010-10-08 10:07:20 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-10-08 10:13:08 +00:00
|
|
|
return filter;
|
2010-10-08 10:07:20 +00:00
|
|
|
}
|
|
|
|
|
2012-12-22 14:46:19 +00:00
|
|
|
double
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::GetStepScaleFactor() const
|
2012-12-22 14:46:19 +00:00
|
|
|
{
|
|
|
|
MOZ_ASSERT(DoesStepApply());
|
|
|
|
|
|
|
|
switch (mType) {
|
|
|
|
case NS_FORM_INPUT_DATE:
|
|
|
|
return kStepScaleFactorDate;
|
|
|
|
case NS_FORM_INPUT_NUMBER:
|
2013-02-16 12:35:57 +00:00
|
|
|
case NS_FORM_INPUT_RANGE:
|
|
|
|
return kStepScaleFactorNumberRange;
|
2013-02-06 22:56:49 +00:00
|
|
|
case NS_FORM_INPUT_TIME:
|
|
|
|
return kStepScaleFactorTime;
|
|
|
|
default:
|
|
|
|
MOZ_NOT_REACHED();
|
|
|
|
return MOZ_DOUBLE_NaN();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
double
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::GetDefaultStep() const
|
2013-02-06 22:56:49 +00:00
|
|
|
{
|
|
|
|
MOZ_ASSERT(DoesStepApply());
|
|
|
|
|
|
|
|
switch (mType) {
|
|
|
|
case NS_FORM_INPUT_DATE:
|
|
|
|
case NS_FORM_INPUT_NUMBER:
|
2013-02-16 12:35:57 +00:00
|
|
|
case NS_FORM_INPUT_RANGE:
|
2013-02-06 22:56:49 +00:00
|
|
|
return kDefaultStep;
|
|
|
|
case NS_FORM_INPUT_TIME:
|
|
|
|
return kDefaultStepTime;
|
2012-12-22 14:46:19 +00:00
|
|
|
default:
|
|
|
|
MOZ_NOT_REACHED();
|
|
|
|
return MOZ_DOUBLE_NaN();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-01-20 11:02:37 +00:00
|
|
|
void
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::UpdateValidityUIBits(bool aIsFocused)
|
2011-01-20 11:02:37 +00:00
|
|
|
{
|
|
|
|
if (aIsFocused) {
|
|
|
|
// If the invalid UI is shown, we should show it while focusing (and
|
|
|
|
// update). Otherwise, we should not.
|
2011-11-16 07:50:19 +00:00
|
|
|
mCanShowInvalidUI = !IsValid() && ShouldShowValidityUI();
|
2011-01-20 11:02:37 +00:00
|
|
|
|
|
|
|
// If neither invalid UI nor valid UI is shown, we shouldn't show the valid
|
|
|
|
// UI while typing.
|
2011-11-16 07:50:19 +00:00
|
|
|
mCanShowValidUI = ShouldShowValidityUI();
|
2011-01-20 11:02:37 +00:00
|
|
|
} else {
|
2011-11-16 07:50:19 +00:00
|
|
|
mCanShowInvalidUI = true;
|
|
|
|
mCanShowValidUI = true;
|
2011-01-20 11:02:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-06-22 09:41:32 +00:00
|
|
|
void
|
2013-03-28 19:41:32 +00:00
|
|
|
HTMLInputElement::UpdateHasRange()
|
2012-06-22 09:41:32 +00:00
|
|
|
{
|
2013-01-31 23:00:08 +00:00
|
|
|
/*
|
|
|
|
* There is a range if min/max applies for the type and if the element
|
|
|
|
* currently have a valid min or max.
|
|
|
|
*/
|
|
|
|
|
2012-06-22 09:41:32 +00:00
|
|
|
mHasRange = false;
|
|
|
|
|
2013-01-31 23:00:08 +00:00
|
|
|
if (!DoesMinMaxApply()) {
|
2012-06-22 09:41:32 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-01-25 23:51:57 +00:00
|
|
|
double minimum = GetMinimum();
|
|
|
|
if (!MOZ_DOUBLE_IS_NaN(minimum)) {
|
2012-07-06 12:40:18 +00:00
|
|
|
mHasRange = true;
|
|
|
|
return;
|
2012-06-22 09:41:32 +00:00
|
|
|
}
|
|
|
|
|
2013-01-25 23:51:57 +00:00
|
|
|
double maximum = GetMaximum();
|
|
|
|
if (!MOZ_DOUBLE_IS_NaN(maximum)) {
|
2012-07-06 12:40:18 +00:00
|
|
|
mHasRange = true;
|
|
|
|
return;
|
2012-06-22 09:41:32 +00:00
|
|
|
}
|
|
|
|
}
|
2013-03-28 19:41:32 +00:00
|
|
|
|
2013-03-28 19:41:32 +00:00
|
|
|
JSObject*
|
|
|
|
HTMLInputElement::WrapNode(JSContext* aCx, JSObject* aScope)
|
|
|
|
{
|
|
|
|
return HTMLInputElementBinding::Wrap(aCx, aScope, this);
|
|
|
|
}
|
|
|
|
|
2013-03-28 19:41:32 +00:00
|
|
|
} // namespace dom
|
|
|
|
} // namespace mozilla
|