diff options
Diffstat (limited to 'WebCore/html/HTMLInputElement.cpp')
-rw-r--r-- | WebCore/html/HTMLInputElement.cpp | 445 |
1 files changed, 166 insertions, 279 deletions
diff --git a/WebCore/html/HTMLInputElement.cpp b/WebCore/html/HTMLInputElement.cpp index c5c55fd..c451680 100644 --- a/WebCore/html/HTMLInputElement.cpp +++ b/WebCore/html/HTMLInputElement.cpp @@ -26,7 +26,7 @@ #include "config.h" #include "HTMLInputElement.h" -#include "BeforeTextInsertedEvent.h" +#include "ChromeClient.h" #include "CSSPropertyNames.h" #include "Document.h" #include "Editor.h" @@ -50,10 +50,8 @@ #include "RenderImage.h" #include "RenderSlider.h" #include "RenderText.h" -#include "RenderTextControl.h" +#include "RenderTextControlSingleLine.h" #include "RenderTheme.h" -#include "SelectionController.h" -#include "TextBreakIterator.h" #include "TextEvent.h" #if USE(LOW_BANDWIDTH_DISPLAY) #include "FrameLoader.h" @@ -61,7 +59,7 @@ #ifdef ANDROID_ACCEPT_CHANGES_TO_FOCUSED_TEXTFIELDS #include "WebViewCore.h" #endif -#include "TextIterator.h" +#include <wtf/StdLibExtras.h> using namespace std; @@ -71,76 +69,24 @@ using namespace HTMLNames; const int maxSavedResults = 256; -// FIXME: According to HTML4, the length attribute's value can be arbitrarily -// large. However, due to http://bugs.webkit.org/show_bugs.cgi?id=14536 things -// get rather sluggish when a text field has a larger number of characters than -// this, even when just clicking in the text field. -static const int cMaxLen = 524288; - -static int numGraphemeClusters(StringImpl* s) -{ - if (!s) - return 0; - - TextBreakIterator* it = characterBreakIterator(s->characters(), s->length()); - if (!it) - return 0; - int num = 0; - while (textBreakNext(it) != TextBreakDone) - ++num; - return num; -} - -static int numCharactersInGraphemeClusters(StringImpl* s, int numGraphemeClusters) -{ - if (!s) - return 0; - - TextBreakIterator* it = characterBreakIterator(s->characters(), s->length()); - if (!it) - return 0; - for (int i = 0; i < numGraphemeClusters; ++i) - if (textBreakNext(it) == TextBreakDone) - return s->length(); - return textBreakCurrent(it); -} - -HTMLInputElement::HTMLInputElement(Document* doc, HTMLFormElement* f) - : HTMLFormControlElementWithState(inputTag, doc, f) -{ - init(); -} - HTMLInputElement::HTMLInputElement(const QualifiedName& tagName, Document* doc, HTMLFormElement* f) : HTMLFormControlElementWithState(tagName, doc, f) -{ - init(); -} - -void HTMLInputElement::init() -{ - m_type = TEXT; - m_maxLen = cMaxLen; - m_size = 20; - m_checked = false; - m_defaultChecked = false; - m_useDefaultChecked = true; - m_indeterminate = false; - - m_haveType = false; - m_activeSubmit = false; - m_autocomplete = Uninitialized; - m_inited = false; - m_autofilled = false; - m_placeholderShouldBeVisible = false; - - xPos = 0; - yPos = 0; - - cachedSelStart = -1; - cachedSelEnd = -1; - - m_maxResults = -1; + , m_data(this, this) + , m_xPos(0) + , m_yPos(0) + , m_maxResults(-1) + , m_type(TEXT) + , m_checked(false) + , m_defaultChecked(false) + , m_useDefaultChecked(true) + , m_indeterminate(false) + , m_haveType(false) + , m_activeSubmit(false) + , m_autocomplete(Uninitialized) + , m_autofilled(false) + , m_inited(false) +{ + ASSERT(hasTagName(inputTag) || hasTagName(isindexTag)); } HTMLInputElement::~HTMLInputElement() @@ -157,7 +103,7 @@ HTMLInputElement::~HTMLInputElement() const AtomicString& HTMLInputElement::name() const { - return m_name.isNull() ? emptyAtom : m_name; + return m_data.name(); } bool HTMLInputElement::autoComplete() const @@ -193,9 +139,6 @@ bool HTMLInputElement::isKeyboardFocusable(KeyboardEvent* event) const return false; if (inputType() == RADIO) { - // Unnamed radio buttons are never focusable (matches WinIE). - if (name().isEmpty()) - return false; // Never allow keyboard tabbing to leave you in the same radio group. Always // skip any other elements in the group. @@ -223,23 +166,15 @@ bool HTMLInputElement::isMouseFocusable() const void HTMLInputElement::updateFocusAppearance(bool restorePreviousSelection) { - if (isTextField()) { - if (!restorePreviousSelection || cachedSelStart == -1) - select(); - else - // Restore the cached selection. - setSelectionRange(cachedSelStart, cachedSelEnd); - - if (document() && document()->frame()) - document()->frame()->revealSelection(); - } else + if (isTextField()) + InputElement::updateFocusAppearance(m_data, document(), restorePreviousSelection); + else HTMLFormControlElementWithState::updateFocusAppearance(restorePreviousSelection); } void HTMLInputElement::aboutToUnload() { - if (isTextField() && focused() && document()->frame()) - document()->frame()->textFieldDidEndEditing(this); + InputElement::aboutToUnload(m_data, document()); } bool HTMLInputElement::shouldUseInputMethod() const @@ -249,23 +184,17 @@ bool HTMLInputElement::shouldUseInputMethod() const void HTMLInputElement::dispatchFocusEvent() { - if (isTextField()) { - setAutofilled(false); - updatePlaceholderVisibility(); - if (inputType() == PASSWORD && document()->frame()) - document()->setUseSecureKeyboardEntryWhenActive(true); - } + InputElement::dispatchFocusEvent(m_data, document()); + + if (isTextField()) + m_autofilled = false; + HTMLFormControlElementWithState::dispatchFocusEvent(); } void HTMLInputElement::dispatchBlurEvent() { - if (isTextField() && document()->frame()) { - updatePlaceholderVisibility(); - if (inputType() == PASSWORD) - document()->setUseSecureKeyboardEntryWhenActive(false); - document()->frame()->textFieldDidEndEditing(this); - } + InputElement::dispatchBlurEvent(m_data, document()); HTMLFormControlElementWithState::dispatchBlurEvent(); } @@ -345,14 +274,14 @@ void HTMLInputElement::setInputType(const String& t) bool isPasswordField = inputType() == PASSWORD; bool willRespectHeightAndWidth = respectHeightAndWidthAttrs(); - if (didStoreValue && !willStoreValue && !m_value.isNull()) { - setAttribute(valueAttr, m_value); - m_value = String(); + if (didStoreValue && !willStoreValue && !m_data.value().isNull()) { + setAttribute(valueAttr, m_data.value()); + m_data.setValue(String()); } if (!didStoreValue && willStoreValue) - m_value = constrainValue(getAttribute(valueAttr)); + m_data.setValue(constrainValue(getAttribute(valueAttr))); else - recheckValue(); + InputElement::updateValueIfNeeded(m_data); if (wasPasswordField && !isPasswordField) unregisterForActivationCallbackIfNeeded(); @@ -377,6 +306,8 @@ void HTMLInputElement::setInputType(const String& t) checkedRadioButtons(this).addButton(this); } + + InputElement::notifyFormStateChanged(m_data, document()); } m_haveType = true; @@ -389,53 +320,53 @@ const AtomicString& HTMLInputElement::type() const // needs to be lowercase according to DOM spec switch (inputType()) { case BUTTON: { - static const AtomicString button("button"); + DEFINE_STATIC_LOCAL(const AtomicString, button, ("button")); return button; } case CHECKBOX: { - static const AtomicString checkbox("checkbox"); + DEFINE_STATIC_LOCAL(const AtomicString, checkbox, ("checkbox")); return checkbox; } case FILE: { - static const AtomicString file("file"); + DEFINE_STATIC_LOCAL(const AtomicString, file, ("file")); return file; } case HIDDEN: { - static const AtomicString hidden("hidden"); + DEFINE_STATIC_LOCAL(const AtomicString, hidden, ("hidden")); return hidden; } case IMAGE: { - static const AtomicString image("image"); + DEFINE_STATIC_LOCAL(const AtomicString, image, ("image")); return image; } case ISINDEX: return emptyAtom; case PASSWORD: { - static const AtomicString password("password"); + DEFINE_STATIC_LOCAL(const AtomicString, password, ("password")); return password; } case RADIO: { - static const AtomicString radio("radio"); + DEFINE_STATIC_LOCAL(const AtomicString, radio, ("radio")); return radio; } case RANGE: { - static const AtomicString range("range"); + DEFINE_STATIC_LOCAL(const AtomicString, range, ("range")); return range; } case RESET: { - static const AtomicString reset("reset"); + DEFINE_STATIC_LOCAL(const AtomicString, reset, ("reset")); return reset; } case SEARCH: { - static const AtomicString search("search"); + DEFINE_STATIC_LOCAL(const AtomicString, search, ("search")); return search; } case SUBMIT: { - static const AtomicString submit("submit"); + DEFINE_STATIC_LOCAL(const AtomicString, submit, ("submit")); return submit; } case TEXT: { - static const AtomicString text("text"); + DEFINE_STATIC_LOCAL(const AtomicString, text, ("text")); return text; } } @@ -512,8 +443,8 @@ int HTMLInputElement::selectionStart() const { if (!isTextField()) return 0; - if (document()->focusedNode() != this && cachedSelStart != -1) - return cachedSelStart; + if (document()->focusedNode() != this && m_data.cachedSelectionStart() != -1) + return m_data.cachedSelectionStart(); if (!renderer()) return 0; return static_cast<RenderTextControl*>(renderer())->selectionStart(); @@ -523,8 +454,8 @@ int HTMLInputElement::selectionEnd() const { if (!isTextField()) return 0; - if (document()->focusedNode() != this && cachedSelEnd != -1) - return cachedSelEnd; + if (document()->focusedNode() != this && m_data.cachedSelectionEnd() != -1) + return m_data.cachedSelectionEnd(); if (!renderer()) return 0; return static_cast<RenderTextControl*>(renderer())->selectionEnd(); @@ -559,11 +490,7 @@ void HTMLInputElement::select() void HTMLInputElement::setSelectionRange(int start, int end) { - if (!isTextField()) - return; - if (!renderer()) - return; - static_cast<RenderTextControl*>(renderer())->setSelectionRange(start, end); + InputElement::updateSelectionRange(m_data, start, end); } void HTMLInputElement::accessKeyAction(bool sendToAnyElement) @@ -618,7 +545,7 @@ void HTMLInputElement::parseMappedAttribute(MappedAttribute *attr) { if (attr->name() == nameAttr) { checkedRadioButtons(this).removeButton(this); - m_name = attr->value(); + m_data.setName(attr->value()); checkedRadioButtons(this).addButton(this); } else if (attr->name() == autocompleteAttr) { if (equalIgnoringCase(attr->value(), "off")) { @@ -636,7 +563,7 @@ void HTMLInputElement::parseMappedAttribute(MappedAttribute *attr) setInputType(attr->value()); } else if (attr->name() == valueAttr) { // We only need to setChanged if the form is looking at the default value right now. - if (m_value.isNull()) + if (m_data.value().isNull()) setChanged(); setValueMatchesRenderer(false); } else if (attr->name() == checkedAttr) { @@ -645,24 +572,18 @@ void HTMLInputElement::parseMappedAttribute(MappedAttribute *attr) setChecked(m_defaultChecked); m_useDefaultChecked = true; } - } else if (attr->name() == maxlengthAttr) { - int oldMaxLen = m_maxLen; - m_maxLen = !attr->isNull() ? attr->value().toInt() : cMaxLen; - if (m_maxLen <= 0 || m_maxLen > cMaxLen) - m_maxLen = cMaxLen; - if (oldMaxLen != m_maxLen) - recheckValue(); - setChanged(); - } else if (attr->name() == sizeAttr) { - m_size = !attr->isNull() ? attr->value().toInt() : 20; - } else if (attr->name() == altAttr) { + } else if (attr->name() == maxlengthAttr) + InputElement::parseMaxLengthAttribute(m_data, attr); + else if (attr->name() == sizeAttr) + InputElement::parseSizeAttribute(m_data, attr); + else if (attr->name() == altAttr) { if (renderer() && inputType() == IMAGE) static_cast<RenderImage*>(renderer())->updateAltText(); } else if (attr->name() == srcAttr) { if (renderer() && inputType() == IMAGE) { if (!m_imageLoader) m_imageLoader.set(new HTMLImageLoader(this)); - m_imageLoader->updateFromElement(); + m_imageLoader->updateFromElementIgnoringPreviousError(); } } else if (attr->name() == usemapAttr || attr->name() == accesskeyAttr) { @@ -707,14 +628,15 @@ void HTMLInputElement::parseMappedAttribute(MappedAttribute *attr) attach(); } setChanged(); - } else if (attr->name() == placeholderAttr) - updatePlaceholderVisibility(true); - else if (attr->name() == autosaveAttr || - attr->name() == incrementalAttr || - attr->name() == minAttr || - attr->name() == maxAttr || - attr->name() == multipleAttr || - attr->name() == precisionAttr) + } else if (attr->name() == placeholderAttr) { + if (isTextField()) + InputElement::updatePlaceholderVisibility(m_data, document(), true); + } else if (attr->name() == autosaveAttr || + attr->name() == incrementalAttr || + attr->name() == minAttr || + attr->name() == maxAttr || + attr->name() == multipleAttr || + attr->name() == precisionAttr) setChanged(); else HTMLFormControlElementWithState::parseMappedAttribute(attr); @@ -772,7 +694,7 @@ RenderObject *HTMLInputElement::createRenderer(RenderArena *arena, RenderStyle * case PASSWORD: case SEARCH: case TEXT: - return new (arena) RenderTextControl(this, false); + return new (arena) RenderTextControlSingleLine(this); } ASSERT(false); return 0; @@ -875,8 +797,8 @@ bool HTMLInputElement::appendFormData(FormDataList& encoding, bool multipart) case IMAGE: if (m_activeSubmit) { - encoding.appendData(name().isEmpty() ? "x" : (name() + ".x"), xPos); - encoding.appendData(name().isEmpty() ? "y" : (name() + ".y"), yPos); + encoding.appendData(name().isEmpty() ? "x" : (name() + ".x"), m_xPos); + encoding.appendData(name().isEmpty() ? "y" : (name() + ".y"), m_yPos); if (!name().isEmpty() && !value().isEmpty()) encoding.appendData(name(), value()); return true; @@ -960,14 +882,19 @@ void HTMLInputElement::setIndeterminate(bool _indeterminate) theme()->stateChanged(renderer(), CheckedState); } -void HTMLInputElement::copyNonAttributeProperties(const Element *source) +int HTMLInputElement::size() const { - const HTMLInputElement *sourceElem = static_cast<const HTMLInputElement *>(source); + return m_data.size(); +} + +void HTMLInputElement::copyNonAttributeProperties(const Element* source) +{ + const HTMLInputElement* sourceElement = static_cast<const HTMLInputElement*>(source); + + m_data.setValue(sourceElement->m_data.value()); + m_checked = sourceElement->m_checked; + m_indeterminate = sourceElement->m_indeterminate; - m_value = sourceElem->m_value; - m_checked = sourceElem->m_checked; - m_indeterminate = sourceElem->m_indeterminate; - HTMLFormControlElementWithState::copyNonAttributeProperties(source); } @@ -981,7 +908,7 @@ String HTMLInputElement::value() const return String(); } - String value = m_value; + String value = m_data.value(); if (value.isNull()) { value = constrainValue(getAttribute(valueAttr)); @@ -1030,14 +957,14 @@ void HTMLInputElement::setValue(const String& value) return; if (isTextField()) - updatePlaceholderVisibility(); - + InputElement::updatePlaceholderVisibility(m_data, document()); + setValueMatchesRenderer(false); if (storesValueSeparateFromAttribute()) { if (inputType() == FILE) m_fileList->clear(); else { - m_value = constrainValue(value); + m_data.setValue(constrainValue(value)); if (isTextField() && inDocument()) document()->updateRendering(); } @@ -1048,47 +975,38 @@ void HTMLInputElement::setValue(const String& value) setAttribute(valueAttr, constrainValue(value)); if (isTextField()) { - unsigned max = m_value.length(); + unsigned max = m_data.value().length(); if (document()->focusedNode() == this) -#ifndef ANDROID_ACCEPT_CHANGES_TO_FOCUSED_TEXTFIELDS - setSelectionRange(max, max); -#else +#ifdef ANDROID_ACCEPT_CHANGES_TO_FOCUSED_TEXTFIELDS { // Make sure our UI side textfield changes to match the RenderTextControl android::WebViewCore::getWebViewCore(document()->view())->updateTextfield(this, false, value); - setSelectionRange(max, max); - } #endif - else { - cachedSelStart = max; - cachedSelEnd = max; + InputElement::updateSelectionRange(m_data, max, max); +#ifdef ANDROID_ACCEPT_CHANGES_TO_FOCUSED_TEXTFIELDS } +#endif + else + cacheSelection(max, max); } + InputElement::notifyFormStateChanged(m_data, document()); } -void HTMLInputElement::setValueFromRenderer(const String& value) +String HTMLInputElement::placeholderValue() const { - // Renderer and our event handler are responsible for constraining values. - ASSERT(value == constrainValue(value) || constrainValue(value).isEmpty()); - - // File upload controls will always use setFileListFromRenderer. - ASSERT (inputType() != FILE); - - if (isTextField()) - updatePlaceholderVisibility(); - - // Workaround for bug where trailing \n is included in the result of textContent. - // The assert macro above may also be simplified to: value == constrainValue(value) - // http://bugs.webkit.org/show_bug.cgi?id=9661 - if (value == "\n") - m_value = ""; - else - m_value = value; + return getAttribute(placeholderAttr).string(); +} - setValueMatchesRenderer(); +bool HTMLInputElement::searchEventsShouldBeDispatched() const +{ + return hasAttribute(incrementalAttr); +} - // Fire the "input" DOM event. - dispatchEventForType(eventNames().inputEvent, true, false); +void HTMLInputElement::setValueFromRenderer(const String& value) +{ + // File upload controls will always use setFileListFromRenderer. + ASSERT(inputType() != FILE); + InputElement::setValueFromRenderer(m_data, document(), value); } void HTMLInputElement::setFileListFromRenderer(const Vector<String>& paths) @@ -1099,6 +1017,7 @@ void HTMLInputElement::setFileListFromRenderer(const Vector<String>& paths) m_fileList->append(File::create(paths[i])); setValueMatchesRenderer(); + InputElement::notifyFormStateChanged(m_data, document()); } bool HTMLInputElement::storesValueSeparateFromAttribute() const @@ -1143,11 +1062,6 @@ void* HTMLInputElement::preDispatchEventHandler(Event *evt) } } else { // For radio buttons, store the current selected radio object. - if (name().isEmpty() || checked()) - return 0; // Match WinIE and don't allow unnamed radio buttons to be checked. - // Checked buttons just stay checked. - // FIXME: Need to learn to work without a form. - // We really want radio groups to end up in sane states, i.e., to have something checked. // Therefore if nothing is currently selected, we won't allow this action to be "undone", since // we want some object in the radio group to actually get selected. @@ -1183,8 +1097,7 @@ void HTMLInputElement::postDispatchEventHandler(Event *evt, void* data) // Make sure it is still a radio button and only do the restoration if it still // belongs to our group. - // Match WinIE and don't allow unnamed radio buttons to be checked. - if (input->form() == form() && input->inputType() == RADIO && !name().isEmpty() && input->name() == name()) { + if (input->form() == form() && input->inputType() == RADIO && input->name() == name()) { // Ok, the old radio button is still in our form and in our group and is still a // radio button, so it's safe to restore selection to it. input->setChecked(true); @@ -1211,25 +1124,24 @@ void HTMLInputElement::defaultEventHandler(Event* evt) // FIXME: We could just call offsetX() and offsetY() on the event, // but that's currently broken, so for now do the computation here. if (me->isSimulated() || !renderer()) { - xPos = 0; - yPos = 0; + m_xPos = 0; + m_yPos = 0; } else { - int offsetX, offsetY; - renderer()->absolutePosition(offsetX, offsetY); - xPos = me->pageX() - offsetX; - // FIXME: Why is yPos a short? - yPos = me->pageY() - offsetY; + // FIXME: This doesn't work correctly with transforms. + IntPoint absOffset = roundedIntPoint(renderer()->localToAbsolute()); + m_xPos = me->pageX() - absOffset.x(); + m_yPos = me->pageY() - absOffset.y(); } } if (isTextField() && evt->type() == eventNames().keydownEvent && evt->isKeyboardEvent() && focused() && document()->frame() - && document()->frame()->doTextFieldCommandFromEvent(this, static_cast<KeyboardEvent*>(evt))) { + && document()->frame()->doTextFieldCommandFromEvent(this, static_cast<KeyboardEvent*>(evt))) { evt->setDefaultHandled(); return; } if (inputType() == RADIO && evt->isMouseEvent() - && evt->type() == eventNames().clickEvent && static_cast<MouseEvent*>(evt)->button() == LeftButton) { + && evt->type() == eventNames().clickEvent && static_cast<MouseEvent*>(evt)->button() == LeftButton) { evt->setDefaultHandled(); return; } @@ -1253,13 +1165,13 @@ void HTMLInputElement::defaultEventHandler(Event* evt) form()->reset(); else { m_activeSubmit = true; - // FIXME: Would be cleaner to get xPos and yPos out of the underlying mouse + // FIXME: Would be cleaner to get m_xPos and m_yPos out of the underlying mouse // event (if any) here instead of relying on the variables set above when // processing the click event. Even better, appendFormData could pass the - // event in, and then we could get rid of xPos and yPos altogether! + // event in, and then we could get rid of m_xPos and m_yPos altogether! if (!form()->prepareSubmit(evt)) { - xPos = 0; - yPos = 0; + m_xPos = 0; + m_yPos = 0; } m_activeSubmit = false; } @@ -1363,9 +1275,8 @@ void HTMLInputElement::defaultEventHandler(Event* evt) if (elt->form() != form()) break; if (n->hasTagName(inputTag)) { - // Match WinIE and don't allow unnamed radio buttons to be checked. HTMLInputElement* inputElt = static_cast<HTMLInputElement*>(n); - if (inputElt->inputType() == RADIO && !name().isEmpty() && inputElt->name() == name() && inputElt->isFocusable()) { + if (inputElt->inputType() == RADIO && inputElt->name() == name() && inputElt->isFocusable()) { inputElt->setChecked(true); document()->setFocusedNode(inputElt); inputElt->dispatchSimulatedClick(evt, false, false); @@ -1440,21 +1351,11 @@ void HTMLInputElement::defaultEventHandler(Event* evt) return; } - if (evt->isBeforeTextInsertedEvent()) { - // Make sure that the text to be inserted will not violate the maxLength. - int oldLen = numGraphemeClusters(value().impl()); - ASSERT(oldLen <= maxLength()); - int selectionLen = numGraphemeClusters(plainText(document()->frame()->selection()->selection().toRange().get()).impl()); - ASSERT(oldLen >= selectionLen); - int maxNewLen = maxLength() - (oldLen - selectionLen); - - // Truncate the inserted text to avoid violating the maxLength and other constraints. - BeforeTextInsertedEvent* textEvent = static_cast<BeforeTextInsertedEvent*>(evt); - textEvent->setText(constrainValue(textEvent->text(), maxNewLen)); - } + if (evt->isBeforeTextInsertedEvent()) + InputElement::handleBeforeTextInsertedEvent(m_data, document(), evt); if (isTextField() && renderer() && (evt->isMouseEvent() || evt->isDragEvent() || evt->isWheelEvent() || evt->type() == eventNames().blurEvent || evt->type() == eventNames().focusEvent)) - static_cast<RenderTextControl*>(renderer())->forwardEvent(evt); + static_cast<RenderTextControlSingleLine*>(renderer())->forwardEvent(evt); if (inputType() == RANGE && renderer()) { RenderSlider* slider = static_cast<RenderSlider*>(renderer()); @@ -1462,11 +1363,8 @@ void HTMLInputElement::defaultEventHandler(Event* evt) MouseEvent* mEvt = static_cast<MouseEvent*>(evt); if (!slider->mouseEventIsInThumb(mEvt)) { IntPoint eventOffset(mEvt->offsetX(), mEvt->offsetY()); - if (mEvt->target() != this) { - IntRect rect = renderer()->absoluteBoundingBoxRect(); - eventOffset.setX(mEvt->pageX() - rect.x()); - eventOffset.setY(mEvt->pageY() - rect.y()); - } + if (mEvt->target() != this) // Does this ever happen now? Was added for <video> controls + eventOffset = roundedIntPoint(renderer()->absoluteToLocal(FloatPoint(mEvt->pageX(), mEvt->pageY()), false, true)); slider->setValueForPosition(slider->positionForOffset(eventOffset)); } } @@ -1500,6 +1398,11 @@ void HTMLInputElement::setDefaultChecked(bool defaultChecked) setAttribute(checkedAttr, defaultChecked ? "" : 0); } +void HTMLInputElement::setDefaultName(const AtomicString& name) +{ + m_data.setName(name); +} + String HTMLInputElement::accept() const { return getAttribute(acceptAttr); @@ -1540,6 +1443,11 @@ void HTMLInputElement::setAlt(const String &value) setAttribute(altAttr, value); } +int HTMLInputElement::maxLength() const +{ + return m_data.maxLength(); +} + void HTMLInputElement::setMaxLength(int _maxLength) { setAttribute(maxlengthAttr, String::number(_maxLength)); @@ -1570,6 +1478,15 @@ void HTMLInputElement::setUseMap(const String &value) setAttribute(usemapAttr, value); } +void HTMLInputElement::setAutofilled(bool b) +{ + if (b == m_autofilled) + return; + + m_autofilled = b; + setChanged(); +} + FileList* HTMLInputElement::files() { if (inputType() != FILE) @@ -1579,15 +1496,7 @@ FileList* HTMLInputElement::files() String HTMLInputElement::constrainValue(const String& proposedValue) const { - return constrainValue(proposedValue, m_maxLen); -} - -void HTMLInputElement::recheckValue() -{ - String oldValue = value(); - String newValue = constrainValue(oldValue); - if (newValue != oldValue) - setValue(newValue); + return InputElement::constrainValue(m_data, proposedValue, m_data.maxLength()); } bool HTMLInputElement::needsActivationCallback() @@ -1607,62 +1516,32 @@ void HTMLInputElement::unregisterForActivationCallbackIfNeeded() document()->unregisterForDocumentActivationCallbacks(this); } -void HTMLInputElement::updatePlaceholderVisibility(bool placeholderValueChanged) -{ - ASSERT(isTextField()); - - bool oldPlaceholderShouldBeVisible = m_placeholderShouldBeVisible; - - m_placeholderShouldBeVisible = value().isEmpty() - && document()->focusedNode() != this - && !getAttribute(placeholderAttr).isEmpty(); - - if ((oldPlaceholderShouldBeVisible != m_placeholderShouldBeVisible || placeholderValueChanged) && renderer()) - static_cast<RenderTextControl*>(renderer())->updatePlaceholderVisibility(); -} - -String HTMLInputElement::constrainValue(const String& proposedValue, int maxLen) const +void HTMLInputElement::cacheSelection(int start, int end) { - String string = proposedValue; - if (isTextField()) { - string.replace("\r\n", " "); - string.replace('\r', ' '); - string.replace('\n', ' '); - StringImpl* s = string.impl(); - int newLen = numCharactersInGraphemeClusters(s, maxLen); - for (int i = 0; i < newLen; ++i) { - const UChar current = (*s)[i]; - if (current < ' ' && current != '\t') { - newLen = i; - break; - } - } - if (newLen < static_cast<int>(string.length())) - return string.substring(0, newLen); - } - return string; + m_data.setCachedSelectionStart(start); + m_data.setCachedSelectionEnd(end); } void HTMLInputElement::addSearchResult() { ASSERT(isSearchField()); if (renderer()) - static_cast<RenderTextControl*>(renderer())->addSearchResult(); + static_cast<RenderTextControlSingleLine*>(renderer())->addSearchResult(); } void HTMLInputElement::onSearch() { ASSERT(isSearchField()); if (renderer()) - static_cast<RenderTextControl*>(renderer())->stopSearchEventTimer(); + static_cast<RenderTextControlSingleLine*>(renderer())->stopSearchEventTimer(); dispatchEventForType(eventNames().searchEvent, true, false); } Selection HTMLInputElement::selection() const { - if (!renderer() || !isTextField() || cachedSelStart == -1 || cachedSelEnd == -1) + if (!renderer() || !isTextField() || m_data.cachedSelectionStart() == -1 || m_data.cachedSelectionEnd() == -1) return Selection(); - return static_cast<RenderTextControl*>(renderer())->selection(cachedSelStart, cachedSelEnd); + return static_cast<RenderTextControl*>(renderer())->selection(m_data.cachedSelectionStart(), m_data.cachedSelectionEnd()); } void HTMLInputElement::documentDidBecomeActive() @@ -1689,9 +1568,11 @@ void HTMLInputElement::didMoveToNewOwnerDocument() HTMLFormControlElementWithState::didMoveToNewOwnerDocument(); } -void HTMLInputElement::getSubresourceAttributeStrings(Vector<String>& urls) const +void HTMLInputElement::addSubresourceAttributeURLs(ListHashSet<KURL>& urls) const { - urls.append(src().string()); + HTMLFormControlElementWithState::addSubresourceAttributeURLs(urls); + + addSubresourceURL(urls, src()); } bool HTMLInputElement::willValidate() const @@ -1700,4 +1581,10 @@ bool HTMLInputElement::willValidate() const return HTMLFormControlElementWithState::willValidate() && inputType() != HIDDEN && inputType() != BUTTON && inputType() != RESET; } + +bool HTMLInputElement::placeholderShouldBeVisible() const +{ + return m_data.placeholderShouldBeVisible(); +} + } // namespace |