Source: smallShowCard.js

/**
 * File Header: smallShowCard.js
 * 
 * Creates the class for the small show card and exports two functions
 * to be used in the calculation of the number of watched episodes and the number of
 * total episodes
 */

/**
 * Class Header: smallShowCard
 * 
 * A small show card that previews information about show on the user's watch list
 * Displays the show title, an image, and the progress the user made in the show
 * 
 * set data() - sets the show card data with the information provided from the data object
 * get data() - returns the show card's data
 */
 export default class smallShowCard extends HTMLElement {
    /**
     * Construct a smallShowCard element
     * @constructor
     */
    constructor() {
        super();

        let shadow = this.attachShadow({ mode: "open" });
        let article = document.createElement('article');
        let style = document.createElement('style');

        style.textContent = `
        * {
          font-family: sans-serif;
          margin: 0px;
          padding: 0px;
          background:#FFFFFF;
        }
      
        a {
          top: 10px;
          text-align: center;
          color: black;
          font-size: 22px;
          text-decoration: none;
        }
      
        a:hover {
          color: blue;
        }
      
        article {
          border: 1px solid rgb(223, 225, 229);
          border-radius: 5px;
          display: flex;
          grid-template-rows: 118px 56px 14px 18px 15px 36px;
          justify-content: space-between;
          height: 150px;
          width: 500px;
          margin-top: 20px !important;
          margin-left: 20px !important;
          justify-content: flex-end;
          position:static;
          box-shadow: 0 4px 8px 0 rgba(0,0,0,0.5);
        }

        article:hover {
          box-shadow: 0 8px 16px 0 rgba(0,0,0,0.7);
        }
      
        div.rating {
          align-items: center;
          column-gap: 5px;
          display: flex;
        }
      
        div.rating>img {
          height: 100%;
          /*display: inline-block;*/
          object-fit: scale-down;
          width: 78px;
          margin-top: 5px;
        }

        .modification {
          padding-right: 0px;
          margin-top: 0px;
        }

        .modification img {
          height: 10%;
          object-fit: contain;
          width: 15px;
          margin-right: 0px;
        }

        article>img {
          object-fit: contain;
          height: 50%;
          width: auto;
          margin-top: auto;
          margin-bottom:auto;
          flex: 1;
        }

        .show-info {
          display: flex;
          flex-direction: column;
          margin-right: 0px;
          padding-left: 10px;
          padding-top: 20px;
          justify-content:flex-start;
          flex: 2;
        }

        div.modification {
          padding-right: 5px;
        }

        p.title {
          display: -webkit-box;
          font-size: 16px;
          height: 36px;
          line-height: 18px;
          overflow: hidden;
          -webkit-line-clamp: 2;
          -webkit-box-orient: vertical;
        }
      
        p:not(.title),
        span,
        .seasons {
          color: #70757A;
          font-size: 12px;
          position:relative; 
          top: -15px;
        }

        time {
          flex: 1;
          color: #70757A;
          font-size: 12px;
        }
        
        progress[value]::-webkit-progress-bar {
          box-shadow: 0 2px 5px rgba(0, 0, 0, 0.25) inset;
          width: 100%;
          height: 8px;
          margin-top:10px;
        }

        `;



        shadow.append(article);
        shadow.append(style);
    }

    /**
     * Called when the .data property is set on this element
     * 
     * For example:
     * let smallShowCard = document.createElement('small-show-card'); // Calls constructor()
     * smallShowCard.data = { foo: 'bar' } // Calls set data({ foo: 'bar' })
     * 
     * expandedShowCard and smallShowCard get data from same data object, smallShowCard just uses part of the data
     * 
     * @function
     * @param {Object} data - The data to pass into the <small-show-card>, must be of the following format:
     *                        {
     *                            "episodeArray": 2D array of booleans representing episodes per season and whether they have been watched
     *                            "imgSrc" : "string"
     *                            "imgAlt" : "string"
     *                            "movie" : boolean representing whether or not item is a move
     *                            "showTitle" : "string"
     *                            "rating" : number
     *                            "review" : "string"
     *                            "id" : num representing place in local storage
     *                        }
     */
    set data(data) {
        // if no data, return
        if (!data) return;

        this.json = data; // Store the data passed in for later

        const shadowDom = this.shadowRoot;
        let article = shadowDom.querySelector('article');

        let watched = episodesWatched(data.episodeArray);
        let total = totalepisodeNum(data.episodeArray);

        article.innerHTML =`<img src="${data['imgSrc']}"
                                  alt="showSrc">
                            <div class="show-info">
                              <p class="title">
                                  <a href="./assets/pages/movie-show-subpage.html?ind=${data['id']}" id="expandedLink">
                                      ${data['showTitle']}
                                  </a>
                              </p>
                              <div class="rating">
                                  <img src="./assets/img/icons/${data['rating']}-star.svg" alt="${data['rating']} stars">
                              </div>
                              <label for="progress"></label>
                              <progress id="progress" value="${watched}" max="${total}"> 32% </progress>
                              <time>${watched} watched / ${total} total</time>
                              <p class="season"> ${data['episodeArray'].length} Season(s) Total </p>
                            </div>
                            
                            <div class="modification">
                              <a href="./assets/pages/add-content.html?ind=${data['id']}" id="editLink">
                                <img src="./assets/img/icons/Edit.svg" alt="edit">
                              </a>
                            </div>`;                            
    }

    /**
     * Returns the data set to the show card
     * 
     * @function
     * @return {Object} - small show card's data
     */
    get data() {
      return this.json;
    }
}

/**
 * Exports a function that returns the total number of episodes stored in the
 * episodeArray in data
 * 
 * @function
 * @param {*} episodeArray The 2D boolean array that stores the watch value of all episodes
 * @returns The number of episodes stored in the episodeArray
 */
export function totalepisodeNum(episodeArray){
  let sum = 0;
  for(let i = 0; i < episodeArray.length; i++){
    sum += episodeArray[i].length;
  } 
  return sum;
}

/**
 * Exports a function that returns the total number of episodes with a watch
 * value of true
 * 
 * @function
 * @param {*} episodeArray The 2D boolean array that stores the watch value of all episodes
 * @returns The number of watched episodes for the given show
 */
export function episodesWatched(episodeArray){
  let sum = 0;
  for(let i = 0; i < episodeArray.length; i++){
    for(let j = 0; j < episodeArray[i].length; j++){
      if(episodeArray[i][j]){
        sum += 1;
      }
    }
  }
  return sum;
}

customElements.define("small-show-card", smallShowCard);