├── README.md
├── favicon.png
├── index.html
├── script.js
└── style.css
/README.md:
--------------------------------------------------------------------------------
1 |
2 | # Quotetalks
3 |
4 | 
5 |
--------------------------------------------------------------------------------
/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MainakRepositor/Quotetalks/887336cb274344f534fe9d775d5b509d3be5a75e/favicon.png
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
13 |
14 | Woops! There was an error!
15 |
16 |
17 |
18 |
19 | What you are is what you have been. What you'll be is what you do now.
20 |
21 |
24 |
25 |
26 |
27 |
28 | Buddha
29 |
30 |
31 |
New Quote
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/script.js:
--------------------------------------------------------------------------------
1 | const quoteContainer = document.getElementById('quote-container')
2 | const quoteText = document.getElementById('quote')
3 | const authorText = document.getElementById('author')
4 | const twitterButton = document.getElementById('twitter')
5 | const newQuoteBtn = document.getElementById('new-quote')
6 | const loader = document.getElementById('loader')
7 | const errorMessage = document.getElementById('error-message')
8 |
9 | function showLoadingSpinner() {
10 | loader.hidden = false
11 | quoteContainer.hidden = true
12 | }
13 |
14 | function removeLoadingSpinner() {
15 | if (!loader.hidden) {
16 | loader.hidden = true
17 | quoteContainer.hidden = false
18 | }
19 | }
20 |
21 | let countCallsToAPI = 0;
22 |
23 | async function getQuoteFromAPI() {
24 | showLoadingSpinner()
25 | const proxyUrl = 'https://guarded-peak-77488.herokuapp.com/'
26 | // const proxyUrl = 'https://cors-anywhere.herokuapp.com/'
27 | const apiUrl = 'http://api.forismatic.com/api/1.0/?method=getQuote&lang=en&format=json'
28 | try {
29 | const response = await fetch(proxyUrl + apiUrl)
30 | const data = await response.json()
31 |
32 | // If author is blank, add Unknown
33 | if (data.quoteAuthor === '') {
34 | authorText.innerText = 'Unknown'
35 | } else {
36 | authorText.innerText = data.quoteAuthor
37 | }
38 |
39 | // Reduce font size for long quotes
40 | if (data.quoteText.length > 120) {
41 | quoteText.classList.add('long-quote')
42 | } else {
43 | quoteText.classList.remove('long-quote')
44 | }
45 | quoteText.innerText = data.quoteText
46 | // Stop Loader & Show Quote
47 | removeLoadingSpinner()
48 |
49 | } catch (error) {
50 | countCallsToAPI += 1
51 | if (countCallsToAPI <= 10) {
52 | getQuoteFromAPI()
53 | console.log('Woops, no quote!', error)
54 | } else if (countCallsToAPI > 10) {
55 | errorMessage.classList.add('visible')
56 | }
57 | }
58 | }
59 |
60 | // Tweet Quote
61 | function tweetQuote() {
62 | const quote = quoteText.innerText
63 | const author = authorText.innerText
64 | const twitterUrl = `https://twitter.com/intent/tweet?text=${quote} - ${author}`
65 |
66 | window.open(twitterUrl, '_blank')
67 | }
68 |
69 |
70 | // Event Listeners
71 | newQuoteBtn.addEventListener('click', getQuoteFromAPI)
72 | twitterButton.addEventListener('click', tweetQuote)
73 |
74 | // On Load
75 | getQuoteFromAPI();
--------------------------------------------------------------------------------
/style.css:
--------------------------------------------------------------------------------
1 | @import url('https://fonts.googleapis.com/css2?family=Quattrocento:wght@400;700&display=swap');
2 |
3 | * { box-sizing: border-box; }
4 |
5 | html {
6 | box-sizing: border-box;
7 | font-size: 12px;
8 | }
9 |
10 | @media screen and (min-width: 768px) {
11 | html {
12 | font-size: 16px;
13 | }
14 | }
15 |
16 | body {
17 | color: #424242;
18 | font-family: 'Quattrocento', serif;
19 | font-weight: 600;
20 | margin: 0;
21 | min-height: 100vh;
22 | text-align: center;
23 | background: linear-gradient(
24 | 60deg,
25 | hsl(224, 85%, 66%),
26 | hsl(269, 85%, 66%),
27 | hsl(314, 85%, 66%),
28 | hsl(359, 85%, 66%),
29 | hsl(44, 85%, 66%),
30 | hsl(89, 85%, 66%),
31 | hsl(134, 85%, 66%),
32 | hsl(179, 85%, 66%)
33 | );
34 | background-size: 300% 300%;
35 | background-position: 0 50%;
36 | border-radius: calc(2 * var(--border-width));
37 | animation: moveGradient 4s alternate infinite;
38 | }
39 | .main {
40 | align-items: center;
41 | background-color: rgb(219, 186, 125);
42 | display: flex;
43 | height: calc(100vh - 25px);
44 | justify-content: center;
45 | left: 12px;
46 | padding: 0 10px;
47 | position: relative;
48 | top: 12px;
49 | width: calc(100vw - 25px);
50 | }
51 |
52 | .quote-container {
53 | max-width: 768px;
54 | width: auto;
55 | }
56 |
57 | .quote-text {
58 | font-size: 2.75rem;
59 | margin-bottom: 16px;
60 | position: relative;
61 | }
62 | #maker
63 | {
64 | font-family: 'Times New Roman', Times, serif;
65 | color: brown;
66 | font-size: 23px;
67 |
68 |
69 | }
70 | .long-quote {
71 | font-size: 2rem;
72 | }
73 |
74 | .fa-quote-left {
75 | font-size: 3rem;
76 | }
77 |
78 | .quote-author {
79 | font-size: 1.2rem;
80 | font-style: italic;
81 | font-weight: 400;
82 | margin-bottom: 16px;
83 | }
84 |
85 | .quote-author::before,
86 | .quote-author::after {
87 | content: "-";
88 | }
89 |
90 | .button {
91 | background: #333;
92 | border-radius: 8px;
93 | border: 0;
94 | box-shadow: 0 0.2rem rgba(121, 121, 121, 0.65);
95 | color: #fff;
96 | cursor: pointer;
97 | font-size: 1.2rem;
98 | height: 2.5rem;
99 | outline: none;
100 | padding: 0.5rem 1.8rem;
101 | position: relative;
102 | transition: filter 0.3s, box-shadow 0.1s, transform 0.1s, background 0.1s ease-in-out;
103 | }
104 |
105 | .button:hover {
106 | filter: brightness(110%);
107 | }
108 |
109 | .button:active {
110 | box-shadow: 0 0.1rem rgba(255, 255, 255, 0.65);
111 | transform: translate(0, 0.2rem)
112 | }
113 |
114 | .button--twitter {
115 | align-items: center;
116 | border-radius: 50px;
117 | bottom: 20px;
118 | display: flex;
119 | font-size: 24px;
120 | height: 50px;
121 | justify-content: center;
122 | left: 50%;
123 | margin-left: -25px;
124 | padding: 0;
125 | position: fixed;
126 | width: 50px;
127 | }
128 |
129 | .button--twitter:hover {
130 | background-color: #1DA1F2;
131 | }
132 |
133 | .button--twitter .fa-twitter {
134 | font-size: 24px;
135 | }
136 |
137 | .button-new-quote {
138 | border-radius: 3px;
139 | cursor: pointer;
140 | display: inline-block;
141 | margin: 0;
142 | padding: 2px 5px;
143 | position: relative;
144 | text-decoration: underline;
145 | transition: background 0.2s ease-in-out;
146 | }
147 |
148 | .button-new-quote:hover {
149 | background: #e8e8e8;
150 | }
151 |
152 | .button-new-quote:active {
153 | bottom: -1px;
154 | }
155 |
156 | .separator {
157 | background-color: #424242;
158 | height: 1px;
159 | margin: 8px auto;
160 | max-width: 360px;
161 | }
162 |
163 | /* Loader */
164 | .loader {
165 | border: 10px solid #f3f3f3;
166 | border-top: 10px solid #3f2f9b;
167 | border-radius: 50%;
168 | width: 100px;
169 | height: 100px;
170 | animation: spinLoader 2s linear infinite;
171 | }
172 |
173 | .error-message {
174 | position: fixed;
175 | top: 24px;
176 | display: none;
177 | }
178 | .error-message.visible {
179 | display: block;
180 | }
181 |
182 | /* Keyframes */
183 |
184 | @keyframes moveGradient {
185 | 50% {
186 | background-position: 100% 50%;
187 | }
188 | }
189 |
190 | @keyframes spinLoader {
191 | 0% { transform: rotate(0deg); }
192 | 100% { transform: rotate(360deg); }
193 | }
--------------------------------------------------------------------------------