util.ts 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. namespace util {
  2. export function loadBase(): void {
  3. let container = document.querySelector('#container');
  4. if (container === null) {
  5. throw new Error('Container not found');
  6. }
  7. let baseTemplate = loadTemplate('base');
  8. baseTemplate.querySelectorAll('template').forEach(t => {
  9. let parent = t.parentNode as Node;
  10. const templateName = t.getAttribute('name');
  11. if (templateName === null) {
  12. return;
  13. }
  14. let template = loadTemplate(templateName);
  15. let firstElement = template.querySelector('*');
  16. if (firstElement !== null) {
  17. for (let i = 0; i < t.classList.length; ++i) {
  18. firstElement.classList.add(t.classList[i]);
  19. }
  20. }
  21. parent.insertBefore(template, t);
  22. parent.removeChild(t);
  23. });
  24. container.appendChild(baseTemplate);
  25. }
  26. export function loadTemplate(id: string): DocumentFragment {
  27. let template = document.querySelector(`#${id}-template`);
  28. if (template !== null && template instanceof HTMLTemplateElement) {
  29. return document.importNode(template.content, true);
  30. } else {
  31. throw new Error(`#${id}-template is not a template`);
  32. }
  33. }
  34. export function clearChildren(node: Node): void {
  35. while (node.lastChild !== null) {
  36. node.removeChild(node.lastChild);
  37. }
  38. }
  39. export function getElement<E extends HTMLElement>(element: ParentNode, selector: string): E {
  40. const e = element.querySelector(selector);
  41. if (e === null) {
  42. throw new Error(`Could not find required element ${selector}`);
  43. }
  44. return e as E;
  45. }
  46. export function loadBackground(url: string): Promise<void> {
  47. if (url.includes('.')) {
  48. return new Promise((resolve, reject) => {
  49. let image = new Image();
  50. image.onload = (event) => resolve();
  51. image.src = url;
  52. });
  53. } else {
  54. return Promise.resolve();
  55. }
  56. }
  57. class ListenerManager {
  58. constructor(
  59. private target: EventTarget,
  60. private event: string,
  61. private handler: EventListener
  62. ) {}
  63. attach(): void {
  64. this.target.addEventListener(this.event, this.handler);
  65. }
  66. detach(): void {
  67. this.target.removeEventListener(this.event, this.handler);
  68. }
  69. }
  70. export class ListenersManager {
  71. private listeners: ListenerManager[] = [];
  72. add(target: EventTarget, event: string, handler: EventListener, attach: boolean = true): void {
  73. let listener = new ListenerManager(target, event, handler);
  74. this.listeners.push(listener);
  75. if (attach) {
  76. listener.attach();
  77. }
  78. }
  79. attach(): void {
  80. this.listeners.forEach(l => l.attach());
  81. }
  82. detach(): void {
  83. this.listeners.forEach(l => l.detach());
  84. }
  85. }
  86. export class FnContext {
  87. current: Symbol = Symbol();
  88. invalidate() {
  89. this.current = Symbol();
  90. }
  91. wrap<T extends Function>(fn: T): T {
  92. const id = this.current;
  93. const wrappedFn = (...args: any[]) => {
  94. if (this.current === id) {
  95. return fn(...args);
  96. }
  97. };
  98. return wrappedFn as any as T;
  99. }
  100. }
  101. }