HF-Grok / static /script.js
AntDX316
updated
9ab3421
// Wait for the DOM to be fully loaded
document.addEventListener('DOMContentLoaded', function() {
// Configure marked.js
marked.setOptions({
breaks: true,
gfm: true,
smartLists: true
});
// API key storage in localStorage
const API_KEY_STORAGE_KEY = 'grok2_api_key';
const apiKeyInput = document.getElementById('api-key-input');
const saveApiKeyBtn = document.getElementById('save-api-key');
const clearApiKeyBtn = document.getElementById('clear-api-key');
const apiKeyStatus = document.getElementById('api-key-status');
// Navigation
const navLinks = document.querySelectorAll('nav ul li a');
const sections = document.querySelectorAll('.section');
// Image Generation
const imagePromptInput = document.getElementById('image-prompt');
const generateImageBtn = document.getElementById('generate-image');
const imageResult = document.getElementById('image-result');
const generationStatus = document.getElementById('generation-status');
// Vision Analysis
const uploadArea = document.getElementById('upload-area');
const imageUploadInput = document.getElementById('image-upload');
const visionPromptInput = document.getElementById('vision-prompt');
const analyzeImageBtn = document.getElementById('analyze-image');
const uploadedImageContainer = document.getElementById('uploaded-image');
const visionResult = document.getElementById('vision-result');
const visionStatus = document.getElementById('vision-status');
let uploadedImage = null;
// Check if API key is stored on load
checkStoredApiKey();
// API Key Management
function checkStoredApiKey() {
const storedApiKey = localStorage.getItem(API_KEY_STORAGE_KEY);
if (storedApiKey) {
apiKeyStatus.textContent = 'βœ… API key is stored';
apiKeyStatus.style.color = '#27ae60';
// Mask the input for security
apiKeyInput.value = 'β€’'.repeat(12);
} else {
apiKeyStatus.textContent = '❌ No API key stored';
apiKeyStatus.style.color = '#e74c3c';
apiKeyInput.value = '';
}
}
saveApiKeyBtn.addEventListener('click', function() {
const apiKey = apiKeyInput.value.trim();
if (apiKey && apiKey !== 'β€’'.repeat(12)) {
localStorage.setItem(API_KEY_STORAGE_KEY, apiKey);
apiKeyStatus.textContent = 'βœ… API key saved successfully';
apiKeyStatus.style.color = '#27ae60';
// Mask the input for security
apiKeyInput.value = 'β€’'.repeat(12);
} else if (apiKey === 'β€’'.repeat(12)) {
apiKeyStatus.textContent = '❓ Please enter a new API key';
apiKeyStatus.style.color = '#f39c12';
} else {
apiKeyStatus.textContent = '❌ Please enter a valid API key';
apiKeyStatus.style.color = '#e74c3c';
}
});
clearApiKeyBtn.addEventListener('click', function() {
localStorage.removeItem(API_KEY_STORAGE_KEY);
apiKeyInput.value = '';
apiKeyStatus.textContent = 'πŸ—‘οΈ API key cleared';
apiKeyStatus.style.color = '#e74c3c';
});
// Navigation between sections
navLinks.forEach(link => {
link.addEventListener('click', function(e) {
e.preventDefault();
// Remove active class from all links and add to current
navLinks.forEach(l => l.classList.remove('active'));
this.classList.add('active');
// Show the selected section
const targetSection = this.getAttribute('data-section');
sections.forEach(section => {
section.classList.remove('active');
if (section.id === targetSection) {
section.classList.add('active');
}
});
});
});
// Image Upload Handling
uploadArea.addEventListener('click', function() {
imageUploadInput.click();
});
uploadArea.addEventListener('dragover', function(e) {
e.preventDefault();
this.classList.add('dragover');
});
uploadArea.addEventListener('dragleave', function() {
this.classList.remove('dragover');
});
uploadArea.addEventListener('drop', function(e) {
e.preventDefault();
this.classList.remove('dragover');
if (e.dataTransfer.files && e.dataTransfer.files[0]) {
handleImageUpload(e.dataTransfer.files[0]);
}
});
imageUploadInput.addEventListener('change', function() {
if (this.files && this.files[0]) {
handleImageUpload(this.files[0]);
}
});
function handleImageUpload(file) {
if (!file.type.match('image.*')) {
visionStatus.textContent = '❌ Please upload an image file';
return;
}
const reader = new FileReader();
reader.onload = function(e) {
const img = document.createElement('img');
img.src = e.target.result;
uploadedImageContainer.innerHTML = '';
uploadedImageContainer.appendChild(img);
uploadedImage = file;
analyzeImageBtn.disabled = false;
visionStatus.textContent = 'βœ… Image uploaded successfully';
};
reader.readAsDataURL(file);
}
// Image Generation
generateImageBtn.addEventListener('click', function() {
const prompt = imagePromptInput.value.trim();
if (!prompt) {
generationStatus.textContent = '❌ Please enter a prompt';
return;
}
const apiKey = localStorage.getItem(API_KEY_STORAGE_KEY);
if (!apiKey) {
generationStatus.textContent = '❌ API key is required. Please add your API key in the API Key section.';
return;
}
// Show loading state
generationStatus.innerHTML = '<span class="loading"></span> Generating image...';
generateImageBtn.disabled = true;
imageResult.innerHTML = '';
// Call the backend API with OpenAI-style format
fetch('/api/generate-image', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
api_key: apiKey,
prompt: prompt,
use_openai_format: true
})
})
.then(response => {
if (!response.ok) {
return response.json().then(err => { throw err; });
}
return response.json();
})
.then(data => {
if (data.image_url) {
// Display the generated image
let imageHTML = `<img src="${data.image_url}" alt="Generated image">`;
// Add caption if available
if (data.caption) {
imageHTML += `<div class="image-caption">${data.caption}</div>`;
}
imageResult.innerHTML = imageHTML;
generationStatus.textContent = 'βœ… Image generated successfully';
} else {
throw new Error('No image URL in response');
}
})
.catch(error => {
generationStatus.textContent = `❌ Error: ${error.error || error.message || 'Unknown error'}`;
console.error('Image generation error:', error);
})
.finally(() => {
generateImageBtn.disabled = false;
});
});
// Vision Analysis
analyzeImageBtn.addEventListener('click', function() {
if (!uploadedImage) {
visionStatus.textContent = '❌ Please upload an image first';
return;
}
const prompt = visionPromptInput.value.trim() || 'Describe this image in detail';
const apiKey = localStorage.getItem(API_KEY_STORAGE_KEY);
if (!apiKey) {
visionStatus.textContent = '❌ API key is required. Please add your API key in the API Key section.';
return;
}
// Show loading state
visionStatus.innerHTML = '<span class="loading"></span> Analyzing image...';
analyzeImageBtn.disabled = true;
visionResult.textContent = '';
// Create form data for file upload
const formData = new FormData();
formData.append('image', uploadedImage);
formData.append('api_key', apiKey);
formData.append('prompt', prompt);
// Call the backend API
fetch('/api/analyze-image', {
method: 'POST',
body: formData
})
.then(response => {
if (!response.ok) {
return response.json().then(err => { throw err; });
}
return response.json();
})
.then(data => {
if (data.analysis) {
// Display the analysis result with Markdown support
visionResult.innerHTML = marked.parse(data.analysis);
visionStatus.textContent = 'βœ… Analysis completed';
} else {
throw new Error('No analysis in response');
}
})
.catch(error => {
visionStatus.textContent = `❌ Error: ${error.error || error.message || 'Unknown error'}`;
console.error('Vision analysis error:', error);
})
.finally(() => {
analyzeImageBtn.disabled = false;
});
});
});