Focus input text field on Esc

Focus the first visible input text field when you press Esc key, or restore the previously focused element on second press

当前为 2018-10-11 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Focus input text field on Esc
  3. // @description Focus the first visible input text field when you press Esc key, or restore the previously focused element on second press
  4. // @version 1.0.6
  5. // @include *
  6. // @author wOxxOm
  7. // @namespace wOxxOm.scripts
  8. // @license MIT License
  9. // @run-at document-start
  10. // ==/UserScript==
  11.  
  12. var TEXT_FIELD = ' search text number url ';
  13. var previousElement;
  14. var scrollPos;
  15. var first;
  16.  
  17. document.addEventListener('keydown', function (e) {
  18. if (e.keyCode !== 27 || e.altKey || e.ctrlKey || e.shiftKey || e.metaKey) {
  19. return;
  20. }
  21. if (window !== top) {
  22. top.postMessage(GM_info.script.name, '*');
  23. e.preventDefault();
  24. e.stopPropagation();
  25. return;
  26. }
  27. run();
  28. }, true);
  29.  
  30. window.addEventListener('message', function (e) {
  31. if (e.data === GM_info.script.name) {
  32. run({relayedFromFrame: true});
  33. }
  34. });
  35.  
  36. function run(params) {
  37. // find text inputs inside visible DOM containers
  38. var inputs = document.getElementsByTagName('input');
  39. for (var i = 0, input, il = inputs.length; i < il && (input = inputs[i]); i++) {
  40. var priority = TEXT_FIELD.indexOf(' ' + input.type + ' ');
  41. if (priority < 0) continue;
  42. var n = input, style;
  43. while (n && n.style && (style = getComputedStyle(n)) && style.display !== 'none' && style.visibility !== 'hidden') {
  44. n = n.parentNode;
  45. }
  46. // visible if reached DOM root
  47. if (n && n.style) continue;
  48. // set the first OR if it's empty, try to select an identically named input field with some text (happens on some sites)
  49. if (!first || (
  50. input.value &&
  51. input.name === first.name && (
  52. !input.form &&
  53. !first.form || input.form.action === first.form.action
  54. )
  55. )) {
  56. first = input;
  57. if (first.value) break;
  58. }
  59. }
  60.  
  61. if (!first) return;
  62.  
  63. var invoke = params && params.relayedFromFrame ? passthru : onkeyup;
  64.  
  65. if (first !== document.activeElement) {
  66. // switch to the found input field
  67. previousElement = document.activeElement;
  68. scrollPos = [scrollX, scrollY];
  69. invoke(setFocus);
  70. } else if (previousElement) {
  71. invoke(restoreFocus);
  72. }
  73. }
  74.  
  75. function setFocus() {
  76. first.focus();
  77. first.select();
  78. }
  79.  
  80. function restoreFocus() {
  81. // in case document.body (page "background") was previously selected
  82. document.activeElement.blur();
  83. previousElement.focus();
  84. scrollTo(scrollPos[0], scrollPos[1]);
  85. }
  86.  
  87. // focusing should be done at key-up to prevent the Esc-keydown being also chain-handled by the just focused element
  88. function onkeyup(cb) {
  89. document.addEventListener('keyup', function keyup(e) {
  90. if (e.keyCode !== 27) return;
  91. document.removeEventListener('keyup', keyup);
  92. cb(e);
  93. });
  94. }
  95.  
  96. function passthru(fn) {
  97. return fn.apply(this, arguments);
  98. }