Skip to content

Instantly share code, notes, and snippets.

@tomhodgins
Last active July 23, 2020 23:59
Show Gist options
  • Save tomhodgins/a64a6d0913c01af00395f5951a5d0597 to your computer and use it in GitHub Desktop.
Save tomhodgins/a64a6d0913c01af00395f5951a5d0597 to your computer and use it in GitHub Desktop.
<!DOCTYPE html>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Star Rating Element</title>
<script type=module>
import StarRating from './star-rating-element.js'
customElements.define('star-rating', StarRating)
</script>
<style>
star-rating {
display: flex;
align-items: center;
}
star-rating svg {
width: 1em;
height: 1em;
}
</style>
<h1>Star Rating</h1>
<h2>Empty</h2>
<star-rating></star-rating>
<h2>No number</h2>
<star-rating stars></star-rating>
<h2>0 Stars</h2>
<star-rating stars=0></star-rating>
<h2>1 Stars</h2>
<star-rating stars=1></star-rating>
<h2>2 Stars</h2>
<star-rating stars=2></star-rating>
<h2>3 Stars</h2>
<star-rating stars=3></star-rating>
<h2>4 Stars</h2>
<star-rating stars=4></star-rating>
<h2>5 Stars</h2>
<star-rating stars=5></star-rating>
<h2>Default Content</h2>
<star-rating stars=5>five star</star-rating>
<h2>Out of Range Negative Number</h2>
<star-rating stars=-1></star-rating>
<h2>Out of Range Positive Number</h2>
<star-rating stars=6 ></star-rating>
<h2>Invalid input</h2>
<star-rating stars=five></star-rating>
import xml from 'https://v2.crocdn.com/_plugins/xml.js'
export default class StarRating extends HTMLElement {
constructor() {
super()
this.stars = 0
}
connectedCallback() {
this.populateStars()
}
populateStars() {
const empty = xml`
<svg aria-hidden="true" focusable="false" data-prefix="far" data-icon="star" class="svg-inline--fa fa-star fa-w-18" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><path fill="currentColor" d="M528.1 171.5L382 150.2 316.7 17.8c-11.7-23.6-45.6-23.9-57.4 0L194 150.2 47.9 171.5c-26.2 3.8-36.7 36.1-17.7 54.6l105.7 103-25 145.5c-4.5 26.3 23.2 46 46.4 33.7L288 439.6l130.7 68.7c23.2 12.2 50.9-7.4 46.4-33.7l-25-145.5 105.7-103c19-18.5 8.5-50.8-17.7-54.6zM388.6 312.3l23.7 138.4L288 385.4l-124.3 65.3 23.7-138.4-100.6-98 139-20.2 62.2-126 62.2 126 139 20.2-100.6 98z"></path></svg>
`
const filled = xml`
<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="star" class="svg-inline--fa fa-star fa-w-18" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><path fill="currentColor" d="M259.3 17.8L194 150.2 47.9 171.5c-26.2 3.8-36.7 36.1-17.7 54.6l105.7 103-25 145.5c-4.5 26.3 23.2 46 46.4 33.7L288 439.6l130.7 68.7c23.2 12.2 50.9-7.4 46.4-33.7l-25-145.5 105.7-103c19-18.5 8.5-50.8-17.7-54.6L382 150.2 316.7 17.8c-11.7-23.6-45.6-23.9-57.4 0z"></path></svg>
`
this.innerHTML = ''
this.append(
...new Array(5).fill('').map((slot, index) =>
(
this.stars <= index
? empty
: filled
).cloneNode(true)
)
)
}
static get observedAttributes() {
return [
'stars'
]
}
attributeChangedCallback(name, oldValue, newValue) {
if (
name === 'stars'
&& newValue !== oldValue
&& isNaN(newValue) === false
) {
this.stars = newValue
this.populateStars()
}
}
clampedNumber(integer = 0) {
return Math.min(Math.max(0, Math.round(Number(integer) || 0)), 5)
}
// stars=5
get stars() {
return this.clampedNumber(this.getAttribute('stars'))
}
set stars(integer = 0) {
return this.setAttribute('stars', this.clampedNumber(integer))
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment