doc_picker.js 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. app.views.DocPicker = class DocPicker extends app.View {
  2. static className = "_list _list-picker";
  3. static events = {
  4. mousedown: "onMouseDown",
  5. mouseup: "onMouseUp",
  6. };
  7. init() {
  8. this.addSubview((this.listFold = new app.views.ListFold(this.el)));
  9. }
  10. activate() {
  11. if (super.activate(...arguments)) {
  12. this.render();
  13. this.onDOMFocus = this.onDOMFocus.bind(this);
  14. $.on(this.el, "focus", this.onDOMFocus, true);
  15. }
  16. }
  17. deactivate() {
  18. if (super.deactivate(...arguments)) {
  19. this.empty();
  20. $.off(this.el, "focus", this.onDOMFocus, true);
  21. this.focusEl = null;
  22. }
  23. }
  24. render() {
  25. let doc;
  26. let html = this.tmpl("docPickerHeader");
  27. let docs = app.docs.all().concat(...(app.disabledDocs.all() || []));
  28. while ((doc = docs.shift())) {
  29. if (doc.version != null) {
  30. var versions;
  31. [docs, versions] = this.extractVersions(docs, doc);
  32. html += this.tmpl(
  33. "sidebarVersionedDoc",
  34. doc,
  35. this.renderVersions(versions),
  36. { open: app.docs.contains(doc) },
  37. );
  38. } else {
  39. html += this.tmpl("sidebarLabel", doc, {
  40. checked: app.docs.contains(doc),
  41. });
  42. }
  43. }
  44. this.html(html + this.tmpl("docPickerNote"));
  45. requestAnimationFrame(() => this.findByTag("input")?.focus());
  46. }
  47. renderVersions(docs) {
  48. let html = "";
  49. for (var doc of docs) {
  50. html += this.tmpl("sidebarLabel", doc, {
  51. checked: app.docs.contains(doc),
  52. });
  53. }
  54. return html;
  55. }
  56. extractVersions(originalDocs, version) {
  57. const docs = [];
  58. const versions = [version];
  59. for (var doc of originalDocs) {
  60. (doc.name === version.name ? versions : docs).push(doc);
  61. }
  62. return [docs, versions];
  63. }
  64. empty() {
  65. this.resetClass();
  66. super.empty(...arguments);
  67. }
  68. getSelectedDocs() {
  69. return [...this.findAllByTag("input")]
  70. .filter((input) => input?.checked)
  71. .map((input) => input.name);
  72. }
  73. onMouseDown() {
  74. this.mouseDown = Date.now();
  75. }
  76. onMouseUp() {
  77. this.mouseUp = Date.now();
  78. }
  79. onDOMFocus(event) {
  80. const { target } = event;
  81. if (target.tagName === "INPUT") {
  82. if (
  83. (!this.mouseDown || !(Date.now() < this.mouseDown + 100)) &&
  84. (!this.mouseUp || !(Date.now() < this.mouseUp + 100))
  85. ) {
  86. $.scrollTo(target.parentNode, null, "continuous");
  87. }
  88. } else if (target.classList.contains(app.views.ListFold.targetClass)) {
  89. target.blur();
  90. if (!this.mouseDown || !(Date.now() < this.mouseDown + 100)) {
  91. if (this.focusEl === $("input", target.nextElementSibling)) {
  92. if (target.classList.contains(app.views.ListFold.activeClass)) {
  93. this.listFold.close(target);
  94. }
  95. let prev = target.previousElementSibling;
  96. while (
  97. prev.tagName !== "LABEL" &&
  98. !prev.classList.contains(app.views.ListFold.targetClass)
  99. ) {
  100. prev = prev.previousElementSibling;
  101. }
  102. if (prev.classList.contains(app.views.ListFold.activeClass)) {
  103. prev = $.makeArray($$("input", prev.nextElementSibling)).pop();
  104. }
  105. this.delay(() => prev.focus());
  106. } else {
  107. if (!target.classList.contains(app.views.ListFold.activeClass)) {
  108. this.listFold.open(target);
  109. }
  110. this.delay(() => $("input", target.nextElementSibling).focus());
  111. }
  112. }
  113. }
  114. this.focusEl = target;
  115. }
  116. };