diff --git a/README.md b/README.md index 6de202be2..0a2857a21 100644 --- a/README.md +++ b/README.md @@ -25,22 +25,24 @@ ______________________________________________________ # Hang in There ### Abstract: -[//]: <> (Briefly describe what you built and its features. What problem is the app solving? How does this application solve that problem?) +[//]: <> (This web application allows users to save both randomly and user generated motivational posters as well as view and delete unmotivational posters already provided. The app solves the problem of offering both motivation and unmotivation by providing aesthetic combinations of inspirational/disparaging images, titles, and quotes. Users create their own posters via forms where they input their own image, title, and quote and save those posters alongside any others generated randomly through the app's code. The app solves this problem by assembling the posters' constituent parts from data sets via JS functions and rendering them to the webpage by manipulating HTML elements. All of this gets applied styling via CSS code.) ### Installation Instructions: -[//]: <> (What steps does a person have to take to get your app cloned down and running?) +[//]: <> (Navigate to https://github.com/litobot/hang-in-there-boilerplate, click the button to fork the repository. Clone it down to your local device by creating a local directory, cd into it and use `git clone git@github.com:litobot/hang-in-there-boilerplate.git`. ) ### Preview of App: -[//]: <> (Provide ONE gif or screenshot of your application - choose the "coolest" piece of functionality to show off. gifs preferred!) +[//]: <> ([url=https://postimg.cc/64xHJq6y][img]https://i.postimg.cc/64xHJq6y/Saved-Posters.png[/img][/url] + +[url=https://postimg.cc/NyVJDbW8][img]https://i.postimg.cc/NyVJDbW8/Unmotivational-Posters.png[/img][/url]) ### Context: -[//]: <> (Give some context for the project here. How long did you have to work on it? How far into the Turing program are you?) +[//]: <> (Give some context for the project here. I worked on the project ~3 hours/day over the span of the allotted time (including the weekend) We were given 11 days to work on it I think? I am a Mod 2 student who has repeated both Mod 1 and Mod 2.) ### Contributors: -[//]: <> (Who worked on this application? Link to your GitHub. Consider also providing LinkedIn link) +[//]: <> (I worked on this application with plenty of assistance from instructors, peers, student support, and my mentors. https://github.com/litobot - https://www.linkedin.com/in/litocroy ) ### Learning Goals: -[//]: <> (What were the learning goals of this project? What tech did you work with?) +[//]: <> (The learning goals were: 1. Practice reading, understanding, and using existing code. 2. Write clean, DRY JavaScript. 3. Use CSS and HTML to match styling and layout of provided comps. Tech I used - Class Lessons/Recordings, MDN docs, Stack Exchange, ChatGPT.) ### Wins + Challenges: -[//]: <> (What are 2-3 wins you have from this project? What were some challenges you faced - and how did you get over them?) +[//]: <> (Some wins for the project: 1. I didn't work myself into the ground like I have in the past. (Maybe I went a little too far in that direction, because I wasn't able to finish without some big help from ChatGPT.) 2. I used lots of resources and got help ahead of time before getting too far down rabbit holes I couldn't dig myself out of. 3. I think I kept my code pretty organized and DRY. Challenges I faced: I'm still having a really hard time with JS syntax in general. I can't just glance at a function and understand even my own code. I have to walk through it pretty slowly. I also don't have a strong grapst of callback functions and I think it was just a lot more code than we wrote in Ruby so scrolling up and down was a pain and I'd get lost often.) diff --git a/Saved Posters.jpg b/Saved Posters.jpg new file mode 100644 index 000000000..3e81de925 Binary files /dev/null and b/Saved Posters.jpg differ diff --git a/Unmotivational Posters.jpg b/Unmotivational Posters.jpg new file mode 100644 index 000000000..7481852c7 Binary files /dev/null and b/Unmotivational Posters.jpg differ diff --git a/index.html b/index.html index ca0707621..984a1b152 100644 --- a/index.html +++ b/index.html @@ -18,6 +18,7 @@

Quote

