jQuery(document).ready(function ($) { // Global variables for filter mode var allDataCache = {}; var currentCheckerId = null; // CAPTCHA token timestamps for refresh logic var captchaTokenTimestamps = {}; /** * Build secure AJAX data object with CAPTCHA tokens and honeypot * @param {string} checkerId - Checker ID * @param {object} baseData - Base data object * @returns {object} - Data object with security fields */ function buildSecureAjaxData(checkerId, baseData) { var thisChecker = $("#checker-" + checkerId); // Add nonce baseData.security = checkerSecurity.nonce; // Add reCAPTCHA token if present var recaptchaToken = thisChecker.find('input[name="recaptcha_token"]').val(); if (recaptchaToken) { baseData.recaptcha_token = recaptchaToken; console.log("Security: reCAPTCHA token added to request"); } else { console.log("Security: No reCAPTCHA token found"); } // Add Turnstile token if present var turnstileToken = thisChecker.find('input[name="turnstile_token"]').val(); if (turnstileToken) { baseData.turnstile_token = turnstileToken; console.log("Security: Turnstile token added to request"); } else { console.log("Security: No Turnstile token found"); } // Add honeypot field (should be empty) var hpInput = thisChecker.find('input[data-hp-field="1"]'); if (hpInput.length) { baseData.honeypot_name = hpInput.attr('name'); baseData.honeypot_value = hpInput.val() || ""; console.log("Security: Honeypot field added (value: " + (hpInput.val() === "" ? "empty" : "filled") + ")"); } else { var legacyHp = thisChecker.find('input[name="website_url_hp"]').val(); if (typeof legacyHp !== 'undefined') { baseData.website_url_hp = legacyHp || ""; console.log("Security: Honeypot field added (legacy value: " + (legacyHp === "" ? "empty" : "filled") + ")"); } } console.log("Security: AJAX data prepared", baseData); return baseData; } /** * Handle AJAX error responses with proper user feedback * @param {object} xhr - XHR object * @param {string} checkerId - Checker ID */ function handleAjaxError(xhr, checkerId) { var thisChecker = $("#checker-" + checkerId); var response = xhr.responseJSON; // WordPress wp_send_json_error format: {success: false, data: {message: "...", type: "..."}} if (response && response.data) { var errorType = response.data.type || 'error'; var errorMessage = response.data.message || 'An error occurred'; // Handle nonce expiry - prompt page refresh if (errorType === 'nonce_expired') { showSecurityError(checkerId, errorMessage, true); return; } // Handle CAPTCHA errors if (errorType === 'recaptcha' || errorType === 'turnstile') { showSecurityError(checkerId, errorMessage, false); // Reset CAPTCHA widget for retry resetCaptchaWidget(checkerId, errorType); return; } // Handle rate limit with enhanced message if (errorType === 'rate_limit') { showSecurityError(checkerId, errorMessage, false); return; } // Handle honeypot trigger (silent fail for bots) if (errorType === 'honeypot') { showSecurityError(checkerId, errorMessage, false); return; } // Generic error showSecurityError(checkerId, errorMessage, false); } else if (response && response.message) { // Alternative format: {success: false, message: "..."} showSecurityError(checkerId, response.message, false); } else { showSecurityError(checkerId, "An error occurred. Please try again.", false); } } /** * Show security-related error message * @param {string} checkerId - Checker ID * @param {string} message - Error message * @param {boolean} requireRefresh - Whether page refresh is required */ function showSecurityError(checkerId, message, requireRefresh) { var thisChecker = $("#checker-" + checkerId); var errorHtml = '
'; errorHtml += '' + message + ''; if (requireRefresh) { errorHtml += '
'; } errorHtml += '
'; // Remove any existing security error thisChecker.find('.dw-checker-security-error').remove(); // Insert error before the form thisChecker.find('.dw-checker-form').prepend(errorHtml); // Handle refresh button click if (requireRefresh) { thisChecker.find('.dw-checker-refresh-btn').on('click', function() { location.reload(); }); } } /** * Reset CAPTCHA widget after error * @param {string} checkerId - Checker ID * @param {string} captchaType - 'recaptcha' or 'turnstile' */ function resetCaptchaWidget(checkerId, captchaType) { var thisChecker = $("#checker-" + checkerId); if (captchaType === 'turnstile' && typeof turnstile !== 'undefined') { // Reset Turnstile widget var turnstileContainer = thisChecker.find('.dw-checker-turnstile-container')[0]; if (turnstileContainer) { turnstile.reset(turnstileContainer); } } if (captchaType === 'recaptcha') { // Clear reCAPTCHA token to force regeneration thisChecker.find('input[name="recaptcha_token"]').val('').removeAttr('data-timestamp'); delete captchaTokenTimestamps[checkerId]; } } /** * Check if CAPTCHA token needs refresh (expired or expiring soon) * @param {string} checkerId - Checker ID * @param {string} captchaType - 'recaptcha' or 'turnstile' * @returns {boolean} - Whether token needs refresh */ function needsCaptchaRefresh(checkerId, captchaType) { var thisChecker = $("#checker-" + checkerId); var tokenInput = thisChecker.find('input[name="' + captchaType + '_token"]'); if (!tokenInput.length || !tokenInput.val()) { return true; } var timestamp = tokenInput.attr('data-timestamp'); if (!timestamp) { return true; } var tokenAge = Date.now() - parseInt(timestamp); // reCAPTCHA v3 tokens expire after 2 minutes, refresh at 90 seconds if (captchaType === 'recaptcha' && tokenAge > 90000) { return true; } // Turnstile tokens expire after 5 minutes, refresh at 4 minutes if (captchaType === 'turnstile' && tokenAge > 240000) { return true; } return false; } /** * Refresh reCAPTCHA token before submission * @param {string} checkerId - Checker ID * @returns {Promise} - Resolves when token is ready */ function refreshRecaptchaToken(checkerId) { return new Promise(function(resolve, reject) { var thisChecker = $("#checker-" + checkerId); if (typeof grecaptcha === 'undefined' || !window.checkerRecaptcha) { resolve(); // No reCAPTCHA configured return; } grecaptcha.ready(function() { grecaptcha.execute(window.checkerRecaptcha.siteKey, { action: window.checkerRecaptcha.action || 'submit' }).then(function(token) { var tokenInput = thisChecker.find('input[name="recaptcha_token"]'); if (!tokenInput.length) { tokenInput = $(''); thisChecker.find('form').append(tokenInput); } tokenInput.val(token).attr('data-timestamp', Date.now().toString()); resolve(); }).catch(function(error) { console.error('reCAPTCHA refresh error:', error); reject(error); }); }); }); } /** * Get AJAX URL from localized variable * @returns {string} - AJAX URL */ function getAjaxUrl() { return checkerSecurity.ajaxurl || '/wp-admin/admin-ajax.php'; } // Initialize checker on page load initializeChecker(); function escapeHtml(value) { if (value === null || value === undefined) return ""; return String(value) .replace(/&/g, "&") .replace(//g, ">") .replace(/"/g, """) .replace(/'/g, "'"); } function ensureCaptchaReady(checkerId) { // If reCAPTCHA is configured, always refresh/generate a token (it will create the hidden input if missing) if (window.checkerRecaptcha) { return waitForRecaptcha() .then(function() { return refreshRecaptchaToken(checkerId); }) .catch(function(err) { return Promise.reject(err); }); } // Refresh Turnstile if stale var thisChecker = $("#checker-" + checkerId); var turnstileInput = thisChecker.find('input[name="turnstile_token"]'); if (turnstileInput.length && turnstileInput.val()) { var ts = parseInt(turnstileInput.attr("data-timestamp") || "0"); var age = Date.now() - ts; if (age > 240000 && typeof turnstile !== "undefined") { var container = thisChecker.find(".dw-checker-turnstile-container")[0]; if (container) { turnstile.reset(container); } turnstileInput.val(""); } } return Promise.resolve(); } function waitForRecaptcha(timeoutMs = 5000) { return new Promise(function(resolve, reject) { var start = Date.now(); (function check() { if (typeof grecaptcha !== "undefined" && typeof grecaptcha.ready === "function") { return resolve(); } if (Date.now() - start > timeoutMs) { return reject(new Error("reCAPTCHA script not loaded")); } setTimeout(check, 200); })(); }); } function initializeChecker() { $(".dw-checker-container").each(function () { var checkerId = $(this).attr("id").replace("checker-", ""); var settingsEl = $("#checker-settings-" + checkerId); if (settingsEl.length) { var settings = JSON.parse(settingsEl.text()); currentCheckerId = checkerId; // Handle URL parameters if (settings.url_params_enabled === "yes") { handleUrlParameters(checkerId, settings); } // Handle initial display mode // Only load data if initial_display is 'all' or 'limited', not 'hidden' if (settings.initial_display === "all" || settings.initial_display === "limited") { loadAllData(checkerId, settings, true); // true = initial load } // Preload captcha tokens to surface badge and avoid first-click delays ensureCaptchaReady(checkerId).catch(function(err){ console.warn("Captcha preload failed", err); showSecurityError(checkerId, checkerSecurity.i18n ? checkerSecurity.i18n.security_error : "Security validation failed.", false); }); } }); } // Get URL parameters function getUrlParams() { var params = {}; var queryString = window.location.search.substring(1); if (!queryString) return params; var pairs = queryString.split("&"); for (var i = 0; i < pairs.length; i++) { var pair = pairs[i].split("="); if (pair[0]) { params[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1] || ""); } } return params; } // Handle URL parameters function handleUrlParameters(checkerId, settings) { var urlParams = getUrlParams(); if (Object.keys(urlParams).length === 0) return; var thisChecker = $("#checker-" + checkerId); var filled = false; // Fill form fields from URL params thisChecker.find(".dw-checker-inputs").each(function () { var fieldName = $(this).data("kolom"); if (urlParams[fieldName]) { $(this).val(urlParams[fieldName]); filled = true; } }); // Auto-submit if enabled and fields were filled if (filled && settings.url_params_auto_search === "yes") { setTimeout(function () { thisChecker.find(".search-button").trigger("click"); }, 500); } } // Load all data for show all mode function loadAllData(checkerId, settings, isInitialLoad) { var limit = settings.initial_display === "limited" ? 10 : settings.max_records; var thisChecker = $("#checker-" + checkerId); // Build secure AJAX data using helper function var ajaxData = buildSecureAjaxData(checkerId, { action: "checker_load_all_data", checker_id: checkerId, limit: limit, initial_load: isInitialLoad ? "yes" : "no" }); $.ajax({ type: "post", url: getAjaxUrl(), data: ajaxData, beforeSend: function () { showLoadingState(checkerId); }, success: function (res) { if (res.success === false) { // Handle error response from wp_send_json_error handleAjaxError({ responseJSON: res }, checkerId); return; } if (res.count > 0) { allDataCache[checkerId] = res; renderResults(checkerId, res); // Enable filter mode if configured if (settings.filter_mode === "filter") { enableFilterMode(checkerId); } } else { showEmptyState(checkerId); } }, error: function (xhr) { handleAjaxError(xhr, checkerId); }, }); } // Enable real-time filter mode function enableFilterMode(checkerId) { var thisChecker = $("#checker-" + checkerId); var allData = allDataCache[checkerId]; if (!allData) return; // Listen to input changes thisChecker.find(".dw-checker-inputs").on("input", function () { var filters = {}; var hasFilters = false; // Collect all filter values thisChecker.find(".dw-checker-inputs").each(function () { var field = $(this).data("kolom"); var value = $(this).val(); if (value) { filters[field] = value.toLowerCase(); hasFilters = true; } }); // If no filters, show all data if (!hasFilters) { renderResults(checkerId, allData); return; } // Filter data client-side var filtered = allData.rows.filter(function (row) { var match = true; for (var field in filters) { var rowValue = (row[field] || "").toLowerCase(); var filterValue = filters[field]; // Check if contains (you can make this configurable) if (rowValue.indexOf(filterValue) === -1) { match = false; break; } } return match; }); // Update display with filtered results var filteredRes = { count: filtered.length, rows: filtered, settings: allData.settings, output: allData.output, }; if (filtered.length > 0) { renderResults(checkerId, filteredRes); } else { showEmptyState(checkerId, "No results match your filters"); } }); // Hide search button in filter mode thisChecker.find(".search-button").hide(); } // Show loading state function showLoadingState(checkerId) { var thisChecker = $("#checker-" + checkerId); thisChecker.find(".dw-checker-results").html(`
Loading...

Loading data...

`); } // Show empty state function showEmptyState(checkerId, message) { message = message || "No results found"; var thisChecker = $("#checker-" + checkerId); thisChecker.find(".dw-checker-results").html( `

` + message + `

Try adjusting your search criteria

`, ); } // Show error state function showErrorState(checkerId, message) { var thisChecker = $("#checker-" + checkerId); thisChecker.find(".dw-checker-results").html( `

Error: ` + message + `

`, ); } // Render results (unified function for all display types) function renderResults(checkerId, res) { var thisChecker = $("#checker-" + checkerId); var displayType = res.settings.display; // Show result container thisChecker.find(".dw-checker-result").show(); thisChecker.find(".dw-checker-form").hide(); // Render based on display type if (displayType === "vertical-table") { renderVerticalTable(checkerId, res); } else if (displayType === "standard-table") { renderStandardTable(checkerId, res); } else if (displayType === "div") { renderDivDisplay(checkerId, res); } else if (displayType === "cards") { renderCardDisplay(checkerId, res); } } // Helper function to get output setting by key function getOutputSetting(output, key) { // Convert output object to array if needed if (Array.isArray(output)) { return output.find(function (o) { return o.key === key; }); } else { // output is an object, find by matching key property for (var prop in output) { if (output[prop].key === key) { return output[prop]; } } } return null; } // Render vertical table display function renderVerticalTable(checkerId, res) { var thisChecker = $("#checker-" + checkerId); var resultDiv = ""; var perPage = 1; // One record per page for vertical table var totalPages = Math.ceil(res.count / perPage); $.each(res.rows, function (index, row) { var isFirst = index === 0; resultDiv += ''; $.each(row, function (q, r) { var id = q.replace(/\s/g, "_").replace(/\./g, "_").toLowerCase(); var outputSetting = getOutputSetting(res.output, q); if (!outputSetting || outputSetting.hide === "yes") return; var prefix = escapeHtml(outputSetting.prefix || ""); var type = outputSetting.type || "text"; var button_text = escapeHtml(outputSetting.button_text || "Click"); var bg_color = escapeHtml(outputSetting.bg_color || "#333333"); var text_color = escapeHtml(outputSetting.text_color || "#ffffff"); var safeQ = escapeHtml(q); var safeVal = escapeHtml(r); if (type == "link_button") { safeVal = '' + button_text + ""; } else if (type == "whatsapp_button") { safeVal = '' + button_text + ""; } else if (type == "image") { safeVal = '' +
            safeQ +
            ''; } resultDiv += ""; resultDiv += '"; resultDiv += '"; resultDiv += ""; }); resultDiv += "
' + safeQ + "' + prefix + safeVal + "
"; }); // Add enhanced pagination if (totalPages > 1) { resultDiv += createEnhancedPagination(totalPages, 1); } thisChecker.find(".dw-checker-results").html(resultDiv); } // Render standard table display function renderStandardTable(checkerId, res) { var thisChecker = $("#checker-" + checkerId); var resultDiv = ''; // Headers if (res.rows.length > 0) { $.each(res.rows[0], function (q, r) { var outputSetting = getOutputSetting(res.output, q); if (!outputSetting || outputSetting.hide === "yes") return; resultDiv += '"; }); } resultDiv += ""; // Rows $.each(res.rows, function (index, row) { resultDiv += ""; $.each(row, function (q, r) { var id = q.replace(/\s/g, "_").replace(/\./g, "_").toLowerCase(); var outputSetting = getOutputSetting(res.output, q); if (!outputSetting || outputSetting.hide === "yes") return; var prefix = escapeHtml(outputSetting.prefix || ""); var type = outputSetting.type || "text"; var button_text = escapeHtml(outputSetting.button_text || "Click"); var bg_color = escapeHtml(outputSetting.bg_color || "#333333"); var text_color = escapeHtml(outputSetting.text_color || "#ffffff"); var safeVal = escapeHtml(r); if (type == "link_button") { safeVal = '' + button_text + ""; } else if (type == "whatsapp_button") { safeVal = '' + button_text + ""; } else if (type == "image") { safeVal = '' +
            escapeHtml(q) +
            ''; } resultDiv += '"; }); resultDiv += ""; }); resultDiv += "
' + escapeHtml(q) + "
' + prefix + safeVal + "
"; thisChecker.find(".dw-checker-results").html(resultDiv); // Initialize DataTable setTimeout(function () { var tbl = thisChecker.find(".dw-checker-result-container"); if (!tbl.length || typeof tbl.DataTable !== "function") { return; } var dt = tbl.DataTable({ paging: true, pageLength: 10, searching: false, // Hide search input info: false, // Hide "Showing X of Y entries" scrollX: false, // Disable horizontal scrolling by default responsive: true, autoWidth: true, deferRender: true, columnDefs: [ { targets: "th", className: "dt-left", width: "auto", }, { targets: "td", className: "dt-left", width: "auto", }, ], drawCallback: function (settings) { var api = this.api(); var tableObj = api.table(); if (!tableObj) { return; } var containerEl = tableObj.container(); var tableWidth = containerEl.clientWidth || containerEl.getBoundingClientRect().width; var contentWidth = tableObj.node().scrollWidth; if (contentWidth > tableWidth) { containerEl.style.overflowX = "auto"; } else { containerEl.style.overflowX = "hidden"; } }, }); // Adjust columns once dt.columns.adjust(); }, 100); } // Render div display function renderDivDisplay(checkerId, res) { var thisChecker = $("#checker-" + checkerId); var resultDiv = ""; var perPage = 1; var totalPages = Math.ceil(res.count / perPage); $.each(res.rows, function (index, row) { var isFirst = index === 0; resultDiv += '
'; $.each(row, function (q, r) { var id = q.replace(/\s/g, "_").replace(/\./g, "_").toLowerCase(); var outputSetting = getOutputSetting(res.output, q); if (!outputSetting || outputSetting.hide === "yes") return; var prefix = escapeHtml(outputSetting.prefix || ""); var type = outputSetting.type || "text"; var button_text = escapeHtml(outputSetting.button_text || "Click"); var bg_color = escapeHtml(outputSetting.bg_color || "#333333"); var text_color = escapeHtml(outputSetting.text_color || "#ffffff"); var safeQ = escapeHtml(q); var safeVal = escapeHtml(r); if (type == "link_button") { safeVal = '' + button_text + ""; } else if (type == "whatsapp_button") { safeVal = '' + button_text + ""; } else if (type == "image") { safeVal = '' +
            safeQ +
            ''; } resultDiv += '
'; resultDiv += '
' + safeQ + "
"; resultDiv += '
' + prefix + safeVal + "
"; resultDiv += "
"; }); resultDiv += "
"; }); // Add enhanced pagination if (totalPages > 1) { resultDiv += createEnhancedPagination(totalPages, 1); } thisChecker.find(".dw-checker-results").html(resultDiv); } // Render card display function renderCardDisplay(checkerId, res) { var thisChecker = $("#checker-" + checkerId); var resultDiv = ""; var perPage = 1; var totalPages = Math.ceil(res.count / perPage); $.each(res.rows, function (index, row) { var isFirst = index === 0; resultDiv += '
'; $.each(row, function (q, r) { var id = q.replace(/\s/g, "_").replace(/\./g, "_").toLowerCase(); var outputSetting = getOutputSetting(res.output, q); if (!outputSetting || outputSetting.hide === "yes") return; var prefix = escapeHtml(outputSetting.prefix || ""); var type = outputSetting.type || "text"; var button_text = escapeHtml(outputSetting.button_text || "Click"); var bg_color = escapeHtml(outputSetting.bg_color || "#333333"); var text_color = escapeHtml(outputSetting.text_color || "#ffffff"); var safeQ = escapeHtml(q); var safeVal = escapeHtml(r); if (type == "link_button") { safeVal = '' + button_text + ""; } else if (type == "whatsapp_button") { safeVal = '' + button_text + ""; } else if (type == "image") { safeVal = '' +
            safeQ +
            ''; } resultDiv += '
'; resultDiv += '' + safeQ + ""; resultDiv += '' + prefix + safeVal + ""; resultDiv += "
"; }); resultDiv += "
"; }); // Add enhanced pagination if (totalPages > 1) { resultDiv += createEnhancedPagination(totalPages, 1); } thisChecker.find(".dw-checker-results").html(resultDiv); } // Create enhanced pagination with Previous/Next buttons function createEnhancedPagination(totalPages, currentPage) { var html = '
'; // Previous button html += ''; // Page numbers (show max 5 pages) var startPage = Math.max(1, currentPage - 2); var endPage = Math.min(totalPages, startPage + 4); if (endPage - startPage < 4) { startPage = Math.max(1, endPage - 4); } for (var i = startPage; i <= endPage; i++) { var active = i === currentPage ? ' style="background: #333; color: #fff;"' : ""; html += '"; } // Next button html += ''; html += "
"; return html; } // Handle pagination clicks (delegated event) $(document).on("click", ".pagination-btn", function () { if ($(this).prop("disabled")) return; var page = parseInt($(this).data("page")); var containers = $(this) .closest(".dw-checker-results") .find(".dw-checker-result-container"); // Hide all containers containers.hide(); // Show selected page (0-indexed) containers.eq(page - 1).show(); // Update pagination buttons var totalPages = containers.length; var newPagination = createEnhancedPagination(totalPages, page); $(this).closest(".dw-checker-pagination").replaceWith(newPagination); }); $(".dw-checker-inputs").on("input change blur", function () { $(this).siblings(".dw-checker-input-validator").remove(); if ($(this).val().length == 0) { $(this) .parents(".dw-checker-field") .append( '
' + $(this).data("kolom") + " is required!
", ); } }); $(".search-button").on("click", function (e) { e.preventDefault(); var $this = $(this); var $id = $this.data("checker"); var this_checker = $("#checker-" + $id); var inputs = this_checker.find(".dw-checker-inputs"); var inputs_count = inputs.length; var validator = []; var submission = []; if (inputs.length > 0) { $.each(inputs, function (m, n) { if ($(n).val().length == 0) { $(n) .parents(".dw-checker-field") .append( '
' + $(n).data("kolom") + " is required!
", ); $(n).addClass("dw-checker-input-validator-border"); return false; } validator.push({ kolom: $(n).data("kolom"), value: $(n).val(), }); submission.push($(n).val()); }); var validator_count = validator.length; if (validator_count == inputs_count) { // Remove any existing security errors this_checker.find('.dw-checker-security-error').remove(); // Function to perform the actual AJAX request var performSearch = function() { // Build secure AJAX data using helper function var ajaxData = buildSecureAjaxData($id, { action: "checker_public_validation", checker_id: $id, validate: validator, }); $.ajax({ type: "post", url: getAjaxUrl(), data: ajaxData, beforeSend: function () { $this.attr("data-text", $(this).text()); $this.text("Searching...").prop("disabled", true); this_checker .find(".dw-checker-result") .find(".dw-checker-title") .html(""); this_checker .find(".dw-checker-result") .find(".dw-checker-description") .html(""); this_checker .find(".dw-checker-result") .find(".dw-checker-results") .html(""); this_checker .find(".dw-checker-result") .find(".dw-checker-bottom-results") .html(""); }, success: function (res) { console.log(res); $this.text($this.attr("data-btn-text")).prop("disabled", false); // Handle error response from wp_send_json_error if (res.success === false) { handleAjaxError({ responseJSON: res }, $id); return; } var title = ""; var desc = ""; if (res.count == 0) { title = "Not Found!"; desc = "Recheck your request and click search again"; } else { var records = "record"; if (res.count > 1) { records = "records"; } title = res.count + " " + records + " found"; desc = "You got " + res.count + " " + records + " matching " + submission.join(" - ") + ""; } $this.text($(this).attr("data-text")).prop("disabled", false); this_checker.find(".dw-checker-form").hide(); this_checker .find(".dw-checker-result") .find(".dw-checker-title") .html(title); this_checker .find(".dw-checker-result") .find(".dw-checker-description") .html(desc); this_checker.find(".dw-checker-result").show(); if (res.rows.length > 0) { var resultDiv = ""; var pagination = ""; if (res.rows.length > 1) { resultDiv += '
'; var list = []; for (var i = 1; i <= res.rows.length; i++) { list.push(i); } $.each(list, function (r, o) { var active = ""; if (r == 0) { active = " active"; } resultDiv += '"; }); resultDiv += "
"; } if (res.settings.display == "vertical-table") { $.each(res.rows, function (index, item) { resultData = item; if (index == 0) { resultDiv += ''; } else { resultDiv += '
'; } var header_color = res.settings.header; var value_color = res.settings.value; $.each(item, function (q, r) { var id = q .replace(" ", "_") .replace(".", "_") .toLowerCase(); var prefix = ""; var type = ""; var button_text = ""; var hidden = "no"; $.each(res.output, function (o, p) { if (q == p.key) { prefix = p.prefix; type = p.type; button_text = p.button_text; if ("hide" in p) { hidden = p.hide; } } }); if (hidden == "yes") { return; } if (type == "link_button") { r = '' + button_text + ""; } else if (type == "whatsapp_button") { r = '' + button_text + ""; } else if (type == "image") { r = '' +
                        q +
                        ''; } resultDiv += ""; resultDiv += '"; resultDiv += '"; resultDiv += ""; }); resultDiv += ""; }); this_checker .find(".dw-checker-result") .find(".dw-checker-results") .html(resultDiv); } else if (res.settings.display == "div") { $.each(res.rows, function (index, item) { resultData = item; var header_color = res.settings.header; var value_color = res.settings.value; // Create container div for this row if (index == 0) { resultDiv += '
'; } else { resultDiv += '"; }); this_checker .find(".dw-checker-result") .find(".dw-checker-results") .html(resultDiv); } else if (res.settings.display == "standard-table") { this_checker.find(".dw-checker-divider:nth-child(3)").hide(); resultDiv = ''; var header_color = res.settings.header; var value_color = res.settings.value; resultDiv += ""; $.each(res.output, function (header, value) { var hidden = "no"; if ("hide" in value) { hidden = value.hide; } if (hidden !== "yes") { resultDiv += ""; } }); resultDiv += ""; resultDiv += ""; $.each(res.rows, function (index, item) { resultData = item; resultDiv += ""; $.each(item, function (q, r) { var id = q .replace(" ", "_") .replace(".", "_") .toLowerCase(); var prefix = ""; var type = ""; var button_text = ""; var hidden = "no"; $.each(res.output, function (o, p) { if (q == p.key) { prefix = p.prefix; type = p.type; button_text = p.button_text; if ("hide" in p) { hidden = p.hide; } } }); if (hidden == "yes") { return; } if (type == "link_button") { r = '' + button_text + ""; } else if (type == "whatsapp_button") { r = '' + button_text + ""; } else if (type == "image") { r = '' +
                        q +
                        ''; } resultDiv += '"; }); resultDiv += ""; }); resultDiv += ""; resultDiv += "
" + value.key + "
' + prefix + r + "
"; this_checker.next(".dw-checker-bottom-results").html(resultDiv); var stdTable = this_checker .next(".dw-checker-bottom-results") .find("table.dw-checker-result-container"); if (stdTable.length && typeof stdTable.DataTable === "function") { stdTable.DataTable({ paging: true, pageLength: 10, searching: false, // Hide search input info: false, // Hide "Showing X of Y entries" scrollX: false, // Disable horizontal scrolling by default responsive: true, autoWidth: true, deferRender: true, columnDefs: [ { targets: "th", className: "dt-left", width: "auto", }, { targets: "td", className: "dt-left", width: "auto", }, ], drawCallback: function () { var api = this.api(); var tableObj = api.table(); if (!tableObj) { return; } var containerEl = tableObj.container(); var tableWidth = containerEl.clientWidth || containerEl.getBoundingClientRect().width; var contentWidth = tableObj.node().scrollWidth; if (contentWidth > tableWidth) { containerEl.style.overflowX = "auto"; } else { containerEl.style.overflowX = "hidden"; } }, }).columns.adjust(); } } else if (res.settings.display == "card") { this_checker.find(".dw-checker-divider:nth-child(3)").hide(); $.each(res.rows, function (index, item) { resultData = item; resultDiv += ` `; resultDiv += '"; this_checker .next(".dw-checker-bottom-results") .html(resultDiv); }); } } }, error: function (xhr) { $this.text($this.attr("data-btn-text")).prop("disabled", false); handleAjaxError(xhr, $id); } }); }; // End of performSearch function ensureCaptchaReady($id) .then(function() { performSearch(); }) .catch(function(err) { console.error("Captcha refresh failed", err); showSecurityError($id, checkerSecurity.i18n ? checkerSecurity.i18n.security_error : "Security validation failed.", false); }); } } }); $(document).on("click", ".dw-checker-result-pagination-button", function (e) { e.preventDefault(); var container = $(this).data("target-pagination"); var page = container - 1; $(".dw-checker-result-pagination-button").removeClass("active"); $(this).addClass("active"); $(".dw-checker-result-container").hide(); $("[data-pagination=" + page + "]").show(); }); $(".back-button").on("click", function () { var checker_id = $(this).data("checker"); $("#checker-" + checker_id) .find(".dw-checker-result") .hide(); $("#checker-" + checker_id) .find(".dw-checker-result") .find(".dw-checker-title") .html(""); $("#checker-" + checker_id) .find(".dw-checker-result") .find(".dw-checker-description") .html(""); $("#checker-" + checker_id) .find(".dw-checker-result") .find(".dw-checker-results") .html(""); $("#checker-" + checker_id) .find(".dw-checker-inputs") .val(""); $("#checker-" + checker_id) .find(".dw-checker-form") .show(); $("#checker-" + checker_id) .find(".dw-checker-divider") .show(); }); // Frontend clear cache button handler $(document).on("click", ".dw-checker-clear-cache-btn", function () { var btn = $(this); var checkerId = btn.data("checker"); var originalText = btn.html(); btn.prop("disabled", true).html(' ' + (checkerSecurity.i18n && checkerSecurity.i18n.refreshing ? checkerSecurity.i18n.refreshing : 'Refreshing...')); $.ajax({ url: getAjaxUrl(), type: "POST", data: { action: "checker_clear_cache", checker_id: checkerId, security: checkerSecurity.nonce }, success: function (response) { if (response.success) { // Show success message briefly btn.html(' ' + (response.data.message || 'Refreshed!')); // Reset button after 2 seconds setTimeout(function () { btn.prop("disabled", false).html(originalText); }, 2000); } else { btn.html(' Failed'); setTimeout(function () { btn.prop("disabled", false).html(originalText); }, 2000); } }, error: function () { btn.html(' Error'); setTimeout(function () { btn.prop("disabled", false).html(originalText); }, 2000); } }); }); // Add CSS animation for spinning icon if (!document.getElementById('dw-checker-spin-animation')) { var style = document.createElement('style'); style.id = 'dw-checker-spin-animation'; style.textContent = '@keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } }'; document.head.appendChild(style); } }); // Image Lightbox Function function openImageLightbox(img) { var fullsizeUrl = img.getAttribute("data-fullsize"); var alt = img.getAttribute("alt"); // Create lightbox overlay var lightbox = document.createElement("div"); lightbox.id = "dw-checker-lightbox"; lightbox.style.cssText = "position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,0.9);z-index:99999;display:flex;align-items:center;justify-content:center;cursor:pointer;"; // Create image element var lightboxImg = document.createElement("img"); lightboxImg.src = fullsizeUrl; lightboxImg.alt = alt; lightboxImg.style.cssText = "max-width:90%;max-height:90%;object-fit:contain;"; // Create close button var closeBtn = document.createElement("span"); closeBtn.innerHTML = "×"; closeBtn.style.cssText = "position:absolute;top:20px;right:40px;color:#fff;font-size:40px;font-weight:bold;cursor:pointer;"; // Append elements lightbox.appendChild(lightboxImg); lightbox.appendChild(closeBtn); document.body.appendChild(lightbox); // Close on click lightbox.onclick = function () { document.body.removeChild(lightbox); }; // Prevent image click from closing lightboxImg.onclick = function (e) { e.stopPropagation(); }; }