├── README.md
├── index.html
├── script.js
└── style.css
/README.md:
--------------------------------------------------------------------------------
1 | # quoteGenerator
2 |
3 | Quotes generator
4 |
5 |
6 |
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 |
30 | New Quote
31 |
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 | }
--------------------------------------------------------------------------------