108 lines
4.7 KiB
JavaScript
108 lines
4.7 KiB
JavaScript
class SimpleCaptcha extends HTMLElement {
|
|
constructor() {
|
|
super();
|
|
this.attachShadow({ mode: "open" });
|
|
}
|
|
|
|
connectedCallback() {
|
|
this.render();
|
|
}
|
|
|
|
render() {
|
|
this.shadowRoot.innerHTML = `
|
|
<style>
|
|
:host {
|
|
display: inline-block;
|
|
font-family: sans-serif;
|
|
--captcha-border: #ccc;
|
|
--captcha-bg: #f9f9f9;
|
|
--captcha-gap: 6px;
|
|
}
|
|
.captcha-wrapper {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: var(--captcha-gap);
|
|
}
|
|
img {
|
|
border: 1px solid var(--captcha-border);
|
|
border-radius: 4px;
|
|
height: 40px;
|
|
object-fit: cover;
|
|
}
|
|
input {
|
|
flex: 1;
|
|
padding: 6px 8px;
|
|
border: 1px solid var(--captcha-border);
|
|
border-radius: 4px;
|
|
}
|
|
button {
|
|
padding: 6px 10px;
|
|
border-radius: 4px;
|
|
border: 1px solid var(--captcha-border);
|
|
background: var(--captcha-bg);
|
|
cursor: pointer;
|
|
}
|
|
</style>
|
|
<div class="captcha-wrapper">
|
|
<img id="img" src="captcha.php?${Date.now()}" alt="Captcha">
|
|
<input id="input" placeholder="Enter code" autocomplete="off">
|
|
<button id="refresh" title="Refresh Captcha">
|
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="8" height="8" viewBox="0 0 256 256" xml:space="preserve">
|
|
<g style="stroke: none; stroke-width: 0; stroke-dasharray: none; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 10; fill: none; fill-rule: nonzero; opacity: 1; " transform="translate(1.4065934065934016 1.4065934065934016) scale(2.81 2.81)">
|
|
<path d="M 81.521 31.109 c -0.86 -1.73 -2.959 -2.438 -4.692 -1.575 c -1.73 0.86 -2.436 2.961 -1.575 4.692 c 2.329 4.685 3.51 9.734 3.51 15.01 C 78.764 67.854 63.617 83 45 83 S 11.236 67.854 11.236 49.236 c 0 -16.222 11.501 -29.805 26.776 -33.033 l -3.129 4.739 c -1.065 1.613 -0.62 3.784 0.992 4.85 c 0.594 0.392 1.264 0.579 1.926 0.579 c 1.136 0 2.251 -0.553 2.924 -1.571 l 7.176 -10.87 c 0.001 -0.001 0.001 -0.002 0.002 -0.003 l 0.018 -0.027 c 0.063 -0.096 0.106 -0.199 0.159 -0.299 c 0.049 -0.093 0.108 -0.181 0.149 -0.279 c 0.087 -0.207 0.152 -0.419 0.197 -0.634 c 0.009 -0.041 0.008 -0.085 0.015 -0.126 c 0.031 -0.182 0.053 -0.364 0.055 -0.547 c 0 -0.014 0.004 -0.028 0.004 -0.042 c 0 -0.066 -0.016 -0.128 -0.019 -0.193 c -0.008 -0.145 -0.018 -0.288 -0.043 -0.431 c -0.018 -0.097 -0.045 -0.189 -0.071 -0.283 c -0.032 -0.118 -0.065 -0.236 -0.109 -0.35 c -0.037 -0.095 -0.081 -0.185 -0.125 -0.276 c -0.052 -0.107 -0.107 -0.211 -0.17 -0.313 c -0.054 -0.087 -0.114 -0.168 -0.175 -0.25 c -0.07 -0.093 -0.143 -0.183 -0.223 -0.27 c -0.074 -0.08 -0.153 -0.155 -0.234 -0.228 c -0.047 -0.042 -0.085 -0.092 -0.135 -0.132 L 36.679 0.775 c -1.503 -1.213 -3.708 -0.977 -4.921 0.53 c -1.213 1.505 -0.976 3.709 0.53 4.921 l 3.972 3.2 C 17.97 13.438 4.236 29.759 4.236 49.236 C 4.236 71.714 22.522 90 45 90 s 40.764 -18.286 40.764 -40.764 C 85.764 42.87 84.337 36.772 81.521 31.109 z" style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 10; fill: rgb(0,0,0); fill-rule: nonzero; opacity: 1;" transform=" matrix(1 0 0 1 0 0) " stroke-linecap="round"/>
|
|
</g>
|
|
</svg>
|
|
</button>
|
|
<button id="submit" title="Submit Captcha">Submit</button>
|
|
</div>
|
|
`;
|
|
|
|
const img = this.shadowRoot.getElementById("img");
|
|
img.addEventListener("click", () => this.refresh());
|
|
|
|
this.shadowRoot.getElementById("refresh")
|
|
.addEventListener("click", () => this.refresh());
|
|
|
|
this.shadowRoot.getElementById("submit")
|
|
.addEventListener("click", () => this.handleSubmit());
|
|
}
|
|
|
|
refresh() {
|
|
const img = this.shadowRoot.getElementById("img");
|
|
img.src = "captcha.php?" + Date.now();
|
|
this.shadowRoot.getElementById("input").value = "";
|
|
}
|
|
|
|
async validate() {
|
|
const input = this.shadowRoot.getElementById("input").value.trim();
|
|
if (!input) return false;
|
|
|
|
const formData = new FormData();
|
|
formData.append("captcha", input);
|
|
|
|
try {
|
|
const res = await fetch("validate.php", { method: "POST", body: formData });
|
|
const data = await res.json();
|
|
|
|
return data.status === "valid";
|
|
} catch (err) {
|
|
console.error("Captcha validation failed:", err);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
async handleSubmit() {
|
|
const isValid = await this.validate();
|
|
|
|
if (isValid) {
|
|
this.dispatchEvent(new CustomEvent("valid"));
|
|
this.refresh();
|
|
} else {
|
|
this.dispatchEvent(new CustomEvent("invalid"));
|
|
this.refresh();
|
|
}
|
|
}
|
|
}
|
|
|
|
customElements.define("simple-captcha", SimpleCaptcha);
|