Home | History | Annotate | Download | only in js
      1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 function focus(element) {
      6   // Focus the target element in order to send keys to it.
      7   // First, the currently active element is blurred, if it is different from
      8   // the target element. We do not want to blur an element unnecessarily,
      9   // because this may cause us to lose the current cursor position in the
     10   // element.
     11   // Secondly, we focus the target element.
     12   // Thirdly, if the target element is newly focused and is a text input, we
     13   // set the cursor position at the end.
     14   // Fourthly, we check if the new active element is the target element. If not,
     15   // we throw an error.
     16   // Additional notes:
     17   //   - |document.activeElement| is the currently focused element, or body if
     18   //     no element is focused
     19   //   - Even if |document.hasFocus()| returns true and the active element is
     20   //     the body, sometimes we still need to focus the body element for send
     21   //     keys to work. Not sure why
     22   //   - You cannot focus a descendant of a content editable node
     23   //   - V8 throws a TypeError when calling setSelectionRange for a non-text
     24   //     input, which still have setSelectionRange defined. For chrome 29+, V8
     25   //     throws a DOMException with code InvalidStateError.
     26   var doc = element.ownerDocument || element;
     27   var prevActiveElement = doc.activeElement;
     28   if (element != prevActiveElement && prevActiveElement)
     29     prevActiveElement.blur();
     30   element.focus();
     31   if (element != prevActiveElement && element.value &&
     32       element.value.length && element.setSelectionRange) {
     33     try {
     34       element.setSelectionRange(element.value.length, element.value.length);
     35     } catch (error) {
     36       if (!(error instanceof TypeError) && !(error instanceof DOMException &&
     37           error.code == DOMException.INVALID_STATE_ERR))
     38         throw error;
     39     }
     40   }
     41   if (element != doc.activeElement)
     42     throw new Error('cannot focus element');
     43 }
     44