applet.js 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. import { dom_manager, type_manager } from "./functions.js";
  2. class applet_builder {
  3. #minimalise;
  4. #maximalise;
  5. #target;
  6. #animation;
  7. constructor() {
  8. this.#minimalise = undefined;
  9. this.#maximalise = undefined;
  10. this.#target = undefined;
  11. this.#animation = undefined;
  12. }
  13. set minimalise(target) {
  14. if (!dom_manager.is_element(target)) {
  15. throw "Minimalise button must be HTML element.";
  16. }
  17. this.#minimalise = target;
  18. }
  19. set maximalise(target) {
  20. if (!dom_manager.is_element(target)) {
  21. throw "Maximalise button must be HTML element.";
  22. }
  23. this.#maximalise = target;
  24. }
  25. set target(target) {
  26. if (!dom_manager.is_element(target)) {
  27. throw "Target must be HTML element.";
  28. }
  29. this.#target = target;
  30. }
  31. set animation(target) {
  32. if (!type_manager.is_function(target)) {
  33. throw "Animation must be an function.";
  34. }
  35. this.#animation = animation;
  36. }
  37. get is_valid() {
  38. if (this.#minimalise === undefined) {
  39. return false;
  40. }
  41. if (this.#maximalise === undefined) {
  42. return false;
  43. }
  44. if (this.#target === undefined) {
  45. return false;
  46. }
  47. return true;
  48. }
  49. get #is_swapable() {
  50. return this.#minimalise === this.#maximalise;
  51. }
  52. #build_swapable() {
  53. return new swapable_applet(
  54. this.#target,
  55. this.#minimalise,
  56. this.#animation
  57. );
  58. }
  59. build() {
  60. if (!this.is_valid) {
  61. throw "Builder is not valid yes.";
  62. }
  63. if (this.#is_swapable) {
  64. return this.#build_swapable();
  65. }
  66. }
  67. }
  68. class applet {
  69. _target;
  70. _animation;
  71. _state;
  72. get _has_animation() {
  73. return this._animation !== undefined;
  74. }
  75. _run_animation() {
  76. const time = this._animation(this._state, this._target);
  77. if (!isInteger(time)) {
  78. throw "Animation must return time which it cost in ms.";
  79. }
  80. return time;
  81. }
  82. show() {
  83. this._state = true;
  84. this._target.style.display = "";
  85. if (this._has_animation) {
  86. this._run_animation();
  87. }
  88. }
  89. hide(now) {
  90. this._state = false;
  91. if (now) {
  92. this._target.style.display = "none";
  93. return;
  94. }
  95. if (!this._has_animation) {
  96. this.hide(true);
  97. return;
  98. }
  99. setTimeout(() => { this.hide(true); }, this._run_animation());
  100. }
  101. }
  102. class swapable_applet extends applet {
  103. #swaper;
  104. constructor(target, swaper, animation) {
  105. super();
  106. if (!dom_manager.is_element(target)) {
  107. throw "Target must be HTML element.";
  108. }
  109. if (!dom_manager.is_element(swaper)) {
  110. throw "Swaper must be HTML element.";
  111. }
  112. if (animation !== undefined && !type_manager.is_function(animation)) {
  113. throw "Animation must be undefined (disabled), or function.";
  114. }
  115. this._target = target;
  116. this.#swaper = swaper;
  117. this._animation = animation;
  118. this._state = false;
  119. this.hide();
  120. this.#listen();
  121. }
  122. #listen() {
  123. this.#swaper.addEventListener("click", () => { this.swap(); });
  124. }
  125. swap() {
  126. if (this._state) {
  127. this.hide();
  128. } else {
  129. this.show();
  130. }
  131. }
  132. }
  133. export { applet_builder };