+ + + + \ No newline at end of file diff --git a/src/main.js b/src/main.js index d818a0ab6..6f0fd34ba 100644 --- a/src/main.js +++ b/src/main.js @@ -1,7 +1,3 @@ -// query selector variables go here 👇 - -// we've provided you with some data to work with 👇 -// tip: you can tuck this data out of view with the dropdown found near the line number where the variable is declared var images = [ "./assets/bees.jpg", "./assets/bridge.jpg", @@ -99,13 +95,324 @@ var quotes = [ "Each person must live their life as a model for others.", "A champion is defined not by their wins but by how they can recover when they fall." ]; -var savedPosters = []; + +const unmotivationalPostersData = [ + { + name: "FAILURE", + description: "Why bother trying? It's probably not worth it.", + price: 68.00, + year: 2019, + vintage: true, + img_url: "./assets/failure.jpg", + }, + { + name: "MEDIOCRITY", + description: "Dreams are just that—dreams.", + price: 127.00, + year: 2021, + vintage: false, + img_url: "./assets/mediocrity.jpg", + }, + { + name: "REGRET", + description: "Hard work rarely pays off.", + price: 89.00, + year: 2018, + vintage: true, + img_url: "./assets/regret.jpg", + }, + { + name: "FUTILITY", + description: "You're not good enough.", + price: 150.00, + year: 2016, + vintage: false, + img_url: "./assets/futility.jpg", + }, + { + name: "DEFEAT", + description: "It's too late to start now.", + price: 35.00, + year: 2023, + vintage: false, + img_url: "./assets/defeat.jpg", + }, + { + name: "HOPELESSNESS", + description: "Stay in your comfort zone; it's safer.", + price: 112.00, + year: 2020, + vintage: true, + img_url: "./assets/hopelessness.jpg", + }, + { + name: "LAZINESS", + description: "You can't change anything.", + price: 25.00, + year: 2022, + vintage: false, + img_url: "./assets/laziness.jpg", + }, + { + name: "PROCRASTINATION", + description: "Better to avoid failure by not trying at all.", + price: 48.00, + year: 2017, + vintage: true, + img_url: "./assets/procrastination.jpg", + }, + { + name: "DESPAIR", + description: "Let someone else do it; you’ll just mess it up.", + price: 73.00, + year: 2015, + vintage: false, + img_url: "./assets/despair.jpg", + }, + { + name: "NEGLECT", + description: "Happiness is overrated.", + price: 160.00, + year: 2019, + vintage: true, + img_url: "./assets/neglect.jpg", + }, + { + name: "FEAR", + description: "Giving up is always an option.", + price: 91.00, + year: 2014, + vintage: false, + img_url: "./assets/fear.jpg", + }, + { + name: "APATHY", + description: "No one cares about your effort.", + price: 110.00, + year: 2016, + vintage: true, + img_url: "./assets/apathy.jpg", + }, + { + name: "MISERY", + description: "Why take risks when you can stay stagnant?", + price: 55.00, + year: 2021, + vintage: false, + img_url: "./assets/misery.jpg", + }, + { + name: "BLAME", + description: "Expect disappointment and you'll never be disappointed.", + price: 39.00, + year: 2017, + vintage: true, + img_url: "./assets/blame.jpg", + }, + { + name: "DOUBT", + description: "Success is for other people, not you.", + price: 140.00, + year: 2020, + vintage: false, + img_url: "./assets/doubt.jpg", + } +]; + var currentPoster; +const savedPosters = []; +const cleanedData = cleanData() +console.log(cleanedData); + +const image = document.querySelector('.poster-img'); +const title = document.querySelector('.poster-title'); +const quote = document.querySelector('.poster-quote'); +const showForm = document.querySelector('.poster-form'); +const mainPoster = document.querySelector('.main-poster'); +const posterGrid = document.querySelector('.saved-posters-grid'); +const savedPostersSection = document.querySelector('.saved-posters'); +const unmotivationalPostersSection = document.querySelector('.unmotivational-posters'); + +// Buttons +const nevermindButton = document.querySelector('.show-main'); +const makeNewPosterButton = document.querySelector('.show-form'); +const backToMainButton = document.querySelector('.back-to-main'); +const showMyPosterButton = document.querySelector('.make-poster'); +const randomPosterButton = document.querySelector('.show-random'); +const showSavedPosterButton = document.querySelector('.show-saved'); +const saveCurrentPosterButton = document.querySelector('.save-poster'); +const unmotivationalPosterButton = document.querySelector('.show-unmotivational'); +const backToMainFromUnmotivationalButton = document.querySelector('.unmotivational-posters .back-to-main'); + +// User Input Fields +const userImageUrlInput = document.querySelector('#poster-image-url'); +const userTitleInput = document.querySelector('#poster-title'); +const userQuoteInput = document.querySelector('#poster-quote'); + +// EL for Buttons +randomPosterButton.addEventListener('click', generateRandomPoster); +saveCurrentPosterButton.addEventListener('click', savePosterHandler); +showMyPosterButton.addEventListener('click', handleNewPosterCreation); +showSavedPosterButton.addEventListener('click', showSavedPostersHandler); -// event listeners go here 👇 +// Page Visibility Helper Functions +// Potentially refactor more (mainPoster) shows up consistently +backToMainFromUnmotivationalButton.addEventListener('click', function() { + toggleVisibility(unmotivationalPostersSection); + toggleVisibility(mainPoster); +}) + +makeNewPosterButton.addEventListener('click', function() { + toggleVisibility(mainPoster); + toggleVisibility(showForm); +}); + +nevermindButton.addEventListener('click', function() { + showElement(mainPoster); + hideElement(showForm); +}); + +backToMainButton.addEventListener('click', function() { + toggleVisibility(mainPoster); + toggleVisibility(savedPostersSection); +}); + +unmotivationalPosterButton.addEventListener('click', function() { + toggleVisibility(mainPoster); + toggleVisibility(unmotivationalPostersSection); + displayUnmotivationalPosters(); +}); + +// Hide/Reveal Page Sections Functions +function toggleVisibility(element) { + element.classList.toggle('hidden'); +} + +function showElement(element) { + element.classList.remove('hidden'); +} + +function hideElement(element) { + element.classList.add('hidden'); +} + +function showUnmotivationalPosters() { + toggleVisibility(mainPoster); + toggleVisibility(unmotivationalPostersSection); +} + +// Functions +function displayUnmotivationalPosters() { + const renderUmotivationalPosters = document.querySelector('.unmotivational-layout'); + renderUmotivationalPosters.innerHTML = ''; + cleanedData.forEach(poster => { + const posterInfo = document.createElement('article'); + posterInfo.classList.add('mini-poster'); + posterInfo.innerHTML = ` + new photo +

