160 lines
4.4 KiB
JavaScript
160 lines
4.4 KiB
JavaScript
"use strict"
|
|
|
|
/** @type {{search: string; lucky?: boolean;}} */
|
|
const query = window.location.search
|
|
.substring(1)
|
|
.split("&")
|
|
.map(keyValue => keyValue.split("="))
|
|
.map(([key, value]) => ({
|
|
[decodeURIComponent(key)]: decodeURIComponent(
|
|
value?.replaceAll("+", "%20")
|
|
),
|
|
}))
|
|
.reduce((previous, current) => ({ ...previous, ...current }), {})
|
|
|
|
/** @type {HTMLInputElement} */
|
|
let input
|
|
|
|
window.addEventListener("load", async () => {
|
|
input = document.getElementById("input")
|
|
input.value = ""
|
|
|
|
setBrightness(JSON.parse(localStorage.getItem("dark") ?? "false"))
|
|
|
|
if (!query.search) return
|
|
|
|
await setMessage("Step 1", "Type in your question")
|
|
const cursor = makeCursor()
|
|
await move(cursor, input)
|
|
input.focus()
|
|
await write()
|
|
await new Promise(resolve => setTimeout(resolve, 1000))
|
|
input.blur()
|
|
|
|
await setMessage("Step 2", "Click on the search button")
|
|
const button = query.lucky
|
|
? document.getElementById("lucky")
|
|
: document.getElementById("search")
|
|
await move(cursor, button)
|
|
button.focus()
|
|
await new Promise(resolve => setTimeout(resolve, 1000))
|
|
|
|
await setMessage("Come on", "Was it really that hard?", "alert-success")
|
|
await new Promise(resolve => setTimeout(resolve, 3000))
|
|
|
|
window.location.href = `https://www.google.com/search?${query.lucky ? "btnI&" : ""
|
|
}q=${query.search}`
|
|
})
|
|
|
|
function makeCursor() {
|
|
const dark = JSON.parse(localStorage.getItem("dark") ?? "false")
|
|
|
|
const cursor = document.createElement("span")
|
|
cursor.className = `bi-cursor-fill text-${dark ? "light" : "dark"}`
|
|
cursor.id = "cursor"
|
|
document.body.appendChild(cursor)
|
|
return cursor
|
|
}
|
|
|
|
/**
|
|
* Move the cursor to the targeted element
|
|
* @param {HTMLSpanElement} cursor
|
|
* @param {HTMLButtonElement} target
|
|
*/
|
|
async function move(cursor, target) {
|
|
return new Promise(resolve => {
|
|
const diffX =
|
|
target.getBoundingClientRect().left +
|
|
target.clientWidth / 2 -
|
|
cursor.getBoundingClientRect().left
|
|
const diffY =
|
|
target.getBoundingClientRect().top +
|
|
target.clientHeight / 2 -
|
|
cursor.getBoundingClientRect().top
|
|
|
|
const steps = 60
|
|
const stepX = diffX / steps
|
|
const stepY = diffY / steps
|
|
|
|
let step = 0
|
|
const interval = setInterval(frame, 1000 / 60)
|
|
|
|
function frame() {
|
|
if (step >= steps) {
|
|
clearInterval(interval)
|
|
resolve()
|
|
} else {
|
|
step++
|
|
cursor.style.top = (parseFloat(cursor.style.top) || 0) + stepY + "px"
|
|
cursor.style.left = (parseFloat(cursor.style.left) || 0) + stepX + "px"
|
|
}
|
|
}
|
|
})
|
|
}
|
|
|
|
async function write() {
|
|
for (const letter of query.search) {
|
|
await new Promise(resolve => setTimeout(resolve, Math.random() * 200 + 100))
|
|
input.value += letter
|
|
input.scrollLeft = input.scrollWidth
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Set the message box under the search buttons.
|
|
* @param {string} heading
|
|
* @param {string} content
|
|
* @param {string} type
|
|
*/
|
|
async function setMessage(heading, content, type = "alert-primary") {
|
|
const message = document.getElementById("message")
|
|
|
|
message.classList.add("opacity-0")
|
|
await new Promise(resolve => setTimeout(resolve, 300))
|
|
|
|
message.classList.remove("alert-primary")
|
|
message.classList.remove("alert-success")
|
|
message.classList.add(type)
|
|
document.getElementById("message-heading").innerText = heading
|
|
document.getElementById("message-content").innerText = content
|
|
|
|
message.classList.remove("opacity-0")
|
|
await new Promise(resolve => setTimeout(resolve, 300))
|
|
}
|
|
|
|
function toggleBrightness() {
|
|
const dark = JSON.parse(localStorage.getItem("dark") ?? "false")
|
|
localStorage.setItem("dark", !dark)
|
|
setBrightness(!dark)
|
|
}
|
|
|
|
/**
|
|
* Apply brightness on the page.
|
|
* @param {boolean} dark
|
|
*/
|
|
function setBrightness(dark) {
|
|
const newbrightness = dark ? "dark" : "light"
|
|
const oldBrightness = dark ? "light" : "dark"
|
|
|
|
for (const oldClass of [
|
|
`bg-${oldBrightness}`,
|
|
`navbar-${oldBrightness}`,
|
|
`btn-${oldBrightness}`,
|
|
`border-${oldBrightness}`,
|
|
]) {
|
|
const newClass = oldClass.replace(oldBrightness, newbrightness)
|
|
for (const element of document.querySelectorAll(`.${oldClass}`)) {
|
|
element.classList.remove(oldClass)
|
|
element.classList.add(newClass)
|
|
}
|
|
}
|
|
|
|
for (const oldClass of [`text-${newbrightness}`]) {
|
|
const newClass = oldClass.replace(newbrightness, oldBrightness)
|
|
for (const element of document.querySelectorAll(`.${oldClass}`)) {
|
|
element.classList.remove(oldClass)
|
|
element.classList.add(newClass)
|
|
}
|
|
}
|
|
}
|