/**
* File Header: expandedMovieCard.js
*
* Creates the class for the expanded movie card
*/
/**
* Class Header: expandedMovieCard
*
* When clicking on a small movie card, it expands and shows more detailed information about the show
* Displays the movie title, image, progress, rating, and comments
*
*
* data() - sets the movie card data with the information provided from the data object
*/
//importing functions from tools.js
import {getShowsFromStorage} from './tools.js';
import {saveShowsToStorage} from './tools.js';
//this variable is used to get the current card's id
var currentInd;
export default class expandedMovieCard extends HTMLElement {
/**
* Construct a expandedMovieCard element
* @constructor
*/
constructor() {
super();
let shadow = this.attachShadow({ mode: "open"});
let article = document.createElement('article');
let style = document.createElement('style');
style.innerHTML = `
#outerbox {
background-color: rgb(1, 107, 112);
padding: 0em 2em 1em 2em;
margin: auto;
resize: none;
width: 96.65vw;
height: 98.3vh;
}
#homebutton {
border: 0;
background-color: rgb(1, 107, 112);
float: right;
margin-right: 0.5em;
}
.topmovieheader {
background-color: rgb(1, 107, 112);
display: flex;
justify-content: space-between;
width: 100%;
font-family: Arial;
color: white;
height: 3em;
}
.half{
display: flex;
align-items: center;
justify-content: space-between;
}
#movieheader {
color: white;
margin-left: 1em;
}
#innerbox {
background-color: rgb(17, 151, 157);
padding: 0.7em 0.7em 0.7em 0.7em;
}
#movieandinfo {
display: flex;
}
#info {
margin-left: 0.7em;
width: 100%;
}
#titleandbuttons {
display: flex;
align-items: center;
justify-content: space-between;
height: 2.5em;
width: 100%;
}
#titleandbuttons p {
display: inline;
height: 2.5em;
line-height: 2.5em;
font-family: 'Oswald', sans-serif;
color: white;
font-size: 1.75em;
margin: 0;
}
#titleandbuttons button {
display: inline;
margin-left: 0.6em;
border: 0;
background-color: rgb(17, 151, 157);
}
.rating {
height: 2.5em;
line-height: 2.5em;
font-family: 'Oswald', sans-serif;
color: white;
font-size: 1.75em;
}
.comments {
height: 2.4em;
line-height: 1.6em;
font-family: 'Oswald', sans-serif;
color: white;
font-size: 1.75em;
}
#commentArea {
width: 100%;
height: 50%;
resize: vertical;
}
#progressheader, #slideVal {
font-family: 'Oswald', sans-serif;
margin-top: 0.3em;
margin-bottom: 0em;
color: white;
font-weight: normal;
font-size: 1.75em;
}
input[type="range"]{
margin: auto;
-webkit-appearance: none;
position: relative;
overflow: hidden;
height: 2%;
width: 100%;
cursor: pointer;
border-radius: 0;
border: 2px solid #999;
}
::-webkit-slider-runnable-track{
background: white;
}
::-webkit-slider-thumb {
-webkit-appearance: none;
width: 20px;
height: 40px;
background: (17, 151, 157);
box-shadow: -1000px 0 0 1000px rgb(30, 235, 54);
border: 2px solid #999;
}
`;
shadow.append(article);
shadow.append(style);
}
/**
* Called when the .data property is set on this element
*
* For example:
* let expandedMovieCard = document.createElement('expanded-movie-card'); // Calls constructor()
* expandedMovieCard.data = { foo: 'bar' } // Calls set data({ foo: 'bar' })
*
* expandedMovieCard and smallMovieCard get data from same data object, smallMovieCard just uses part of the data
* expandedMovieCard theoretically can just take a copy of the data object in the smallMovieCard
*
* @function
* @param {Object} data - The data to pass into the <expanded-movie-card>, must be of the following format:
* {
* "movieName" : "string"
* "movieFar" : "string"
* "movieTime" : "string"
* "imgSrc" : "string"
* "imgAlt" : "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;
const shadowDom = this.shadowRoot;
update(data, shadowDom);
}
get data() {
return this.json;
}
}
/**
*
* @param {*} data data passed in to expandedShowCard
* @param {*} shadowDom shadowDom associated with current object
*
* This function gets the article associated with the shadow and then calls innerHTML on it
* The generation will create the page with a progress bar representing true or false on if the
* episode is watched or not
*
* Then, createActionListeners is called to generate listerners for the buttons created
*
*/
export function update(data, shadowDom){
let article = shadowDom.querySelector('article');
article.innerHTML = generatedInnerHTML(data);
CreateActionListeners(data, shadowDom);
currentInd = data.id;
}
/**
*
* @param {*} data data passed in to expandedShowCard
* @param {*} shadowDom shadowDom associated with current object
*
* Creates action listener for the trash button
*/
export function CreateActionListeners(data, shadowDom) {
/**
* Sets action listener for the trash button, which lets you delete only
* the current entry
*
* When you confirm the deletion, you are immediately redirected to the home page
* The entry is deleted from localStorage, and all ids for the remaining cards are updated
* to be continuous
* Then they are saved to localStorage again
*/
let editbutton = shadowDom.getElementById("editbutton");
editbutton.addEventListener('click', () => {
window.location.href = `./add-content.html?ind=${data['id']}`;
});
let trashButton = shadowDom.getElementById("trashbutton");
trashButton.addEventListener("click", function() {
if(true/*confirm("Are you sure you want to delete this entry?")*/) {
let ind = currentInd;
let cards = getShowsFromStorage();
//edge case if there's only one show right now
if(cards.length == 1) {
localStorage.removeItem('shows');
window.location.href = '../../index.html';
return;
}
//removes current entry
cards.splice(ind, 1);
//after you splice the cards, you must update the ids for each
for(let i = 0; i < cards.length; i++) {
cards[i].id = i;
}
//saves the new array (without the deleted entry) to localStorage
saveShowsToStorage(cards);
//redirects you to the home page
window.location.href = '../../index.html';
}
else {
return;
}
;});
let cards = getShowsFromStorage();
let progressSlider = shadowDom.getElementById('myRange');
progressSlider.addEventListener('change', () => {
data.movieFar = progressSlider.value;
cards[data.id] = data;
// update local storage
saveShowsToStorage(cards);
});
let progressVal = shadowDom.getElementById("slideVal");
progressSlider.oninput = function () {
progressVal.innerHTML = `${this.value}/${data.movieTime}`;
}
}
/**
*
* @param {*} data a reference to the movie data object
* @returns {string} string representing the innerHTML of the expandedMovieCard
*/
export function generatedInnerHTML(data){
if(data.imgSrc == "./assets/img/icons/bingetracker_logo.png"){
data.imgSrc = "../img/icons/bingetracker_logo.png";
}
let innerHTML =
`<div id="outerbox">
<div class="topmovieheader">
<div class="half"><h4 id="movieheader">Movie</h4></div>
<div class="half"><a href="../../index.html" id="homebuttonlink"><button id="homebutton">
<img height="35em" src="../img/icons/home.png"></img>
</button></a></div>
</div>
<div id="innerbox">
<div id="movieandinfo">
<img id="movieimage" src=${data.imgSrc} alt=${data.imgAlt} height="240 em">
<div id="info">
<div id="titleandbuttons">
<p class="title">Name: ${data.movieName}</p>
<div id="buttons">
<button id="editbutton">
<img height="27em" src="../img/icons/edit.png"></img>
</button>
<button id="trashbutton">
<img height="27em" src="../img/icons/trash.png">
</img>
</button>
</div>
</div>
<div class="rating">Rating: ${data.rating}/5</div>
<div class="comments">Comments:</div>
<textarea id="commentArea" disabled> ${data.review}</textarea>
</div>
</div>
<div>
<h2 id="progressheader">Progress: </h2>
<span id="slideVal"> ${data.movieFar}/${data.movieTime} </span> <br>
<input type="range" min="0" max=${data.movieTime} value=${data.movieFar} class="slider" id="myRange">
</div>
</div>`
return innerHTML;
}
customElements.define("expanded-movie-card", expandedMovieCard);