Skip to content

Commit 1a5bbfb

Browse files
committed
Slideshow as WebComponent
1 parent 0df7db0 commit 1a5bbfb

File tree

2 files changed

+186
-0
lines changed

2 files changed

+186
-0
lines changed

LinkDotNet.Blog.Web/Pages/_Host.cshtml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,5 +46,6 @@
4646
<script async src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.0.1/languages/csharp.min.js" integrity="sha512-2GO++5/u4InQ3/o7fLh93nyZIzTFl7fYi7+RjP7pgxsXikSCRf5jjw8U8vQSfCfFolN8G8xAxct9696uVxtQSg==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
4747
<script async src="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/js/all.min.js" integrity="sha512-RXf+QSDCUQs5uwRKaDoXt55jygZZm2V++WUZduaU/Ui/9EGp3f/2KZVahFZBKGH0s774sd3HmrhUy+SgOFQLVQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
4848
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script>
49+
<script async src="components/slideshow.js" ></script>
4950
</body>
5051
</html>
Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
const templateSlideshowContainer = document.createElement('template')
2+
templateSlideshowContainer.innerHTML = `
3+
<style>
4+
.slideshow-container {
5+
max-width: 1000px;
6+
position: relative;
7+
margin: auto;
8+
}
9+
10+
.mySlides {
11+
display: none;
12+
}
13+
14+
.prev, .next {
15+
cursor: pointer;
16+
position: absolute;
17+
top: 50%;
18+
width: auto;
19+
margin-top: -22px;
20+
padding: 16px;
21+
color: black;
22+
font-weight: bold;
23+
font-size: 18px;
24+
transition: 0.6s ease;
25+
border-radius: 0 3px 3px 0;
26+
user-select: none;
27+
background-color: rgba(0,0,0,0.4);
28+
}
29+
30+
.next {
31+
right: 0;
32+
border-radius: 3px 0 0 3px;
33+
}
34+
35+
.prev:hover, .next:hover {
36+
background-color: rgba(0,0,0,0.8);
37+
}
38+
39+
.text {
40+
color: var(--white);p
41+
font-size: 15px;
42+
padding: 8px 12px;
43+
position: absolute;
44+
bottom: 8px;
45+
width: 100%;
46+
text-align: center;
47+
}
48+
49+
.numbertext {
50+
color: var(--white);
51+
font-size: 12px;
52+
padding: 8px 12px;
53+
position: absolute;
54+
top: 0;
55+
}
56+
57+
.dot {
58+
cursor: pointer;
59+
height: 15px;
60+
width: 15px;
61+
margin: 0 2px;
62+
background-color: #bbb;
63+
border-radius: 50%;
64+
display: inline-block;
65+
transition: background-color 0.6s ease;
66+
}
67+
68+
.active, .dot:hover {
69+
background-color: #717171;
70+
}
71+
</style>
72+
73+
<div class="slideshow-container">
74+
<a class="prev" onclick="this.getRootNode().host.plusSlides(-1)">&#10094;</a>
75+
<a class="next" onclick="this.getRootNode().host.plusSlides(1)">&#10095;</a>
76+
</div>
77+
`
78+
79+
class Slideshow extends HTMLElement {
80+
slideIndex = 1
81+
82+
constructor() {
83+
super();
84+
85+
this.attachShadow({ mode: 'open' })
86+
87+
const elements = this.getSlideshowElements()
88+
const slideShowContainer = templateSlideshowContainer.content.cloneNode(true)
89+
const innerContainer = slideShowContainer.querySelector(".slideshow-container")
90+
const dotContainer = document.createElement("div")
91+
dotContainer.style = 'text-align: center'
92+
for (let i = 0; i < elements.length; i++) {
93+
const container = document.createElement("div")
94+
container.classList.add('mySlides')
95+
96+
const numberText = document.createElement("div")
97+
numberText.classList.add('numbertext')
98+
numberText.innerHTML = `${i + 1} / ${elements.length}`
99+
container.appendChild(numberText)
100+
101+
const image = document.createElement("img")
102+
image.src = elements[i].url
103+
image.style = 'width:100%'
104+
container.appendChild(image)
105+
106+
const text = document.createElement("div")
107+
text.classList.add("text")
108+
text.innerHTML = elements[i].title
109+
text.style.color = elements[i].color ?? 'black'
110+
container.appendChild(text)
111+
112+
innerContainer.appendChild(container)
113+
114+
const dot = document.createElement("span")
115+
dot.classList.add('dot')
116+
dot.addEventListener('click', () => this.showSlides(i + 1))
117+
dotContainer.appendChild(dot)
118+
}
119+
120+
slideShowContainer.appendChild(dotContainer)
121+
this.shadowRoot.appendChild(slideShowContainer)
122+
this.showSlides(1)
123+
}
124+
125+
getSlideshowElements() {
126+
const nodes = []
127+
128+
this.childNodes.forEach(node => {
129+
if (node.tagName !== 'SLIDE-SHOW-IMAGE') {
130+
return
131+
}
132+
133+
const imgUrl = node.getAttribute('src')
134+
const title = node.getAttribute('title')
135+
const color = node.getAttribute('color')
136+
137+
if (!imgUrl || !title) {
138+
return
139+
}
140+
141+
nodes.push({url: imgUrl, title: title, color: color})
142+
})
143+
144+
return nodes
145+
}
146+
147+
plusSlides(step) {
148+
this.showSlides(this.slideIndex + step);
149+
}
150+
151+
showSlides(newSlideIndex) {
152+
let i;
153+
const slides = this.shadowRoot.querySelectorAll(".mySlides");
154+
const dots = this.shadowRoot.querySelectorAll(".dot");
155+
if (newSlideIndex > slides.length) {
156+
this.slideIndex = 1
157+
}
158+
else if (newSlideIndex < 1) {
159+
this.slideIndex = slides.length
160+
}
161+
else {
162+
this.slideIndex = newSlideIndex
163+
}
164+
165+
166+
for (i = 0; i < slides.length; i++) {
167+
slides[i].style.display = "none";
168+
}
169+
170+
for (i = 0; i < dots.length; i++) {
171+
dots[i].className = dots[i].className.replace(" active", "");
172+
}
173+
slides[this.slideIndex - 1].style.display = "block";
174+
dots[this.slideIndex - 1].className += " active";
175+
}
176+
}
177+
178+
class SlideshowImage extends HTMLElement {
179+
constructor() {
180+
super();
181+
}
182+
}
183+
184+
customElements.define("slide-show", Slideshow)
185+
customElements.define("slide-show-image", SlideshowImage)

0 commit comments

Comments
 (0)