Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(278)

Side by Side Diff: Source/core/html/HTMLTextFormControlElement.cpp

Issue 258063005: Blink does not respect input.selectionStart and input.selectionEnd for some cases (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Addressing changes asked in previous patch Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 145 matching lines...) Expand 10 before | Expand all | Expand 10 after
156 if (!placeholderElement() || placeholderValueChanged) 156 if (!placeholderElement() || placeholderValueChanged)
157 updatePlaceholderText(); 157 updatePlaceholderText();
158 HTMLElement* placeholder = placeholderElement(); 158 HTMLElement* placeholder = placeholderElement();
159 if (!placeholder) 159 if (!placeholder)
160 return; 160 return;
161 placeholder->setInlineStyleProperty(CSSPropertyVisibility, placeholderShould BeVisible() ? CSSValueVisible : CSSValueHidden); 161 placeholder->setInlineStyleProperty(CSSPropertyVisibility, placeholderShould BeVisible() ? CSSValueVisible : CSSValueHidden);
162 } 162 }
163 163
164 void HTMLTextFormControlElement::setSelectionStart(int start) 164 void HTMLTextFormControlElement::setSelectionStart(int start)
165 { 165 {
166 setSelectionRange(start, std::max(start, selectionEnd()), selectionDirection ()); 166 if (!innerEditorValue().isEmpty())
167 setSelectionRange(start, std::max(start, selectionEnd()), selectionDirec tion());
168 else
169 setSelectionRange(start, std::max(start, m_cachedSelectionEnd), selectio nDirection());
167 } 170 }
168 171
169 void HTMLTextFormControlElement::setSelectionEnd(int end) 172 void HTMLTextFormControlElement::setSelectionEnd(int end)
170 { 173 {
171 setSelectionRange(std::min(end, selectionStart()), end, selectionDirection() ); 174 if (!innerEditorValue().isEmpty())
175 setSelectionRange(std::min(end, selectionStart()), end, selectionDirecti on());
176 else
177 setSelectionRange(std::min(end, m_cachedSelectionStart), end, selectionD irection());
172 } 178 }
173 179
174 void HTMLTextFormControlElement::setSelectionDirection(const String& direction) 180 void HTMLTextFormControlElement::setSelectionDirection(const String& direction)
175 { 181 {
176 setSelectionRange(selectionStart(), selectionEnd(), direction); 182 setSelectionRange(selectionStart(), selectionEnd(), direction);
177 } 183 }
178 184
179 void HTMLTextFormControlElement::select() 185 void HTMLTextFormControlElement::select()
180 { 186 {
181 setSelectionRange(0, std::numeric_limits<int>::max(), SelectionHasNoDirectio n); 187 setSelectionRange(0, std::numeric_limits<int>::max(), SelectionHasNoDirectio n);
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
277 283
278 void HTMLTextFormControlElement::setSelectionRange(int start, int end, TextField SelectionDirection direction) 284 void HTMLTextFormControlElement::setSelectionRange(int start, int end, TextField SelectionDirection direction)
279 { 285 {
280 document().updateLayoutIgnorePendingStylesheets(); 286 document().updateLayoutIgnorePendingStylesheets();
281 287
282 if (!renderer() || !renderer()->isTextControl()) 288 if (!renderer() || !renderer()->isTextControl())
283 return; 289 return;
284 290
285 end = std::max(end, 0); 291 end = std::max(end, 0);
286 start = std::min(std::max(start, 0), end); 292 start = std::min(std::max(start, 0), end);
293 int textLength = innerEditorValue().length();
294 if (textLength) {
295 if (textLength < start) {
296 start = textLength;
297 end = textLength;
298 } else if (textLength < end) {
299 end = textLength;
300 }
301 }
302 cacheSelection(start, end, direction);
303 bool isCaretSelection = (start == end);
304 bool shouldSetSelection = (document().focusedElement() == this) || (!isCaret Selection && start < textLength);
287 305
288 if (!hasVisibleTextArea(renderer(), innerEditorElement())) { 306 if (!hasVisibleTextArea(renderer(), innerEditorElement()))
289 cacheSelection(start, end, direction);
290 return; 307 return;
291 }
292 VisiblePosition startPosition = visiblePositionForIndex(start); 308 VisiblePosition startPosition = visiblePositionForIndex(start);
293 VisiblePosition endPosition; 309 VisiblePosition endPosition;
294 if (start == end) 310 if (start == end)
295 endPosition = startPosition; 311 endPosition = startPosition;
296 else 312 else
297 endPosition = visiblePositionForIndex(end); 313 endPosition = visiblePositionForIndex(end);
298 314
299 // startPosition and endPosition can be null position for example when 315 // startPosition and endPosition can be null position for example when
300 // "-webkit-user-select: none" style attribute is specified. 316 // "-webkit-user-select: none" style attribute is specified.
301 if (startPosition.isNotNull() && endPosition.isNotNull()) { 317 if (startPosition.isNotNull() && endPosition.isNotNull()) {
302 ASSERT(startPosition.deepEquivalent().deprecatedNode()->shadowHost() == this 318 ASSERT(startPosition.deepEquivalent().deprecatedNode()->shadowHost() == this
303 && endPosition.deepEquivalent().deprecatedNode()->shadowHost() == th is); 319 && endPosition.deepEquivalent().deprecatedNode()->shadowHost() == th is);
304 } 320 }
305 VisibleSelection newSelection; 321 VisibleSelection newSelection;
306 if (direction == SelectionHasBackwardDirection) 322 if (direction == SelectionHasBackwardDirection)
307 newSelection = VisibleSelection(endPosition, startPosition); 323 newSelection = VisibleSelection(endPosition, startPosition);
308 else 324 else
309 newSelection = VisibleSelection(startPosition, endPosition); 325 newSelection = VisibleSelection(startPosition, endPosition);
310 newSelection.setIsDirectional(direction != SelectionHasNoDirection); 326 newSelection.setIsDirectional(direction != SelectionHasNoDirection);
311 327
312 if (LocalFrame* frame = document().frame()) 328 LocalFrame* frame = document().frame();
329 if (frame && shouldSetSelection)
313 frame->selection().setSelection(newSelection); 330 frame->selection().setSelection(newSelection);
314 } 331 }
315 332
316 VisiblePosition HTMLTextFormControlElement::visiblePositionForIndex(int index) c onst 333 VisiblePosition HTMLTextFormControlElement::visiblePositionForIndex(int index) c onst
317 { 334 {
318 if (index <= 0) 335 if (index <= 0)
319 return VisiblePosition(firstPositionInNode(innerEditorElement()), DOWNST REAM); 336 return VisiblePosition(firstPositionInNode(innerEditorElement()), DOWNST REAM);
320 RefPtrWillBeRawPtr<Range> range = Range::create(document()); 337 RefPtrWillBeRawPtr<Range> range = Range::create(document());
321 range->selectNodeContents(innerEditorElement(), ASSERT_NO_EXCEPTION); 338 range->selectNodeContents(innerEditorElement(), ASSERT_NO_EXCEPTION);
322 CharacterIterator it(range.get()); 339 CharacterIterator it(range.get());
323 it.advance(index - 1); 340 it.advance(index - 1);
324 return VisiblePosition(it.range()->endPosition(), UPSTREAM); 341 return VisiblePosition(it.range()->endPosition(), UPSTREAM);
325 } 342 }
326 343
327 int HTMLTextFormControlElement::indexForVisiblePosition(const VisiblePosition& p os) const 344 int HTMLTextFormControlElement::indexForVisiblePosition(const VisiblePosition& p os) const
328 { 345 {
329 Position indexPosition = pos.deepEquivalent().parentAnchoredEquivalent(); 346 Position indexPosition = pos.deepEquivalent().parentAnchoredEquivalent();
330 if (enclosingTextFormControl(indexPosition) != this) 347 if (enclosingTextFormControl(indexPosition) != this)
331 return 0; 348 return 0;
332 ASSERT(indexPosition.document()); 349 ASSERT(indexPosition.document());
333 RefPtrWillBeRawPtr<Range> range = Range::create(*indexPosition.document()); 350 RefPtrWillBeRawPtr<Range> range = Range::create(*indexPosition.document());
334 range->setStart(innerEditorElement(), 0, ASSERT_NO_EXCEPTION); 351 range->setStart(innerEditorElement(), 0, ASSERT_NO_EXCEPTION);
335 range->setEnd(indexPosition.containerNode(), indexPosition.offsetInContainer Node(), ASSERT_NO_EXCEPTION); 352 range->setEnd(indexPosition.containerNode(), indexPosition.offsetInContainer Node(), ASSERT_NO_EXCEPTION);
336 return TextIterator::rangeLength(range.get()); 353 return TextIterator::rangeLength(range.get());
337 } 354 }
338 355
339 int HTMLTextFormControlElement::selectionStart() const 356 int HTMLTextFormControlElement::selectionStart() const
340 { 357 {
341 if (!isTextFormControl()) 358 if (!isTextFormControl() || innerEditorValue().isEmpty())
harpreet.sk 2014/07/02 10:13:05 We require check in selectionStart() and selection
342 return 0; 359 return 0;
343 if (document().focusedElement() != this) 360 if (document().focusedElement() != this)
344 return m_cachedSelectionStart; 361 return m_cachedSelectionStart;
345
346 return computeSelectionStart(); 362 return computeSelectionStart();
347 } 363 }
348 364
349 int HTMLTextFormControlElement::computeSelectionStart() const 365 int HTMLTextFormControlElement::computeSelectionStart() const
350 { 366 {
351 ASSERT(isTextFormControl()); 367 ASSERT(isTextFormControl());
352 LocalFrame* frame = document().frame(); 368 LocalFrame* frame = document().frame();
353 if (!frame) 369 if (!frame)
354 return 0; 370 return 0;
355 371
356 return indexForVisiblePosition(VisiblePosition(frame->selection().start())); 372 return indexForVisiblePosition(VisiblePosition(frame->selection().start()));
357 } 373 }
358 374
359 int HTMLTextFormControlElement::selectionEnd() const 375 int HTMLTextFormControlElement::selectionEnd() const
360 { 376 {
361 if (!isTextFormControl()) 377 if (!isTextFormControl() || innerEditorValue().isEmpty())
362 return 0; 378 return 0;
363 if (document().focusedElement() != this) 379 if (document().focusedElement() != this)
364 return m_cachedSelectionEnd; 380 return m_cachedSelectionEnd;
365 return computeSelectionEnd(); 381 return computeSelectionEnd();
366 } 382 }
367 383
368 int HTMLTextFormControlElement::computeSelectionEnd() const 384 int HTMLTextFormControlElement::computeSelectionEnd() const
369 { 385 {
370 ASSERT(isTextFormControl()); 386 ASSERT(isTextFormControl());
371 LocalFrame* frame = document().frame(); 387 LocalFrame* frame = document().frame();
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
470 void HTMLTextFormControlElement::restoreCachedSelection() 486 void HTMLTextFormControlElement::restoreCachedSelection()
471 { 487 {
472 setSelectionRange(m_cachedSelectionStart, m_cachedSelectionEnd, m_cachedSele ctionDirection); 488 setSelectionRange(m_cachedSelectionStart, m_cachedSelectionEnd, m_cachedSele ctionDirection);
473 } 489 }
474 490
475 void HTMLTextFormControlElement::selectionChanged(bool userTriggered) 491 void HTMLTextFormControlElement::selectionChanged(bool userTriggered)
476 { 492 {
477 if (!renderer() || !isTextFormControl()) 493 if (!renderer() || !isTextFormControl())
478 return; 494 return;
479 495
480 // selectionStart() or selectionEnd() will return cached selection when this node doesn't have focus 496 if (document().focusedElement() == this)
481 cacheSelection(computeSelectionStart(), computeSelectionEnd(), computeSelect ionDirection()); 497 cacheSelection(computeSelectionStart(), computeSelectionEnd(), computeSe lectionDirection());
482 498
483 if (LocalFrame* frame = document().frame()) { 499 if (LocalFrame* frame = document().frame()) {
484 if (frame->selection().isRange() && userTriggered) 500 if (frame->selection().isRange() && userTriggered)
485 dispatchEvent(Event::createBubble(EventTypeNames::select)); 501 dispatchEvent(Event::createBubble(EventTypeNames::select));
486 } 502 }
487 } 503 }
488 504
489 void HTMLTextFormControlElement::parseAttribute(const QualifiedName& name, const AtomicString& value) 505 void HTMLTextFormControlElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
490 { 506 {
491 if (name == placeholderAttr) { 507 if (name == placeholderAttr) {
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after
653 669
654 return "ltr"; 670 return "ltr";
655 } 671 }
656 672
657 HTMLElement* HTMLTextFormControlElement::innerEditorElement() const 673 HTMLElement* HTMLTextFormControlElement::innerEditorElement() const
658 { 674 {
659 return toHTMLElement(userAgentShadowRoot()->getElementById(ShadowElementName s::innerEditor())); 675 return toHTMLElement(userAgentShadowRoot()->getElementById(ShadowElementName s::innerEditor()));
660 } 676 }
661 677
662 } // namespace Webcore 678 } // namespace Webcore
OLDNEW
« no previous file with comments | « LayoutTests/fast/forms/validationMessage-expected.txt ('k') | Source/core/html/forms/TextFieldInputType.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698