toasters.js 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. document.body.style.backgroundColor = "#eee";
  2. const container = document.getElementById("toasts-content");
  3. let incrementer = 0;
  4. export default class Toast {
  5. // should add type checking
  6. constructor({ content, persistant, timeout }) {
  7. this.identifier = `toast-${incrementer}`;
  8. incrementer++;
  9. this.visible = false;
  10. this.content = content;
  11. this.persistant = persistant;
  12. this.timeout = timeout;
  13. if (!this.persistant) this.startTimer();
  14. this.dragListener();
  15. }
  16. get content() {
  17. return this._content;
  18. }
  19. set content(value) {
  20. this._content = value;
  21. this.display();
  22. }
  23. startTimer() {
  24. setTimeout(this.clear.bind(this), this.timeout);
  25. }
  26. display() {
  27. if (!this.visible) {
  28. container.insertAdjacentHTML("beforeend", `<div class="toast ${this.identifier}">${this.content}</div>`);
  29. this.find();
  30. } else
  31. this.element.innerHTML = this.content;
  32. this.visible = true;
  33. }
  34. dragListener() {
  35. /** handles mouse drag **/
  36. this.element.addEventListener("mousedown", event => {
  37. const initialX = this.element.getBoundingClientRect().x;
  38. let shiftX = event.clientX - initialX;
  39. const move = ({ pageX }) => {
  40. let opacity = 1.2 - Math.abs(pageX - shiftX - initialX) / 100;
  41. this.element.style.opacity = opacity;
  42. this.element.style.left = `${pageX - shiftX - initialX}px`;
  43. }
  44. window.addEventListener("mousemove", move, false);
  45. window.addEventListener("mouseup", () => {
  46. this.handleInputLoss();
  47. window.removeEventListener("mousemove", move, false);
  48. }, false);
  49. }, false);
  50. /** handles touch devices **/
  51. this.element.addEventListener("touchstart", event => {
  52. const initialX = this.element.getBoundingClientRect().x;
  53. let shiftX = event.touches[0].clientX - initialX;
  54. const move = ({ touches }) => {
  55. // if multiple touches on device, none are registered to the toast anymore
  56. if (touches.length === 1) {
  57. let pageX = touches[0].pageX
  58. let opacity = 1.2 - Math.abs(pageX - shiftX - initialX) / 100;
  59. this.element.style.opacity = opacity;
  60. this.element.style.left = `${pageX - shiftX - initialX}px`;
  61. }
  62. }
  63. window.addEventListener("touchmove", move, false);
  64. window.addEventListener("touchend", () => {
  65. this.handleInputLoss();
  66. window.removeEventListener("touchmove", move, false);
  67. }, false);
  68. }, false);
  69. }
  70. handleInputLoss() {
  71. if (this.element.style.opacity < 0.15) return this.clear();
  72. else {
  73. this.element.style.opacity = 1;
  74. this.element.style.left = 0;
  75. this.element.style.transition = "opacity .2s linear, left .2s linear";
  76. setTimeout(() => {
  77. this.element.style.transition = null;
  78. }, 200)
  79. }
  80. }
  81. find() {
  82. for (let i = 0; i < container.childNodes.length; i++)
  83. if (container.childNodes[i].classList.contains(this.identifier))
  84. return this.element = container.childNodes[i];
  85. }
  86. clear() {
  87. this.element.remove();
  88. }
  89. }