selectionRange.js 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. exports.getSelectionRange = getSelectionRange;
  6. exports.hasSelectionSupport = hasSelectionSupport;
  7. exports.setSelectionRange = setSelectionRange;
  8. var _isElementType = require("../misc/isElementType");
  9. // https://github.com/jsdom/jsdom/blob/c2fb8ff94917a4d45e2398543f5dd2a8fed0bdab/lib/jsdom/living/nodes/HTMLInputElement-impl.js#L45
  10. var selectionSupportType;
  11. (function (selectionSupportType) {
  12. selectionSupportType["text"] = "text";
  13. selectionSupportType["search"] = "search";
  14. selectionSupportType["url"] = "url";
  15. selectionSupportType["tel"] = "tel";
  16. selectionSupportType["password"] = "password";
  17. })(selectionSupportType || (selectionSupportType = {}));
  18. const InputSelection = Symbol('inputSelection');
  19. function hasSelectionSupport(element) {
  20. return (0, _isElementType.isElementType)(element, 'textarea') || (0, _isElementType.isElementType)(element, 'input') && Boolean(selectionSupportType[element.type]);
  21. }
  22. function getSelectionRange(element) {
  23. if (hasSelectionSupport(element)) {
  24. return {
  25. selectionStart: element.selectionStart,
  26. selectionEnd: element.selectionEnd
  27. };
  28. }
  29. if ((0, _isElementType.isElementType)(element, 'input')) {
  30. var _InputSelection;
  31. return (_InputSelection = element[InputSelection]) != null ? _InputSelection : {
  32. selectionStart: null,
  33. selectionEnd: null
  34. };
  35. }
  36. const selection = element.ownerDocument.getSelection(); // there should be no editing if the focusNode is outside of element
  37. // TODO: properly handle selection ranges
  38. if (selection != null && selection.rangeCount && element.contains(selection.focusNode)) {
  39. const range = selection.getRangeAt(0);
  40. return {
  41. selectionStart: range.startOffset,
  42. selectionEnd: range.endOffset
  43. };
  44. } else {
  45. return {
  46. selectionStart: null,
  47. selectionEnd: null
  48. };
  49. }
  50. }
  51. function setSelectionRange(element, newSelectionStart, newSelectionEnd) {
  52. const {
  53. selectionStart,
  54. selectionEnd
  55. } = getSelectionRange(element);
  56. if (selectionStart === newSelectionStart && selectionEnd === newSelectionEnd) {
  57. return;
  58. }
  59. if (hasSelectionSupport(element)) {
  60. element.setSelectionRange(newSelectionStart, newSelectionEnd);
  61. }
  62. if ((0, _isElementType.isElementType)(element, 'input')) {
  63. ;
  64. element[InputSelection] = {
  65. selectionStart: newSelectionStart,
  66. selectionEnd: newSelectionEnd
  67. };
  68. } // Moving the selection inside <input> or <textarea> does not alter the document Selection.
  69. if ((0, _isElementType.isElementType)(element, 'input') || (0, _isElementType.isElementType)(element, 'textarea')) {
  70. return;
  71. }
  72. const range = element.ownerDocument.createRange();
  73. range.selectNodeContents(element); // istanbul ignore else
  74. if (element.firstChild) {
  75. range.setStart(element.firstChild, newSelectionStart);
  76. range.setEnd(element.firstChild, newSelectionEnd);
  77. }
  78. const selection = element.ownerDocument.getSelection(); // istanbul ignore else
  79. if (selection) {
  80. selection.removeAllRanges();
  81. selection.addRange(range);
  82. }
  83. }