PageSourceSearch

https://www.grammarcheck.ai/web_assets/frontend/script/login.js?v=51

js grammarcheck.ai collected 2026-09-24 11:11:39 UTC 8,010 bytes, 236 lines download raw bytes

1/**
2 * Global Configuration & State
3 */
4const API_URLS = {
5    register: `${websiteBaseUrl}/emd/register/web`,
6    login: `${websiteBaseUrl}/emd/login/web`,
7    forgot: `${websiteBaseUrl}/emd/forgot-password`,
8    reset: (token) => `${websiteBaseUrl}/emd/reset-password/${token}`,
9    google: `${websiteBaseUrl}/emd/login/google`
10};
11
12const ERROR_ICONS = {
13    validation: `${websiteBaseUrl}/web_assets/frontend/img/notextfound.png?v=1.2`,
14    error: `${websiteBaseUrl}/web_assets/frontend/img/error_icon.svg?v=1.2`
15};
16
17$(document).ready(function () {
18    // Cache common selectors
19    const $errorMsg = $(".alert-msg");
20    const $inputs = $(".form-control");
21
22    // 1. Auto-hide error messages
23    if ($errorMsg.length) {
24        setTimeout(() => $errorMsg.fadeOut("slow"), 3000);
25    }
26
27    // 2. Event Listeners
28    $(".signup_button").on("click", handleRegisterClick);
29    $(".sign_in_button").on("click", handleLoginClick);
30    $(".forgot_button").on("click", handleForgotClick);
31    $(".reset_button").on("click", handleResetClick);
32    $(".google_sign_in_button").on("click", () => window.location.href = API_URLS.google);
33    $(".toggle-password").on("click", togglePasswordVisibility);
34
35    // 3. Enter Key Support
36    $inputs.on("keydown", function (e) {
37        if (e.key === "Enter") {
38            e.preventDefault();
39            $(this).closest("form, .login_container,.login_form_container").find("button[type=submit], .signup_button, .sign_in_button,.reset_button").first().click();
40            $(":focus").blur()
41        }
42    });
43});
44
45/**
46 * Helper: UI Loading State
47 */
48const toggleLoading = ($btn, isLoading, text = "") => {
49    if (isLoading) {
50        $btn.addClass("temp_disable").prop("disabled", true).removeClass("button_hover_forms").text(text);
51    } else {
52        $btn.removeClass("temp_disable").prop("disabled", false).addClass("button_hover_forms").text(text);
53    }
54};
55
56/**
57 * Helper: Generic Validation
58 */
59const validateForm = (data) => {
60    const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
61
62    if (data.hasOwnProperty('name') && !data.name.trim()) return "Please enter your name";
63    if (data.hasOwnProperty('email') && !emailRegex.test(data.email)) return "Please enter a valid email address";
64    if (data.hasOwnProperty('password') && data.password.length < 8) return "Password must be at least 8 characters";
65    if (data.hasOwnProperty('confirm_password') && data.password !== data.confirm_password) return "Passwords do not match";
66
67    return null; // Passes validation
68};
69
70/**
71 * Registration Logic
72 */
73const handleRegisterClick = function (e) {
74    e.preventDefault();
75    const $btn = $(this);
76    if ($btn.hasClass("temp_disable")) return;
77
78    const payload = {
79        name: $("#name").val(),
80        email: $("#email").val(),
81        password: $("#password").val()
82    };
83
84    const error = validateForm(payload);
85    if (error) {
86        return showLimitModal("Validation Error", error, true);
87    }
88
89    toggleLoading($btn, true, "Signing Up...");
90
91    with_cloudflare_captcha(false, Date.now() / 1000, (hash, token, body) => {
92        $.ajax({
93            url: API_URLS.register,
94            method: "POST",
95            data: payload,
96            success: (res) => handleAuthSuccess(res, payload.email),
97            error: (xhr) => handleAuthError(xhr, payload.email),
98            complete: () => toggleLoading($btn, false, "Sign Up")
99        });
100    }, "light", "#signup-captcha");
101};
102
103/**
104 * Login Logic
105 */
106const handleLoginClick = function (e) {
107    e.preventDefault();
108    const $btn = $(this);
109    if ($btn.hasClass("temp_disable")) return;
110
111    const payload = {
112        email: $("#email").val(),
113        password: $("#password").val()
114    };
115
116    const error = validateForm(payload);
117    if (error) return showLimitModal("Validation Error", error, true);
118
119    toggleLoading($btn, true, "Signing In...");
120
121    with_cloudflare_captcha(false, Date.now() / 1000, (hash, token, body) => {
122        $.ajax({
123            url: API_URLS.login,
124            method: "POST",
125            data: {
126                ...payload,
127                emd_captcha_hash: hash,
128                emd_captcha_token: token,
129                // emd_captcha_3: Date.now() / 1000
130            },
131            success: (res) => handleAuthSuccess(res, payload.email),
132            error: (xhr) => handleAuthError(xhr, payload.email),
133            complete: () => toggleLoading($btn, false, "Sign In")
134        });
135    }, "light", "#captcha");
136};
137
138/**
139 * Shared Auth Handlers
140 */
141const handleAuthSuccess = (res, email) => {
142    if (res.status) {
143        window.location.href = res.url;
144    } else if (res.verify_require) {
145        const encodedEmail = encodeURIComponent(btoa(email));
146        window.location.href = `${websiteBaseUrl}/verify-email?email=${encodedEmail}`;
147    } else {
148        showLimitModal("Error!", res.mess || "Action failed", true);
149    }
150};
151
152const handleAuthError = (xhr, email) => {
153    const res = xhr.responseJSON || {};
154    if (res.verify_require) {
155        const encodedEmail = encodeURIComponent(btoa(email));
156        window.location.href = `${websiteBaseUrl}/verify-email?email=${encodedEmail}`;
157    } else {
158        const msg = res.errors ? Object.values(res.errors).flat().join(" ") : (res.mess || res.message || "Something went wrong");
159        showLimitModal("Error!", msg, true);
160    }
161};
162
163/**
164 * Forgot Password logic
165 */
166const handleForgotClick = function (e) {
167    const $btn = $(this);
168    const email = $("#email").val();
169
170    if (validateForm({ email })) return showLimitModal("Error", "Valid email required", true);
171
172    toggleLoading($btn, true, "Sending...");
173    $.post(API_URLS.forgot, { email })
174        .done(data => {
175            if (data.status) {
176                $("h1").text("Recovery Email sent!");
177                $(".login_container p").text(`We sent instructions to ${email}`);
178                $btn.text("Send again");
179                $(".form-group").first().hide();
180                //--- Email sent message ---//
181                $(".message").addClass("gc-text-success").text("Email sent successfully!");
182                setTimeout(() => {
183                    $(".message").removeClass("gc-text-success").empty();
184                }, 3000);
185            } else {
186                showLimitModal("Error", data.mess, true);
187            }
188        })
189        .fail(xhr => showLimitModal("Error", xhr.responseJSON?.message || "Failed to send email", true))
190        .always(() => toggleLoading($btn, false, "Send again"));
191};
192
193/**
194 * Reset Password Logic
195 */
196const handleResetClick = function (e) {
197    const $btn = $(this);
198    const payload = {
199        password: $("#new_password").val(),
200        confirm_password: $("#confirm_password").val()
201    };
202
203    const error = validateForm(payload);
204    if (error) return showLimitModal("Validation Error", error, true);
205
206    const token = window.location.pathname.split("/").pop();
207    toggleLoading($btn, true, "Resetting...");
208
209    $.post(API_URLS.reset(token), { ...payload, token })
210        .done(data => {
211            if (data.status) {
212                $("h1").text("Success!");
213                $(".login_container p").text("Password reset successfully.");
214                $(".form-group").hide();
215                $('.reset_button').closest('.form-group').show();
216                $btn.text("Login Now").off("click").on("click", () => {
217                    window.location.href = `${websiteBaseUrl}/login`;
218                });
219            } else {
220                showLimitModal("Error", data.mess, true);
221            }
222        })
223        .always(() => toggleLoading($btn, false, "Login"));
224};
225
226/**
227 * Password Toggle
228 */
229const togglePasswordVisibility = function () {
230    const $input = $(this).prev("input");
231    const $img = $(this).find("img");
232    const isPassword = $input.attr("type") === "password";
233
234    $input.attr("type", isPassword ? "text" : "password");
235    $img.attr("src", isPassword ? "/web_assets/frontend/img/Eye Open.svg" : "/web_assets/frontend/img/Eye Closed.svg");
236};

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.