Chromium Code Reviews| 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 Apple Inc. All rights reserved. | 5 * Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved. |
| 6 * (C) 2006 Alexey Proskuryakov (ap@nypop.com) | 6 * (C) 2006 Alexey Proskuryakov (ap@nypop.com) |
| 7 * | 7 * |
| 8 * This library is free software; you can redistribute it and/or | 8 * This library is free software; you can redistribute it and/or |
| 9 * modify it under the terms of the GNU Library General Public | 9 * modify it under the terms of the GNU Library General Public |
| 10 * License as published by the Free Software Foundation; either | 10 * License as published by the Free Software Foundation; either |
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 157 if (!placeholderElement() || placeholderValueChanged) | 157 if (!placeholderElement() || placeholderValueChanged) |
| 158 updatePlaceholderText(); | 158 updatePlaceholderText(); |
| 159 HTMLElement* placeholder = placeholderElement(); | 159 HTMLElement* placeholder = placeholderElement(); |
| 160 if (!placeholder) | 160 if (!placeholder) |
| 161 return; | 161 return; |
| 162 placeholder->setInlineStyleProperty(CSSPropertyVisibility, placeholderShould BeVisible() ? CSSValueVisible : CSSValueHidden); | 162 placeholder->setInlineStyleProperty(CSSPropertyVisibility, placeholderShould BeVisible() ? CSSValueVisible : CSSValueHidden); |
| 163 } | 163 } |
| 164 | 164 |
| 165 void HTMLTextFormControlElement::setSelectionStart(int start) | 165 void HTMLTextFormControlElement::setSelectionStart(int start) |
| 166 { | 166 { |
| 167 setSelectionRange(start, max(start, selectionEnd()), selectionDirection()); | 167 setSelectionRange(start, max(start, selectionEndForJavascriptBindings()), se lectionDirection()); |
| 168 } | 168 } |
| 169 | 169 |
| 170 void HTMLTextFormControlElement::setSelectionEnd(int end) | 170 void HTMLTextFormControlElement::setSelectionEnd(int end) |
| 171 { | 171 { |
| 172 setSelectionRange(min(end, selectionStart()), end, selectionDirection()); | 172 setSelectionRange(min(end, selectionStartForJavascriptBindings()), end, sele ctionDirection()); |
| 173 } | 173 } |
| 174 | 174 |
| 175 void HTMLTextFormControlElement::setSelectionDirection(const String& direction) | 175 void HTMLTextFormControlElement::setSelectionDirection(const String& direction) |
| 176 { | 176 { |
| 177 setSelectionRange(selectionStart(), selectionEnd(), direction); | 177 setSelectionRange(selectionStart(), selectionEnd(), direction); |
| 178 } | 178 } |
| 179 | 179 |
| 180 void HTMLTextFormControlElement::select() | 180 void HTMLTextFormControlElement::select() |
| 181 { | 181 { |
| 182 setSelectionRange(0, numeric_limits<int>::max(), SelectionHasNoDirection); | 182 setSelectionRange(0, numeric_limits<int>::max(), SelectionHasNoDirection); |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 278 | 278 |
| 279 void HTMLTextFormControlElement::setSelectionRange(int start, int end, TextField SelectionDirection direction) | 279 void HTMLTextFormControlElement::setSelectionRange(int start, int end, TextField SelectionDirection direction) |
| 280 { | 280 { |
| 281 document().updateLayoutIgnorePendingStylesheets(); | 281 document().updateLayoutIgnorePendingStylesheets(); |
| 282 | 282 |
| 283 if (!renderer() || !renderer()->isTextControl()) | 283 if (!renderer() || !renderer()->isTextControl()) |
| 284 return; | 284 return; |
| 285 | 285 |
| 286 end = max(end, 0); | 286 end = max(end, 0); |
| 287 start = min(max(start, 0), end); | 287 start = min(max(start, 0), end); |
| 288 int textLength = innerTextValue().length(); | |
| 289 if (textLength) { | |
| 290 if (textLength < start) { | |
| 291 start = textLength; | |
| 292 end = textLength; | |
| 293 } else if (textLength >= start && textLength < end) { | |
|
Inactive
2014/06/02 15:32:45
nit: The "textLength >= start && " part seems unne
harpreet.sk
2014/07/02 10:13:05
Done.
| |
| 294 end = textLength; | |
| 295 } | |
| 296 } | |
| 297 cacheSelection(start, end, direction); | |
| 298 bool isCaretSelection = (start == end); | |
| 299 bool shouldSetSelection = (document().focusedElement() == this) || (!isCaret Selection && start < textLength); | |
|
tkent
2014/06/01 23:40:55
Why is !isCaretSelection necessary?
harpreet.sk
2014/07/02 10:13:05
This check is necessary because when input is not
| |
| 288 | 300 |
| 289 if (!hasVisibleTextArea(renderer(), innerTextElement())) { | 301 if (!hasVisibleTextArea(renderer(), innerTextElement())) |
| 290 cacheSelection(start, end, direction); | |
| 291 return; | 302 return; |
| 292 } | |
| 293 VisiblePosition startPosition = visiblePositionForIndex(start); | 303 VisiblePosition startPosition = visiblePositionForIndex(start); |
| 294 VisiblePosition endPosition; | 304 VisiblePosition endPosition; |
| 295 if (start == end) | 305 if (start == end) |
| 296 endPosition = startPosition; | 306 endPosition = startPosition; |
| 297 else | 307 else |
| 298 endPosition = visiblePositionForIndex(end); | 308 endPosition = visiblePositionForIndex(end); |
| 299 | 309 |
| 300 // startPosition and endPosition can be null position for example when | 310 // startPosition and endPosition can be null position for example when |
| 301 // "-webkit-user-select: none" style attribute is specified. | 311 // "-webkit-user-select: none" style attribute is specified. |
| 302 if (startPosition.isNotNull() && endPosition.isNotNull()) { | 312 if (startPosition.isNotNull() && endPosition.isNotNull()) { |
| 303 ASSERT(startPosition.deepEquivalent().deprecatedNode()->shadowHost() == this | 313 ASSERT(startPosition.deepEquivalent().deprecatedNode()->shadowHost() == this |
| 304 && endPosition.deepEquivalent().deprecatedNode()->shadowHost() == th is); | 314 && endPosition.deepEquivalent().deprecatedNode()->shadowHost() == th is); |
| 305 } | 315 } |
| 306 VisibleSelection newSelection; | 316 VisibleSelection newSelection; |
| 307 if (direction == SelectionHasBackwardDirection) | 317 if (direction == SelectionHasBackwardDirection) |
| 308 newSelection = VisibleSelection(endPosition, startPosition); | 318 newSelection = VisibleSelection(endPosition, startPosition); |
| 309 else | 319 else |
| 310 newSelection = VisibleSelection(startPosition, endPosition); | 320 newSelection = VisibleSelection(startPosition, endPosition); |
| 311 newSelection.setIsDirectional(direction != SelectionHasNoDirection); | 321 newSelection.setIsDirectional(direction != SelectionHasNoDirection); |
| 312 | 322 |
| 313 if (LocalFrame* frame = document().frame()) | 323 LocalFrame* frame = document().frame(); |
| 324 if (frame && shouldSetSelection) | |
| 314 frame->selection().setSelection(newSelection); | 325 frame->selection().setSelection(newSelection); |
| 315 } | 326 } |
| 316 | 327 |
| 317 VisiblePosition HTMLTextFormControlElement::visiblePositionForIndex(int index) c onst | 328 VisiblePosition HTMLTextFormControlElement::visiblePositionForIndex(int index) c onst |
| 318 { | 329 { |
| 319 if (index <= 0) | 330 if (index <= 0) |
| 320 return VisiblePosition(firstPositionInNode(innerTextElement()), DOWNSTRE AM); | 331 return VisiblePosition(firstPositionInNode(innerTextElement()), DOWNSTRE AM); |
| 321 RefPtrWillBeRawPtr<Range> range = Range::create(document()); | 332 RefPtrWillBeRawPtr<Range> range = Range::create(document()); |
| 322 range->selectNodeContents(innerTextElement(), ASSERT_NO_EXCEPTION); | 333 range->selectNodeContents(innerTextElement(), ASSERT_NO_EXCEPTION); |
| 323 CharacterIterator it(range.get()); | 334 CharacterIterator it(range.get()); |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 334 RefPtrWillBeRawPtr<Range> range = Range::create(*indexPosition.document()); | 345 RefPtrWillBeRawPtr<Range> range = Range::create(*indexPosition.document()); |
| 335 range->setStart(innerTextElement(), 0, ASSERT_NO_EXCEPTION); | 346 range->setStart(innerTextElement(), 0, ASSERT_NO_EXCEPTION); |
| 336 range->setEnd(indexPosition.containerNode(), indexPosition.offsetInContainer Node(), ASSERT_NO_EXCEPTION); | 347 range->setEnd(indexPosition.containerNode(), indexPosition.offsetInContainer Node(), ASSERT_NO_EXCEPTION); |
| 337 return TextIterator::rangeLength(range.get()); | 348 return TextIterator::rangeLength(range.get()); |
| 338 } | 349 } |
| 339 | 350 |
| 340 int HTMLTextFormControlElement::selectionStart() const | 351 int HTMLTextFormControlElement::selectionStart() const |
| 341 { | 352 { |
| 342 if (!isTextFormControl()) | 353 if (!isTextFormControl()) |
| 343 return 0; | 354 return 0; |
| 344 if (document().focusedElement() != this) | 355 if (document().focusedElement() != this) { |
| 356 if (!innerTextValue().length()) | |
|
tkent
2014/06/01 23:40:55
As I wrote again and again, adjusting value on sel
harpreet.sk
2014/07/02 10:13:05
We require a check in selectionStart() and selecti
| |
| 357 return 0; | |
| 345 return m_cachedSelectionStart; | 358 return m_cachedSelectionStart; |
| 359 } | |
| 346 | 360 |
| 347 return computeSelectionStart(); | 361 return computeSelectionStart(); |
| 348 } | 362 } |
| 349 | 363 |
| 364 int HTMLTextFormControlElement::selectionStartForJavascriptBindings() const | |
| 365 { | |
| 366 if (!isTextFormControl()) | |
| 367 return 0; | |
| 368 | |
| 369 return m_cachedSelectionStart; | |
| 370 } | |
| 371 | |
| 350 int HTMLTextFormControlElement::computeSelectionStart() const | 372 int HTMLTextFormControlElement::computeSelectionStart() const |
| 351 { | 373 { |
| 352 ASSERT(isTextFormControl()); | 374 ASSERT(isTextFormControl()); |
| 353 LocalFrame* frame = document().frame(); | 375 LocalFrame* frame = document().frame(); |
| 354 if (!frame) | 376 if (!frame) |
| 355 return 0; | 377 return 0; |
| 356 | 378 |
| 357 return indexForVisiblePosition(VisiblePosition(frame->selection().start())); | 379 return indexForVisiblePosition(VisiblePosition(frame->selection().start())); |
| 358 } | 380 } |
| 359 | 381 |
| 360 int HTMLTextFormControlElement::selectionEnd() const | 382 int HTMLTextFormControlElement::selectionEnd() const |
| 361 { | 383 { |
| 362 if (!isTextFormControl()) | 384 if (!isTextFormControl()) |
| 363 return 0; | 385 return 0; |
| 364 if (document().focusedElement() != this) | 386 if (document().focusedElement() != this) { |
| 387 if (!innerTextValue().length()) | |
|
Inactive
2014/06/02 15:32:45
if (innerTextValue().isEmpty())
harpreet.sk
2014/07/02 10:13:05
Done.
| |
| 388 return 0; | |
| 365 return m_cachedSelectionEnd; | 389 return m_cachedSelectionEnd; |
| 390 } | |
| 366 return computeSelectionEnd(); | 391 return computeSelectionEnd(); |
| 367 } | 392 } |
| 368 | 393 |
| 394 int HTMLTextFormControlElement::selectionEndForJavascriptBindings() const | |
| 395 { | |
| 396 if (!isTextFormControl()) | |
| 397 return 0; | |
| 398 | |
| 399 return m_cachedSelectionEnd; | |
| 400 } | |
| 401 | |
| 369 int HTMLTextFormControlElement::computeSelectionEnd() const | 402 int HTMLTextFormControlElement::computeSelectionEnd() const |
| 370 { | 403 { |
| 371 ASSERT(isTextFormControl()); | 404 ASSERT(isTextFormControl()); |
| 372 LocalFrame* frame = document().frame(); | 405 LocalFrame* frame = document().frame(); |
| 373 if (!frame) | 406 if (!frame) |
| 374 return 0; | 407 return 0; |
| 375 | 408 |
| 376 return indexForVisiblePosition(VisiblePosition(frame->selection().end())); | 409 return indexForVisiblePosition(VisiblePosition(frame->selection().end())); |
| 377 } | 410 } |
| 378 | 411 |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 471 void HTMLTextFormControlElement::restoreCachedSelection() | 504 void HTMLTextFormControlElement::restoreCachedSelection() |
| 472 { | 505 { |
| 473 setSelectionRange(m_cachedSelectionStart, m_cachedSelectionEnd, m_cachedSele ctionDirection); | 506 setSelectionRange(m_cachedSelectionStart, m_cachedSelectionEnd, m_cachedSele ctionDirection); |
| 474 } | 507 } |
| 475 | 508 |
| 476 void HTMLTextFormControlElement::selectionChanged(bool userTriggered) | 509 void HTMLTextFormControlElement::selectionChanged(bool userTriggered) |
| 477 { | 510 { |
| 478 if (!renderer() || !isTextFormControl()) | 511 if (!renderer() || !isTextFormControl()) |
| 479 return; | 512 return; |
| 480 | 513 |
| 481 // selectionStart() or selectionEnd() will return cached selection when this node doesn't have focus | 514 if (document().focusedElement() == this) |
| 482 cacheSelection(computeSelectionStart(), computeSelectionEnd(), computeSelect ionDirection()); | 515 cacheSelection(computeSelectionStart(), computeSelectionEnd(), computeSe lectionDirection()); |
| 483 | 516 |
| 484 if (LocalFrame* frame = document().frame()) { | 517 if (LocalFrame* frame = document().frame()) { |
| 485 if (frame->selection().isRange() && userTriggered) | 518 if (frame->selection().isRange() && userTriggered) |
| 486 dispatchEvent(Event::createBubble(EventTypeNames::select)); | 519 dispatchEvent(Event::createBubble(EventTypeNames::select)); |
| 487 } | 520 } |
| 488 } | 521 } |
| 489 | 522 |
| 490 void HTMLTextFormControlElement::parseAttribute(const QualifiedName& name, const AtomicString& value) | 523 void HTMLTextFormControlElement::parseAttribute(const QualifiedName& name, const AtomicString& value) |
| 491 { | 524 { |
| 492 if (name == placeholderAttr) { | 525 if (name == placeholderAttr) { |
| (...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 651 | 684 |
| 652 return "ltr"; | 685 return "ltr"; |
| 653 } | 686 } |
| 654 | 687 |
| 655 HTMLElement* HTMLTextFormControlElement::innerTextElement() const | 688 HTMLElement* HTMLTextFormControlElement::innerTextElement() const |
| 656 { | 689 { |
| 657 return toHTMLElement(userAgentShadowRoot()->getElementById(ShadowElementName s::innerEditor())); | 690 return toHTMLElement(userAgentShadowRoot()->getElementById(ShadowElementName s::innerEditor())); |
| 658 } | 691 } |
| 659 | 692 |
| 660 } // namespace Webcore | 693 } // namespace Webcore |
| OLD | NEW |