├── README.md ├── index.html ├── script.js └── style.css /README.md: -------------------------------------------------------------------------------- 1 | # quoteGenerator 2 | 3 | Quotes generator 4 | 5 |
6 | logo 7 |
8 | 9 |

Quotes generator

10 | 11 |
12 | 13 | 14 | 15 | # 📗 Table of Contents 16 | 17 | - [quoteGenerator](#quotegenerator) 18 | - [📗 Table of Contents](#-table-of-contents) 19 | - [📖 Quotes Generator ](#-quotes-generator-) 20 | - [🛠 Built With ](#-built-with-) 21 | - [Tech Stack ](#tech-stack-) 22 | - [Key Features ](#key-features-) 23 | - [🚀 Live Demo ](#-live-demo-) 24 | - [💻 Getting Started ](#-getting-started-) 25 | - [Prerequisites](#prerequisites) 26 | - [Setup](#setup) 27 | - [Install](#install) 28 | - [Usage](#usage) 29 | - [Run tests](#run-tests) 30 | - [Deployment](#deployment) 31 | - [👥 Authors ](#-authors-) 32 | - [🔭 Future Features ](#-future-features-) 33 | - [🤝 Contributing ](#-contributing-) 34 | - [⭐️ Show your support ](#️-show-your-support-) 35 | - [🙏 Acknowledgments ](#-acknowledgments-) 36 | - [❓ FAQ (OPTIONAL) ](#-faq-optional-) 37 | - [📝 License ](#-license-) 38 | 39 | 40 | 41 | # 📖 Quotes Generator 42 | 43 | This is a quote generator in which asynchronous requests are made. 44 | 1- The DOM is manipulated; 45 | 2- Interesting things are used such as the Math.random() function; 46 | 3- The Math.floor() function it is used because I wanted to round down numbers in order to return the largest integer; 47 | 4- The class.List property is used to access the class of an element; 48 | 5- And, the "await" operator is implemented to wait for a promise. Remember that the "await" operator can only be used within an asynchronous function. 49 | 50 | 51 | ## 🛠 Built With 52 | 53 | ### Tech Stack 54 | 55 |
56 | Client 57 | 60 |
61 | 62 | 63 | 64 | ### Key Features 65 | 66 | - **[key_feature_1]** 67 | - **[key_feature_2]** 68 | - **[key_feature_3]** 69 | 70 |

(back to top)

71 | 72 | 73 | 74 | ## 🚀 Live Demo 75 | 76 | - [Live Demo Link](https://alejandroq12.github.io/quoteGenerator/) 77 | 78 |

(back to top)

79 | 80 | 81 | 82 | ## 💻 Getting Started 83 | 84 | To get a local copy up and running, follow these steps. 85 | 86 | ### Prerequisites 87 | 88 | In order to run this project you need: 89 | 90 | 97 | 98 | ### Setup 99 | 100 | Clone this repository to your desired folder: 101 | 102 | 110 | 111 | ### Install 112 | 113 | Install this project with: 114 | 115 | 123 | 124 | ### Usage 125 | 126 | To run the project, execute the following command: 127 | 128 | 135 | 136 | ### Run tests 137 | 138 | To run tests, run the following command: 139 | 140 | 147 | 148 | ### Deployment 149 | 150 | You can deploy this project using: 151 | 152 | 159 | 160 |

(back to top)

161 | 162 | 163 | 164 | ## 👥 Authors 165 | 166 | 👤 **Julio Quezada** 167 | 168 | - GitHub: [@githubhandle](https://github.com/githubhandle) 169 | - Twitter: [@twitterhandle](https://twitter.com/twitterhandle) 170 | - LinkedIn: [LinkedIn](https://linkedin.com/in/linkedinhandle) 171 | 172 |

(back to top)

173 | 174 | 175 | 176 | ## 🔭 Future Features 177 | 178 | - [ ] **[new_feature_1]** 179 | - [ ] **[new_feature_2]** 180 | - [ ] **[new_feature_3]** 181 | 182 |

