Replace Divs With Custom Elements For Superior Markup without JS and prevent hell "Divs"

artydev - Apr 30 '23 - - Dev Community

A nice article Matthew James Taylor.

Here is an example CustomElement:


import { MVU } from "./mvu.js"
const {html} = MVU;

let productTemplate = (num, data) => html` 
  <a-product data-opened="false">  
    <product-title>
      Product order ${num} 
    </product-title>
    <product-content>
      <product-description>
        ${data.description}
      </product-description>
      <img src=${data.thumbnail} />
    </product-content> 
  </a-product>
`

let catalog = document.querySelector("the-catalog")
catalog.addEventListener("click", (e) =>  { 
  let target = e.target.parentNode
  let status = target.dataset.opened
  target.dataset.opened = status == "true" ? "false" : "true" 
}) 

function getRandomInt(max) {
  return Math.floor(Math.random() * max); 
}

let button = document.querySelector("button.adder")  
button.onclick = () =>   { 
  button.innerText = "loading..."
  fetch(`https://dummyjson.com/products/${getRandomInt(100)}`) 
    .then(res => res.json())
    .then(json =>  { 
      let num_product = Number(catalog.dataset.numarticles) + 1
      catalog.dataset.numarticles = num_product 
      catalog.appendChild(productTemplate(num_product, json)) 
      button.innerText = "Add new article"
  })
} 

let btnclose =  document.querySelector("button.closer")  
btnclose.onclick = () => {
  Array.from(catalog.childNodes).forEach(elt => {
      if (elt.tagName == "SPAN")  {
         (elt.querySelector("a-product").dataset.opened = "false")
      }
  })
}
Enter fullscreen mode Exit fullscreen mode
body {
  background: #122439;
}

a-product {
  font-family: "Segoe UI";
  font-weight: bold;
  display:block; 
  cursor:pointer;
  width:600px;
  display:block;
}

a-product[data-opened="false"]  product-title ~ product-content {
  display:none;
}

a-product[data-opened="true"]  product-title ~ product-content {
  display:block;
  margin-left: 50px;
}

product-description {
  display:block;
  margin-bottom:20px;
  color:white;
}

product-title {
  display:block;
  color:red;
  margin:20px
}

img {
  width: 200px;
  border: 1px solid white;
  padding:5px;
}
Enter fullscreen mode Exit fullscreen mode
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .