1c573070b8fde92877aaaacfb6941621573c7e256a23756ba81b0b342dab2f8cd6fc72a877cc7e840deadb5684e8b73e54e109ac65b2050cecf49880c4909b 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. import { elt, range, removeChildren, removeChildrenAndAdd } from "./dom.js"
  2. import { ie, ie_version } from "./browser.js"
  3. // Detect drag-and-drop
  4. export let dragAndDrop = function() {
  5. // There is *some* kind of drag-and-drop support in IE6-8, but I
  6. // couldn't get it to work yet.
  7. if (ie && ie_version < 9) return false
  8. let div = elt('div')
  9. return "draggable" in div || "dragDrop" in div
  10. }()
  11. let zwspSupported
  12. export function zeroWidthElement(measure) {
  13. if (zwspSupported == null) {
  14. let test = elt("span", "\u200b")
  15. removeChildrenAndAdd(measure, elt("span", [test, document.createTextNode("x")]))
  16. if (measure.firstChild.offsetHeight != 0)
  17. zwspSupported = test.offsetWidth <= 1 && test.offsetHeight > 2 && !(ie && ie_version < 8)
  18. }
  19. let node = zwspSupported ? elt("span", "\u200b") :
  20. elt("span", "\u00a0", null, "display: inline-block; width: 1px; margin-right: -1px")
  21. node.setAttribute("cm-text", "")
  22. return node
  23. }
  24. // Feature-detect IE's crummy client rect reporting for bidi text
  25. let badBidiRects
  26. export function hasBadBidiRects(measure) {
  27. if (badBidiRects != null) return badBidiRects
  28. let txt = removeChildrenAndAdd(measure, document.createTextNode("A\u062eA"))
  29. let r0 = range(txt, 0, 1).getBoundingClientRect()
  30. let r1 = range(txt, 1, 2).getBoundingClientRect()
  31. removeChildren(measure)
  32. if (!r0 || r0.left == r0.right) return false // Safari returns null in some cases (#2780)
  33. return badBidiRects = (r1.right - r0.right < 3)
  34. }
  35. // See if "".split is the broken IE version, if so, provide an
  36. // alternative way to split lines.
  37. export let splitLinesAuto = "\n\nb".split(/\n/).length != 3 ? string => {
  38. let pos = 0, result = [], l = string.length
  39. while (pos <= l) {
  40. let nl = string.indexOf("\n", pos)
  41. if (nl == -1) nl = string.length
  42. let line = string.slice(pos, string.charAt(nl - 1) == "\r" ? nl - 1 : nl)
  43. let rt = line.indexOf("\r")
  44. if (rt != -1) {
  45. result.push(line.slice(0, rt))
  46. pos += rt + 1
  47. } else {
  48. result.push(line)
  49. pos = nl + 1
  50. }
  51. }
  52. return result
  53. } : string => string.split(/\r\n?|\n/)
  54. export let hasSelection = window.getSelection ? te => {
  55. try { return te.selectionStart != te.selectionEnd }
  56. catch(e) { return false }
  57. } : te => {
  58. let range
  59. try {range = te.ownerDocument.selection.createRange()}
  60. catch(e) {}
  61. if (!range || range.parentElement() != te) return false
  62. return range.compareEndPoints("StartToEnd", range) != 0
  63. }
  64. export let hasCopyEvent = (() => {
  65. let e = elt("div")
  66. if ("oncopy" in e) return true
  67. e.setAttribute("oncopy", "return;")
  68. return typeof e.oncopy == "function"
  69. })()
  70. let badZoomedRects = null
  71. export function hasBadZoomedRects(measure) {
  72. if (badZoomedRects != null) return badZoomedRects
  73. let node = removeChildrenAndAdd(measure, elt("span", "x"))
  74. let normal = node.getBoundingClientRect()
  75. let fromRange = range(node, 0, 1).getBoundingClientRect()
  76. return badZoomedRects = Math.abs(normal.left - fromRange.left) > 1
  77. }