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

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: New patch fixing existing bug Created 6 years, 6 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 146 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698