1848 lines
64 KiB
JavaScript
1848 lines
64 KiB
JavaScript
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 = '<div class="dw-checker-security-error" style="color: #dc3545; padding: 10px; margin: 10px 0; background: #f8d7da; border-radius: 4px;">';
|
|
errorHtml += '<strong>' + message + '</strong>';
|
|
if (requireRefresh) {
|
|
errorHtml += '<br><button type="button" class="dw-checker-refresh-btn" style="margin-top: 10px; padding: 5px 15px; cursor: pointer;">' +
|
|
(checkerSecurity.i18n && checkerSecurity.i18n.refresh_page ? checkerSecurity.i18n.refresh_page : 'Refresh Page') + '</button>';
|
|
}
|
|
errorHtml += '</div>';
|
|
|
|
// 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 = $('<input type="hidden" name="recaptcha_token">');
|
|
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, """)
|
|
.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(`
|
|
<div class="dw-checker-loading" style="text-align: center; padding: 2rem;">
|
|
<div class="spinner-border" role="status" style="width: 3rem; height: 3rem; border-width: 0.3rem;">
|
|
<span class="visually-hidden">Loading...</span>
|
|
</div>
|
|
<p style="margin-top: 1rem; color: #666;">Loading data...</p>
|
|
</div>
|
|
`);
|
|
}
|
|
|
|
// Show empty state
|
|
function showEmptyState(checkerId, message) {
|
|
message = message || "No results found";
|
|
var thisChecker = $("#checker-" + checkerId);
|
|
thisChecker.find(".dw-checker-results").html(
|
|
`
|
|
<div class="dw-checker-empty-state" style="text-align: center; padding: 3rem 1rem;">
|
|
<svg width="64" height="64" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="margin-bottom: 1rem; color: #ccc;">
|
|
<circle cx="11" cy="11" r="8"></circle>
|
|
<path d="m21 21-4.35-4.35"></path>
|
|
</svg>
|
|
<h3 style="color: #666; margin-bottom: 0.5rem;">` +
|
|
message +
|
|
`</h3>
|
|
<p style="color: #999;">Try adjusting your search criteria</p>
|
|
</div>
|
|
`,
|
|
);
|
|
}
|
|
|
|
// Show error state
|
|
function showErrorState(checkerId, message) {
|
|
var thisChecker = $("#checker-" + checkerId);
|
|
thisChecker.find(".dw-checker-results").html(
|
|
`
|
|
<div class="dw-checker-error-state" style="text-align: center; padding: 2rem; color: #dc3545;">
|
|
<p><strong>Error:</strong> ` +
|
|
message +
|
|
`</p>
|
|
</div>
|
|
`,
|
|
);
|
|
}
|
|
|
|
// 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 +=
|
|
'<table class="dw-checker-result-container" data-pagination="' +
|
|
index +
|
|
'" style="' +
|
|
(isFirst ? "" : "display: none;") +
|
|
"border-color: " +
|
|
res.settings.divider +
|
|
"; border-width: " +
|
|
res.settings.divider_width +
|
|
'px;"><tbody>';
|
|
|
|
$.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 =
|
|
'<a href="' +
|
|
safeVal +
|
|
'" class="button dw-checker-value-button dw-checker-btn-' +
|
|
id +
|
|
'" target="_blank" rel="noopener" style="background-color: ' +
|
|
bg_color +
|
|
"; color: " +
|
|
text_color +
|
|
';">' +
|
|
button_text +
|
|
"</a>";
|
|
} else if (type == "whatsapp_button") {
|
|
safeVal =
|
|
'<a href="https://wa.me/' +
|
|
safeVal +
|
|
'" class="button dw-checker-value-button dw-checker-btn-' +
|
|
id +
|
|
'" target="_blank" rel="noopener" style="background-color: ' +
|
|
bg_color +
|
|
"; color: " +
|
|
text_color +
|
|
';">' +
|
|
button_text +
|
|
"</a>";
|
|
} else if (type == "image") {
|
|
safeVal =
|
|
'<img src="' +
|
|
safeVal +
|
|
'" class="dw-checker-image dw-checker-img-' +
|
|
id +
|
|
'" style="max-width: 150px; height: auto; cursor: pointer;" onclick="openImageLightbox(this)" data-fullsize="' +
|
|
safeVal +
|
|
'" alt="' +
|
|
safeQ +
|
|
'" />';
|
|
}
|
|
|
|
resultDiv += "<tr>";
|
|
resultDiv +=
|
|
'<th style="border-color: ' +
|
|
res.settings.divider +
|
|
"; border-width: " +
|
|
res.settings.divider_width +
|
|
'px;"><span class="dw-checker-result-header" style="color:' +
|
|
res.settings.header +
|
|
'">' +
|
|
safeQ +
|
|
"</span></th>";
|
|
resultDiv +=
|
|
'<td style="border-color: ' +
|
|
res.settings.divider +
|
|
"; border-width: " +
|
|
res.settings.divider_width +
|
|
'px;"><span class="dw-checker-result-value" style="color:' +
|
|
res.settings.value +
|
|
'">' +
|
|
prefix +
|
|
safeVal +
|
|
"</span></td>";
|
|
resultDiv += "</tr>";
|
|
});
|
|
|
|
resultDiv += "</tbody></table>";
|
|
});
|
|
|
|
// 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 =
|
|
'<table class="dw-checker-result-container display" style="width:100%"><thead><tr>';
|
|
|
|
// 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 +=
|
|
'<th style="color:' + res.settings.header + '">' + escapeHtml(q) + "</th>";
|
|
});
|
|
}
|
|
resultDiv += "</tr></thead><tbody>";
|
|
|
|
// Rows
|
|
$.each(res.rows, function (index, row) {
|
|
resultDiv += "<tr>";
|
|
$.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 =
|
|
'<a href="' +
|
|
safeVal +
|
|
'" class="button dw-checker-value-button dw-checker-btn-' +
|
|
id +
|
|
'" target="_blank" rel="noopener" style="background-color: ' +
|
|
bg_color +
|
|
"; color: " +
|
|
text_color +
|
|
';">' +
|
|
button_text +
|
|
"</a>";
|
|
} else if (type == "whatsapp_button") {
|
|
safeVal =
|
|
'<a href="https://wa.me/' +
|
|
safeVal +
|
|
'" class="button dw-checker-value-button dw-checker-btn-' +
|
|
id +
|
|
'" target="_blank" rel="noopener" style="background-color: ' +
|
|
bg_color +
|
|
"; color: " +
|
|
text_color +
|
|
';">' +
|
|
button_text +
|
|
"</a>";
|
|
} else if (type == "image") {
|
|
safeVal =
|
|
'<img src="' +
|
|
safeVal +
|
|
'" class="dw-checker-image dw-checker-img-' +
|
|
id +
|
|
'" style="max-width: 150px; height: auto; cursor: pointer;" onclick="openImageLightbox(this)" data-fullsize="' +
|
|
safeVal +
|
|
'" alt="' +
|
|
escapeHtml(q) +
|
|
'" />';
|
|
}
|
|
|
|
resultDiv +=
|
|
'<td style="color:' +
|
|
res.settings.value +
|
|
'">' +
|
|
prefix +
|
|
safeVal +
|
|
"</td>";
|
|
});
|
|
resultDiv += "</tr>";
|
|
});
|
|
|
|
resultDiv += "</tbody></table>";
|
|
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 +=
|
|
'<div class="dw-checker-result-container" data-pagination="' +
|
|
index +
|
|
'" style="' +
|
|
(isFirst ? "" : "display: none;") +
|
|
'">';
|
|
|
|
$.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 =
|
|
'<a href="' +
|
|
safeVal +
|
|
'" class="button dw-checker-value-button dw-checker-btn-' +
|
|
id +
|
|
'" target="_blank" rel="noopener" style="background-color: ' +
|
|
bg_color +
|
|
"; color: " +
|
|
text_color +
|
|
';">' +
|
|
button_text +
|
|
"</a>";
|
|
} else if (type == "whatsapp_button") {
|
|
safeVal =
|
|
'<a href="https://wa.me/' +
|
|
safeVal +
|
|
'" class="button dw-checker-value-button dw-checker-btn-' +
|
|
id +
|
|
'" target="_blank" rel="noopener" style="background-color: ' +
|
|
bg_color +
|
|
"; color: " +
|
|
text_color +
|
|
';">' +
|
|
button_text +
|
|
"</a>";
|
|
} else if (type == "image") {
|
|
safeVal =
|
|
'<img src="' +
|
|
safeVal +
|
|
'" class="dw-checker-image dw-checker-img-' +
|
|
id +
|
|
'" style="max-width: 150px; height: auto; cursor: pointer;" onclick="openImageLightbox(this)" data-fullsize="' +
|
|
safeVal +
|
|
'" alt="' +
|
|
safeQ +
|
|
'" />';
|
|
}
|
|
|
|
resultDiv +=
|
|
'<div class="dw-checker-result-div" style="border-bottom-color: ' +
|
|
res.settings.divider +
|
|
"; border-bottom-width: " +
|
|
res.settings.divider_width +
|
|
'px;">';
|
|
resultDiv +=
|
|
'<div class="result-header"><span class="dw-checker-result-header" style="color:' +
|
|
res.settings.header +
|
|
';">' +
|
|
safeQ +
|
|
"</span></div>";
|
|
resultDiv +=
|
|
'<div class="result-value"><span class="dw-checker-result-value" style="color:' +
|
|
res.settings.value +
|
|
';">' +
|
|
prefix +
|
|
safeVal +
|
|
"</span></div>";
|
|
resultDiv += "</div>";
|
|
});
|
|
|
|
resultDiv += "</div>";
|
|
});
|
|
|
|
// 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 +=
|
|
'<div class="dw-checker-result-container dw-checker-card-container" data-pagination="' +
|
|
index +
|
|
'" style="' +
|
|
(isFirst ? "" : "display: none;") +
|
|
'">';
|
|
|
|
$.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 =
|
|
'<a href="' +
|
|
safeVal +
|
|
'" class="button dw-checker-value-button dw-checker-btn-' +
|
|
id +
|
|
'" target="_blank" rel="noopener" style="background-color: ' +
|
|
bg_color +
|
|
"; color: " +
|
|
text_color +
|
|
';">' +
|
|
button_text +
|
|
"</a>";
|
|
} else if (type == "whatsapp_button") {
|
|
safeVal =
|
|
'<a href="https://wa.me/' +
|
|
safeVal +
|
|
'" class="button dw-checker-value-button dw-checker-btn-' +
|
|
id +
|
|
'" target="_blank" rel="noopener" style="background-color: ' +
|
|
bg_color +
|
|
"; color: " +
|
|
text_color +
|
|
';">' +
|
|
button_text +
|
|
"</a>";
|
|
} else if (type == "image") {
|
|
safeVal =
|
|
'<img src="' +
|
|
safeVal +
|
|
'" class="dw-checker-image dw-checker-img-' +
|
|
id +
|
|
'" style="max-width: 100%; height: auto; cursor: pointer;" onclick="openImageLightbox(this)" data-fullsize="' +
|
|
safeVal +
|
|
'" alt="' +
|
|
safeQ +
|
|
'" />';
|
|
}
|
|
|
|
resultDiv +=
|
|
'<div class="dw-checker-single-card" style="background-color: ' +
|
|
bg_color +
|
|
"; color: " +
|
|
text_color +
|
|
"; border-color: " +
|
|
res.settings.divider +
|
|
"; border-width: " +
|
|
res.settings.divider_width +
|
|
'px;">';
|
|
resultDiv +=
|
|
'<span class="dw-checker-card-header" style="color:' +
|
|
text_color +
|
|
'">' +
|
|
safeQ +
|
|
"</span>";
|
|
resultDiv +=
|
|
'<span class="dw-checker-card-value" style="color:' +
|
|
text_color +
|
|
'">' +
|
|
prefix +
|
|
safeVal +
|
|
"</span>";
|
|
resultDiv += "</div>";
|
|
});
|
|
|
|
resultDiv += "</div>";
|
|
});
|
|
|
|
// 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 =
|
|
'<div class="dw-checker-pagination" style="margin-top: 1rem; display: flex; gap: 0.5rem; justify-content: center; align-items: center; flex-wrap: wrap;">';
|
|
|
|
// Previous button
|
|
html +=
|
|
'<button class="pagination-btn pagination-prev" data-page="' +
|
|
(currentPage - 1) +
|
|
'" ' +
|
|
(currentPage === 1 ? "disabled" : "") +
|
|
' style="padding: 0.5rem 1rem; border: 1px solid #ddd; background: #fff; cursor: pointer;">Previous</button>';
|
|
|
|
// 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 +=
|
|
'<button class="pagination-btn pagination-page" data-page="' +
|
|
i +
|
|
'"' +
|
|
active +
|
|
' style="padding: 0.5rem 1rem; border: 1px solid #ddd; background: #fff; cursor: pointer;">' +
|
|
i +
|
|
"</button>";
|
|
}
|
|
|
|
// Next button
|
|
html +=
|
|
'<button class="pagination-btn pagination-next" data-page="' +
|
|
(currentPage + 1) +
|
|
'" ' +
|
|
(currentPage === totalPages ? "disabled" : "") +
|
|
' style="padding: 0.5rem 1rem; border: 1px solid #ddd; background: #fff; cursor: pointer;">Next</button>';
|
|
|
|
html += "</div>";
|
|
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(
|
|
'<div class="dw-checker-input-validator">' +
|
|
$(this).data("kolom") +
|
|
" is required!</div>",
|
|
);
|
|
}
|
|
});
|
|
|
|
$(".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(
|
|
'<div class="dw-checker-input-validator">' +
|
|
$(n).data("kolom") +
|
|
" is required!</div>",
|
|
);
|
|
$(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 <b>" +
|
|
submission.join(" - ") +
|
|
"</b>";
|
|
}
|
|
$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 += '<div class="dw-checker-result-pagination">';
|
|
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 +=
|
|
'<button class="dw-checker-result-pagination-button' +
|
|
active +
|
|
'" data-target-pagination="' +
|
|
o +
|
|
'">' +
|
|
o +
|
|
"</button>";
|
|
});
|
|
resultDiv += "</div>";
|
|
}
|
|
|
|
if (res.settings.display == "vertical-table") {
|
|
$.each(res.rows, function (index, item) {
|
|
resultData = item;
|
|
if (index == 0) {
|
|
resultDiv +=
|
|
'<table class="dw-checker-result-container" data-pagination="' +
|
|
index +
|
|
'" style="border-color: ' +
|
|
res.settings.divider +
|
|
"; border-width: " +
|
|
res.settings.divider_width +
|
|
'px;"><tbody>';
|
|
} else {
|
|
resultDiv +=
|
|
'<table class="dw-checker-result-container" data-pagination="' +
|
|
index +
|
|
'" style="display: none; border-color: ' +
|
|
res.settings.divider +
|
|
"; border-width: " +
|
|
res.settings.divider_width +
|
|
'px;"><tbody>';
|
|
}
|
|
|
|
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 =
|
|
'<a href="' +
|
|
r +
|
|
'" class="button dw-checker-value-button dw-checker-btn-' +
|
|
id +
|
|
'" target="_blank" rel="noopener">' +
|
|
button_text +
|
|
"</a>";
|
|
} else if (type == "whatsapp_button") {
|
|
r =
|
|
'<a href="https://wa.me/' +
|
|
r +
|
|
'" class="button dw-checker-value-button dw-checker-btn-' +
|
|
id +
|
|
'" target="_blank" rel="noopener">' +
|
|
button_text +
|
|
"</a>";
|
|
} else if (type == "image") {
|
|
r =
|
|
'<img src="' +
|
|
r +
|
|
'" class="dw-checker-image dw-checker-img-' +
|
|
id +
|
|
'" style="max-width: 150px; height: auto; cursor: pointer;" onclick="openImageLightbox(this)" data-fullsize="' +
|
|
r +
|
|
'" alt="' +
|
|
q +
|
|
'" />';
|
|
}
|
|
resultDiv += "<tr>";
|
|
resultDiv +=
|
|
'<th style="border-color: ' +
|
|
res.settings.divider +
|
|
"; border-width: " +
|
|
res.settings.divider_width +
|
|
'px;"><span class="dw-checker-result-header" style="color:' +
|
|
header_color +
|
|
'">' +
|
|
q +
|
|
"</span></th>";
|
|
resultDiv +=
|
|
'<td style="border-color: ' +
|
|
res.settings.divider +
|
|
"; border-width: " +
|
|
res.settings.divider_width +
|
|
'px;"><span class="dw-checker-result-value" style="color:' +
|
|
value_color +
|
|
'">' +
|
|
prefix +
|
|
r +
|
|
"</span></td>";
|
|
resultDiv += "</tr>";
|
|
});
|
|
resultDiv += "</tbody></table>";
|
|
});
|
|
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 +=
|
|
'<div class="dw-checker-result-container" data-pagination="' +
|
|
index +
|
|
'">';
|
|
} else {
|
|
resultDiv +=
|
|
'<div class="dw-checker-result-container" data-pagination="' +
|
|
index +
|
|
'" style="display: none;">';
|
|
}
|
|
|
|
// Loop through each field in the row
|
|
$.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 =
|
|
'<a href="' +
|
|
r +
|
|
'" class="button dw-checker-value-button dw-checker-btn-' +
|
|
id +
|
|
'" target="_blank" rel="noopener">' +
|
|
button_text +
|
|
"</a>";
|
|
} else if (type == "whatsapp_button") {
|
|
r =
|
|
'<a href="https://wa.me/' +
|
|
r +
|
|
'" class="button dw-checker-value-button dw-checker-btn-' +
|
|
id +
|
|
'" target="_blank" rel="noopener">' +
|
|
button_text +
|
|
"</a>";
|
|
} else if (type == "image") {
|
|
r =
|
|
'<img src="' +
|
|
r +
|
|
'" class="dw-checker-image dw-checker-img-' +
|
|
id +
|
|
'" style="max-width: 150px; height: auto; cursor: pointer;" onclick="openImageLightbox(this)" data-fullsize="' +
|
|
r +
|
|
'" alt="' +
|
|
q +
|
|
'" />';
|
|
}
|
|
|
|
resultDiv +=
|
|
'<div class="dw-checker-result-div" style="border-bottom-color: ' +
|
|
res.settings.divider +
|
|
"; border-bottom-width: " +
|
|
res.settings.divider_width +
|
|
'px;">';
|
|
resultDiv +=
|
|
'<div class="result-header"><span class="dw-checker-result-header" style="color:' +
|
|
header_color +
|
|
';">' +
|
|
q +
|
|
"</span></div>";
|
|
resultDiv +=
|
|
'<div class="result-value"><span class="dw-checker-result-value" style="color:' +
|
|
value_color +
|
|
';">' +
|
|
prefix +
|
|
r +
|
|
"</span></div>";
|
|
resultDiv += "</div>";
|
|
});
|
|
|
|
// Close container div for this row
|
|
resultDiv += "</div>";
|
|
});
|
|
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 =
|
|
'<table class="dw-checker-result-container display nowrap">';
|
|
|
|
var header_color = res.settings.header;
|
|
var value_color = res.settings.value;
|
|
|
|
resultDiv += "<thead><tr>";
|
|
$.each(res.output, function (header, value) {
|
|
var hidden = "no";
|
|
if ("hide" in value) {
|
|
hidden = value.hide;
|
|
}
|
|
if (hidden !== "yes") {
|
|
resultDiv += "<th>" + value.key + "</th>";
|
|
}
|
|
});
|
|
resultDiv += "</tr><thead>";
|
|
|
|
resultDiv += "<tbody>";
|
|
$.each(res.rows, function (index, item) {
|
|
resultData = item;
|
|
|
|
resultDiv += "<tr>";
|
|
$.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 =
|
|
'<a href="' +
|
|
r +
|
|
'" class="button dw-checker-value-button dw-checker-btn-' +
|
|
id +
|
|
'" target="_blank" rel="noopener">' +
|
|
button_text +
|
|
"</a>";
|
|
} else if (type == "whatsapp_button") {
|
|
r =
|
|
'<a href="https://wa.me/' +
|
|
r +
|
|
'" class="button dw-checker-value-button dw-checker-btn-' +
|
|
id +
|
|
'" target="_blank" rel="noopener">' +
|
|
button_text +
|
|
"</a>";
|
|
} else if (type == "image") {
|
|
r =
|
|
'<img src="' +
|
|
r +
|
|
'" class="dw-checker-image dw-checker-img-' +
|
|
id +
|
|
'" style="max-width: 150px; height: auto; cursor: pointer;" onclick="openImageLightbox(this)" data-fullsize="' +
|
|
r +
|
|
'" alt="' +
|
|
q +
|
|
'" />';
|
|
}
|
|
resultDiv +=
|
|
'<td style="border-color: ' +
|
|
res.settings.divider +
|
|
"; border-width: " +
|
|
res.settings.divider_width +
|
|
'px;"><span class="dw-checker-result-value" style="color:' +
|
|
value_color +
|
|
'">' +
|
|
prefix +
|
|
r +
|
|
"</span></td>";
|
|
});
|
|
resultDiv += "</tr>";
|
|
});
|
|
resultDiv += "</tbody>";
|
|
resultDiv += "</table>";
|
|
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 +=
|
|
`
|
|
<style>
|
|
.dw-checker-card-container {
|
|
grid-template-columns: repeat(` +
|
|
res.settings.column +
|
|
`, 1fr);
|
|
}
|
|
@media (max-width: 1280px){
|
|
.dw-checker-card-container {
|
|
grid-template-columns: repeat(3, 1fr);
|
|
}
|
|
}
|
|
@media (max-width: 820px){
|
|
.dw-checker-card-container {
|
|
grid-template-columns: repeat(2, 1fr);
|
|
}
|
|
}
|
|
@media (max-width: 482px){
|
|
.dw-checker-card-container {
|
|
grid-template-columns: repeat(1, 1fr);
|
|
}
|
|
}
|
|
</style>
|
|
`;
|
|
resultDiv +=
|
|
'<div class="dw-checker-result-container dw-checker-card-container" data-pagination="' +
|
|
index +
|
|
'" style="display:none;">';
|
|
$.each(item, function (q, r) {
|
|
var id = q
|
|
.replace(" ", "_")
|
|
.replace(".", "_")
|
|
.toLowerCase();
|
|
var prefix = "";
|
|
var type = "";
|
|
var button_text = "";
|
|
var hidden = "no";
|
|
var bg_color = "#cccccc";
|
|
var text_color = "#000000";
|
|
$.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 ("bg_color" in p) {
|
|
bg_color = p.bg_color;
|
|
}
|
|
if ("text_color" in p) {
|
|
text_color = p.text_color;
|
|
}
|
|
}
|
|
});
|
|
if (hidden == "yes") {
|
|
return;
|
|
}
|
|
if (type == "link_button") {
|
|
r =
|
|
'<a href="' +
|
|
r +
|
|
'" class="button dw-checker-value-button dw-checker-btn-' +
|
|
id +
|
|
'" target="_blank" rel="noopener">' +
|
|
button_text +
|
|
"</a>";
|
|
} else if (type == "whatsapp_button") {
|
|
r =
|
|
'<a href="https://wa.me/' +
|
|
r +
|
|
'" class="button dw-checker-value-button dw-checker-btn-' +
|
|
id +
|
|
'" target="_blank" rel="noopener">' +
|
|
button_text +
|
|
"</a>";
|
|
} else if (type == "image") {
|
|
r =
|
|
'<img src="' +
|
|
r +
|
|
'" class="dw-checker-image dw-checker-img-' +
|
|
id +
|
|
'" style="max-width: 100%; height: auto; cursor: pointer;" onclick="openImageLightbox(this)" data-fullsize="' +
|
|
r +
|
|
'" alt="' +
|
|
q +
|
|
'" />';
|
|
}
|
|
resultDiv +=
|
|
`<div class="dw-checker-single-card" style="background-color: ` +
|
|
bg_color +
|
|
`; color: ` +
|
|
text_color +
|
|
`; border-color: ` +
|
|
res.settings.divider +
|
|
`; border-width: ` +
|
|
res.settings.divider_width +
|
|
`px;">
|
|
<span class="dw-checker-card-header" style="color:` +
|
|
text_color +
|
|
`">` +
|
|
q +
|
|
`</span>
|
|
<span class="dw-checker-card-value" style="color:` +
|
|
text_color +
|
|
`">` +
|
|
prefix +
|
|
r +
|
|
`</span>
|
|
</div>`;
|
|
});
|
|
resultDiv += "</div>";
|
|
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('<span class="dashicons dashicons-update" style="animation: spin 1s linear infinite; vertical-align: middle;"></span> ' +
|
|
(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('<span class="dashicons dashicons-yes" style="vertical-align: middle;"></span> ' +
|
|
(response.data.message || 'Refreshed!'));
|
|
|
|
// Reset button after 2 seconds
|
|
setTimeout(function () {
|
|
btn.prop("disabled", false).html(originalText);
|
|
}, 2000);
|
|
} else {
|
|
btn.html('<span class="dashicons dashicons-warning" style="vertical-align: middle;"></span> Failed');
|
|
setTimeout(function () {
|
|
btn.prop("disabled", false).html(originalText);
|
|
}, 2000);
|
|
}
|
|
},
|
|
error: function () {
|
|
btn.html('<span class="dashicons dashicons-warning" style="vertical-align: middle;"></span> 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();
|
|
};
|
|
}
|