products-carousel.js 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. ---
  2. ---
  3. // Used to confuse an IDE and not highlight everything in red because of the front matter
  4. console.log("");
  5. let margin = parseInt(window.getComputedStyle(document.documentElement).getPropertyValue("--margin"))
  6. class ProductsCarousel extends HTMLElement {
  7. getScrollDelta(pane) {
  8. return pane.querySelector(".card").offsetWidth + margin * 2
  9. }
  10. constructor() {
  11. super()
  12. this.innerHTML = `
  13. <div class="carousel">
  14. <div class="header horizontally-centered top-level-card">
  15. <button id="arrow-left" class="arrow rounded-shadow hover-reactive">
  16. <img src="/assets/navigation-left.png" alt="Arrow Left"/>
  17. </button>
  18. <button id="arrow-right" class="arrow rounded-shadow hover-reactive">
  19. <img src="/assets/navigation-right.png" alt="Arrow Right"/>
  20. </button>
  21. <h1>Products</h1>
  22. <div class="badge">
  23. {{ site.products.size }}<span> in total</span>
  24. </div>
  25. </div>
  26. <div id="carousel-pane"
  27. class="horizontally-centered top-level-card no-url-highlighting"
  28. data-current-entry="0"
  29. data-entry-count="{{ site.products.size }}"
  30. >
  31. {% assign sorted_products = site.products | sort: "latest_release" %}
  32. {% for product in sorted_products reversed %}
  33. <div class="container-wrapper">
  34. <a class="card rounded-shadow hover-reactive container" href="{{ product.url }}">
  35. <div class="icon" style='background-image: url("{{ product.icon }}")'></div>
  36. <div class="name">{{ product.name }}</div>
  37. <div class="description">{{ product.description | markdownify }}</div>
  38. <div id="icon-container">
  39. {% for source in product.sources %}
  40. {% assign splitted_source = source | split: " | " %}
  41. {% assign type = splitted_source.first | strip %}
  42. {% assign slugged_name = type | downcase | slugify: "pretty" %}
  43. <div class="source-badge" data-type="{{ slugged_name }}">
  44. <img src="{{ "/assets/icon-" | append: slugged_name | append: ".png" }}"
  45. alt="{{ slugged_name }}"
  46. />
  47. </div>
  48. {% endfor %}
  49. </div>
  50. </a>
  51. </div>
  52. {% endfor %}
  53. </div>
  54. </div>
  55. `
  56. let pane = this.querySelector("#carousel-pane")
  57. let cards = this.querySelectorAll(".card")
  58. let greatestHeight = 0
  59. for (let cardIndex = 1; cardIndex <= cards.length; cardIndex++) {
  60. let styleElement = document.createElement("style")
  61. styleElement.innerText = `
  62. .container-wrapper:nth-child(${cardIndex}) {
  63. position: relative;
  64. animation-name: card-appearance;
  65. animation-duration: 1s;
  66. transform: translate(${500 * cardIndex}px, ${35 * cardIndex}px);
  67. animation-timing-function: ease;
  68. animation-fill-mode: forwards;
  69. }
  70. `
  71. this.appendChild(styleElement)
  72. let height = cards[cardIndex - 1].offsetHeight
  73. if (height > greatestHeight)
  74. greatestHeight = height
  75. }
  76. for (let index = 0; index < cards.length; index++)
  77. cards[index].style.height = greatestHeight - margin * 2 + 'px'
  78. let arrowRight = this.querySelector("#arrow-right")
  79. arrowRight.addEventListener("click", (event) => {
  80. let currentEntry = parseInt(pane.dataset.currentEntry) + 1
  81. if (currentEntry >= cards.length)
  82. currentEntry = 0
  83. pane.dataset.currentEntry = currentEntry.toString()
  84. pane.style.transform = "translateX(" + currentEntry * -this.getScrollDelta(pane) + "px)"
  85. })
  86. let arrowLeft = this.querySelector("#arrow-left")
  87. arrowLeft.addEventListener("click", (event) => {
  88. let currentEntry = parseInt(pane.dataset.currentEntry) - 1
  89. if (currentEntry < 0)
  90. currentEntry = cards.length - 1
  91. pane.dataset.currentEntry = currentEntry.toString()
  92. pane.style.transform = "translateX(" + currentEntry * -this.getScrollDelta(pane) + "px)"
  93. })
  94. }
  95. }
  96. customElements.define("products-carousel", ProductsCarousel)