sidebar_hover.js 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. // TODO: This file was created by bulk-decaffeinate.
  2. // Sanity-check the conversion and remove this comment.
  3. /*
  4. * decaffeinate suggestions:
  5. * DS002: Fix invalid constructor
  6. * DS102: Remove unnecessary code created because of implicit returns
  7. * DS103: Rewrite code to no longer use __guard__, or convert again using --optional-chaining
  8. * DS206: Consider reworking classes to avoid initClass
  9. * DS207: Consider shorter variations of null checks
  10. * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md
  11. */
  12. const Cls = (app.views.SidebarHover = class SidebarHover extends app.View {
  13. static initClass() {
  14. this.itemClass = '_list-hover';
  15. this.events = {
  16. focus: 'onFocus',
  17. blur: 'onBlur',
  18. mouseover: 'onMouseover',
  19. mouseout: 'onMouseout',
  20. scroll: 'onScroll',
  21. click: 'onClick'
  22. };
  23. this.routes =
  24. {after: 'onRoute'};
  25. }
  26. constructor(el) {
  27. this.position = this.position.bind(this);
  28. this.onFocus = this.onFocus.bind(this);
  29. this.onBlur = this.onBlur.bind(this);
  30. this.onMouseover = this.onMouseover.bind(this);
  31. this.onMouseout = this.onMouseout.bind(this);
  32. this.onScroll = this.onScroll.bind(this);
  33. this.onClick = this.onClick.bind(this);
  34. this.onRoute = this.onRoute.bind(this);
  35. this.el = el;
  36. if (!isPointerEventsSupported()) {
  37. delete this.constructor.events.mouseover;
  38. }
  39. super(...arguments);
  40. }
  41. show(el) {
  42. if (el !== this.cursor) {
  43. this.hide();
  44. if (this.isTarget(el) && this.isTruncated(el.lastElementChild || el)) {
  45. this.cursor = el;
  46. this.clone = this.makeClone(this.cursor);
  47. $.append(document.body, this.clone);
  48. if (this.offsetTop == null) { this.offsetTop = this.el.offsetTop; }
  49. this.position();
  50. }
  51. }
  52. }
  53. hide() {
  54. if (this.cursor) {
  55. $.remove(this.clone);
  56. this.cursor = (this.clone = null);
  57. }
  58. }
  59. position() {
  60. if (this.cursor) {
  61. const rect = $.rect(this.cursor);
  62. if (rect.top >= this.offsetTop) {
  63. this.clone.style.top = rect.top + 'px';
  64. this.clone.style.left = rect.left + 'px';
  65. } else {
  66. this.hide();
  67. }
  68. }
  69. }
  70. makeClone(el) {
  71. const clone = el.cloneNode(true);
  72. clone.classList.add('clone');
  73. return clone;
  74. }
  75. isTarget(el) {
  76. return __guard__(el != null ? el.classList : undefined, x => x.contains(this.constructor.itemClass));
  77. }
  78. isSelected(el) {
  79. return el.classList.contains('active');
  80. }
  81. isTruncated(el) {
  82. return el.scrollWidth > el.offsetWidth;
  83. }
  84. onFocus(event) {
  85. this.focusTime = Date.now();
  86. this.show(event.target);
  87. }
  88. onBlur() {
  89. this.hide();
  90. }
  91. onMouseover(event) {
  92. if (this.isTarget(event.target) && !this.isSelected(event.target) && this.mouseActivated()) {
  93. this.show(event.target);
  94. }
  95. }
  96. onMouseout(event) {
  97. if (this.isTarget(event.target) && this.mouseActivated()) {
  98. this.hide();
  99. }
  100. }
  101. mouseActivated() {
  102. // Skip mouse events caused by focus events scrolling the sidebar.
  103. return !this.focusTime || ((Date.now() - this.focusTime) > 500);
  104. }
  105. onScroll() {
  106. this.position();
  107. }
  108. onClick(event) {
  109. if (event.target === this.clone) {
  110. $.click(this.cursor);
  111. }
  112. }
  113. onRoute() {
  114. this.hide();
  115. }
  116. });
  117. Cls.initClass();
  118. var isPointerEventsSupported = function() {
  119. const el = document.createElement('div');
  120. el.style.cssText = 'pointer-events: auto';
  121. return el.style.pointerEvents === 'auto';
  122. };
  123. function __guard__(value, transform) {
  124. return (typeof value !== 'undefined' && value !== null) ? transform(value) : undefined;
  125. }