├── bg-book2.jpg ├── bg.jpg ├── book.html ├── home.html ├── index.html ├── index.js ├── script.js ├── style.css ├── style1.css └── template.ejs /bg-book2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/its-varun/library/1470aec34f87d558da272d8e0f04e31119d584b6/bg-book2.jpg -------------------------------------------------------------------------------- /bg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/its-varun/library/1470aec34f87d558da272d8e0f04e31119d584b6/bg.jpg -------------------------------------------------------------------------------- /book.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | Google Books Embedded Viewer API Example 7 | 8 | 22 | 23 | 24 |
25 |
26 |
27 | 28 | 29 | -------------------------------------------------------------------------------- /home.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Book Finder 6 | 7 | 8 | 9 |
10 |
11 |

Search the Book

12 |
13 |
14 | 15 | 16 |
17 |
18 |
19 |
20 |

Search Result

21 |
22 |
23 |
24 |
25 |
26 |
27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Website with Login & Registration Form 8 | 9 | 10 | 11 | 12 | 13 |
14 | 19 |
20 |
21 |
22 | 23 | 24 | 50 | 51 | 52 | 100 |
101 |
102 | 103 | 104 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | $(document).ready(function() { 2 | var item, tile, author, publisher, bookLink, bookImg; 3 | var outputList = document.getElementById("list-output"); 4 | var bookUrl = "https://www.googleapis.com/books/v1/volumes?q="; 5 | var apiKey = "key=AIzaSyDtXC7kb6a7xKJdm_Le6_BYoY5biz6s8Lw"; 6 | var placeHldr = ''; 7 | var searchData; 8 | 9 | //listener for search button 10 | $("#search").click(function() { 11 | outputList.innerHTML = ""; //empty html output 12 | document.body.style.backgroundImage = "url('')"; 13 | searchData = $("#search-box").val(); 14 | //handling empty search input field 15 | if(searchData === "" || searchData === null) { 16 | displayError(); 17 | } 18 | else { 19 | // console.log(searchData); 20 | // $.get("https://www.googleapis.com/books/v1/volumes?q="+searchData, getBookData()}); 21 | $.ajax({ 22 | url: bookUrl + searchData, 23 | dataType: "json", 24 | success: function(response) { 25 | console.log(response) 26 | if (response.totalItems === 0) { 27 | alert("no result!.. try again") 28 | } 29 | else { 30 | $("#title").animate({'margin-top': '5px'}, 1000); //search box animation 31 | $(".book-list").css("visibility", "visible"); 32 | displayResults(response); 33 | } 34 | }, 35 | error: function () { 36 | alert("Something went wrong..
"+"Try again!"); 37 | } 38 | }); 39 | } 40 | $("#search-box").val(""); //clearn search box 41 | }); 42 | 43 | /* 44 | * function to display result in index.html 45 | * @param response 46 | */ 47 | function displayResults(response) { 48 | for (var i = 0; i < response.items.length; i+=2) { 49 | item = response.items[i]; 50 | title1 = item.volumeInfo.title; 51 | author1 = item.volumeInfo.authors; 52 | publisher1 = item.volumeInfo.publisher; 53 | bookLink1 = item.volumeInfo.previewLink; 54 | bookIsbn = item.volumeInfo.industryIdentifiers[1].identifier 55 | bookImg1 = (item.volumeInfo.imageLinks) ? item.volumeInfo.imageLinks.thumbnail : placeHldr ; 56 | 57 | item2 = response.items[i+1]; 58 | title2 = item2.volumeInfo.title; 59 | author2 = item2.volumeInfo.authors; 60 | publisher2 = item2.volumeInfo.publisher; 61 | bookLink2 = item2.volumeInfo.previewLink; 62 | bookIsbn2 = item2.volumeInfo.industryIdentifiers[1].identifier 63 | bookImg2 = (item2.volumeInfo.imageLinks) ? item2.volumeInfo.imageLinks.thumbnail : placeHldr ; 64 | 65 | // in production code, item.text should have the HTML entities escaped. 66 | outputList.innerHTML += '
' + 67 | formatOutput(bookImg1, title1, author1, publisher1, bookLink1, bookIsbn) + 68 | formatOutput(bookImg2, title2, author2, publisher2, bookLink2, bookIsbn2) + 69 | '
'; 70 | 71 | console.log(outputList); 72 | } 73 | } 74 | 75 | /* 76 | * card element formatter using es6 backticks and templates (indivial card) 77 | * @param bookImg title author publisher bookLink 78 | * @return htmlCard 79 | */ 80 | function formatOutput(bookImg, title, author, publisher, bookLink, bookIsbn) { 81 | // console.log(title + ""+ author +" "+ publisher +" "+ bookLink+" "+ bookImg) 82 | var viewUrl = 'book.html?isbn='+bookIsbn; //constructing link for bookviewer 83 | var htmlCard = `
84 |
85 |
86 |
87 | ... 88 |
89 |
90 |
91 |
${title}
92 |

Author: ${author}

93 |

Publisher: ${publisher}

94 | Read Book 95 |
96 |
97 |
98 |
99 |
` 100 | return htmlCard; 101 | } 102 | 103 | //handling error for empty search box 104 | function displayError() { 105 | alert("search term can not be empty!") 106 | } 107 | 108 | }); 109 | -------------------------------------------------------------------------------- /script.js: -------------------------------------------------------------------------------- 1 | const formOpenBtn = document.querySelector("#form-open"); 2 | const home = document.querySelector(".home"); 3 | const formContainer = document.querySelector(".form_container"); 4 | const formCloseBtn = document.querySelector(".form_close"); 5 | const signupBtn = document.querySelector("#signup"); 6 | const loginBtn = document.querySelector("#login"); 7 | const pwShowHide = document.querySelectorAll(".pw_hide"); 8 | const loginEmail = document.querySelector("#login-email"); 9 | const loginPassword = document.querySelector("#login-password"); 10 | const loginRememberMe = document.querySelector("#login-remember-me"); 11 | const loginButton = document.querySelector("#login-button"); 12 | const signupUsername = document.querySelector("#signup-username"); 13 | const signupPhone = document.querySelector("#signup-phone"); 14 | const signupEmail = document.querySelector("#signup-email"); 15 | const signupPassword = document.querySelector("#signup-password"); 16 | const signupConfirmPassword = document.querySelector("#signup-confirm-password"); 17 | const signupButton = document.querySelector("#signup-button"); 18 | const emailError = document.querySelector(".email-error"); 19 | const phoneError = document.querySelector(".phone-error"); 20 | const usernameError = document.querySelector(".username-error"); 21 | const passwordError = document.querySelector(".password-error"); 22 | const confirmPasswordError = document.querySelector(".confirm-password-error"); 23 | const otpForm = document.querySelector("#otp-form"); 24 | const otpInput = document.querySelector("#otp-input"); 25 | const otpSubmitButton = document.querySelector("#otp-submit-button"); 26 | 27 | formOpenBtn.addEventListener("click", () => home.classList.add("show")); 28 | formCloseBtn.addEventListener("click", () => home.classList.remove("show")); 29 | 30 | pwShowHide.forEach((icon) => { 31 | icon.addEventListener("click", () => { 32 | let getPwInput = icon.parentElement.querySelector("input"); 33 | if (getPwInput.type === "password") { 34 | getPwInput.type = "text"; 35 | icon.classList.replace("uil-eye-slash", "uil-eye"); 36 | } else { 37 | getPwInput.type = "password"; 38 | icon.classList.replace("uil-eye", "uil-eye-slash"); 39 | } 40 | }); 41 | }); 42 | 43 | signupBtn.addEventListener("click", (e) => { 44 | e.preventDefault(); 45 | formContainer.classList.add("active"); 46 | }); 47 | loginBtn.addEventListener("click", (e) => { 48 | e.preventDefault(); 49 | formContainer.classList.remove("active"); 50 | }); 51 | 52 | function validateEmail(email) { 53 | const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; 54 | return emailRegex.test(email); 55 | } 56 | 57 | function validatePhone(phone) { 58 | const phoneRegex = /^\d{10}$/; 59 | return phoneRegex.test(phone); 60 | } 61 | 62 | function validatePassword(password) { 63 | return password.length >= 8; 64 | } 65 | 66 | function checkConfirmPassword() { 67 | const password = signupPassword.value; 68 | const confirmPassword = signupConfirmPassword.value; 69 | 70 | if (confirmPassword !== password) { 71 | confirmPasswordError.innerHTML = "Passwords don't match"; 72 | return false; 73 | } else { 74 | confirmPasswordError.innerHTML = ""; 75 | return true; 76 | } 77 | } 78 | 79 | loginButton.addEventListener("click", (e) => { 80 | e.preventDefault(); 81 | 82 | const email = loginEmail.value.trim(); 83 | const password = loginPassword.value.trim(); 84 | const rememberMe = loginRememberMe.checked; 85 | 86 | if (!validateEmail(email)) { 87 | emailError.innerHTML = "Please enter a valid email"; 88 | return; 89 | } else { 90 | emailError.innerHTML = ""; 91 | } 92 | 93 | if (!validatePassword(password)) { 94 | passwordError.innerHTML = "Password must be at least 8 characters long"; 95 | return; 96 | } else { 97 | passwordError.innerHTML = ""; 98 | } 99 | 100 | // Code for login goes here 101 | }); 102 | 103 | signupButton.addEventListener("click", (e) => { 104 | e.preventDefault(); 105 | 106 | const username = signupUsername.value.trim(); 107 | const phone = signupPhone.value.trim(); 108 | const email = signupEmail.value.trim(); 109 | const password = signupPassword.value.trim(); 110 | const confirmPassword = signupConfirmPassword.value.trim(); 111 | 112 | if (username.length === 0) { 113 | usernameError.innerHTML = "Please enter a username"; 114 | return; 115 | } else { 116 | usernameError.innerHTML = ""; 117 | } 118 | 119 | if (!validatePhone(phone)) { 120 | phoneError.innerHTML = "Please enter a valid phone number"; 121 | return; 122 | } else { 123 | phoneError.innerHTML = ""; 124 | } 125 | 126 | if (!validateEmail(email)) { 127 | emailError.innerHTML = "Please enter a valid email"; 128 | return; 129 | } else { 130 | emailError.innerHTML = ""; 131 | } 132 | 133 | if (!validatePassword(password)) { 134 | passwordError.innerHTML = "Password must be at least 8 characters long"; 135 | return; 136 | } else { 137 | passwordError.innerHTML = ""; 138 | } 139 | 140 | if (!checkConfirmPassword()) { 141 | return; 142 | } 143 | 144 | alert("Signup is successful"); 145 | }); 146 | function openPage() { 147 | window.open("home.html", "_blank"); 148 | } 149 | 150 | 151 | -------------------------------------------------------------------------------- /style.css: -------------------------------------------------------------------------------- 1 | /* Import Google font - Poppins */ 2 | @import url("https://fonts.googleapis.com/css2?family=Poppins:wght@200;300;400;500;600;700&display=swap"); 3 | * { 4 | margin: 0; 5 | padding: 0; 6 | box-sizing: border-box; 7 | font-family: "Poppins", sans-serif; 8 | } 9 | 10 | a { 11 | text-decoration: none; 12 | } 13 | 14 | .header { 15 | position: fixed; 16 | height: 80px; 17 | width: 100%; 18 | z-index: 100; 19 | padding: 0 20px; 20 | } 21 | 22 | .nav { 23 | max-width: 1100px; 24 | width: 100%; 25 | margin: 0 auto; 26 | } 27 | 28 | .nav, 29 | .nav_item { 30 | display: flex; 31 | height: 100%; 32 | align-items: center; 33 | justify-content: space-between; 34 | } 35 | 36 | .nav_logo, 37 | .nav_link, 38 | .button { 39 | color: #fff; 40 | } 41 | 42 | .nav_logo { 43 | font-size: 25px; 44 | } 45 | 46 | .nav_item { 47 | column-gap: 25px; 48 | } 49 | 50 | .nav_link:hover { 51 | color: #d9d9d9; 52 | } 53 | 54 | .button { 55 | padding: 6px 24px; 56 | border: 2px solid #fff; 57 | background: transparent; 58 | border-radius: 6px; 59 | cursor: pointer; 60 | } 61 | 62 | .button:active { 63 | transform: scale(0.98); 64 | } 65 | 66 | .signup_form .input_box { 67 | position: relative; 68 | margin-bottom: 20px; 69 | } 70 | 71 | .signup_form .input_box input { 72 | width: 100%; 73 | border-radius: 5px; 74 | background-color: #f2f2f2; 75 | color: #333; 76 | font-size: 16px; 77 | font-weight: 300; 78 | letter-spacing: 1px; 79 | } 80 | 81 | .signup_form .input_box i { 82 | position: absolute; 83 | left: 425px; 84 | top: 50%; 85 | transform: translateY(-50%); 86 | font-size: 22px; 87 | color: #999; 88 | } 89 | .signup_form .as i { 90 | position: absolute; 91 | left: 4px; 92 | top: 50%; 93 | transform: translateY(-50%); 94 | font-size: 22px; 95 | color: #999; 96 | } 97 | 98 | .signup_form .input_box .password { 99 | cursor: pointer; 100 | } 101 | 102 | .social_media { 103 | display: flex; 104 | justify-content: center; 105 | align-items: center; 106 | margin-top: 20px; 107 | } 108 | 109 | .social_media button { 110 | display: flex; 111 | justify-content: center; 112 | align-items: center; 113 | margin: 0 10px; 114 | background-color: #fff; 115 | border: 1px solid #ddd; 116 | border-radius: 5px; 117 | color: #333; 118 | font-weight: 500; 119 | transition: all 0.3s ease; 120 | cursor: pointer; 121 | } 122 | 123 | .social_media button:hover { 124 | background-color: #7d2ae8; /* changed hover color to purple */ 125 | border-color: #7d2ae8; 126 | color: #fff; 127 | } 128 | 129 | /* Home */ 130 | .home { 131 | position: relative; 132 | height: 100vh; 133 | width: 100%; 134 | background-image: url("bg.jpg"); 135 | background-size: cover; 136 | background-position: center; 137 | } 138 | 139 | .home::before { 140 | content: ""; 141 | position: absolute; 142 | height: 100%; 143 | width: 100%; 144 | background-color: rgba(0, 0, 0, 0.6); 145 | z-index: 100; 146 | opacity: 0; 147 | pointer-events: none; 148 | transition: all 0.5s ease-out; 149 | } 150 | 151 | .home.show::before { 152 | opacity: 1; 153 | pointer-events: auto; 154 | } 155 | 156 | /* Form */ 157 | .form_container { 158 | position: fixed; 159 | max-width: 500px; /* changed max-width to 400px */ 160 | width: 100%; 161 | top: 50%; 162 | left: 50%; 163 | transform: translate(-50%, -50%) scale(1.2); 164 | z-index: 101; 165 | background: #fff; 166 | padding: 25px; 167 | border-radius: 12px; 168 | box-shadow: rgba(0, 0, 0, 0.1); 169 | opacity: 0; 170 | pointer-events: none; 171 | transition: all 0.4s ease-out; 172 | } 173 | 174 | .home.show .form_container { 175 | opacity: 1; 176 | pointer-events: auto; 177 | transform: translate(-50%, -50%) scale(1); 178 | } 179 | 180 | .signup_form { 181 | display: none; 182 | } 183 | 184 | .form_container.active .signup_form { 185 | display: block; 186 | } 187 | 188 | .form_container.active .login_form { 189 | display: none; 190 | } 191 | 192 | .form_close { 193 | position: absolute; 194 | top: 10px; 195 | right: 20px; 196 | color: #0b0217; 197 | font-size: 22px; 198 | opacity: 0.7; 199 | cursor: pointer; 200 | } 201 | 202 | .form_container h2 { 203 | font-size: 22px; 204 | color: #0b0217; 205 | text-align: center; 206 | } 207 | 208 | .input_box { 209 | position: relative; 210 | margin-top: 30px; 211 | width: 100%; 212 | height: 40px; 213 | } 214 | 215 | .input_box input { 216 | height: 100%; 217 | width: 100%; 218 | border: none; 219 | outline: none; 220 | padding: 0 30px; 221 | color: #333; 222 | transition: all 0.2s ease; 223 | border-bottom: 1.5px solid #aaaaaa; 224 | } 225 | 226 | .input_box input:focus { 227 | border-color: #7d2ae8; 228 | } 229 | 230 | .input_box i { 231 | position: absolute; 232 | top: 50%; /* adjusted top position of icons */ 233 | transform: translateY(-50%); 234 | font-size: 20px; 235 | color: #707070; 236 | } 237 | 238 | .input_box i.email, 239 | .input_box i.password { 240 | left: 0; 241 | } 242 | 243 | .input_box input:focus ~ i.email, 244 | .input_box input:focus ~ i.password { 245 | color: #7d2ae8; 246 | } 247 | 248 | .input_box i.pw_hide { 249 | right: 0; 250 | font-size: 18px; 251 | cursor: pointer; 252 | } 253 | 254 | .option_field { 255 | margin-top: 14px; 256 | display: flex; 257 | align-items: center; 258 | justify-content: space-between; 259 | } 260 | 261 | .checkbox { 262 | display: flex; 263 | column-gap: 8px; 264 | white-space: nowrap; 265 | } 266 | 267 | .checkbox input { 268 | accent-color: #7d2ae8; 269 | } 270 | 271 | .checkbox label { 272 | font-size: 12px; 273 | cursor: pointer; 274 | user-select: none; 275 | color: #0b0217; 276 | } 277 | 278 | .form_container a { 279 | color: #7d2ae8; 280 | font-size: 12px; 281 | display: block; 282 | margin-top: 10px; 283 | text-align: center; 284 | } 285 | 286 | .form_container a:hover { 287 | text-decoration: underline; 288 | } 289 | 290 | .form_container .button { 291 | background: #7d2ae8; 292 | margin-top: 30px; 293 | width: 100%; 294 | padding: 10px 0; 295 | border-radius: 10px; 296 | color: #fff; 297 | font-weight: 600; 298 | } 299 | 300 | .error { 301 | color: #ff0000; 302 | font-size: 12px; 303 | margin-top: 5px; 304 | } 305 | 306 | .hidden { 307 | display: none; 308 | } -------------------------------------------------------------------------------- /style1.css: -------------------------------------------------------------------------------- 1 | 2 | 3 | body { 4 | background-image: url("bg-book2.jpg"); 5 | background-color: #017199; 6 | Background-attachment:fixed; 7 | background-position: center; 8 | background-repeat: no-repeat; 9 | background-size: cover; 10 | 11 | 12 | } 13 | 14 | .center { 15 | margin: auto; 16 | margin-top: 200px; 17 | } 18 | 19 | #header { 20 | font-family: 'Righteous', sans-serif; 21 | font-size: 3rem; 22 | } 23 | 24 | h2 { 25 | font-family: 'Righteous', sans-serif; 26 | } 27 | 28 | .book-list { 29 | margin-top: 50px; 30 | visibility: hidden; 31 | } 32 | -------------------------------------------------------------------------------- /template.ejs: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |
5 | ... 6 |
7 |
8 |
9 |
<%= title %>
10 |

Author: <%= author %>

11 |

Publisher: <%= publisher %>

12 |
13 |
14 |
15 |
16 |
17 | --------------------------------------------------------------------------------