liveBook · Manning

Wcia-photo-carousel

As explained in Web Components in Action

A book-specific custom HTML element representing a photo carousel with album metadata, photo URLs, and navigation controls.

wcia-photo-carousel is a custom HTML element for displaying an album title, author, photo list, current image, and back/forward controls. section 2.6

Configure the element through attributes and implement it with a small HTMLElement subclass:

  • Pass title, author, and comma-separated photo URLs as HTML attributes. section 2.6
  • Register the tag with customElements.define and initialize it in connectedCallback. section 2.6
  • Render the heading, image container, and navigation buttons with innerHTML. section 2.6
  • Track the current photo index, display its URL, and wrap navigation at both ends. section 2.6

Using the carousel

<wcia-photo-carousel title="Future Vacation Photos" author="Ben Farrell" photos="images/fBmIASF.jpg,images/3zxD6rz.jpg,images/nKBgeLOr.jpg,images/yVjJZ1Yr.jpg"></wcia-photo-carousel> section 2.6

Listing 2.15. Demo code recap
<html>
<head>
    <title>Photo Carousel</title>
    <script>
        class PhotoCarousel extends HTMLElement {                           #1
            connectedCallback() {
                this._photoIndex = 0;
                this._photos = this.getAttribute('photos').split(',');

                this.innerHTML = '<h2>'+ this.getAttribute('title') + '</h2>' +
                    '<h4>by '+ this.getAttribute('author') + '</h4>' +
                    '<div class="image-container"></div>' +
                    '<button class="back">&lt</button>' +
                    '<button class="forward">                               #2
                       &gt
                     </button>';

                this.showPhoto();

                this.querySelector('button.back').addEventListener('click',#3
                   event => this.onBackButtonClick(event));

                this.querySelector('button.forward').addEventListener('click',
                   event =>
                this.onForwardButtonClick(event));
            }
            /**
             * handler for when user clicks the back button
             * @param event
             */
            onBackButtonClick(event) {                                     #4
                this._photoIndex --;
                if (this._photoIndex < 0) {
                    this._photoIndex = this._photos.length-1;
                }
                this.showPhoto();

            }

            /**
             * handler for when user clicks the forward button
             * @param event
             */
            onForwardButtonClick(event) {                                  #5
                this._photoIndex ++;
                if (this._photoIndex >= this._photos.length) {
                    this._photoIndex = 0;
                }
                this.showPhoto();
            }

            showPhoto() {                                                  #6
                this.querySelector('.image-container').style.backgroundImage
                  = 'url(' + this._photos[this._photoIndex] + ')';
            }
        }

        if (!customElements.get(                                           #7
          'wcia-photo-carousel')) {
            customElements.define('wcia-photo-carousel', PhotoCarousel);
        }

    </script>

    <style>                                                                #8
        wcia-photo-carousel {
            position: relative;
            width: 500px;
            height: 300px;
            display: flex;
            padding-top: 10px;
            flex-direction: column;
            border-color: black;
            border-width: 1px;
            border-style: solid;
        }

        wcia-photo-carousel h2, h4 {
            margin-bottom: 0;
            margin-top: 0;
            margin-left: 10px;
        }
        wcia-photo-carousel .image-container {
            margin-top: 15px;
            flex: 1;
            background-color: black;
            background-size: contain;
            background-repeat: no-repeat;
            background-position: 50%;
        }

        wcia-photo-carousel button {
            cursor: pointer;
            background: transparent;
            border: none;
            font-size: 48px;
            color: white;
            position: absolute;
            top: 50%;
        }

        wcia-photo-carousel button.back {
            left: 10px;
        }

        wcia-photo-carousel button.forward {
            right: 10px;
        }

    </style>

</head>
    <body>
        <wcia-photo-carousel                                               #9
                title="Future Vacation Photos"
                author="Ben Farrell"
                photos="images/fBmIASF.jpg,images/3zxD6rz.jpg,images/
                nKBgeLOr.jpg,images/yVjJZ1Yr.jpg">
        </wcia-photo-carousel>
    </body>
</html>

Browse the complete demo recap, including registration, rendering, image display, and button listeners. section 2.6

How Web Components in Action covers it

How deep it goes
Builds the component incrementally from markup through registration, rendering, styling, and wrapped click navigation.
Examples
Uses an album element with title, author, comma-separated image paths, an image container, and back/forward buttons.
What you can do after
Build it from scratch as a browser custom element with configurable metadata, image display, styling, and cyclic navigation.
How it connects
Connects custom elements with HTMLElement subclasses, lifecycle callbacks, DOM queries, event listeners, CSS, and HTML attributes.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Web Components in Action. The section links point to the parts of the book it draws on.