diff --git a/public/static/cookies.js b/public/static/cookies.js new file mode 100644 index 0000000..722cae2 --- /dev/null +++ b/public/static/cookies.js @@ -0,0 +1,14 @@ +// After the settings page finishes loading +document.addEventListener( + 'DOMContentLoaded', + () => { + let cookie = decodeURIComponent(document.cookie) + if (cookie !== '') { + document.querySelector('.cookies input').value = cookie + } else { + document.querySelector('.cookies input').value = + 'No cookies has been saved on your system' + } + }, + false +) diff --git a/public/static/settings.js b/public/static/settings.js index 87c4f58..ca25f6e 100644 --- a/public/static/settings.js +++ b/public/static/settings.js @@ -1,186 +1,73 @@ -/* - UI: Method for selecting all search engines - - This function is called when user click on - `select all` and `deselect all` toogle element. - - - If select all is pressed toggle all options and insert all value - joined with comma to input which is saved in cookie. - then changes text to `deselect all`. - eg value: 'ddg,searx,' - - - If deselect all is pressed uncheck all options and insert empty - value to input which is saved in cookie. -*/ -function selectAllHandler(elem) { - let span = elem.parentElement.querySelector("span"); - let mainInput = document.getElementsByName("searchEng")[0]; - let prevStateSelectAll = span.innerText == "Select all" ? true : false; - document.querySelectorAll(".searchEng-elem").forEach((engine) => { - if (prevStateSelectAll) { - engine.querySelector('input[type="checkbox"]').checked = true; - } else { - engine.querySelector('input[type="checkbox"]').checked = false; - } - }); - if (prevStateSelectAll) { - let getValues = () => { - let value = ""; - document - .querySelectorAll('[data-isCheckbox]:not([data-value="all"])') - .forEach((elem) => { - value += elem.getAttribute("data-value") + ","; - }); - return value; - }; - mainInput.value = getValues(); - } else { - mainInput.value = ""; - } - span.innerText = prevStateSelectAll ? "Deselect all" : "Select all"; +function toggleAllSelection() { + document + .querySelectorAll('.engine') + .forEach( + (engine_checkbox) => + (engine_checkbox.checked = + document.querySelector('.select_all').checked) + ) } -/* - UI: Filter settings as per category - - There are two elements one is `category` and `detail`. - Category contains `data-id` when a user click it - we need to show detail element having - `data-detailId` whose value is same as `data-id`. - - When a user clicks on a category on sidebar, view - settings containing `data-id` of sidebar element's `data-detailId` - and hide other settings - - - if `all` is clicked then show all settings. -*/ -document.querySelectorAll(".settings-sidebar .set-name").forEach((filter) => { - let target = filter.getAttribute("data-detailId"); - filter.addEventListener("click", () => { - try { - document.querySelector(".set-name.active").classList.remove("active"); - } catch (e) {} - filter.classList.add("active"); - if (target == "all") { - document.querySelectorAll(".set-item").forEach((elem) => { - elem.style.display = "block"; - }); - return; - } - document - .querySelectorAll('.set-item[data-id="' + target + '"]') - .forEach((elem) => { - elem.style.display = "block"; - }); - document - .querySelectorAll('.set-item:not([data-id="' + target + '"])') - .forEach((elem) => { - elem.style.display = "none"; - }); - }); -}); - - -/* - This function is called when a user click on submit button - it validates all user inputs and saves to a cookie. - - - if input having `required` attr and is empty it generates a - error text and insert above the setting element - - - else store setttings to a cookie. -*/ -function submitSettings() { - let form = document.settings; - let stopProceeding = false; - document.querySelectorAll(".errTxt").forEach((e) => e.remove()); - for (let i = 0; i < form.elements.length; i++) { - let input = form.elements[i]; - if (input.value == "" && input.hasAttribute("required")) { - stopProceeding = true; - let elem = input.parentElement.querySelector("[takeInput]"); - let errTxt = document.createElement("p"); - errTxt.classList.add("errTxt"); - errTxt.innerText = "This setting can't be empty!!"; - elem.classList.add("invalid"); - elem.parentElement.insertBefore(errTxt, elem); - let sidebarElement = input.closest(".set-item").getAttribute("data-id"); - document - .querySelector( - `.settings-sidebar .set-name[data-detailId="${sidebarElement}` - ) - .click(); - stopProceeding = true; - } - } - if (!stopProceeding) { - var expiration_date = new Date(); - expiration_date.setFullYear(expiration_date.getFullYear() + 1); - let formData = new FormData(document.querySelector("form")); - for (var [key, value] of formData.entries()) { - document.cookie = `${key}=${value}; expires=${expiration_date.toUTCString()}`; - } - } else { - return false; - } - // On settings saved successfully - alert("Settings saved succssfully!"); - window.location.reload(); +function setActiveTab(current_tab) { + document + .querySelectorAll('.tab') + .forEach((tab) => tab.classList.remove('active')) + document + .querySelectorAll('.btn') + .forEach((tab) => tab.classList.remove('active')) + current_tab.classList.add('active') + document + .querySelector(`.${current_tab.innerText.toLowerCase().replace(' ', '_')}`) + .classList.add('active') } - -/* - This function will be called on page ready. - it iterates over saved cookies and if cookie name is - in the list of valid cookies then load it. - - - if cookie is searchEng(type=toggle/checkbox) we deselect - all checkboxes and select those which are stored in cookie. - - - if cookie is of type `select` we deselect default selected - option and then select option which is stored in cookie. -*/ -function loadUserSettings() { - let inputs = ["searchEng", "theme", "color-sch"]; - var keyValuePairs = document.cookie.split(";"); - for (var i = 0; i < keyValuePairs.length; i++) { - var name = keyValuePairs[i].substring(0, keyValuePairs[i].indexOf("=")); - var value = keyValuePairs[i].substring(keyValuePairs[i].indexOf("=") + 1); - name = name.trim(); - if (!inputs.includes(name)) { - continue; +function setClientSettings() { + let cookie_dictionary = new Object() + document.querySelectorAll('select').forEach((select_tag) => { + if (select_tag.name === 'themes') { + cookie_dictionary['theme'] = select_tag.value + } else if (select_tag.name === 'colorschemes') { + cookie_dictionary['colorscheme'] = select_tag.value } - let input = document.getElementsByName(name)[0]; - input.value = value; - if (name == "searchEng") { - // Unload all checked engines - document - .querySelectorAll(".searchEng-elem input[type=checkbox]") - .forEach((e) => { - e.checked = false; - }); - value = value.replace(" ", ""); - value.split(",").forEach((val) => { - if (!val) { - return; + }) + let engines = [] + document.querySelectorAll('.engine').forEach((engine_checkbox) => { + if (engine_checkbox.checked === true) { + engines.push(engine_checkbox.parentNode.parentNode.innerText.trim()) + } + }) + cookie_dictionary['engines'] = engines + let expiration_date = new Date() + expiration_date.setFullYear(expiration_date.getFullYear() + 1) + document.cookie = `appCookie=${JSON.stringify( + cookie_dictionary + )}; expires=${expiration_date.toUTCString()}` + + document.querySelector('.message').innerText = + '✅ The settings have been saved sucessfully!!' + + setTimeout(() => { + document.querySelector('.message').innerText = '' + }, 10000) +} + +function getClientSettings() { + let cookie = decodeURIComponent(document.cookie) + + if (cookie !== '') { + let cookie_value = decodeURIComponent(document.cookie) + .split(';') + .map((item) => item.split('=')) + .reduce((acc, [_, v]) => (acc = JSON.parse(v)) && acc, {}) + + let links = Array.from(document.querySelectorAll('link')).forEach( + (item) => { + if (item.href.includes('static/themes')) { + item.href = `static/themes/${cookie_value['theme']}.css` + } else if (item.href.includes('static/colorschemes')) { + item.href = `static/colorschemes/${cookie_value['colorscheme']}.css` } - document - .querySelector(`[data-isCheckbox][data-value="${val}"]`) - .parentElement.querySelector("input").checked = true; - }); - } else { - // Unload all selected options - document - .querySelector( - `[data-input="${name}"] .options span[data-value="${value}"]` - ) - .removeAttribute("selected"); - singleSelectClickHandler( - document.querySelector(`.options span[data-value="${value}"]`) - ); - } + } + ) } } - -// Code where settings are loaded from cookie. -loadUserSettings(); diff --git a/public/static/themes/simple.css b/public/static/themes/simple.css index dfcda52..3d77878 100644 --- a/public/static/themes/simple.css +++ b/public/static/themes/simple.css @@ -263,38 +263,38 @@ footer { /* Styles for the about page */ -.about-container article{ +.about-container article { font-size: 1.5rem; - color:var(--fg); + color: var(--fg); padding-bottom: 10px; } -.about-container article h1{ +.about-container article h1 { color: var(--2); font-size: 2.8rem; } -.about-container article div{ +.about-container article div { padding-bottom: 15px; } -.about-container a{ - color:var(--3); +.about-container a { + color: var(--3); } -.about-container article h2{ +.about-container article h2 { color: var(--3); font-size: 1.8rem; padding-bottom: 10px; } -.about-container p{ - color:var(--fg); - font-size: 1.6rem; +.about-container p { + color: var(--fg); + font-size: 1.6rem; padding-bottom: 10px; } -.about-container h3{ +.about-container h3 { font-size: 1.5rem; } @@ -302,12 +302,10 @@ footer { width: 80%; } -/* css for settings page t */ -.settings { - margin: 2rem; - width: 80%; - height: 100%; - color: var(--fg); +.settings_container { + display: flex; + justify-content: space-around; + width: 80dvw; } .settings h1 { @@ -315,268 +313,187 @@ footer { font-size: 2.5rem; } - .settings hr { border-color: var(--3); - margin: .3rem 0 1rem 0; + margin: 0.3rem 0 1rem 0; } -.settings-view { - display: flex; - flex: 1 0 auto; - margin: 1.5rem 0; -} - -.settings-sidebar { - width: 25%; - height: 100%; -} - -.settings-sidebar .set-name { +.settings_container .sidebar { + width: 30%; cursor: pointer; font-size: 2rem; - display: block; - margin-right: .5rem; - margin-left: -.7rem; - padding: .7rem; + display: flex; + flex-direction: column; + margin-right: 0.5rem; + margin-left: -0.7rem; + padding: 0.7rem; border-radius: 5px; font-weight: bold; - margin-bottom: .5rem; + margin-bottom: 0.5rem; + color: var(--fg); + text-transform: capitalize; + gap: 1.5rem; } -.settings-sidebar .set-name:hover, .settings-sidebar .set-name.active { - background-color: rgba(255, 255, 255, 0.15); - +.settings_container .sidebar .btn { + padding: 0.5rem; + border-radius: 0.5rem; } -.settings-detail { +.settings_container .sidebar .btn.active { + background-color: var(--2); +} + +.settings_container .main_container { + width: 70%; border-left: 1.5px solid var(--3); padding-left: 3rem; } -.settings-detail .set-item { - margin: 2rem 0; - margin-top: 0; -} - -.settings-detail .set-name { - font-size: 2rem; - font-weight: bold; - color: var(--4) -} - -.settings-detail .set-desc { - font-size: 1.5rem; - margin-bottom: .5rem; -} - -/* css for custom select */ -.custom-select, .options { - font-size: 1.5rem; - background-color: var(--bg); - width: 250px; - padding: 1rem 1.7rem; - border-radius: 7px; -} - -.custom-select { - position: relative; - vertical-align: middle; - margin: .7rem 0; -} - -.custom-select.invalid { - border: 1px solid red; -} - -.custom-select svg { - float: right; -} - -.options { +.settings_container .tab { display: none; - position: absolute; - left: 0; - margin-top: 1.3rem; - width: 100%; - padding: .7rem 1rem; - cursor: pointer; - z-index: 3; - max-height: 15rem; - overflow-y: auto; } -.options span { - display: block; - padding: 1rem; - width: 100%; - border-radius: 5px; - vertical-align: middle; +.settings_container .tab.active { + display: flex; + flex-direction: column; + justify-content: space-around; } -.options span:hover { - background-color: var(--1); -} - -.selected-multiple-option { - padding: .8rem; - border-radius: 5px; - background-color: var(--bg); - margin: .5rem .3rem; -} - -.selected-multiple-option svg { - width: 1.3rem; - height: 1.3rem; - vertical-align: middle; - margin-bottom: .5rem; - cursor: pointer; -} - -.select-multiple-show { - margin: 1rem 0; - font-size: 1.5rem; -} - -.underlined-text { - font-size: 1.7rem; - cursor: pointer; - margin-bottom: .5rem; - display: block; -} - -.settings .submit-btn { +.settings_container button { + margin-top: 1rem; padding: 1rem 2rem; font-size: 1.5rem; background: var(--3); color: var(--bg); - border-radius: .5rem; + border-radius: 0.5rem; border: 2px solid transparent; font-weight: bold; - transition: all .1s ease-out; + transition: all 0.1s ease-out; cursor: pointer; box-shadow: 5px 5px; + outline: none; } -.settings .submit-btn:active { - outline: none; +.settings_container button:active { box-shadow: none; translate: 5px 5px; } -/* Css for error text */ - -.errTxt { - color: white; - background: red; - padding: .5rem; - border-radius: 5px; - font-size: 1.3rem; - width: max-content; -} - -/* Css for toggle element */ - -label, -label::before, -label::after { - transition: 200ms all ease-in-out 50ms; - box-sizing: border-box; - backface-visibility: hidden; -} - -input[type="checkbox"] { - display: none; -} - -/*Button is :CHECKED*/ - -input[type="checkbox"]:checked ~ div[data-isCheckbox] { - background: rgba(73,168,68,1); - box-shadow: 0 0 2px rgba(73,168,68,1); -} - -input[type="checkbox"]:checked ~ div[data-isCheckbox] label { - left: 25px; - transform: rotate(360deg); -} - - -/*shared*/ - -div[data-isCheckbox], -label { - border-radius: 50px; -} - - -/*'un':checked state*/ - -div[data-isCheckbox] { - height: 25px; - width: 50px; - background: rgba(43, 43, 43, 1); - position: relative; - box-shadow: 0 0 2px rgba(43,43,43,1); - -} - -label { - height: 20px; - width: 20px; - background: rgba(255, 255, 255, 1); - position: absolute; - top: 3px; - left: 3px; - cursor: pointer; -} - -label::before { - content: ''; - height: 15px; - width: 3px; - position: absolute; - top: calc(50% - 8px); - left: calc(50% - 1.5px); - transform: rotate(45deg); -} - -label::after { - content: ''; - height: 3px; - width: 15px; - position: absolute; - top: calc(50% - 2.5px); - left: calc(50% - 8px); - transform: rotate(45deg); -} - -label::before, -label::after{ - background: rgba(43,43,43,1); - border-radius: 5px; -} - -/* pesduo class on toggle */ - -input[type="checkbox"]:checked ~ div label::before{ - height: 15px; - top: calc(55% - 8px); - left: calc(60% - 2px); - background: rgba(73,168,68,1); -} - -input[type="checkbox"]:checked ~ div label::after{ - width: 7px; - top: calc(95% - 7px); - left: calc(22.5% - 2px); - background: rgba(73,168,68,1); -} - -.searchEng-elem { - display: flex; - gap: 3rem; - align-items: center; +.settings_container .main_container .message { font-size: 1.5rem; - margin: 1rem 0; + color: var(--fg); +} + +.settings_container .tab h3 { + font-size: 2rem; + font-weight: bold; + color: var(--4); + margin-top: 1.5rem; + text-transform: capitalize; +} + +.settings_container .tab .description { + font-size: 1.5rem; + margin-bottom: 0.5rem; + color: var(--fg); +} + +.settings_container .user_interface select { + margin: 0.7rem 0; + width: 20rem; + background-color: var(--bg); + color: var(--fg); + padding: 1rem 2rem; + border-radius: 0.5rem; + outline: none; + border: none; + text-transform: capitalize; +} + +.settings_container .user_interface option:hover { + background-color: var(--1); +} + +.settings_container .engines .engine_selection { + display: flex; + flex-direction: column; + justify-content: center; + gap: 1rem; + padding: 1rem 0; +} + +.settings_container .engines .toggle_btn { + color: var(--fg); + font-size: 1.5rem; + display: flex; + gap: 0.5rem; + align-items: center; +} + +.settings_container .engines hr { + margin: 0; +} + +/* The switch - the box around the slider */ +.switch { + position: relative; + display: inline-block; + width: 6rem; + height: 3.4rem; +} + +/* Hide default HTML checkbox */ +.switch input { + opacity: 0; + width: 0; + height: 0; +} + +/* The slider */ +.slider { + position: absolute; + cursor: pointer; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: var(--bg); + -webkit-transition: 0.4s; + transition: 0.4s; +} + +.slider:before { + position: absolute; + content: ''; + height: 2.6rem; + width: 2.6rem; + left: 0.4rem; + bottom: 0.4rem; + background-color: var(--fg); + -webkit-transition: 0.4s; + transition: 0.4s; +} + +input:checked + .slider { + background-color: var(--3); +} + +input:focus + .slider { + box-shadow: 0 0 1px var(--3); +} + +input:checked + .slider:before { + -webkit-transform: translateX(2.6rem); + -ms-transform: translateX(2.6rem); + transform: translateX(2.6rem); +} + +/* Rounded sliders */ +.slider.round { + border-radius: 3.4rem; +} + +.slider.round:before { + border-radius: 50%; } diff --git a/public/static/ui_plugins.js b/public/static/ui_plugins.js deleted file mode 100644 index 53dddb5..0000000 --- a/public/static/ui_plugins.js +++ /dev/null @@ -1,110 +0,0 @@ -/* - Select plugin - Note: Only for single select option - Usage example: - ``` - -
+ Select the search engines from the list of engines that you want results + from +
+