| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) | 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) |
| 3 * (C) 1999 Antti Koivisto (koivisto@kde.org) | 3 * (C) 1999 Antti Koivisto (koivisto@kde.org) |
| 4 * (C) 2001 Dirk Mueller (mueller@kde.org) | 4 * (C) 2001 Dirk Mueller (mueller@kde.org) |
| 5 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2010 Apple Inc. All rights reserv
ed. | 5 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2010 Apple Inc. All rights reserv
ed. |
| 6 * (C) 2006 Alexey Proskuryakov (ap@nypop.com) | 6 * (C) 2006 Alexey Proskuryakov (ap@nypop.com) |
| 7 * Copyright (C) 2007 Samuel Weinig (sam@webkit.org) | 7 * Copyright (C) 2007 Samuel Weinig (sam@webkit.org) |
| 8 * | 8 * |
| 9 * This library is free software; you can redistribute it and/or | 9 * This library is free software; you can redistribute it and/or |
| 10 * modify it under the terms of the GNU Library General Public | 10 * modify it under the terms of the GNU Library General Public |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 90 | 90 |
| 91 PassRefPtrWillBeRawPtr<HTMLTextAreaElement> HTMLTextAreaElement::create(Document
& document, HTMLFormElement* form) | 91 PassRefPtrWillBeRawPtr<HTMLTextAreaElement> HTMLTextAreaElement::create(Document
& document, HTMLFormElement* form) |
| 92 { | 92 { |
| 93 RefPtrWillBeRawPtr<HTMLTextAreaElement> textArea = adoptRefWillBeNoop(new HT
MLTextAreaElement(document, form)); | 93 RefPtrWillBeRawPtr<HTMLTextAreaElement> textArea = adoptRefWillBeNoop(new HT
MLTextAreaElement(document, form)); |
| 94 textArea->ensureUserAgentShadowRoot(); | 94 textArea->ensureUserAgentShadowRoot(); |
| 95 return textArea.release(); | 95 return textArea.release(); |
| 96 } | 96 } |
| 97 | 97 |
| 98 void HTMLTextAreaElement::didAddUserAgentShadowRoot(ShadowRoot& root) | 98 void HTMLTextAreaElement::didAddUserAgentShadowRoot(ShadowRoot& root) |
| 99 { | 99 { |
| 100 root.appendChild(TextControlInnerTextElement::create(document())); | 100 root.appendChild(TextControlInnerEditorElement::create(document())); |
| 101 } | 101 } |
| 102 | 102 |
| 103 const AtomicString& HTMLTextAreaElement::formControlType() const | 103 const AtomicString& HTMLTextAreaElement::formControlType() const |
| 104 { | 104 { |
| 105 DEFINE_STATIC_LOCAL(const AtomicString, textarea, ("textarea", AtomicString:
:ConstructFromLiteral)); | 105 DEFINE_STATIC_LOCAL(const AtomicString, textarea, ("textarea", AtomicString:
:ConstructFromLiteral)); |
| 106 return textarea; | 106 return textarea; |
| 107 } | 107 } |
| 108 | 108 |
| 109 FormControlState HTMLTextAreaElement::saveFormControlState() const | 109 FormControlState HTMLTextAreaElement::saveFormControlState() const |
| 110 { | 110 { |
| 111 return m_isDirty ? FormControlState(value()) : FormControlState(); | 111 return m_isDirty ? FormControlState(value()) : FormControlState(); |
| 112 } | 112 } |
| 113 | 113 |
| 114 void HTMLTextAreaElement::restoreFormControlState(const FormControlState& state) | 114 void HTMLTextAreaElement::restoreFormControlState(const FormControlState& state) |
| 115 { | 115 { |
| 116 setValue(state[0]); | 116 setValue(state[0]); |
| 117 } | 117 } |
| 118 | 118 |
| 119 void HTMLTextAreaElement::childrenChanged(bool changedByParser, Node* beforeChan
ge, Node* afterChange, int childCountDelta) | 119 void HTMLTextAreaElement::childrenChanged(bool changedByParser, Node* beforeChan
ge, Node* afterChange, int childCountDelta) |
| 120 { | 120 { |
| 121 HTMLElement::childrenChanged(changedByParser, beforeChange, afterChange, chi
ldCountDelta); | 121 HTMLElement::childrenChanged(changedByParser, beforeChange, afterChange, chi
ldCountDelta); |
| 122 setLastChangeWasNotUserEdit(); | 122 setLastChangeWasNotUserEdit(); |
| 123 if (m_isDirty) | 123 if (m_isDirty) |
| 124 setInnerTextValue(value()); | 124 setInnerEditorValue(value()); |
| 125 else | 125 else |
| 126 setNonDirtyValue(defaultValue()); | 126 setNonDirtyValue(defaultValue()); |
| 127 } | 127 } |
| 128 | 128 |
| 129 bool HTMLTextAreaElement::isPresentationAttribute(const QualifiedName& name) con
st | 129 bool HTMLTextAreaElement::isPresentationAttribute(const QualifiedName& name) con
st |
| 130 { | 130 { |
| 131 if (name == alignAttr) { | 131 if (name == alignAttr) { |
| 132 // Don't map 'align' attribute. This matches what Firefox, Opera and IE
do. | 132 // Don't map 'align' attribute. This matches what Firefox, Opera and IE
do. |
| 133 // See http://bugs.webkit.org/show_bug.cgi?id=7075 | 133 // See http://bugs.webkit.org/show_bug.cgi?id=7075 |
| 134 return false; | 134 return false; |
| (...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 283 | 283 |
| 284 void HTMLTextAreaElement::handleBeforeTextInsertedEvent(BeforeTextInsertedEvent*
event) const | 284 void HTMLTextAreaElement::handleBeforeTextInsertedEvent(BeforeTextInsertedEvent*
event) const |
| 285 { | 285 { |
| 286 ASSERT(event); | 286 ASSERT(event); |
| 287 ASSERT(renderer()); | 287 ASSERT(renderer()); |
| 288 int signedMaxLength = maxLength(); | 288 int signedMaxLength = maxLength(); |
| 289 if (signedMaxLength < 0) | 289 if (signedMaxLength < 0) |
| 290 return; | 290 return; |
| 291 unsigned unsignedMaxLength = static_cast<unsigned>(signedMaxLength); | 291 unsigned unsignedMaxLength = static_cast<unsigned>(signedMaxLength); |
| 292 | 292 |
| 293 const String& currentValue = innerTextValue(); | 293 const String& currentValue = innerEditorValue(); |
| 294 unsigned currentLength = computeLengthForSubmission(currentValue); | 294 unsigned currentLength = computeLengthForSubmission(currentValue); |
| 295 if (currentLength + computeLengthForSubmission(event->text()) < unsignedMaxL
ength) | 295 if (currentLength + computeLengthForSubmission(event->text()) < unsignedMaxL
ength) |
| 296 return; | 296 return; |
| 297 | 297 |
| 298 // selectionLength represents the selection length of this text field to be | 298 // selectionLength represents the selection length of this text field to be |
| 299 // removed by this insertion. | 299 // removed by this insertion. |
| 300 // If the text field has no focus, we don't need to take account of the | 300 // If the text field has no focus, we don't need to take account of the |
| 301 // selection length. The selection is the source of text drag-and-drop in | 301 // selection length. The selection is the source of text drag-and-drop in |
| 302 // that case, and nothing in the text field will be removed. | 302 // that case, and nothing in the text field will be removed. |
| 303 unsigned selectionLength = focused() ? computeLengthForSubmission(plainText(
document().frame()->selection().selection().toNormalizedRange().get())) : 0; | 303 unsigned selectionLength = focused() ? computeLengthForSubmission(plainText(
document().frame()->selection().selection().toNormalizedRange().get())) : 0; |
| 304 ASSERT(currentLength >= selectionLength); | 304 ASSERT(currentLength >= selectionLength); |
| 305 unsigned baseLength = currentLength - selectionLength; | 305 unsigned baseLength = currentLength - selectionLength; |
| 306 unsigned appendableLength = unsignedMaxLength > baseLength ? unsignedMaxLeng
th - baseLength : 0; | 306 unsigned appendableLength = unsignedMaxLength > baseLength ? unsignedMaxLeng
th - baseLength : 0; |
| 307 event->setText(sanitizeUserInputValue(event->text(), appendableLength)); | 307 event->setText(sanitizeUserInputValue(event->text(), appendableLength)); |
| 308 } | 308 } |
| 309 | 309 |
| 310 String HTMLTextAreaElement::sanitizeUserInputValue(const String& proposedValue,
unsigned maxLength) | 310 String HTMLTextAreaElement::sanitizeUserInputValue(const String& proposedValue,
unsigned maxLength) |
| 311 { | 311 { |
| 312 if (maxLength > 0 && U16_IS_LEAD(proposedValue[maxLength - 1])) | 312 if (maxLength > 0 && U16_IS_LEAD(proposedValue[maxLength - 1])) |
| 313 --maxLength; | 313 --maxLength; |
| 314 return proposedValue.left(maxLength); | 314 return proposedValue.left(maxLength); |
| 315 } | 315 } |
| 316 | 316 |
| 317 void HTMLTextAreaElement::updateValue() const | 317 void HTMLTextAreaElement::updateValue() const |
| 318 { | 318 { |
| 319 if (m_valueIsUpToDate) | 319 if (m_valueIsUpToDate) |
| 320 return; | 320 return; |
| 321 | 321 |
| 322 ASSERT(renderer()); | 322 ASSERT(renderer()); |
| 323 m_value = innerTextValue(); | 323 m_value = innerEditorValue(); |
| 324 const_cast<HTMLTextAreaElement*>(this)->m_valueIsUpToDate = true; | 324 const_cast<HTMLTextAreaElement*>(this)->m_valueIsUpToDate = true; |
| 325 const_cast<HTMLTextAreaElement*>(this)->notifyFormStateChanged(); | 325 const_cast<HTMLTextAreaElement*>(this)->notifyFormStateChanged(); |
| 326 m_isDirty = true; | 326 m_isDirty = true; |
| 327 const_cast<HTMLTextAreaElement*>(this)->updatePlaceholderVisibility(false); | 327 const_cast<HTMLTextAreaElement*>(this)->updatePlaceholderVisibility(false); |
| 328 } | 328 } |
| 329 | 329 |
| 330 String HTMLTextAreaElement::value() const | 330 String HTMLTextAreaElement::value() const |
| 331 { | 331 { |
| 332 updateValue(); | 332 updateValue(); |
| 333 return m_value; | 333 return m_value; |
| (...skipping 23 matching lines...) Expand all Loading... |
| 357 String normalizedValue = newValue.isNull() ? "" : newValue; | 357 String normalizedValue = newValue.isNull() ? "" : newValue; |
| 358 normalizedValue.replace("\r\n", "\n"); | 358 normalizedValue.replace("\r\n", "\n"); |
| 359 normalizedValue.replace('\r', '\n'); | 359 normalizedValue.replace('\r', '\n'); |
| 360 | 360 |
| 361 // Return early because we don't want to move the caret or trigger other sid
e effects | 361 // Return early because we don't want to move the caret or trigger other sid
e effects |
| 362 // when the value isn't changing. This matches Firefox behavior, at least. | 362 // when the value isn't changing. This matches Firefox behavior, at least. |
| 363 if (normalizedValue == value()) | 363 if (normalizedValue == value()) |
| 364 return; | 364 return; |
| 365 | 365 |
| 366 m_value = normalizedValue; | 366 m_value = normalizedValue; |
| 367 setInnerTextValue(m_value); | 367 setInnerEditorValue(m_value); |
| 368 if (eventBehavior == DispatchNoEvent) | 368 if (eventBehavior == DispatchNoEvent) |
| 369 setLastChangeWasNotUserEdit(); | 369 setLastChangeWasNotUserEdit(); |
| 370 updatePlaceholderVisibility(false); | 370 updatePlaceholderVisibility(false); |
| 371 setNeedsStyleRecalc(SubtreeStyleChange); | 371 setNeedsStyleRecalc(SubtreeStyleChange); |
| 372 m_suggestedValue = String(); | 372 m_suggestedValue = String(); |
| 373 | 373 |
| 374 // Set the caret to the end of the text value. | 374 // Set the caret to the end of the text value. |
| 375 if (document().focusedElement() == this) { | 375 if (document().focusedElement() == this) { |
| 376 unsigned endOfString = m_value.length(); | 376 unsigned endOfString = m_value.length(); |
| 377 setSelectionRange(endOfString, endOfString); | 377 setSelectionRange(endOfString, endOfString); |
| 378 } | 378 } |
| 379 | 379 |
| 380 notifyFormStateChanged(); | 380 notifyFormStateChanged(); |
| 381 if (eventBehavior == DispatchNoEvent) { | 381 if (eventBehavior == DispatchNoEvent) { |
| 382 setTextAsOfLastFormControlChangeEvent(normalizedValue); | 382 setTextAsOfLastFormControlChangeEvent(normalizedValue); |
| 383 } else { | 383 } else { |
| 384 if (eventBehavior == DispatchInputAndChangeEvent) | 384 if (eventBehavior == DispatchInputAndChangeEvent) |
| 385 dispatchFormControlInputEvent(); | 385 dispatchFormControlInputEvent(); |
| 386 dispatchFormControlChangeEvent(); | 386 dispatchFormControlChangeEvent(); |
| 387 } | 387 } |
| 388 } | 388 } |
| 389 | 389 |
| 390 void HTMLTextAreaElement::setInnerTextValue(const String& value) | 390 void HTMLTextAreaElement::setInnerEditorValue(const String& value) |
| 391 { | 391 { |
| 392 HTMLTextFormControlElement::setInnerTextValue(value); | 392 HTMLTextFormControlElement::setInnerEditorValue(value); |
| 393 m_valueIsUpToDate = true; | 393 m_valueIsUpToDate = true; |
| 394 } | 394 } |
| 395 | 395 |
| 396 String HTMLTextAreaElement::defaultValue() const | 396 String HTMLTextAreaElement::defaultValue() const |
| 397 { | 397 { |
| 398 StringBuilder value; | 398 StringBuilder value; |
| 399 | 399 |
| 400 // Since there may be comments, ignore nodes other than text nodes. | 400 // Since there may be comments, ignore nodes other than text nodes. |
| 401 for (Node* n = firstChild(); n; n = n->nextSibling()) { | 401 for (Node* n = firstChild(); n; n = n->nextSibling()) { |
| 402 if (n->isTextNode()) | 402 if (n->isTextNode()) |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 449 String HTMLTextAreaElement::suggestedValue() const | 449 String HTMLTextAreaElement::suggestedValue() const |
| 450 { | 450 { |
| 451 return m_suggestedValue; | 451 return m_suggestedValue; |
| 452 } | 452 } |
| 453 | 453 |
| 454 void HTMLTextAreaElement::setSuggestedValue(const String& value) | 454 void HTMLTextAreaElement::setSuggestedValue(const String& value) |
| 455 { | 455 { |
| 456 m_suggestedValue = value; | 456 m_suggestedValue = value; |
| 457 | 457 |
| 458 if (!value.isNull()) | 458 if (!value.isNull()) |
| 459 setInnerTextValue(m_suggestedValue); | 459 setInnerEditorValue(m_suggestedValue); |
| 460 else | 460 else |
| 461 setInnerTextValue(m_value); | 461 setInnerEditorValue(m_value); |
| 462 updatePlaceholderVisibility(false); | 462 updatePlaceholderVisibility(false); |
| 463 setNeedsStyleRecalc(SubtreeStyleChange); | 463 setNeedsStyleRecalc(SubtreeStyleChange); |
| 464 } | 464 } |
| 465 | 465 |
| 466 String HTMLTextAreaElement::validationMessage() const | 466 String HTMLTextAreaElement::validationMessage() const |
| 467 { | 467 { |
| 468 if (!willValidate()) | 468 if (!willValidate()) |
| 469 return String(); | 469 return String(); |
| 470 | 470 |
| 471 if (customError()) | 471 if (customError()) |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 545 if (placeholderText.isEmpty()) { | 545 if (placeholderText.isEmpty()) { |
| 546 if (placeholder) | 546 if (placeholder) |
| 547 userAgentShadowRoot()->removeChild(placeholder); | 547 userAgentShadowRoot()->removeChild(placeholder); |
| 548 return; | 548 return; |
| 549 } | 549 } |
| 550 if (!placeholder) { | 550 if (!placeholder) { |
| 551 RefPtrWillBeRawPtr<HTMLDivElement> newElement = HTMLDivElement::create(d
ocument()); | 551 RefPtrWillBeRawPtr<HTMLDivElement> newElement = HTMLDivElement::create(d
ocument()); |
| 552 placeholder = newElement.get(); | 552 placeholder = newElement.get(); |
| 553 placeholder->setShadowPseudoId(AtomicString("-webkit-input-placeholder",
AtomicString::ConstructFromLiteral)); | 553 placeholder->setShadowPseudoId(AtomicString("-webkit-input-placeholder",
AtomicString::ConstructFromLiteral)); |
| 554 placeholder->setAttribute(idAttr, ShadowElementNames::placeholder()); | 554 placeholder->setAttribute(idAttr, ShadowElementNames::placeholder()); |
| 555 userAgentShadowRoot()->insertBefore(placeholder, innerTextElement()->nex
tSibling()); | 555 userAgentShadowRoot()->insertBefore(placeholder, innerEditorElement()->n
extSibling()); |
| 556 } | 556 } |
| 557 placeholder->setTextContent(placeholderText); | 557 placeholder->setTextContent(placeholderText); |
| 558 } | 558 } |
| 559 | 559 |
| 560 bool HTMLTextAreaElement::isInteractiveContent() const | 560 bool HTMLTextAreaElement::isInteractiveContent() const |
| 561 { | 561 { |
| 562 return true; | 562 return true; |
| 563 } | 563 } |
| 564 | 564 |
| 565 bool HTMLTextAreaElement::supportsAutofocus() const | 565 bool HTMLTextAreaElement::supportsAutofocus() const |
| 566 { | 566 { |
| 567 return true; | 567 return true; |
| 568 } | 568 } |
| 569 | 569 |
| 570 } | 570 } |
| OLD | NEW |