update
This commit is contained in:
@@ -0,0 +1,203 @@
|
||||
@props([
|
||||
'name' => 'thumbnail',
|
||||
'label' => 'Thumbnail',
|
||||
'value' => null,
|
||||
'placeholder' => 'Chọn File',
|
||||
'required' => false,
|
||||
'horizontal' => true,
|
||||
'labelClass' => 'col-md-3 text-right',
|
||||
'inputClass' => 'col-md-9',
|
||||
])
|
||||
|
||||
@php
|
||||
$uniqueId = 'image-picker-' . uniqid();
|
||||
$currentValue = old($name) ?? $value;
|
||||
@endphp
|
||||
|
||||
@if ($horizontal)
|
||||
<div class="row form-group align-items-center mb-0">
|
||||
<label for="{{ $name }}" class="{{ $labelClass }}">
|
||||
{{ $label }}
|
||||
@if ($required)
|
||||
<span class="text-danger">*</span>
|
||||
@endif
|
||||
</label>
|
||||
<div class="{{ $inputClass }} p-1">
|
||||
@else
|
||||
<div class="form-group mb-3">
|
||||
<label for="{{ $name }}" class="mb-2">
|
||||
{{ $label }}
|
||||
@if ($required)
|
||||
<span class="text-danger">*</span>
|
||||
@endif
|
||||
</label>
|
||||
<div>
|
||||
@endif
|
||||
<div class="row">
|
||||
<div class="col-md-8 bg-customer">
|
||||
<input type="text" id="{{ $uniqueId }}-input" name="{{ $name }}" value="{{ $currentValue }}"
|
||||
class="form-control image-picker-input" placeholder="{{ $placeholder }}"
|
||||
data-picker-id="{{ $uniqueId }}" @if ($required) required @endif>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<button type="button" class="btn btn-outline-secondary btn-open-image-picker"
|
||||
data-picker-id="{{ $uniqueId }}">
|
||||
<i data-lucide="folder-open" class="w-14px h-14px me-1"></i> Chọn hình ảnh
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- Image Preview --}}
|
||||
<div class="mt-2" id="{{ $uniqueId }}-preview-wrapper" style="display: {{ $currentValue ? 'block' : 'none' }};">
|
||||
<div class="position-relative d-inline-block">
|
||||
<div id="{{ $uniqueId }}-preview-container"
|
||||
class="img-thumbnail bg-light d-flex align-items-center justify-content-center"
|
||||
style="max-width: 200px; max-height: 150px; min-width: 100px; min-height: 80px; cursor: pointer; overflow: hidden;"
|
||||
data-bs-toggle="modal" data-bs-target="#{{ $uniqueId }}-modal">
|
||||
@if ($currentValue)
|
||||
@if (str_ends_with(strtolower($currentValue), '.svg'))
|
||||
<object data="{{ $currentValue }}" type="image/svg+xml"
|
||||
style="max-width: 100%; max-height: 150px; width: auto; height: auto;">
|
||||
<img src="{{ $currentValue }}" alt="Preview" style="max-width: 100%; max-height: 150px;">
|
||||
</object>
|
||||
@else
|
||||
<img src="{{ $currentValue }}" alt="Preview"
|
||||
style="max-width: 100%; max-height: 150px; object-fit: contain;">
|
||||
@endif
|
||||
@endif
|
||||
</div>
|
||||
<button type="button" class="btn btn-sm btn-danger position-absolute btn-remove-image end-0 top-0"
|
||||
data-picker-id="{{ $uniqueId }}" style="transform: translate(50%, -50%);">
|
||||
<i data-lucide="x" class="w-12px h-12px"></i>
|
||||
</button>
|
||||
</div>
|
||||
<small class="text-muted d-block mt-1">Click vào ảnh để xem phóng to</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- Image Preview Modal --}}
|
||||
<div class="modal fade" id="{{ $uniqueId }}-modal" tabindex="-1" aria-hidden="true">
|
||||
<div class="modal-dialog modal-lg modal-dialog-centered">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">
|
||||
<i data-lucide="image" class="w-18px h-18px me-2"></i>
|
||||
Preview Image
|
||||
</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body bg-light p-3 text-center">
|
||||
<div id="{{ $uniqueId }}-modal-container" class="d-flex align-items-center justify-content-center"
|
||||
style="min-height: 300px;">
|
||||
@if ($currentValue)
|
||||
@if (str_ends_with(strtolower($currentValue), '.svg'))
|
||||
<object data="{{ $currentValue }}" type="image/svg+xml"
|
||||
style="max-width: 100%; max-height: 70vh; width: auto; height: auto;">
|
||||
<img src="{{ $currentValue }}" alt="Full Preview"
|
||||
style="max-width: 100%; max-height: 70vh;">
|
||||
</object>
|
||||
@else
|
||||
<img src="{{ $currentValue }}" alt="Full Preview" class="img-fluid"
|
||||
style="max-height: 70vh;">
|
||||
@endif
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@pushOnce('custom-scripts')
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
// Prevent multiple initializations
|
||||
if (window.imagePickerInitialized) return;
|
||||
window.imagePickerInitialized = true;
|
||||
|
||||
// Function to check if file is SVG
|
||||
function isSvg(url) {
|
||||
return url && url.toLowerCase().endsWith('.svg');
|
||||
}
|
||||
|
||||
// Function to update preview
|
||||
function updateImagePreview(pickerId, url) {
|
||||
const $wrapper = $(`#${pickerId}-preview-wrapper`);
|
||||
const $container = $(`#${pickerId}-preview-container`);
|
||||
const $modalContainer = $(`#${pickerId}-modal-container`);
|
||||
|
||||
if (url && url.trim() !== '') {
|
||||
if (isSvg(url)) {
|
||||
$container.html(`
|
||||
<object data="${url}" type="image/svg+xml"
|
||||
style="max-width: 100%; max-height: 150px; width: auto; height: auto;">
|
||||
<img src="${url}" alt="Preview" style="max-width: 100%; max-height: 150px;">
|
||||
</object>
|
||||
`);
|
||||
$modalContainer.html(`
|
||||
<object data="${url}" type="image/svg+xml"
|
||||
style="max-width: 100%; max-height: 70vh; width: auto; height: auto;">
|
||||
<img src="${url}" alt="Full Preview" style="max-width: 100%; max-height: 70vh;">
|
||||
</object>
|
||||
`);
|
||||
} else {
|
||||
$container.html(`
|
||||
<img src="${url}" alt="Preview" style="max-width: 100%; max-height: 150px; object-fit: contain;">
|
||||
`);
|
||||
$modalContainer.html(`
|
||||
<img src="${url}" alt="Full Preview" class="img-fluid" style="max-height: 70vh;">
|
||||
`);
|
||||
}
|
||||
$wrapper.slideDown(200);
|
||||
|
||||
// Reinitialize Lucide icons
|
||||
if (typeof lucide !== 'undefined') {
|
||||
lucide.createIcons();
|
||||
}
|
||||
} else {
|
||||
$wrapper.slideUp(200);
|
||||
}
|
||||
}
|
||||
|
||||
// Listen for input changes
|
||||
$(document).on('input change', '.image-picker-input', function() {
|
||||
const pickerId = $(this).data('picker-id');
|
||||
updateImagePreview(pickerId, $(this).val());
|
||||
});
|
||||
|
||||
// Remove image button
|
||||
$(document).on('click', '.btn-remove-image', function(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
const pickerId = $(this).data('picker-id');
|
||||
const $input = $(`#${pickerId}-input`);
|
||||
$input.val('');
|
||||
$(`#${pickerId}-preview-wrapper`).slideUp(200);
|
||||
});
|
||||
|
||||
// Open CKFinder popup
|
||||
$(document).on('click', '.btn-open-image-picker', function() {
|
||||
const pickerId = $(this).data('picker-id');
|
||||
const $input = $(`#${pickerId}-input`);
|
||||
|
||||
if (typeof CKFinder !== 'undefined') {
|
||||
CKFinder.popup({
|
||||
connectorPath: '{{ route('ckfinder_connector') }}',
|
||||
chooseFiles: true,
|
||||
width: 800,
|
||||
height: 600,
|
||||
onInit: function(finder) {
|
||||
finder.on('files:choose', function(evt) {
|
||||
const fileUrl = evt.data.files.first().getUrl();
|
||||
$input.val(fileUrl).trigger('input');
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
console.error('CKFinder is not loaded');
|
||||
alert('CKFinder chưa được tải. Vui lòng thử lại.');
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@endPushOnce
|
||||
Reference in New Issue
Block a user