HF-Grok / script.js
AntDX316
updated
9ab3421
// Wait for the DOM to be fully loaded
document.addEventListener('DOMContentLoaded', function() {
// 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.textContent = '⏳ Generating image...';
generateImageBtn.disabled = true;
// Call the Grok-2 Image API
callGrokImageApi(prompt, apiKey)
.then(imageUrl => {
// Display the generated image
imageResult.innerHTML = `<img src="${imageUrl}" alt="Generated image">`;
generationStatus.textContent = 'βœ… Image generated successfully';
})
.catch(error => {
generationStatus.textContent = `❌ Error: ${error.message}`;
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.textContent = '⏳ Analyzing image...';
analyzeImageBtn.disabled = true;
// Call the Grok-2 Vision API
callGrokVisionApi(uploadedImage, prompt, apiKey)
.then(analysisResult => {
// Display the analysis result
visionResult.textContent = analysisResult;
visionStatus.textContent = 'βœ… Analysis completed';
})
.catch(error => {
visionStatus.textContent = `❌ Error: ${error.message}`;
console.error('Vision analysis error:', error);
})
.finally(() => {
analyzeImageBtn.disabled = false;
});
});
// API Calls
async function callGrokImageApi(prompt, apiKey) {
generationStatus.textContent = '⏳ Calling Grok-2 Image API...';
try {
const response = await fetch('https://api.x.ai/v1/images/generations', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${apiKey}`
},
body: JSON.stringify({
model: "grok-2-image-1212",
prompt: prompt,
n: 1,
size: "1024x1024"
})
});
if (!response.ok) {
const errorData = await response.json().catch(() => ({ error: { message: `Status code: ${response.status}` } }));
console.log("API Error Response:", errorData);
throw new Error(errorData.error?.message || `API error: ${response.status}`);
}
const data = await response.json();
console.log("API Success Response:", data);
// Handle various response formats
if (data.data && data.data[0] && data.data[0].url) {
return data.data[0].url; // OpenAI format
} else if (data.images && data.images[0]) {
return data.images[0]; // Alternate format
} else if (data.url) {
return data.url; // Simple format
} else {
console.log("Unexpected response format:", data);
throw new Error("Unexpected response format from API");
}
} catch (error) {
console.error('Image generation API error:', error);
throw new Error(`Failed to generate image: ${error.message}`);
}
}
async function callGrokVisionApi(imageFile, prompt, apiKey) {
visionStatus.textContent = '⏳ Calling Grok-2 Vision API...';
try {
// Convert image to base64
const base64Image = await fileToBase64(imageFile);
const response = await fetch('https://api.x.ai/v1/chat/completions', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${apiKey}`
},
body: JSON.stringify({
model: "grok-2-vision-1212",
messages: [
{
role: "user",
content: [
{ type: "text", text: prompt },
{
type: "image_url",
image_url: {
url: `data:image/${imageFile.type};base64,${base64Image}`
}
}
]
}
],
max_tokens: 1000
})
});
if (!response.ok) {
const errorData = await response.json().catch(() => ({ error: { message: `Status code: ${response.status}` } }));
console.log("Vision API Error Response:", errorData);
throw new Error(errorData.error?.message || `API error: ${response.status}`);
}
const data = await response.json();
console.log("Vision API Success Response:", data);
// Handle different response formats
if (data.choices && data.choices[0] && data.choices[0].message) {
return data.choices[0].message.content;
} else if (data.response) {
return data.response;
} else {
console.log("Unexpected vision response format:", data);
return "Received a response from the API, but in an unexpected format.";
}
} catch (error) {
console.error('Vision API error:', error);
throw new Error(`Failed to analyze image: ${error.message}`);
}
}
// Helper function to convert File to base64
function fileToBase64(file) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => {
const base64String = reader.result.split(',')[1];
resolve(base64String);
};
reader.onerror = error => reject(error);
});
}
});