Initial commit: Open sourcing all of the Maple Open Technologies code.
This commit is contained in:
commit
755d54a99d
2010 changed files with 448675 additions and 0 deletions
|
|
@ -0,0 +1,19 @@
|
|||
/**
|
||||
* MaplePress Admin Styles
|
||||
*
|
||||
* @package MaplePress
|
||||
*/
|
||||
|
||||
.maplepress-admin {
|
||||
max-width: 800px;
|
||||
}
|
||||
|
||||
.maplepress-status-active {
|
||||
color: #46b450;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.maplepress-status-inactive {
|
||||
color: #dc3232;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
/**
|
||||
* MaplePress Public Styles
|
||||
*
|
||||
* @package MaplePress
|
||||
*/
|
||||
|
||||
.maplepress-search-widget {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.maplepress-search-results {
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.maplepress-search-result-item {
|
||||
margin-bottom: 15px;
|
||||
padding: 15px;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.maplepress-search-result-item h3 {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,440 @@
|
|||
/**
|
||||
* MaplePress Search Speed Test - Admin Styles
|
||||
*/
|
||||
|
||||
.mpss-wrap {
|
||||
max-width: 1200px;
|
||||
margin: 20px auto 20px 0;
|
||||
}
|
||||
|
||||
.mpss-card {
|
||||
background: #fff;
|
||||
border: 1px solid #ccd0d4;
|
||||
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.04);
|
||||
padding: 20px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.mpss-card h2 {
|
||||
margin-top: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.mpss-card h3 {
|
||||
border-bottom: 1px solid #eee;
|
||||
padding-bottom: 10px;
|
||||
margin-top: 25px;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
/* Mode Selection */
|
||||
.mpss-mode-selection {
|
||||
margin: 20px 0;
|
||||
}
|
||||
|
||||
.mpss-radio-label {
|
||||
display: block;
|
||||
padding: 15px;
|
||||
margin: 10px 0;
|
||||
border: 2px solid #ddd;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
.mpss-radio-label:hover {
|
||||
border-color: #2271b1;
|
||||
background: #f9f9f9;
|
||||
}
|
||||
|
||||
.mpss-radio-label input[type="radio"] {
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.mpss-radio-label input[type="radio"]:checked + .mpss-radio-title {
|
||||
color: #2271b1;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.mpss-radio-label input[type="radio"]:checked ~ .mpss-radio-title {
|
||||
color: #2271b1;
|
||||
}
|
||||
|
||||
.mpss-radio-title {
|
||||
font-weight: 600;
|
||||
font-size: 14px;
|
||||
display: block;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.mpss-radio-desc {
|
||||
font-size: 13px;
|
||||
color: #666;
|
||||
display: block;
|
||||
margin-left: 25px;
|
||||
}
|
||||
|
||||
/* Test Info */
|
||||
.mpss-test-info ul {
|
||||
list-style: none;
|
||||
margin: 10px 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.mpss-test-info li {
|
||||
padding: 8px 0;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
}
|
||||
|
||||
.mpss-test-info li:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
/* Warning */
|
||||
.mpss-warning {
|
||||
background: #fff3cd;
|
||||
border-left: 4px solid #ffc107;
|
||||
padding: 12px 15px;
|
||||
margin: 20px 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.mpss-warning .dashicons {
|
||||
color: #856404;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
/* Progress */
|
||||
.mpss-progress {
|
||||
margin: 20px 0;
|
||||
}
|
||||
|
||||
.mpss-progress-bar {
|
||||
width: 100%;
|
||||
height: 30px;
|
||||
background: #f0f0f0;
|
||||
border-radius: 15px;
|
||||
overflow: hidden;
|
||||
margin-top: 15px;
|
||||
}
|
||||
|
||||
.mpss-progress-fill {
|
||||
height: 100%;
|
||||
background: linear-gradient(90deg, #667eea, #764ba2);
|
||||
transition: width 0.3s ease;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #fff;
|
||||
font-weight: 600;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.mpss-progress-fill.pulsing::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: -100%;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: linear-gradient(90deg, transparent, rgba(255,255,255,0.3), transparent);
|
||||
animation: shimmer 2s infinite;
|
||||
}
|
||||
|
||||
@keyframes shimmer {
|
||||
0% {
|
||||
left: -100%;
|
||||
}
|
||||
100% {
|
||||
left: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.mpss-progress-fill.pulsing {
|
||||
animation: pulse 1.5s ease-in-out infinite;
|
||||
}
|
||||
|
||||
@keyframes pulse {
|
||||
0%, 100% {
|
||||
opacity: 1;
|
||||
}
|
||||
50% {
|
||||
opacity: 0.8;
|
||||
}
|
||||
}
|
||||
|
||||
.spin {
|
||||
animation: spin 1s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
from {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
/* Test Meta */
|
||||
.mpss-test-meta {
|
||||
display: flex;
|
||||
gap: 20px;
|
||||
flex-wrap: wrap;
|
||||
margin: 15px 0 25px 0;
|
||||
padding: 15px;
|
||||
background: #f9f9f9;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.mpss-test-meta span {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.mpss-test-meta strong {
|
||||
color: #2271b1;
|
||||
}
|
||||
|
||||
/* Summary Cards */
|
||||
.mpss-summary-cards {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
|
||||
gap: 15px;
|
||||
margin: 20px 0;
|
||||
}
|
||||
|
||||
.mpss-profile-card {
|
||||
border: 2px solid #ddd;
|
||||
border-radius: 8px;
|
||||
padding: 20px;
|
||||
text-align: center;
|
||||
transition: transform 0.2s;
|
||||
}
|
||||
|
||||
.mpss-profile-card:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.mpss-profile-card h4 {
|
||||
margin: 0 0 15px 0;
|
||||
font-size: 16px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.mpss-profile-metrics {
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
margin: 15px 0;
|
||||
}
|
||||
|
||||
.mpss-metric {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.mpss-metric-label {
|
||||
font-size: 11px;
|
||||
color: #666;
|
||||
text-transform: uppercase;
|
||||
display: block;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.mpss-metric-value {
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.mpss-status-badge {
|
||||
display: inline-block;
|
||||
padding: 5px 12px;
|
||||
border-radius: 12px;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.mpss-status-excellent {
|
||||
background: #d4edda;
|
||||
color: #155724;
|
||||
border-color: #46b450;
|
||||
}
|
||||
|
||||
.mpss-status-good {
|
||||
background: #d1ecf1;
|
||||
color: #0c5460;
|
||||
border-color: #00a0d2;
|
||||
}
|
||||
|
||||
.mpss-status-fair {
|
||||
background: #fff3cd;
|
||||
color: #856404;
|
||||
border-color: #ffc107;
|
||||
}
|
||||
|
||||
.mpss-status-poor {
|
||||
background: #f8d7da;
|
||||
color: #721c24;
|
||||
border-color: #dc3545;
|
||||
}
|
||||
|
||||
.mpss-status-critical {
|
||||
background: #dc3232;
|
||||
color: #fff;
|
||||
border-color: #dc3232;
|
||||
}
|
||||
|
||||
.mpss-profile-details {
|
||||
font-size: 12px;
|
||||
color: #666;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
/* Chart Container */
|
||||
.mpss-chart-container {
|
||||
margin: 30px 0;
|
||||
padding: 20px;
|
||||
background: #fff;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
#mpss-chart {
|
||||
max-height: 400px;
|
||||
}
|
||||
|
||||
/* Results Table */
|
||||
.mpss-table-container {
|
||||
margin: 30px 0;
|
||||
}
|
||||
|
||||
#mpss-results-table {
|
||||
margin-top: 15px;
|
||||
}
|
||||
|
||||
#mpss-results-table th {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
#mpss-results-table td {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
/* Recommendations */
|
||||
.mpss-recommendations {
|
||||
margin: 30px 0;
|
||||
}
|
||||
|
||||
.mpss-recommendation {
|
||||
padding: 15px;
|
||||
margin: 15px 0;
|
||||
border-left: 4px solid;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.mpss-recommendation h4 {
|
||||
margin: 0 0 10px 0;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.mpss-recommendation p {
|
||||
margin: 0;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.mpss-recommendation-success {
|
||||
background: #d4edda;
|
||||
border-color: #46b450;
|
||||
color: #155724;
|
||||
}
|
||||
|
||||
.mpss-recommendation-info {
|
||||
background: #d1ecf1;
|
||||
border-color: #00a0d2;
|
||||
color: #0c5460;
|
||||
}
|
||||
|
||||
.mpss-recommendation-warning {
|
||||
background: #fff3cd;
|
||||
border-color: #ffc107;
|
||||
color: #856404;
|
||||
}
|
||||
|
||||
.mpss-recommendation-error {
|
||||
background: #f8d7da;
|
||||
border-color: #dc3545;
|
||||
color: #721c24;
|
||||
}
|
||||
|
||||
.mpss-recommendation-critical {
|
||||
background: #dc3232;
|
||||
border-color: #dc3232;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/* Site Info */
|
||||
.mpss-site-info {
|
||||
margin: 30px 0;
|
||||
padding: 20px;
|
||||
background: #f9f9f9;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.mpss-site-info ul {
|
||||
list-style: none;
|
||||
margin: 10px 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.mpss-site-info li {
|
||||
padding: 8px 0;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.mpss-site-info strong {
|
||||
color: #2271b1;
|
||||
min-width: 150px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
/* Actions */
|
||||
.mpss-actions {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
margin-top: 30px;
|
||||
padding-top: 20px;
|
||||
border-top: 1px solid #ddd;
|
||||
}
|
||||
|
||||
.mpss-actions button {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 5px;
|
||||
}
|
||||
|
||||
/* Responsive */
|
||||
@media (max-width: 768px) {
|
||||
.mpss-summary-cards {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.mpss-test-meta {
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.mpss-actions {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.mpss-actions button {
|
||||
width: 100%;
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
/**
|
||||
* MaplePress Admin JavaScript
|
||||
*
|
||||
* @package MaplePress
|
||||
*/
|
||||
|
||||
(function($) {
|
||||
'use strict';
|
||||
|
||||
$(document).ready(function() {
|
||||
// Admin-specific JavaScript can be added here
|
||||
console.log('MaplePress Admin JS loaded');
|
||||
});
|
||||
|
||||
})(jQuery);
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
/**
|
||||
* MaplePress Public JavaScript
|
||||
*
|
||||
* @package MaplePress
|
||||
*/
|
||||
|
||||
(function($) {
|
||||
'use strict';
|
||||
|
||||
$(document).ready(function() {
|
||||
// Public-facing JavaScript can be added here
|
||||
console.log('MaplePress Public JS loaded');
|
||||
});
|
||||
|
||||
})(jQuery);
|
||||
894
native/wordpress/maplepress-plugin/assets/js/speedtest-simple.js
Normal file
894
native/wordpress/maplepress-plugin/assets/js/speedtest-simple.js
Normal file
|
|
@ -0,0 +1,894 @@
|
|||
/**
|
||||
* MaplePress Search Speed Test - Simple Admin JavaScript
|
||||
*/
|
||||
|
||||
(function($) {
|
||||
'use strict';
|
||||
|
||||
var testResults = null;
|
||||
var performanceChart = null;
|
||||
|
||||
$(document).ready(function() {
|
||||
// Note: Notification permission will be requested when user runs first test
|
||||
// (requestNotificationPermission() can only be called from user gesture)
|
||||
|
||||
// Run test button
|
||||
$('#mpss-run-test').on('click', function() {
|
||||
runSpeedTest();
|
||||
});
|
||||
|
||||
// Cancel test button
|
||||
$(document).on('click', '#mpss-cancel-test', function() {
|
||||
if (confirm('Are you sure you want to cancel the test?')) {
|
||||
cancelTest();
|
||||
}
|
||||
});
|
||||
|
||||
// Run again button
|
||||
$(document).on('click', '#mpss-run-again', function() {
|
||||
resetTest();
|
||||
});
|
||||
|
||||
// Export results button
|
||||
$(document).on('click', '#mpss-export-results', function() {
|
||||
exportResults();
|
||||
});
|
||||
|
||||
|
||||
// Share results button
|
||||
$(document).on('click', '#mpss-share-results', function() {
|
||||
showShareModal();
|
||||
});
|
||||
|
||||
// Close share modal
|
||||
$(document).on('click', '#mpss-close-share-modal', function() {
|
||||
closeShareModal();
|
||||
});
|
||||
|
||||
// Share buttons
|
||||
$(document).on('click', '.mpss-share-twitter', function() {
|
||||
shareToTwitter();
|
||||
});
|
||||
|
||||
$(document).on('click', '.mpss-share-facebook', function() {
|
||||
shareToFacebook();
|
||||
});
|
||||
|
||||
$(document).on('click', '.mpss-share-linkedin', function() {
|
||||
shareToLinkedIn();
|
||||
});
|
||||
|
||||
$(document).on('click', '.mpss-share-copy', function() {
|
||||
copyShareLink();
|
||||
});
|
||||
|
||||
// Handle mode card selection
|
||||
$('.mpss-mode-card').on('click', function() {
|
||||
var $radio = $(this).find('input[type="radio"]');
|
||||
$radio.prop('checked', true);
|
||||
|
||||
// Update visual state of cards
|
||||
$('.mpss-mode-card-inner').css({
|
||||
'border-color': '#e0e0e0',
|
||||
'box-shadow': '0 1px 3px rgba(0, 0, 0, 0.05)',
|
||||
'transform': 'scale(1)'
|
||||
});
|
||||
|
||||
$(this).find('.mpss-mode-card-inner').css({
|
||||
'border-color': '#667eea',
|
||||
'box-shadow': '0 4px 15px rgba(102, 126, 234, 0.3)',
|
||||
'transform': 'scale(1.02)'
|
||||
});
|
||||
});
|
||||
|
||||
// Add hover effects for mode cards
|
||||
$('.mpss-mode-card').hover(
|
||||
function() {
|
||||
if (!$(this).find('input[type="radio"]').is(':checked')) {
|
||||
$(this).find('.mpss-mode-card-inner').css({
|
||||
'transform': 'translateY(-2px)',
|
||||
'box-shadow': '0 4px 10px rgba(0, 0, 0, 0.1)'
|
||||
});
|
||||
}
|
||||
},
|
||||
function() {
|
||||
if (!$(this).find('input[type="radio"]').is(':checked')) {
|
||||
$(this).find('.mpss-mode-card-inner').css({
|
||||
'transform': 'scale(1)',
|
||||
'box-shadow': '0 1px 3px rgba(0, 0, 0, 0.05)'
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
// Add hover effect for run button
|
||||
$('#mpss-run-test').hover(
|
||||
function() {
|
||||
$(this).css({
|
||||
'transform': 'translateY(-2px)',
|
||||
'box-shadow': '0 6px 20px rgba(102, 126, 234, 0.5)'
|
||||
});
|
||||
},
|
||||
function() {
|
||||
$(this).css({
|
||||
'transform': 'translateY(0)',
|
||||
'box-shadow': '0 4px 15px rgba(102, 126, 234, 0.4)'
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
// Add focus effect for select dropdown
|
||||
$('#mpss-query-count').on('focus', function() {
|
||||
$(this).css({
|
||||
'border-color': '#667eea',
|
||||
'box-shadow': '0 0 0 3px rgba(102, 126, 234, 0.1)'
|
||||
});
|
||||
}).on('blur', function() {
|
||||
$(this).css({
|
||||
'border-color': '#e0e0e0',
|
||||
'box-shadow': 'none'
|
||||
});
|
||||
});
|
||||
|
||||
// Initialize the first card as selected
|
||||
$('.mpss-mode-card').first().find('.mpss-mode-card-inner').css({
|
||||
'border-color': '#667eea',
|
||||
'box-shadow': '0 4px 15px rgba(102, 126, 234, 0.3)',
|
||||
'transform': 'scale(1.02)'
|
||||
});
|
||||
});
|
||||
|
||||
var progressInterval = null;
|
||||
var currentAjaxRequest = null;
|
||||
|
||||
function runSpeedTest() {
|
||||
// Request notification permission on first test run
|
||||
requestNotificationPermission();
|
||||
|
||||
var queryCount = parseInt($('#mpss-query-count').val()) || 10;
|
||||
var executionMode = $('input[name="execution_mode"]:checked').val() || 'serial';
|
||||
|
||||
console.log('Starting speed test with ' + queryCount + ' queries in ' + executionMode + ' mode');
|
||||
console.log('Execution mode value:', executionMode);
|
||||
console.log('Radio button checked:', $('input[name="execution_mode"]:checked').length);
|
||||
|
||||
// Hide config, show progress
|
||||
$('.mpss-test-config').fadeOut();
|
||||
$('#mpss-results').hide();
|
||||
$('#mpss-progress').fadeIn();
|
||||
|
||||
var modeText = executionMode === 'parallel' ? 'many at once' : 'one at a time';
|
||||
$('#mpss-progress-text').text('Testing ' + queryCount + ' searches (' + modeText + ')...');
|
||||
$('#mpss-progress-fill').css('width', '10%');
|
||||
|
||||
// Initialize counter
|
||||
$('#mpss-total-count').text(queryCount);
|
||||
$('#mpss-completed-count').text(0);
|
||||
|
||||
// Calculate and display estimated time
|
||||
var estimatedSeconds = Math.ceil((queryCount * 200) / 1000); // 200ms per query
|
||||
if (executionMode === 'parallel') {
|
||||
estimatedSeconds = Math.ceil(estimatedSeconds * 0.1); // Parallel is much faster
|
||||
}
|
||||
updateTimeEstimate(estimatedSeconds);
|
||||
|
||||
// Start animated progress counter
|
||||
startProgressAnimation(queryCount, estimatedSeconds);
|
||||
|
||||
// Make AJAX request
|
||||
currentAjaxRequest = $.ajax({
|
||||
url: mpssAjax.ajaxurl,
|
||||
method: 'POST',
|
||||
data: {
|
||||
action: 'mpss_run_test',
|
||||
nonce: mpssAjax.nonce,
|
||||
query_count: queryCount,
|
||||
execution_mode: executionMode
|
||||
},
|
||||
success: function(response) {
|
||||
currentAjaxRequest = null;
|
||||
console.log('Response received:', response);
|
||||
|
||||
// Stop the progress animation
|
||||
stopProgressAnimation();
|
||||
|
||||
if (response.success) {
|
||||
testResults = response.data;
|
||||
console.log('Test results:', testResults);
|
||||
|
||||
// Complete the progress
|
||||
$('#mpss-completed-count').text(queryCount);
|
||||
$('#mpss-progress-fill').css('width', '100%');
|
||||
$('#mpss-progress-text').text('Test complete!');
|
||||
|
||||
setTimeout(function() {
|
||||
displayResults(testResults);
|
||||
}, 500);
|
||||
} else {
|
||||
showError('Test failed: ' + (response.data ? response.data.message : 'Unknown error'));
|
||||
}
|
||||
},
|
||||
error: function(xhr, status, error) {
|
||||
currentAjaxRequest = null;
|
||||
|
||||
// Don't show error if request was aborted (cancelled by user)
|
||||
if (status === 'abort') {
|
||||
return;
|
||||
}
|
||||
|
||||
console.error('AJAX error:', error);
|
||||
stopProgressAnimation();
|
||||
showError('Network error: ' + error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function cancelTest() {
|
||||
// Abort the AJAX request
|
||||
if (currentAjaxRequest) {
|
||||
currentAjaxRequest.abort();
|
||||
currentAjaxRequest = null;
|
||||
}
|
||||
|
||||
// Stop the animation
|
||||
stopProgressAnimation();
|
||||
|
||||
// Hide progress and show config
|
||||
$('#mpss-progress').fadeOut(function() {
|
||||
$('.mpss-test-config').fadeIn();
|
||||
});
|
||||
|
||||
// Show cancellation message
|
||||
alert('Test cancelled');
|
||||
}
|
||||
|
||||
function updateTimeEstimate(secondsRemaining) {
|
||||
if (secondsRemaining <= 0) {
|
||||
$('#mpss-time-estimate').text('Almost done...');
|
||||
return;
|
||||
}
|
||||
|
||||
var minutes = Math.floor(secondsRemaining / 60);
|
||||
var seconds = secondsRemaining % 60;
|
||||
|
||||
var timeText = 'Estimated time: ';
|
||||
if (minutes > 0) {
|
||||
timeText += minutes + ' min ' + seconds + ' sec';
|
||||
} else {
|
||||
timeText += seconds + ' sec';
|
||||
}
|
||||
|
||||
$('#mpss-time-estimate').text(timeText);
|
||||
}
|
||||
|
||||
function startProgressAnimation(totalCount, estimatedSeconds) {
|
||||
// Clear any existing interval
|
||||
if (progressInterval) {
|
||||
clearInterval(progressInterval);
|
||||
}
|
||||
|
||||
var currentCount = 0;
|
||||
var estimatedTime = totalCount * 200; // Rough estimate: 200ms per search
|
||||
var updateInterval = 100; // Update every 100ms
|
||||
var incrementPerUpdate = totalCount / (estimatedTime / updateInterval);
|
||||
var reachedNinetyFive = false;
|
||||
var timeRemaining = estimatedSeconds;
|
||||
var lastTimeUpdate = Date.now();
|
||||
|
||||
progressInterval = setInterval(function() {
|
||||
// Update time estimate every second
|
||||
var now = Date.now();
|
||||
if (now - lastTimeUpdate >= 1000) {
|
||||
timeRemaining--;
|
||||
updateTimeEstimate(timeRemaining);
|
||||
lastTimeUpdate = now;
|
||||
}
|
||||
|
||||
// After reaching 95%, slow down significantly
|
||||
if (currentCount >= totalCount * 0.95 && !reachedNinetyFive) {
|
||||
reachedNinetyFive = true;
|
||||
incrementPerUpdate = incrementPerUpdate * 0.1; // Slow down to 10% speed
|
||||
// Update the message and add pulsing animation
|
||||
$('#mpss-progress-text').html('Almost done, finalizing results...');
|
||||
$('#mpss-progress-fill').addClass('pulsing');
|
||||
}
|
||||
|
||||
currentCount += incrementPerUpdate;
|
||||
|
||||
// Cap at 99% until we get the real result
|
||||
var displayCount = Math.min(Math.floor(currentCount), Math.floor(totalCount * 0.99));
|
||||
var percentage = Math.min((displayCount / totalCount) * 100, 99);
|
||||
|
||||
$('#mpss-completed-count').text(displayCount);
|
||||
$('#mpss-progress-fill').css('width', percentage + '%');
|
||||
|
||||
// Stop at 99%
|
||||
if (displayCount >= totalCount * 0.99) {
|
||||
clearInterval(progressInterval);
|
||||
progressInterval = null;
|
||||
}
|
||||
}, updateInterval);
|
||||
}
|
||||
|
||||
function stopProgressAnimation() {
|
||||
if (progressInterval) {
|
||||
clearInterval(progressInterval);
|
||||
progressInterval = null;
|
||||
}
|
||||
}
|
||||
|
||||
function displayResults(data) {
|
||||
console.log('Displaying results...');
|
||||
|
||||
// Calculate average time for notification
|
||||
var avgTime = data.total_time / data.total_queries;
|
||||
|
||||
// Play completion sound and show notification
|
||||
playCompletionSound();
|
||||
showTestCompleteNotification(avgTime, data.total_queries);
|
||||
|
||||
// Hide progress, show results
|
||||
$('#mpss-progress').fadeOut();
|
||||
$('#mpss-results').fadeIn();
|
||||
|
||||
// Display recommendations
|
||||
displayRecommendations(data.total_queries, data.mode);
|
||||
|
||||
// Display summary stats (only total queries and total time)
|
||||
$('#mpss-total-queries').text(data.total_queries.toLocaleString());
|
||||
$('#mpss-total-time').text(data.total_time + ' sec');
|
||||
|
||||
// Add mode-specific explanation
|
||||
var $chart = $('#mpss-chart');
|
||||
var existingExplanation = $chart.parent().find('.mpss-mode-explanation');
|
||||
if (existingExplanation.length) {
|
||||
existingExplanation.remove();
|
||||
}
|
||||
|
||||
var explanation = '';
|
||||
if (data.mode === 'parallel') {
|
||||
explanation = '<div class="mpss-mode-explanation" style="padding: 15px; margin-bottom: 20px; background: linear-gradient(to right, rgba(102, 126, 234, 0.1), rgba(118, 75, 162, 0.1)); border-left: 4px solid #667eea; border-radius: 8px;">' +
|
||||
'<strong style="color: #667eea; font-size: 14px;">👥 Stress Test Mode:</strong><br>' +
|
||||
'<span style="font-size: 13px; color: #666; line-height: 1.6;">' +
|
||||
'We simulated <strong>' + data.total_queries + ' people</strong> searching your site at the same time. It took <strong>' + data.total_time + ' seconds</strong> to handle everyone.' +
|
||||
'</span>' +
|
||||
'</div>';
|
||||
} else {
|
||||
explanation = '<div class="mpss-mode-explanation" style="padding: 15px; margin-bottom: 20px; background: linear-gradient(to right, rgba(240, 147, 251, 0.1), rgba(245, 87, 108, 0.1)); border-left: 4px solid #f093fb; border-radius: 8px;">' +
|
||||
'<strong style="color: #f093fb; font-size: 14px;">👤 Normal Mode:</strong><br>' +
|
||||
'<span style="font-size: 13px; color: #666; line-height: 1.6;">' +
|
||||
'We tested <strong>' + data.total_queries + ' searches</strong> one at a time. The total test took <strong>' + data.total_time + ' seconds</strong> to complete.' +
|
||||
'</span>' +
|
||||
'</div>';
|
||||
}
|
||||
|
||||
$chart.parent().prepend(explanation);
|
||||
|
||||
// Display chart
|
||||
displayChart(data);
|
||||
}
|
||||
|
||||
function displayChart(data) {
|
||||
var chartContainer = $('#mpss-chart').parent();
|
||||
|
||||
// Destroy existing chart
|
||||
if (performanceChart) {
|
||||
performanceChart.destroy();
|
||||
performanceChart = null;
|
||||
}
|
||||
|
||||
// Restore the canvas if needed
|
||||
if (!chartContainer.find('canvas').length) {
|
||||
chartContainer.html('<canvas id="mpss-chart"></canvas>');
|
||||
}
|
||||
|
||||
var ctx = document.getElementById('mpss-chart').getContext('2d');
|
||||
|
||||
// Prepare data
|
||||
var labels = data.results.map(function(r, i) { return 'Query ' + (i + 1); });
|
||||
var times = data.results.map(function(r) { return r.duration_ms; });
|
||||
|
||||
// Determine title based on mode
|
||||
var chartTitle = 'How Long Each Search Took';
|
||||
var chartSubtitle = '';
|
||||
|
||||
if (data.mode === 'parallel') {
|
||||
chartSubtitle = 'Each dot shows how long one search took (all happening at the same time)';
|
||||
} else {
|
||||
chartSubtitle = 'Each dot shows how long one search took (one after another)';
|
||||
}
|
||||
|
||||
// Create chart
|
||||
performanceChart = new Chart(ctx, {
|
||||
type: 'line',
|
||||
data: {
|
||||
labels: labels,
|
||||
datasets: [{
|
||||
label: 'Response Time (ms)',
|
||||
data: times,
|
||||
backgroundColor: 'rgba(102, 126, 234, 0.3)',
|
||||
borderColor: 'rgba(102, 126, 234, 1)',
|
||||
borderWidth: 2,
|
||||
pointRadius: 3,
|
||||
tension: 0.1
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
maintainAspectRatio: true,
|
||||
plugins: {
|
||||
legend: {
|
||||
position: 'top',
|
||||
},
|
||||
title: {
|
||||
display: true,
|
||||
text: chartTitle
|
||||
},
|
||||
subtitle: {
|
||||
display: true,
|
||||
text: chartSubtitle,
|
||||
font: {
|
||||
size: 11,
|
||||
style: 'italic'
|
||||
},
|
||||
color: '#666'
|
||||
}
|
||||
},
|
||||
scales: {
|
||||
x: {
|
||||
display: false
|
||||
},
|
||||
y: {
|
||||
beginAtZero: true,
|
||||
title: {
|
||||
display: true,
|
||||
text: 'Response Time (ms)'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function exportResults() {
|
||||
if (!testResults) {
|
||||
alert('No results to export');
|
||||
return;
|
||||
}
|
||||
|
||||
// Calculate metrics
|
||||
var avgTime = testResults.total_time / testResults.total_queries;
|
||||
var avgMs = (avgTime * 1000).toFixed(0);
|
||||
var modeLabel = testResults.mode === 'parallel' ? 'Stress Test - Many People at Once' : 'Normal - One Person at a Time';
|
||||
var date = new Date();
|
||||
var dateStr = date.toLocaleDateString() + ' ' + date.toLocaleTimeString();
|
||||
|
||||
// Calculate statistics
|
||||
var times = testResults.results.map(function(r) { return r.duration_ms; });
|
||||
var minTime = Math.min.apply(null, times);
|
||||
var maxTime = Math.max.apply(null, times);
|
||||
var medianTime = calculateMedian(times);
|
||||
|
||||
// Build HTML report
|
||||
var html = '<!DOCTYPE html>\n';
|
||||
html += '<html lang="en">\n';
|
||||
html += '<head>\n';
|
||||
html += ' <meta charset="UTF-8">\n';
|
||||
html += ' <meta name="viewport" content="width=device-width, initial-scale=1.0">\n';
|
||||
html += ' <title>Search Speed Test Report - ' + dateStr + '</title>\n';
|
||||
html += ' <style>\n';
|
||||
html += ' * { margin: 0; padding: 0; box-sizing: border-box; }\n';
|
||||
html += ' body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; background: #f5f5f5; padding: 40px 20px; color: #333; line-height: 1.6; }\n';
|
||||
html += ' .container { max-width: 1000px; margin: 0 auto; background: white; padding: 50px; border-radius: 20px; box-shadow: 0 10px 40px rgba(0, 0, 0, 0.1); }\n';
|
||||
html += ' .header { text-align: center; margin-bottom: 50px; padding-bottom: 30px; border-bottom: 3px solid #667eea; }\n';
|
||||
html += ' .header h1 { font-size: 42px; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text; margin-bottom: 15px; }\n';
|
||||
html += ' .header .date { font-size: 16px; color: #666; }\n';
|
||||
html += ' .summary-section { text-align: center; padding: 40px; background: linear-gradient(135deg, rgba(102, 126, 234, 0.1), rgba(118, 75, 162, 0.1)); border-radius: 16px; margin-bottom: 40px; border: 3px solid #667eea; }\n';
|
||||
html += ' .summary-icon { font-size: 80px; margin-bottom: 20px; }\n';
|
||||
html += ' .summary-title { font-size: 32px; font-weight: 700; color: #667eea; margin-bottom: 15px; }\n';
|
||||
html += ' .summary-message { font-size: 18px; color: #666; }\n';
|
||||
html += ' .metrics { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 20px; margin-bottom: 40px; }\n';
|
||||
html += ' .metric { background: linear-gradient(135deg, rgba(102, 126, 234, 0.1), rgba(118, 75, 162, 0.1)); padding: 25px; border-radius: 12px; text-align: center; }\n';
|
||||
html += ' .metric-label { font-size: 13px; color: #666; text-transform: uppercase; font-weight: 600; margin-bottom: 10px; }\n';
|
||||
html += ' .metric-value { font-size: 32px; font-weight: 800; color: #667eea; }\n';
|
||||
html += ' .section { margin-bottom: 40px; }\n';
|
||||
html += ' .section h2 { font-size: 24px; color: #333; margin-bottom: 20px; padding-bottom: 10px; border-bottom: 2px solid #e0e0e0; }\n';
|
||||
html += ' .info-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 15px; }\n';
|
||||
html += ' .info-item { padding: 15px; background: #f9f9f9; border-radius: 8px; }\n';
|
||||
html += ' .info-label { font-size: 12px; color: #666; text-transform: uppercase; margin-bottom: 5px; }\n';
|
||||
html += ' .info-value { font-size: 18px; font-weight: 600; color: #333; }\n';
|
||||
html += ' .footer { text-align: center; padding-top: 30px; margin-top: 50px; border-top: 2px solid #e0e0e0; color: #999; font-size: 14px; }\n';
|
||||
html += ' @media print { body { background: white; padding: 0; } .container { box-shadow: none; padding: 30px; } }\n';
|
||||
html += ' </style>\n';
|
||||
html += '</head>\n';
|
||||
html += '<body>\n';
|
||||
html += ' <div class="container">\n';
|
||||
html += ' <div class="header">\n';
|
||||
html += ' <h1>Search Speed Test Report</h1>\n';
|
||||
html += ' <div class="date">Generated on ' + escapeHtml(dateStr) + '</div>\n';
|
||||
html += ' </div>\n';
|
||||
html += ' \n';
|
||||
html += ' <div class="summary-section">\n';
|
||||
html += ' <div class="summary-icon">🚀</div>\n';
|
||||
html += ' <div class="summary-title">Search Speed Test Results</div>\n';
|
||||
html += ' <div class="summary-message">Average response time: ' + avgMs + ' ms</div>\n';
|
||||
html += ' </div>\n';
|
||||
html += ' \n';
|
||||
html += ' <div class="metrics">\n';
|
||||
html += ' <div class="metric">\n';
|
||||
html += ' <div class="metric-label">Average Time</div>\n';
|
||||
html += ' <div class="metric-value">' + avgMs + ' ms</div>\n';
|
||||
html += ' </div>\n';
|
||||
html += ' <div class="metric">\n';
|
||||
html += ' <div class="metric-label">Total Tests</div>\n';
|
||||
html += ' <div class="metric-value">' + testResults.total_queries + '</div>\n';
|
||||
html += ' </div>\n';
|
||||
html += ' <div class="metric">\n';
|
||||
html += ' <div class="metric-label">Total Time</div>\n';
|
||||
html += ' <div class="metric-value">' + testResults.total_time + ' s</div>\n';
|
||||
html += ' </div>\n';
|
||||
html += ' <div class="metric">\n';
|
||||
html += ' <div class="metric-label">Test Mode</div>\n';
|
||||
html += ' <div class="metric-value" style="font-size: 18px;">' + escapeHtml(modeLabel.split(' - ')[0]) + '</div>\n';
|
||||
html += ' </div>\n';
|
||||
html += ' </div>\n';
|
||||
html += ' \n';
|
||||
html += ' <div class="section">\n';
|
||||
html += ' <h2>Detailed Statistics</h2>\n';
|
||||
html += ' <div class="info-grid">\n';
|
||||
html += ' <div class="info-item">\n';
|
||||
html += ' <div class="info-label">Fastest Response</div>\n';
|
||||
html += ' <div class="info-value">' + minTime.toFixed(0) + ' ms</div>\n';
|
||||
html += ' </div>\n';
|
||||
html += ' <div class="info-item">\n';
|
||||
html += ' <div class="info-label">Slowest Response</div>\n';
|
||||
html += ' <div class="info-value">' + maxTime.toFixed(0) + ' ms</div>\n';
|
||||
html += ' </div>\n';
|
||||
html += ' <div class="info-item">\n';
|
||||
html += ' <div class="info-label">Median Response</div>\n';
|
||||
html += ' <div class="info-value">' + medianTime.toFixed(0) + ' ms</div>\n';
|
||||
html += ' </div>\n';
|
||||
html += ' <div class="info-item">\n';
|
||||
html += ' <div class="info-label">Test Mode</div>\n';
|
||||
html += ' <div class="info-value">' + escapeHtml(modeLabel) + '</div>\n';
|
||||
html += ' </div>\n';
|
||||
html += ' </div>\n';
|
||||
html += ' </div>\n';
|
||||
html += ' \n';
|
||||
html += ' <div class="section">\n';
|
||||
html += ' <h2>General Recommendations</h2>\n';
|
||||
html += ' <div style="background: rgba(102, 126, 234, 0.1); padding: 25px; border-radius: 12px; border-left: 4px solid #667eea;">\n';
|
||||
html += ' <p><strong>💡 Optimization Tips</strong></p>\n';
|
||||
html += ' <p>Consider these strategies to improve search performance:</p>\n';
|
||||
html += ' <ul style="margin-top: 15px; margin-left: 20px;">\n';
|
||||
html += ' <li>Install and configure a caching plugin (e.g., WP Super Cache, W3 Total Cache)</li>\n';
|
||||
html += ' <li>Optimize your database with plugins like WP-Optimize</li>\n';
|
||||
html += ' <li>Review and optimize database indexes</li>\n';
|
||||
html += ' <li>Consider upgrading your hosting plan for better resources</li>\n';
|
||||
html += ' <li>Monitor performance regularly as your site grows</li>\n';
|
||||
html += ' </ul>\n';
|
||||
html += ' </div>\n';
|
||||
html += ' </div>\n';
|
||||
html += ' \n';
|
||||
html += ' <div class="footer">\n';
|
||||
html += ' <p>Generated by MaplePress Search Speed Test Plugin</p>\n';
|
||||
html += ' <p>Website: ' + escapeHtml(window.location.hostname) + '</p>\n';
|
||||
html += ' </div>\n';
|
||||
html += ' </div>\n';
|
||||
html += '</body>\n';
|
||||
html += '</html>';
|
||||
|
||||
// Create and download the HTML file
|
||||
var htmlBlob = new Blob([html], {type: 'text/html'});
|
||||
var url = URL.createObjectURL(htmlBlob);
|
||||
|
||||
var link = document.createElement('a');
|
||||
link.href = url;
|
||||
link.download = 'search-speed-test-report-' + Date.now() + '.html';
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
document.body.removeChild(link);
|
||||
URL.revokeObjectURL(url);
|
||||
|
||||
// Show success message
|
||||
alert('✅ Report exported! Open the HTML file in your browser and use "Print to PDF" to create a PDF version.');
|
||||
}
|
||||
|
||||
function calculateMedian(arr) {
|
||||
var sorted = arr.slice().sort(function(a, b) { return a - b; });
|
||||
var mid = Math.floor(sorted.length / 2);
|
||||
if (sorted.length % 2 === 0) {
|
||||
return (sorted[mid - 1] + sorted[mid]) / 2;
|
||||
}
|
||||
return sorted[mid];
|
||||
}
|
||||
|
||||
function resetTest() {
|
||||
$('#mpss-results').fadeOut();
|
||||
$('.mpss-test-config').fadeIn();
|
||||
testResults = null;
|
||||
}
|
||||
|
||||
function showError(message) {
|
||||
$('#mpss-progress').fadeOut();
|
||||
$('.mpss-test-config').fadeIn();
|
||||
alert('Error: ' + message);
|
||||
}
|
||||
|
||||
function displayRecommendations(totalQueries, mode) {
|
||||
var recommendations = [];
|
||||
|
||||
// Query count recommendations
|
||||
if (totalQueries < 100) {
|
||||
recommendations.push({
|
||||
type: 'info',
|
||||
icon: '📊',
|
||||
title: 'Try more searches',
|
||||
message: 'Testing with ' + totalQueries + ' searches gives you a basic idea. Try 500-1000 searches for more accurate results.'
|
||||
});
|
||||
}
|
||||
|
||||
// Mode-based recommendations
|
||||
if (mode === 'serial') {
|
||||
recommendations.push({
|
||||
type: 'info',
|
||||
icon: '🔄',
|
||||
title: 'Try Stress Test mode',
|
||||
message: 'You tested in Normal mode. Try "Stress Test - Many People at Once" to see how your site handles high traffic.'
|
||||
});
|
||||
} else {
|
||||
recommendations.push({
|
||||
type: 'info',
|
||||
icon: '👥',
|
||||
title: 'Consider traffic patterns',
|
||||
message: 'Stress Test mode shows worst-case performance. If your site rarely gets simultaneous searches, Normal mode results matter more.'
|
||||
});
|
||||
}
|
||||
|
||||
// Build HTML
|
||||
var html = '<div style="margin: 30px 0;">';
|
||||
html += '<h3 style="margin-bottom: 20px; font-size: 18px; color: #333;">💡 Quick Tips</h3>';
|
||||
|
||||
for (var i = 0; i < recommendations.length; i++) {
|
||||
var rec = recommendations[i];
|
||||
var bgColor, borderColor;
|
||||
|
||||
if (rec.type === 'success') {
|
||||
bgColor = '#d1fae5';
|
||||
borderColor = '#10b981';
|
||||
} else if (rec.type === 'info') {
|
||||
bgColor = '#dbeafe';
|
||||
borderColor = '#3b82f6';
|
||||
} else if (rec.type === 'warning') {
|
||||
bgColor = '#fef3c7';
|
||||
borderColor = '#f59e0b';
|
||||
} else {
|
||||
bgColor = '#fee2e2';
|
||||
borderColor = '#ef4444';
|
||||
}
|
||||
|
||||
html += '<div style="padding: 15px; margin: 15px 0; background: ' + bgColor + '; border-left: 4px solid ' + borderColor + '; border-radius: 8px;">';
|
||||
html += '<div style="font-size: 16px; font-weight: 600; color: #333; margin-bottom: 8px;">' + rec.icon + ' ' + rec.title + '</div>';
|
||||
html += '<div style="font-size: 14px; color: #666; line-height: 1.6;">' + rec.message + '</div>';
|
||||
html += '</div>';
|
||||
}
|
||||
|
||||
html += '</div>';
|
||||
|
||||
$('#mpss-recommendations').html(html);
|
||||
}
|
||||
|
||||
function escapeHtml(text) {
|
||||
var map = {
|
||||
'&': '&',
|
||||
'<': '<',
|
||||
'>': '>',
|
||||
'"': '"',
|
||||
"'": '''
|
||||
};
|
||||
return String(text).replace(/[&<>"']/g, function(m) { return map[m]; });
|
||||
}
|
||||
|
||||
function showShareModal() {
|
||||
if (!testResults) {
|
||||
alert('No results to share');
|
||||
return;
|
||||
}
|
||||
|
||||
// Calculate metrics
|
||||
var avgTime = testResults.total_time / testResults.total_queries;
|
||||
var avgMs = (avgTime * 1000).toFixed(0);
|
||||
var modeLabel = testResults.mode === 'parallel' ? 'Stress Test' : 'Normal';
|
||||
|
||||
// Build share graphic
|
||||
var graphicHtml = '<div style="text-align: center;">';
|
||||
graphicHtml += '<div style="font-size: 64px; margin-bottom: 15px;">🚀</div>';
|
||||
graphicHtml += '<div style="font-size: 28px; font-weight: 700; margin-bottom: 10px;">My Search Speed Test Results</div>';
|
||||
graphicHtml += '<div style="font-size: 48px; font-weight: 800; margin: 20px 0; text-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);">' + avgMs + ' ms</div>';
|
||||
graphicHtml += '<div style="font-size: 18px; opacity: 0.9; margin-bottom: 10px;">Average Response Time</div>';
|
||||
graphicHtml += '<div style="font-size: 14px; opacity: 0.8; margin-top: 20px;">Tested ' + testResults.total_queries + ' searches in ' + modeLabel + ' mode</div>';
|
||||
graphicHtml += '</div>';
|
||||
|
||||
$('#mpss-share-graphic').html(graphicHtml);
|
||||
|
||||
// Show modal with flex display
|
||||
$('#mpss-share-modal').css('display', 'flex').hide().fadeIn(300);
|
||||
}
|
||||
|
||||
function closeShareModal() {
|
||||
$('#mpss-share-modal').fadeOut(300);
|
||||
}
|
||||
|
||||
function shareToTwitter() {
|
||||
if (!testResults) return;
|
||||
|
||||
var avgTime = testResults.total_time / testResults.total_queries;
|
||||
var avgMs = (avgTime * 1000).toFixed(0);
|
||||
|
||||
var text = 'I just tested my website\'s search speed! 🚀 Average response time: ' + avgMs + 'ms #WebPerformance #SiteSpeed';
|
||||
var url = window.location.href;
|
||||
|
||||
var twitterUrl = 'https://twitter.com/intent/tweet?text=' + encodeURIComponent(text) + '&url=' + encodeURIComponent(url);
|
||||
window.open(twitterUrl, '_blank', 'width=550,height=420');
|
||||
}
|
||||
|
||||
function shareToFacebook() {
|
||||
if (!testResults) return;
|
||||
|
||||
var url = window.location.href;
|
||||
var facebookUrl = 'https://www.facebook.com/sharer/sharer.php?u=' + encodeURIComponent(url);
|
||||
window.open(facebookUrl, '_blank', 'width=550,height=420');
|
||||
}
|
||||
|
||||
function shareToLinkedIn() {
|
||||
if (!testResults) return;
|
||||
|
||||
var avgTime = testResults.total_time / testResults.total_queries;
|
||||
var avgMs = (avgTime * 1000).toFixed(0);
|
||||
|
||||
var url = window.location.href;
|
||||
var title = 'Website Search Speed Test Results';
|
||||
var summary = 'I tested my website\'s search performance. Average response time: ' + avgMs + 'ms';
|
||||
|
||||
var linkedinUrl = 'https://www.linkedin.com/sharing/share-offsite/?url=' + encodeURIComponent(url);
|
||||
window.open(linkedinUrl, '_blank', 'width=550,height=420');
|
||||
}
|
||||
|
||||
function copyShareLink() {
|
||||
if (!testResults) return;
|
||||
|
||||
var avgTime = testResults.total_time / testResults.total_queries;
|
||||
var avgMs = (avgTime * 1000).toFixed(0);
|
||||
|
||||
var text = 'I just tested my website\'s search speed! 🚀 Average response time: ' + avgMs + 'ms\n' + window.location.href;
|
||||
|
||||
// Try to use modern clipboard API
|
||||
if (navigator.clipboard && navigator.clipboard.writeText) {
|
||||
navigator.clipboard.writeText(text).then(function() {
|
||||
alert('✅ Link copied to clipboard!');
|
||||
}).catch(function() {
|
||||
fallbackCopyText(text);
|
||||
});
|
||||
} else {
|
||||
fallbackCopyText(text);
|
||||
}
|
||||
}
|
||||
|
||||
function fallbackCopyText(text) {
|
||||
// Fallback for older browsers
|
||||
var textArea = document.createElement('textarea');
|
||||
textArea.value = text;
|
||||
textArea.style.position = 'fixed';
|
||||
textArea.style.top = '0';
|
||||
textArea.style.left = '0';
|
||||
textArea.style.width = '2em';
|
||||
textArea.style.height = '2em';
|
||||
textArea.style.padding = '0';
|
||||
textArea.style.border = 'none';
|
||||
textArea.style.outline = 'none';
|
||||
textArea.style.boxShadow = 'none';
|
||||
textArea.style.background = 'transparent';
|
||||
document.body.appendChild(textArea);
|
||||
textArea.select();
|
||||
|
||||
try {
|
||||
document.execCommand('copy');
|
||||
alert('✅ Link copied to clipboard!');
|
||||
} catch (err) {
|
||||
alert('❌ Could not copy to clipboard. Please copy manually:\n\n' + text);
|
||||
}
|
||||
|
||||
document.body.removeChild(textArea);
|
||||
}
|
||||
|
||||
function requestNotificationPermission() {
|
||||
// Check if browser supports notifications
|
||||
if (!('Notification' in window)) {
|
||||
console.log('This browser does not support desktop notifications');
|
||||
return;
|
||||
}
|
||||
|
||||
// Request permission if not already granted or denied
|
||||
if (Notification.permission === 'default') {
|
||||
Notification.requestPermission();
|
||||
}
|
||||
}
|
||||
|
||||
function showTestCompleteNotification(avgTime, totalQueries) {
|
||||
// Check if notifications are supported and permitted
|
||||
if (!('Notification' in window) || Notification.permission !== 'granted') {
|
||||
return;
|
||||
}
|
||||
|
||||
var avgMs = (avgTime * 1000).toFixed(0);
|
||||
var title = 'Search Speed Test Complete!';
|
||||
var body = 'Tested ' + totalQueries + ' searches. Average response time: ' + avgMs + 'ms';
|
||||
var icon = ''; // WordPress doesn't have a default icon, but we could add one
|
||||
|
||||
try {
|
||||
var notification = new Notification(title, {
|
||||
body: body,
|
||||
icon: icon,
|
||||
badge: icon,
|
||||
tag: 'mpss-test-complete',
|
||||
requireInteraction: false
|
||||
});
|
||||
|
||||
// Auto-close notification after 5 seconds
|
||||
setTimeout(function() {
|
||||
notification.close();
|
||||
}, 5000);
|
||||
|
||||
// Focus window when notification is clicked
|
||||
notification.onclick = function() {
|
||||
window.focus();
|
||||
notification.close();
|
||||
};
|
||||
} catch (e) {
|
||||
console.log('Could not show notification:', e);
|
||||
}
|
||||
}
|
||||
|
||||
function playCompletionSound() {
|
||||
// Create a simple success sound using Web Audio API
|
||||
try {
|
||||
var audioContext = new (window.AudioContext || window.webkitAudioContext)();
|
||||
var oscillator = audioContext.createOscillator();
|
||||
var gainNode = audioContext.createGain();
|
||||
|
||||
oscillator.connect(gainNode);
|
||||
gainNode.connect(audioContext.destination);
|
||||
|
||||
// Set sound parameters for a pleasant "ding" sound
|
||||
oscillator.frequency.value = 800; // Start frequency
|
||||
oscillator.type = 'sine';
|
||||
|
||||
gainNode.gain.setValueAtTime(0.3, audioContext.currentTime);
|
||||
gainNode.gain.exponentialRampToValueAtTime(0.01, audioContext.currentTime + 0.5);
|
||||
|
||||
oscillator.start(audioContext.currentTime);
|
||||
oscillator.stop(audioContext.currentTime + 0.5);
|
||||
|
||||
// Add a second tone for a pleasant chord
|
||||
setTimeout(function() {
|
||||
var oscillator2 = audioContext.createOscillator();
|
||||
var gainNode2 = audioContext.createGain();
|
||||
|
||||
oscillator2.connect(gainNode2);
|
||||
gainNode2.connect(audioContext.destination);
|
||||
|
||||
oscillator2.frequency.value = 1000;
|
||||
oscillator2.type = 'sine';
|
||||
|
||||
gainNode2.gain.setValueAtTime(0.2, audioContext.currentTime);
|
||||
gainNode2.gain.exponentialRampToValueAtTime(0.01, audioContext.currentTime + 0.4);
|
||||
|
||||
oscillator2.start(audioContext.currentTime);
|
||||
oscillator2.stop(audioContext.currentTime + 0.4);
|
||||
}, 100);
|
||||
} catch (e) {
|
||||
console.log('Could not play sound:', e);
|
||||
}
|
||||
}
|
||||
|
||||
})(jQuery);
|
||||
Loading…
Add table
Add a link
Reference in a new issue