2026-01-21 19:46:50 +01:00
|
|
|
/**
|
|
|
|
|
* WC Licensed Product - Frontend Scripts
|
|
|
|
|
*
|
|
|
|
|
* @package Jeremias\WcLicensedProduct
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
(function($) {
|
|
|
|
|
'use strict';
|
|
|
|
|
|
|
|
|
|
var WCLicensedProductFrontend = {
|
2026-01-21 20:32:35 +01:00
|
|
|
$modal: null,
|
|
|
|
|
$form: null,
|
|
|
|
|
|
2026-01-28 11:27:08 +01:00
|
|
|
/**
|
|
|
|
|
* Sanitize a value for safe use in jQuery selectors
|
|
|
|
|
* License IDs should be numeric only
|
|
|
|
|
*/
|
|
|
|
|
sanitizeForSelector: function(value) {
|
|
|
|
|
return String(value).replace(/[^\d]/g, '');
|
|
|
|
|
},
|
|
|
|
|
|
2026-01-21 19:46:50 +01:00
|
|
|
init: function() {
|
2026-01-21 20:32:35 +01:00
|
|
|
this.$modal = $('#wclp-transfer-modal');
|
|
|
|
|
this.$form = $('#wclp-transfer-form');
|
2026-01-21 19:46:50 +01:00
|
|
|
this.bindEvents();
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
bindEvents: function() {
|
|
|
|
|
$(document).on('click', '.copy-license-btn', this.copyLicenseKey);
|
2026-01-26 15:29:57 +01:00
|
|
|
$(document).on('click', '.copy-secret-btn', this.copySecret);
|
2026-01-21 20:32:35 +01:00
|
|
|
|
|
|
|
|
// Transfer modal events
|
|
|
|
|
$(document).on('click', '.wclp-transfer-btn', this.openTransferModal.bind(this));
|
|
|
|
|
$(document).on('click', '.wclp-modal-close, .wclp-modal-cancel, .wclp-modal-overlay', this.closeTransferModal.bind(this));
|
|
|
|
|
$(document).on('submit', '#wclp-transfer-form', this.submitTransfer.bind(this));
|
|
|
|
|
|
2026-01-25 18:31:36 +01:00
|
|
|
// Older versions toggle
|
|
|
|
|
$(document).on('click', '.older-versions-toggle', this.toggleOlderVersions);
|
|
|
|
|
|
2026-01-26 15:29:57 +01:00
|
|
|
// Secret toggle
|
|
|
|
|
$(document).on('click', '.secret-toggle', this.toggleSecret);
|
|
|
|
|
|
2026-01-21 20:32:35 +01:00
|
|
|
// Close modal on escape key
|
|
|
|
|
$(document).on('keyup', function(e) {
|
|
|
|
|
if (e.key === 'Escape') {
|
|
|
|
|
WCLicensedProductFrontend.closeTransferModal();
|
|
|
|
|
}
|
|
|
|
|
});
|
2026-01-21 19:46:50 +01:00
|
|
|
},
|
|
|
|
|
|
2026-01-25 18:31:36 +01:00
|
|
|
/**
|
|
|
|
|
* Toggle older versions visibility
|
|
|
|
|
*/
|
|
|
|
|
toggleOlderVersions: function(e) {
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
|
|
|
|
|
var $btn = $(this);
|
|
|
|
|
var $list = $btn.siblings('.older-versions-list');
|
|
|
|
|
var isExpanded = $btn.attr('aria-expanded') === 'true';
|
|
|
|
|
|
|
|
|
|
$btn.attr('aria-expanded', !isExpanded);
|
|
|
|
|
$list.slideToggle(200);
|
|
|
|
|
},
|
|
|
|
|
|
2026-01-26 15:29:57 +01:00
|
|
|
/**
|
|
|
|
|
* Toggle secret visibility
|
|
|
|
|
*/
|
|
|
|
|
toggleSecret: function(e) {
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
|
|
|
|
|
var $btn = $(this);
|
|
|
|
|
var $content = $btn.siblings('.secret-content');
|
|
|
|
|
var isExpanded = $btn.attr('aria-expanded') === 'true';
|
|
|
|
|
|
|
|
|
|
$btn.attr('aria-expanded', !isExpanded);
|
|
|
|
|
$content.slideToggle(200);
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Copy secret to clipboard
|
|
|
|
|
*/
|
|
|
|
|
copySecret: function(e) {
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
|
|
|
|
|
var $btn = $(this);
|
|
|
|
|
var secret = $btn.data('secret');
|
|
|
|
|
|
|
|
|
|
if (!secret) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Use modern clipboard API if available
|
|
|
|
|
if (navigator.clipboard && navigator.clipboard.writeText) {
|
|
|
|
|
navigator.clipboard.writeText(secret)
|
|
|
|
|
.then(function() {
|
|
|
|
|
WCLicensedProductFrontend.showCopyFeedback($btn, true);
|
|
|
|
|
})
|
|
|
|
|
.catch(function() {
|
|
|
|
|
WCLicensedProductFrontend.fallbackCopy(secret, $btn);
|
|
|
|
|
});
|
|
|
|
|
} else {
|
|
|
|
|
WCLicensedProductFrontend.fallbackCopy(secret, $btn);
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
|
2026-01-21 19:46:50 +01:00
|
|
|
/**
|
|
|
|
|
* Copy license key to clipboard
|
|
|
|
|
*/
|
|
|
|
|
copyLicenseKey: function(e) {
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
|
|
|
|
|
var $btn = $(this);
|
|
|
|
|
var licenseKey = $btn.data('license-key');
|
|
|
|
|
|
|
|
|
|
if (!licenseKey) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Use modern clipboard API if available
|
|
|
|
|
if (navigator.clipboard && navigator.clipboard.writeText) {
|
|
|
|
|
navigator.clipboard.writeText(licenseKey)
|
|
|
|
|
.then(function() {
|
|
|
|
|
WCLicensedProductFrontend.showCopyFeedback($btn, true);
|
|
|
|
|
})
|
|
|
|
|
.catch(function() {
|
|
|
|
|
WCLicensedProductFrontend.fallbackCopy(licenseKey, $btn);
|
|
|
|
|
});
|
|
|
|
|
} else {
|
|
|
|
|
WCLicensedProductFrontend.fallbackCopy(licenseKey, $btn);
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Fallback copy method for older browsers
|
|
|
|
|
*/
|
|
|
|
|
fallbackCopy: function(text, $btn) {
|
|
|
|
|
var $temp = $('<textarea>');
|
|
|
|
|
$('body').append($temp);
|
|
|
|
|
$temp.val(text).select();
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
var success = document.execCommand('copy');
|
|
|
|
|
WCLicensedProductFrontend.showCopyFeedback($btn, success);
|
|
|
|
|
} catch (err) {
|
|
|
|
|
WCLicensedProductFrontend.showCopyFeedback($btn, false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$temp.remove();
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Show feedback after copy attempt
|
|
|
|
|
*/
|
|
|
|
|
showCopyFeedback: function($btn, success) {
|
|
|
|
|
var message = success
|
|
|
|
|
? wcLicensedProduct.strings.copied
|
|
|
|
|
: wcLicensedProduct.strings.copyFailed;
|
|
|
|
|
|
|
|
|
|
var $feedback = $('<span class="copy-feedback"></span>')
|
|
|
|
|
.text(message)
|
|
|
|
|
.addClass(success ? 'success' : 'error');
|
|
|
|
|
|
|
|
|
|
$btn.after($feedback);
|
|
|
|
|
|
|
|
|
|
setTimeout(function() {
|
|
|
|
|
$feedback.fadeOut(300, function() {
|
|
|
|
|
$(this).remove();
|
|
|
|
|
});
|
|
|
|
|
}, 1500);
|
2026-01-21 20:32:35 +01:00
|
|
|
},
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Open transfer modal
|
|
|
|
|
*/
|
|
|
|
|
openTransferModal: function(e) {
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
|
|
|
|
|
var $btn = $(e.currentTarget);
|
|
|
|
|
var licenseId = $btn.data('license-id');
|
|
|
|
|
var currentDomain = $btn.data('current-domain');
|
|
|
|
|
|
2026-01-28 11:27:08 +01:00
|
|
|
// Validate license ID is numeric
|
|
|
|
|
if (!licenseId || !/^\d+$/.test(String(licenseId))) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-21 20:32:35 +01:00
|
|
|
$('#transfer-license-id').val(licenseId);
|
|
|
|
|
$('#transfer-current-domain').text(currentDomain);
|
|
|
|
|
$('#transfer-new-domain').val('');
|
|
|
|
|
$('#wclp-transfer-message').hide().removeClass('success error');
|
|
|
|
|
$('#wclp-transfer-submit').prop('disabled', false);
|
|
|
|
|
|
|
|
|
|
this.$modal.show();
|
|
|
|
|
$('#transfer-new-domain').focus();
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Close transfer modal
|
|
|
|
|
*/
|
|
|
|
|
closeTransferModal: function(e) {
|
|
|
|
|
if (e && $(e.target).closest('.wclp-modal-content').length && !$(e.target).is('.wclp-modal-close, .wclp-modal-cancel')) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
this.$modal.hide();
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Submit transfer request
|
|
|
|
|
*/
|
|
|
|
|
submitTransfer: function(e) {
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
|
|
|
|
|
var self = this;
|
|
|
|
|
var licenseId = $('#transfer-license-id').val();
|
|
|
|
|
var newDomain = $('#transfer-new-domain').val().trim();
|
|
|
|
|
var $message = $('#wclp-transfer-message');
|
|
|
|
|
var $submit = $('#wclp-transfer-submit');
|
|
|
|
|
|
|
|
|
|
// Basic validation
|
|
|
|
|
if (!newDomain) {
|
|
|
|
|
$message.text(wcLicensedProduct.strings.invalidDomain)
|
|
|
|
|
.removeClass('success').addClass('error').show();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Confirm transfer
|
|
|
|
|
if (!confirm(wcLicensedProduct.strings.transferConfirm)) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Disable submit button
|
|
|
|
|
$submit.prop('disabled', true);
|
|
|
|
|
$message.hide();
|
|
|
|
|
|
|
|
|
|
// Send AJAX request
|
|
|
|
|
$.ajax({
|
|
|
|
|
url: wcLicensedProduct.ajaxUrl,
|
|
|
|
|
type: 'POST',
|
|
|
|
|
data: {
|
|
|
|
|
action: 'wclp_customer_transfer_license',
|
|
|
|
|
nonce: wcLicensedProduct.transferNonce,
|
|
|
|
|
license_id: licenseId,
|
|
|
|
|
new_domain: newDomain
|
|
|
|
|
},
|
|
|
|
|
success: function(response) {
|
|
|
|
|
if (response.success) {
|
|
|
|
|
$message.text(response.data.message)
|
|
|
|
|
.removeClass('error').addClass('success').show();
|
|
|
|
|
|
|
|
|
|
// Update the domain display in the license card
|
2026-01-28 11:27:08 +01:00
|
|
|
var safeLicenseId = self.sanitizeForSelector(licenseId);
|
|
|
|
|
if (safeLicenseId) {
|
|
|
|
|
var $domainDisplay = $('.license-domain-display[data-license-id="' + safeLicenseId + '"]');
|
|
|
|
|
$domainDisplay.find('.domain-value').text(response.data.new_domain);
|
|
|
|
|
$domainDisplay.find('.wclp-transfer-btn').data('current-domain', response.data.new_domain);
|
|
|
|
|
}
|
2026-01-21 20:32:35 +01:00
|
|
|
|
|
|
|
|
// Close modal after a short delay
|
|
|
|
|
setTimeout(function() {
|
|
|
|
|
self.closeTransferModal();
|
|
|
|
|
}, 1500);
|
|
|
|
|
} else {
|
|
|
|
|
$message.text(response.data.message || wcLicensedProduct.strings.transferError)
|
|
|
|
|
.removeClass('success').addClass('error').show();
|
|
|
|
|
$submit.prop('disabled', false);
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
error: function(xhr) {
|
|
|
|
|
var message = wcLicensedProduct.strings.transferError;
|
|
|
|
|
if (xhr.responseJSON && xhr.responseJSON.data && xhr.responseJSON.data.message) {
|
|
|
|
|
message = xhr.responseJSON.data.message;
|
|
|
|
|
}
|
|
|
|
|
$message.text(message)
|
|
|
|
|
.removeClass('success').addClass('error').show();
|
|
|
|
|
$submit.prop('disabled', false);
|
|
|
|
|
}
|
|
|
|
|
});
|
2026-01-21 19:46:50 +01:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
$(document).ready(function() {
|
|
|
|
|
WCLicensedProductFrontend.init();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
})(jQuery);
|