| Server IP : 127.0.0.1 / Your IP : 216.73.216.48 Web Server : Apache/2.4.58 (Win64) OpenSSL/3.1.3 PHP/8.2.12 System : Windows NT DESKTOP-3H4FHQJ 10.0 build 19045 (Windows 10) AMD64 User : win 10 ( 0) PHP Version : 8.2.12 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : OFF | Perl : OFF | Python : OFF | Sudo : OFF | Pkexec : OFF Directory : D:/xampp/htdocs-coblaa/pureFaith/ |
Upload File : |
<!DOCTYPE html>
<html lang="en">
<?php
session_start();
include('db.php');
?>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Spirit Lens</title>
<!-- Use the Inter font from Google Fonts -->
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700&display=swap" rel="stylesheet">
<!-- Load Tailwind CSS from CDN -->
<script src="https://cdn.tailwindcss.com"></script>
<style>
body {
font-family: 'Inter', sans-serif;
background-color: #f3f4f6;
}
/* Custom styling for the thumbnail to ensure it fits the new height constraint */
.preview-thumbnail {
max-height: 100px;
width: auto;
cursor: pointer;
border: 3px solid transparent;
transition: border-color 0.2s ease-in-out;
}
.preview-thumbnail.selected {
border-color: #4f46e5;
}
</style>
</head>
<body class="flex items-center justify-center min-h-screen p-4">
<!-- Main container for the form -->
<div class="bg-white p-8 md:p-10 rounded-3xl shadow-2xl w-full max-w-2xl border border-gray-200 transform transition-all duration-300 hover:scale-[1.01]">
<!-- Page Title -->
<h1 class="text-3xl md:text-4xl font-extrabold text-center text-gray-900 mb-8">
CBclip Video Upload
</h1>
<!-- The main form for video details -->
<form id="uploadForm" class="space-y-6">
<!-- Video Input Section -->
<div>
<label for="videoFile" class="block text-sm font-medium text-gray-700 mb-2">
Video Input
</label>
<div class="mt-1 flex justify-center px-6 pt-5 pb-6 border-2 border-gray-300 border-dashed rounded-xl">
<div class="space-y-1 text-center">
<!-- SVG for a file upload icon -->
<svg class="mx-auto h-12 w-12 text-gray-400" stroke="currentColor" fill="none" viewBox="0 0 48 48" aria-hidden="true">
<path d="M28 8H12a4 4 0 00-4 4v20m32-12v8m0 0v8a4 4 0 01-4 4H12a4 4 0 01-4-4v-4m32-4l-3.172-3.172a4 4 0 00-5.656 0L28 28M8 32l9.172-9.172a4 4 0 015.656 0L28 28m0 0l4 4m4-24h8m-4-4v8m-12 4h.02" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
</svg>
<div class="flex text-sm text-gray-600">
<label for="videoFile" class="relative cursor-pointer bg-white rounded-md font-medium text-indigo-600 hover:text-indigo-500 focus-within:outline-none focus-within:ring-2 focus-within:ring-offset-2 focus-within:ring-indigo-500">
<span>Upload a file</span>
<input id="videoFile" name="videoFile" type="file" accept="video/*" class="sr-only">
</label>
<p class="pl-1">or drag and drop</p>
</div>
<p class="text-xs text-gray-500">
MP4, MOV, AVI, etc. up to 1GB
</p>
</div>
</div>
</div>
<!-- Video Name Display (Initially hidden) -->
<div id="videoNameContainer" class="hidden mt-4 text-center">
<p class="text-lg font-medium text-gray-900 break-words" id="videoNameDisplay"></p>
</div>
<!-- Video Thumbnail Previews Section (Initially hidden) -->
<div id="previewsContainer" class="hidden my-4">
<h2 class="text-sm font-medium text-gray-700 mb-2">Video Previews</h2>
<div class="flex flex-col sm:flex-row items-center justify-center space-y-4 sm:space-y-0 sm:space-x-4">
<div class="rounded-xl overflow-hidden shadow-md text-center">
<img id="previewThumbnail1" src="" alt="Video thumbnail preview 1" class="preview-thumbnail mx-auto object-cover">
</div>
<div class="rounded-xl overflow-hidden shadow-md text-center">
<img id="previewThumbnail2" src="" alt="Video thumbnail preview 2" class="preview-thumbnail mx-auto object-cover">
</div>
<div class="rounded-xl overflow-hidden shadow-md text-center">
<img id="previewThumbnail3" src="" alt="Video thumbnail preview 3" class="preview-thumbnail mx-auto object-cover">
</div>
</div>
<!-- Upload Custom Thumbnail button -->
<div class="mt-4 text-center">
<button type="button" id="uploadThumbBtn" class="px-4 py-2 text-sm font-medium text-indigo-600 bg-white border border-indigo-600 rounded-lg hover:bg-indigo-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500">
Upload Custom Thumbnail
</button>
<!-- Hidden file input for custom thumbnail -->
<input type="file" id="customThumbFile" accept="image/*" class="sr-only">
</div>
</div>
<!-- Hidden input to store the selected thumbnail data -->
<input type="hidden" id="selectedThumbnailData" name="selectedThumbnail">
<!-- Video Name Input Section -->
<div>
<label for="videoName" class="block text-sm font-medium text-gray-700">
Video Name
</label>
<input type="text" id="videoName" name="videoName" required class="mt-1 block w-full px-4 py-2 border border-gray-300 rounded-lg shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 transition-colors">
</div>
<!-- Faith Input Section -->
<div>
<label for="faithName" class="block text-sm font-medium text-gray-700">
Faith Name
</label>
<select type="text" id="faithName" name="faithName" required class="mt-1 block w-full px-4 py-2 border border-gray-300 rounded-lg shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 transition-colors">
<option>Select</option>
<?php
$get_video_faith ="select * from cb_faithtb";
$run_get_video_faith = mysqli_query($con,$get_video_faith);
while($row_get_video_faith= mysqli_fetch_array($run_get_video_faith))
{
$cb_faith = $row_get_video_faith['cb_faith'];
?>
<option ><?php echo $cb_faith ?></option>
<?php } ?>
</select>
</div>
<!-- Description Input Section -->
<div>
<label for="description" class="block text-sm font-medium text-gray-700">
Description
</label>
<textarea id="description" name="description" rows="4" class="mt-1 block w-full px-4 py-2 border border-gray-300 rounded-lg shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 transition-colors"></textarea>
</div>
<!-- Buttons Section -->
<div class="flex flex-col sm:flex-row justify-end items-center space-y-4 sm:space-y-0 sm:space-x-4">
<!-- Cancel Button -->
<button type="button" id="cancelBtn" class="w-full sm:w-auto px-6 py-2 border border-gray-300 rounded-lg shadow-sm text-sm font-medium text-gray-700 bg-white hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 transition-colors">
Cancel
</button>
<!-- Upload Button -->
<button type="submit" id="uploadBtn" class="w-full sm:w-auto px-6 py-2 border border-transparent rounded-lg shadow-sm text-sm font-medium text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 transition-colors">
Upload
</button>
</div>
</form>
<!-- Message box for user feedback -->
<div id="messageBox" class="mt-6 hidden p-4 rounded-lg text-sm text-center font-medium transition-all duration-300" role="alert"></div>
</div>
<script>
// Get references to the form and buttons
const uploadForm = document.getElementById('uploadForm');
const cancelBtn = document.getElementById('cancelBtn');
const messageBox = document.getElementById('messageBox');
// Get references for the thumbnail preview elements
const videoFile = document.getElementById('videoFile');
const videoNameContainer = document.getElementById('videoNameContainer');
const videoNameDisplay = document.getElementById('videoNameDisplay');
const previewsContainer = document.getElementById('previewsContainer');
const previewThumbnail1 = document.getElementById('previewThumbnail1');
const previewThumbnail2 = document.getElementById('previewThumbnail2');
const previewThumbnail3 = document.getElementById('previewThumbnail3');
const thumbnails = [previewThumbnail1, previewThumbnail2, previewThumbnail3];
// Get references for the new custom thumbnail elements
const uploadThumbBtn = document.getElementById('uploadThumbBtn');
const customThumbFile = document.getElementById('customThumbFile');
const selectedThumbnailDataInput = document.getElementById('selectedThumbnailData');
// Create an off-screen video element and canvas for generating the thumbnail
const tempVideo = document.createElement('video');
const tempCanvas = document.createElement('canvas');
let tempVideoUrl = null;
/**
* Clears all form fields and hides the previews and video name display.
*/
function clearForm() {
uploadForm.reset();
clearPreviews();
unselectThumbnails();
videoNameContainer.classList.add('hidden');
videoNameDisplay.textContent = '';
// Clean up the temporary URL if it exists
if (tempVideoUrl) {
URL.revokeObjectURL(tempVideoUrl);
tempVideoUrl = null;
}
}
/**
* Hides the thumbnail previews and clears the image sources.
*/
function clearPreviews() {
previewsContainer.classList.add('hidden');
previewThumbnail1.src = '';
previewThumbnail2.src = '';
previewThumbnail3.src = '';
}
/**
* Displays a message in the message box.
* @param {string} message The message to display.
* @param {string} type The type of message ('success' or 'error').
*/
function showMessage(message, type) {
messageBox.textContent = message;
messageBox.classList.remove('hidden', 'bg-red-100', 'text-red-700', 'bg-green-100', 'text-green-700');
if (type === 'success') {
messageBox.classList.add('bg-green-100', 'text-green-700');
} else if (type === 'error') {
messageBox.classList.add('bg-red-100', 'text-red-700');
}
}
/**
* Generates and displays a thumbnail from a video at a specific time.
* @param {HTMLVideoElement} videoElement The video element to use.
* @param {HTMLCanvasElement} canvasElement The canvas element to use.
* @param {HTMLImageElement} imageElement The image element to display the thumbnail.
* @param {number} time The time in seconds to capture the frame.
*/
function generateThumbnail(videoElement, canvasElement, imageElement, time) {
// Wait for the video to seek to the specified time
videoElement.currentTime = time;
videoElement.addEventListener('seeked', () => {
// Set canvas dimensions to match the video
canvasElement.width = videoElement.videoWidth;
canvasElement.height = videoElement.videoHeight;
// Get the canvas context and draw the video frame
const ctx = canvasElement.getContext('2d');
ctx.drawImage(videoElement, 0, 0, canvasElement.width, canvasElement.height);
// Generate a data URL from the canvas and set it as the image source
imageElement.src = canvasElement.toDataURL('image/jpeg');
}, { once: true });
}
/**
* Unselects all thumbnails.
*/
function unselectThumbnails() {
thumbnails.forEach(thumb => thumb.classList.remove('selected'));
selectedThumbnailDataInput.value = '';
}
// Add a listener to the file input to show the thumbnail previews
videoFile.addEventListener('change', (event) => {
const file = event.target.files[0];
if (file) {
unselectThumbnails();
// Show video name preview
videoNameDisplay.textContent = file.name;
videoNameContainer.classList.remove('hidden');
// Create a temporary video URL and assign it to a global variable
tempVideoUrl = URL.createObjectURL(file);
tempVideo.src = tempVideoUrl;
tempVideo.addEventListener('loadedmetadata', () => {
const duration = tempVideo.duration;
// Capture thumbnails at 10%, 50%, and 90% of the video duration
generateThumbnail(tempVideo, tempCanvas, previewThumbnail1, duration * 0.1);
generateThumbnail(tempVideo, tempCanvas, previewThumbnail2, duration * 0.5);
generateThumbnail(tempVideo, tempCanvas, previewThumbnail3, duration * 0.9);
// Show the preview container
previewsContainer.classList.remove('hidden');
}, { once: true });
// Handle potential errors loading the video
tempVideo.addEventListener('error', () => {
console.error('Error loading video file for thumbnail generation.');
clearPreviews();
}, { once: true });
} else {
clearPreviews();
videoNameContainer.classList.add('hidden');
videoNameDisplay.textContent = '';
// Clean up the temporary URL
if (tempVideoUrl) {
URL.revokeObjectURL(tempVideoUrl);
tempVideoUrl = null;
}
}
});
// Add event listeners to the thumbnails to handle selection
thumbnails.forEach(thumb => {
thumb.addEventListener('click', () => {
unselectThumbnails();
thumb.classList.add('selected');
selectedThumbnailDataInput.value = thumb.src;
showMessage('Thumbnail selected!', 'success');
});
});
// Add event listener for the custom thumbnail upload button
uploadThumbBtn.addEventListener('click', () => {
// Programmatically click the hidden file input
customThumbFile.click();
});
// Add event listener for the hidden custom thumbnail file input
customThumbFile.addEventListener('change', (event) => {
const file = event.target.files[0];
if (file) {
const imageUrl = URL.createObjectURL(file);
unselectThumbnails();
// Set the first thumbnail to the uploaded custom image
previewThumbnail1.src = imageUrl;
previewThumbnail1.classList.add('selected');
// Clear the other two thumbnails to avoid confusion
previewThumbnail2.src = '';
previewThumbnail3.src = '';
selectedThumbnailDataInput.value = imageUrl;
showMessage('Custom thumbnail selected!', 'success');
// Clear the file input value to allow re-uploading the same file
event.target.value = '';
}
});
// Add an event listener to the form for submission
uploadForm.addEventListener('submit', async function(event) {
// Prevent the default form submission behavior
event.preventDefault();
console.log('Form submission intercepted.');
const videoFile = document.getElementById('videoFile').files[0];
const videoName = document.getElementById('videoName').value;
const description = document.getElementById('description').value;
const selectedThumbnailData = document.getElementById('selectedThumbnailData').value;
const faithName = document.getElementById('faithName').value;
if (!videoFile) {
showMessage('Please select a video file.', 'error');
return;
}
if (!videoName) {
showMessage('Please enter a video name.', 'error');
return;
}
if (faithName=='Select') {
showMessage('Please enter a video name.', 'error');
return;
}
if (!selectedThumbnailData) {
showMessage('Please select a thumbnail.', 'error');
return;
}
// Create a FormData object to send files and data
const formData = new FormData();
formData.append('videoFile', videoFile);
formData.append('videoName', videoName);
formData.append('faithName', faithName);
formData.append('description', description);
formData.append('thumbnailData', selectedThumbnailData);
try {
showMessage('Uploading...', 'success');
// This 'fetch' call will fail if the HTML file is opened directly from a local disk (file://)
// It must be served from a web server (e.g., http://localhost/...)
const response = await fetch('./upload_script.php', {
method: 'POST',
body: formData
});
if (response.ok) {
const result = await response.json();
if (result.success) {
showMessage('Video uploaded successfully!', 'success');
clearForm();
} else {
showMessage('Upload failed: ' + result.message, 'error');
}
} else {
showMessage('Network error: ' + response.statusText, 'error');
}
} catch (error) {
showMessage('An unexpected error occurred: ' + error.message, 'error');
console.error('Upload Error:', error);
}
});
// Add an event listener to the cancel button
cancelBtn.addEventListener('click', function() {
clearForm();
showMessage('Upload cancelled.', 'error');
});
</script>
</body>
</html>