${poster.title}

+

${poster.quote}

+ `; + posterInfo.addEventListener('dblclick', deleteUnmotivationalPoster); + console.log(targetUnmotivationalPoster); + renderUmotivationalPosters.appendChild(posterInfo); + }); +} + +// If either the image, quote, title, or background is clicked --> I want the poster to get deleted +// If I click on the image, I can compare that to the objects in the cleanedData array and remove that entire objects +// If I click on the poster itself, I still have access to the constituent parts + // And I can compare one of those to the cleanedData array and delete the entire object + + +function targetUnmotivationalPoster(event) { + console.log(event); + console.log(event.target); + console.log(event.currentTarget); +} + +// I was not able to generate the deleteUnmotivationalPoster function on my own. +// I have been having a couple of crummy days and I just wanted to be able to get this functionality in, + // but by no means am I taking credit for it. I just wanted something that worked so I could see it. +// Because this project is not graded, I +// I shamelessly used ChatGPT to generate this function and I'm going to spend a lot of time dissecting it. +function deleteUnmotivationalPoster(event) { + const posterElement = event.currentTarget; + const posterIndex = posterElement.dataset.index; + cleanedData.splice(posterIndex, 1); + posterElement.remove(); + displayUnmotivationalPosters(); +} + +// Updates HTML elements with poster parts +function updatePosterDisplay(poster) { + image.src = poster.imageURL; + title.innerText = poster.title; + quote.innerText = poster.quote; +} + +function handleNewPosterCreation(event) { + event.preventDefault(); // Form submission default is to refresh page (not desired here) + currentPoster = createPoster(userImageUrlInput.value, userTitleInput.value, userQuoteInput.value); + saveUserPosterData(currentPoster); + updatePosterDisplay(currentPoster); + toggleVisibility(mainPoster); + toggleVisibility(showForm); +} + +// Saves poster parts in respective arrays for future random poster generation +// For User Input Form +function saveUserPosterData(poster) { + images.push(currentPoster.imageURL); + titles.push(currentPoster.title); + quotes.push(currentPoster.quote); +} + +function generateRandomPoster() { + var randomImage = images[getRandomIndex(images)]; + var randomTitle = titles[getRandomIndex(titles)]; + var randomQuote = quotes[getRandomIndex(quotes)]; + currentPoster = createPoster(randomImage, randomTitle, randomQuote); + image.src = randomImage; + title.innerText = randomTitle; + quote.innerText = randomQuote; + console.log(currentPoster) +} + +function cleanData() { + return unmotivationalPostersData.map(sanitizeData); +} + +function sanitizeData(data) { + return createPoster(data.img_url, data.name, data.description); +} + +function saveCurrentPoster() { + if (savedPosters.includes(currentPoster)) { + return; + } + savedPosters.push(currentPoster); + // This is how we're inserting mini saved posters into the grid + // on the Saved Posters Page. + posterGrid.insertAdjacentHTML('afterbegin', + `
+ new photo +

