/ Gists / Web components

Gists - Web components

On gists

Convert Vue component to Web component

Web components Vue.js

HelloWorld.ce.vue #

<!-- ce je jen interni oznaceni ze to bude custom element = web component -->
<script setup>
defineProps({
  msg: {
    type: String,
    required: true,
    default: 'AAA'
  }
})
</script>

<template>
  <div>{{ msg }}</div>
</template>

<style scoped>
h1 {
  font-weight: 500;
  font-size: 2.6rem;
  position: relative;
  top: -10px;
}

h3 {
  font-size: 1.2rem;
}

.greetings h1,
.greetings h3 {
  text-align: center;
}

@media (min-width: 1024px) {
  .greetings h1,
  .greetings h3 {
    text-align: left;
  }
}
</style>

On gists

My demo component

Web components

index.html #

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>JS Bin</title>
</head>
<body>

	<!--
	https://jsbin.com/tupofihode/1/edit?html,css,js,output
	-->
	       <pan-kokot name="Ondrej Stanček" skills="Umí to tavit s HTP stejně jako s V6, odborník na CMS modul parametry">
	       Kdo nemá plyn na podlaze nikdy nejedl Vindalo
	       </pan-kokot>

	
</body>
</html>

On gists

Has (:has selector)

CSS Web components CSS trick

hover-group.css #

/*

https://www.matuzo.at/blog/2022/100daysof-day50/

*/

table:has(input:focus) tr:not(:focus-within) {
	opacity: 0.1;
}

/* siblings but not me */
.gallery:has(img:hover) > img:not(:hover) {
  /* rule */
}


/* has both, video + h2 */
post:has(h2):has(video) {
	
}


/* has video or h2 or both*/
post:has(h2, video) {
	
}


/* has only video */
post:has(video) {
	
}

/* has not video
do not use!!!  post:has(:not(video)  # post that has any element that is not a video
*/
post:not(:has(video)) {

}


/* previous element */
span:has(+ post) {
	color: red;
}

/* more or equals 4 children = quantity query */
post:has(> *:nth-child(4n)) {

}


/*
https://jsbin.com/mafuhoquka/edit?html,css,output

<article>
		<div>1</div>
		<div>2</div>
		<div>3</div>
		<div>4</div>
		<div>5</div>
		<div>6</div>
		<div>7</div>
		<div>8</div>
		<div>9</div>
		<div>10</div>
</div>

/* prev */
article div:has(+ :hover) {
	background: pink;
}

/* next */
article div:hover + div {
	background: lime;
}


/* prev all */
article div:has(~ :hover) {
	background: pink;
}

/* next all */
article div:hover ~ div {
	background: lime;
}

/* https://bejamas.io/blog/learn-css-has-selector-by-examples-top-use-cases/ */
/* At most 3 (3 or less, excluding 0) children */
ul:has(> :nth-child(-n+3):last-child) {
	outline: 1px solid red;
}

/* At most 3 (3 or less, including 0) children */
ul:not(:has(> :nth-child(3))) {
	outline: 1px solid red;
}

/* Exactly 5 children */
ul:has(> :nth-child(5):last-child) {
	outline: 1px solid blue;
}

/* At least 10 (10 or more) children */
ul:has(> :nth-child(10)) {
	outline: 1px solid green;
}

/* Between 7 and 9 children (boundaries inclusive) */
ul:has(> :nth-child(7)):has(> :nth-child(-n+9):last-child) {
	outline: 1px solid yellow;
}



/* ranges */
/*
<div>
  <h2>Start Title (First line green, last line red)</h2>
  <p>First line between h2</p>
  <h4>Second line between h2</h4>
  <h5>Last line between h2</h5>
  <h2>End Title</h2>
</div>
*/

/* Select the first line between h2 */
h2 + :has(~ h2) {
  color: green;
}

/* Select the last line between h2 */
h2 ~ :has(+ h2) {
  color: red;
}
/* Select all lines between h2 */
h2 ~ :has(~ h2) {
  font-style: italic;
}



/* 'And' operation: selects <p> elements containing both class 'a' and 'b' children */
p:has(.a):has(.b) {
  font-weight: bold;
}

/* 'Or' operation: selects <p> elements containing either class 'a' or 'b' children */
p:has(.a, .b) {
  font-style: italic;
}


/* Select all parent elements containing a <p> element */
:has(p) {
  background-color: lightblue;
}

/* Select parent elements with a direct child <p> element */
:has(> p) {
  border: 1px solid red;
}
/* Select <div> elements with a direct child <p> element */
div:has(> p) {
  padding: 10px;
}
/* Select the adjacent previous <div> sibling of a <p> element */
div:has(+ p) {
  margin-bottom: 20px;
}
/* Select all previous <div> siblings of a <p> element */
div:has(~ p) {
  color: green;
}

On gists

Web component

JavaScript Web components

calendar.js #

class AmbiCalendar extends HTMLElement
{
    constructor()
    {
      super();
      this.shadow = this.attachShadow({ mode: "open"});
    }

    connectedCallback()
    {
      this.render(true, []);

      fetch('/api/v1/dk_workshop_date?filters[dk_voucher_id]=' + this.getAttribute('voucherId'))
      .then((response) => {
        if (response.ok) {
          return response.json();
        } else {
          return Promise.reject(response);
        }

      }).then((data) => {
        this.render(false, data);
      }).catch(function (err) {
        // There was an error
        console.warn('Something went wrong.', err);
      });
    }

    render(loading, data)
    {
      let body = '';

      if (loading) {
        body = '<div>loading...</div>';
      } else {
        data.map((item) => {
          body += `<li>${item.date_from} - ${item.date_to}</li>`;
        });
      }

      this.shadow.innerHTML = `
        <h1>Ambi calendar</h1>
        <lu>
            ${body}
        </lu>
      `;
    }
}

customElements.define('ambi-calendar', AmbiCalendar);