(back to top)

183 | 184 | 185 | 186 | ## 🤝 Contributing 187 | 188 | Contributions, issues, and feature requests are welcome! 189 | 190 | Feel free to check the [issues page](../../issues/). 191 | 192 |

(back to top)

193 | 194 | 195 | 196 | ## ⭐️ Show your support 197 | 198 | If you like this project... 199 | 200 |

(back to top)

201 | 202 | 203 | 204 | ## 🙏 Acknowledgments 205 | 206 | 207 | I would like to thank.. 208 | 209 |

(back to top)

210 | 211 | 212 | 213 | ## ❓ FAQ (OPTIONAL) 214 | 215 | - **[Question_1]** 216 | 217 | - [Answer_1] 218 | 219 | 220 |

(back to top)

221 | 222 | 223 | 224 | ## 📝 License 225 | 226 | This project is [MIT](./LICENSE) licensed. 227 | 228 | 229 |

(back to top)

230 | 231 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Template 8 | 10 | 11 | 12 | 13 | 14 |
15 | 16 |
17 | 18 | 19 |
20 | 21 |
22 | 23 |
24 | 25 |
26 | 29 | 32 | 33 |
34 |
35 | 36 |
37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /script.js: -------------------------------------------------------------------------------- 1 | const quoteContainer = document.getElementById("quote-container"); 2 | const quoteText = document.getElementById("quote"); 3 | const authorText = document.getElementById("author"); 4 | const twitterBtn = document.getElementById("twitter"); 5 | const newQuoteBtn = document.getElementById("new-quote"); 6 | const loader = document.getElementById("loader"); 7 | 8 | 9 | let apiQuotes = []; 10 | 11 | 12 | function ShowLoadingSpinner() { 13 | loader.hidden = false; 14 | quoteContainer.hidden = true; 15 | } 16 | 17 | // Hide Loading 18 | function removeLoadingSpinner() { 19 | if (!loader.hidden) { 20 | quoteContainer.hidden = false; 21 | loader.hidden = true; 22 | } 23 | } 24 | 25 | 26 | // Show New Quote 27 | function newQuote(){ 28 | ShowLoadingSpinner(); 29 | // Pick a random quote from apiQuotes array' 30 | const quote = apiQuotes[Math.floor(Math.random() * apiQuotes.length)]; 31 | // Check if author field is blank and replace it with 'Unknown' 32 | if (!quote.author){ 33 | authorText.textContent = 'Unknown'; 34 | } else { 35 | authorText.textContent = quote.author; 36 | } 37 | // Check Quote length to determine styling 38 | if (quote.text.length > 120){ 39 | quoteText.classList.add('long-quote'); 40 | } else { 41 | quoteText.classList.remove('long-quote'); 42 | } 43 | // Set Quote, Hide Loader 44 | quoteText.textContent = quote.text; 45 | removeLoadingSpinner(); 46 | 47 | } 48 | 49 | // Get Quotes From API 50 | async function getQuotes() { 51 | ShowLoadingSpinner(); 52 | const apiUrl='https://jacintodesign.github.io/quotes-api/data/quotes.json'; 53 | try { 54 | const response = await fetch(apiUrl); 55 | apiQuotes = await response.json(); 56 | newQuote(); 57 | } catch(error){ 58 | // Catch error here 59 | } 60 | } 61 | 62 | 63 | // Tweet Quote 64 | function tweetQuote() { 65 | const twitterUrl = `https://twitter.com/intent/tweet?text=${quoteText.textContent} - ${authorText.textContent}`; 66 | window.open(twitterUrl, '_blank'); 67 | } 68 | 69 | // Event listeners 70 | newQuoteBtn.addEventListener('click', newQuote); 71 | twitterBtn.addEventListener('click', tweetQuote); 72 | 73 | // On load 74 | getQuotes(); -------------------------------------------------------------------------------- /style.css: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/css2?family=Bangers&family=Montserrat:wght@200&family=Poiret+One&display=swap'); 2 | 3 | html { 4 | box-sizing: border-box; 5 | } 6 | 7 | body { 8 | margin: 0; 9 | min-height: 100vh; 10 | background-color: #f0edf5; 11 | background-image: url("data:image/svg+xml,%3Csvg width='80' height='80' viewBox='0 0 80 80' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill='none' fill-rule='evenodd'%3E%3Cg fill='%23070707' fill-opacity='0.1'%3E%3Cpath d='M50 50c0-5.523 4.477-10 10-10s10 4.477 10 10-4.477 10-10 10c0 5.523-4.477 10-10 10s-10-4.477-10-10 4.477-10 10-10zM10 10c0-5.523 4.477-10 10-10s10 4.477 10 10-4.477 10-10 10c0 5.523-4.477 10-10 10S0 25.523 0 20s4.477-10 10-10zm10 8c4.418 0 8-3.582 8-8s-3.582-8-8-8-8 3.582-8 8 3.582 8 8 8zm40 40c4.418 0 8-3.582 8-8s-3.582-8-8-8-8 3.582-8 8 3.582 8 8 8z' /%3E%3C/g%3E%3C/g%3E%3C/svg%3E"); 12 | color: #000; 13 | font-family: Monserrat, sans-serif; 14 | font-weight: 700; 15 | text-align: center; 16 | display: flex; 17 | align-items: center; 18 | justify-content: center; 19 | } 20 | .quote-container{ 21 | width: auto; 22 | max-width: 900px; 23 | padding: 20px 30px; 24 | border-radius: 10px; 25 | background-color: rgba(255, 255, 255, 0.5); 26 | box-shadow: 0 10px 10px 10px rgba(0, 0, 0, 0.2); 27 | } 28 | 29 | .quote-text{ 30 | font-size: 2.75rem; 31 | } 32 | 33 | .long-quote { 34 | font-size: 2rem; 35 | } 36 | 37 | .fa-quote-left { 38 | font-size: 4rem; 39 | } 40 | 41 | .quote-author { 42 | margin-top: 15px; 43 | font-size: 2rem; 44 | font-weight: 400; 45 | font-style: italic; 46 | } 47 | 48 | .button-container{ 49 | margin-top: 15px; 50 | display: flex; 51 | justify-content: space-between; 52 | 53 | } 54 | 55 | button { 56 | cursor: pointer; 57 | font-size: 1.2rem; 58 | height: 2.5rem; 59 | border: none; 60 | border-radius: 10px; 61 | color: #fff; 62 | background: #333; 63 | outline: none; 64 | padding: 0.5rem 1.8rem; 65 | box-shadow: 0 0.3rem rgba(121, 121, 121, 0.65); 66 | 67 | } 68 | 69 | button:hover{ 70 | filter: brightness(110%); 71 | } 72 | 73 | button:active{ 74 | transform: translate(0, 0.3rem); 75 | box-shadow: 0 0.1rem rgba(255, 255, 255, 0.65); 76 | } 77 | 78 | .twitter-button:hover { 79 | color: #38a1f3; 80 | } 81 | 82 | .fa-twitter { 83 | font-size: 1.5rem; 84 | } 85 | 86 | /* Loader */ 87 | .loader { 88 | border: 16px solid #f3f3f3; 89 | border-top: 16px solid #333; 90 | border-radius: 50%; 91 | width: 120px; 92 | height: 120px; 93 | animation: spin 2s linear infinite; 94 | } 95 | 96 | @keyframes spin { 97 | 0% { transform: rotate(0deg); } 98 | 100% { transform: rotate(360deg); } 99 | } 100 | 101 | /* Media Query Tablet or Smaller */ 102 | @media screen and (max-width: 1000px) { 103 | .quote-container{ 104 | margin: auto 10px; 105 | } 106 | .quote-text { 107 | font-size: 2.5rem; 108 | } 109 | } --------------------------------------------------------------------------------