plugins_Waivers_assets_js_controllers_camera-capture-controller.js
import { Controller } from "@hotwired/stimulus"
/**
* Camera Capture Controller
*
* Provides enhanced mobile camera capture functionality.
* Works in conjunction with HTML5 file input capture attribute.
*
* Note: Most camera functionality is handled by HTML5 capture="environment"
* attribute. This controller provides UI enhancements and fallback behavior.
*
* Targets:
* - cameraInput: File input with camera capture
* - cameraButton: Optional button to trigger camera
* - preview: Preview area for captured images
*
* Actions:
* - triggerCamera: Open device camera
* - handleCapture: Handle image capture
*/
class CameraCaptureController extends Controller {
static targets = ["cameraInput", "cameraButton", "preview"]
/**
* Initialize controller
*/
connect() {
console.log('CameraCaptureController connected')
this.detectMobileDevice()
}
/**
* Detect if user is on mobile device
* Updates UI to show mobile-specific instructions
*/
detectMobileDevice() {
const isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)
if (isMobile) {
console.log('Mobile device detected - camera capture available')
// Could add visual indicators that camera is available
if (this.hasCameraInputTarget) {
const parent = this.cameraInputTarget.parentElement
const helpText = parent.querySelector('.form-text')
if (helpText) {
helpText.classList.add('text-success')
helpText.innerHTML = '<i class="bi bi-camera-fill"></i> ' + helpText.innerHTML
}
}
}
}
/**
* Trigger camera input
* Useful if you have a custom camera button instead of using the file input directly
*
* @param {Event} event Button click event
*/
triggerCamera(event) {
event.preventDefault()
if (this.hasCameraInputTarget) {
this.cameraInputTarget.click()
}
}
/**
* Handle image capture
* Called when user selects/captures an image
*
* @param {Event} event File input change event
*/
handleCapture(event) {
const files = event.target.files
if (files && files.length > 0) {
console.log(`Captured ${files.length} image(s)`)
// Show preview if target exists
if (this.hasPreviewTarget) {
this.showImagePreview(files[0])
}
// Dispatch custom event for other controllers to handle
this.dispatch('imageCaptured', {
detail: { files: Array.from(files) }
})
}
}
/**
* Show image preview (optional enhancement)
*
* @param {File} file Image file to preview
*/
showImagePreview(file) {
const reader = new FileReader()
reader.onload = (e) => {
this.previewTarget.innerHTML = `
<div class="card">
<img src="${e.target.result}" class="card-img-top" alt="Preview" style="max-height: 300px; object-fit: contain;">
<div class="card-body">
<p class="card-text text-center">
<small class="text-muted">${file.name} (${this.formatFileSize(file.size)})</small>
</p>
</div>
</div>
`
this.previewTarget.style.display = 'block'
}
reader.readAsDataURL(file)
}
/**
* Format file size
*
* @param {number} bytes File size in bytes
* @returns {string} Formatted size
*/
formatFileSize(bytes) {
if (bytes === 0) return '0 Bytes'
const k = 1024
const sizes = ['Bytes', 'KB', 'MB']
const i = Math.floor(Math.log(bytes) / Math.log(k))
return Math.round(bytes / Math.pow(k, i) * 100) / 100 + ' ' + sizes[i]
}
/**
* Check if browser supports camera capture
*
* @returns {boolean} True if capture is supported
*/
static supportsCameraCapture() {
const input = document.createElement('input')
input.setAttribute('capture', 'camera')
return input.capture !== undefined
}
}
// Add to global controllers registry
if (!window.Controllers) {
window.Controllers = {}
}
window.Controllers["camera-capture"] = CameraCaptureController