${currentPoster.title}

+

${currentPoster.quote}

+
` + ); +} + +function savePosterHandler() { + saveCurrentPoster(); + showSavedPostersHandler(); +} + +function showSavedPostersHandler() { + toggleVisibility(mainPoster); + toggleVisibility(savedPostersSection); +} -// functions and event handlers go here 👇 -// (we've provided two to get you started)! function getRandomIndex(array) { return Math.floor(Math.random() * array.length); } @@ -116,4 +423,56 @@ function createPoster(imageURL, title, quote) { imageURL: imageURL, title: title, quote: quote} -} \ No newline at end of file +} + +window.addEventListener('load', generateRandomPoster); + +// Create console.log to verify click occurs where desired + + +// How to target one unmoti poster? +// Double click on poster deletes unmoti poster from cleanedData + // Therefore it will not display on page + // Utilize `.remove` +// EL for double click anywhere on unmoti poster + // Utilize currentTarget + // Every poster will require EL (forEach) + + + + + +// Before refactoring Event Listeners - (Save for now) + +// makeNewPosterButton.addEventListener("click", function() { + // mainPoster.classList.toggle('hidden') + // showForm.classList.toggle('hidden') + // }); + +// showSavedPosterButton.addEventListener('click', function() { +// mainPoster.classList.toggle('hidden') +// savedPostersSection.classList.toggle('hidden') +// }); + +// nevermindButton.addEventListener('click', function() { +// mainPoster.classList.remove('hidden') +// showForm.classList.toggle('hidden') +// }) + +// backToMainButton.addEventListener('click', function() { +// mainPoster.classList.toggle('hidden') +// savedPostersSection.classList.toggle('hidden') +// }) + +// showMyPosterButton.addEventListener('click', function(event) { +// event.preventDefault(); +// currentPoster = createPoster(userImageUrlInput.value, userTitleInput.value, userQuoteInput.value); +// images.push(currentPoster.imageURL); +// titles.push(currentPoster.title); +// quotes.push(currentPoster.quote); +// image.src = currentPoster.imageURL; +// title.innerText = currentPoster.title; +// quote.innerText = currentPoster.quote; +// mainPoster.classList.toggle('hidden'); +// showForm.classList.toggle('hidden'); +// }); \ No newline at end of file diff --git a/styles.css b/styles.css index 0402eaee9..b4d077bce 100644 --- a/styles.css +++ b/styles.css @@ -144,3 +144,27 @@ button:hover { margin-bottom: 10px; text-transform: uppercase; } + +.unmotivational-layout { + display: flex; + justify-content: space-between; + flex-wrap: wrap; + gap: 10px; + column-gap: 10px; + padding: 2% 16%; +} + +.unmotivational-layout .mini-poster { + background: gray; + border-radius: 3%; +} + +.unmotivational-layout .mini-poster h2 { + color: black; + padding-top: 6%; + font-weight: 100 +} + +.unmotivational-layout .mini-poster h4 { + font-weight: 100; +} \ No newline at end of file