Browse Source
changes in food distribution api controller and service and pages newly added detailed report
master
changes in food distribution api controller and service and pages newly added detailed report
master
5 changed files with 697 additions and 14 deletions
-
34src/main/java/com/gcc/commissionerreview/controller/FoodDistrubutionReportApiController.java
-
5src/main/java/com/gcc/commissionerreview/controller/MainController.java
-
47src/main/java/com/gcc/commissionerreview/service/Fooddistributionservice.java
-
566src/main/resources/templates/modules/fooddistribution/fooddistributiondetailedreport.html
-
59src/main/resources/templates/modules/fooddistribution/fooddistributionreport.html
@ -0,0 +1,566 @@ |
|||
<!DOCTYPE html> |
|||
<html lang="en" xmlns:th="http://www.thymeleaf.org"> |
|||
|
|||
<head> |
|||
<title>Food Distribution Detailed Report</title> |
|||
|
|||
<!-- Bootstrap 5 CSS --> |
|||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css" rel="stylesheet"> |
|||
<!-- FontAwesome CSS for icons --> |
|||
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" rel="stylesheet"> |
|||
<!-- DataTables CSS --> |
|||
<link href="https://cdn.datatables.net/1.13.4/css/jquery.dataTables.min.css" rel="stylesheet" /> |
|||
<link href="https://cdn.datatables.net/buttons/2.3.6/css/buttons.dataTables.min.css" rel="stylesheet" /> |
|||
|
|||
<style> |
|||
body { |
|||
background-color: #f8f9fa; |
|||
} |
|||
|
|||
.page-header-title h4 { |
|||
margin: 20px 0; |
|||
text-align: center; |
|||
font-weight: bold; |
|||
color: #003366; |
|||
text-transform: uppercase; |
|||
} |
|||
|
|||
.filter-section { |
|||
background: #fff; |
|||
padding: 15px; |
|||
border-radius: 8px; |
|||
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05); |
|||
margin-bottom: 20px; |
|||
} |
|||
|
|||
table.dataTable th, |
|||
table.dataTable td { |
|||
text-align: center; |
|||
vertical-align: middle; |
|||
border: 1px solid #dee2e6 !important; |
|||
white-space: normal !important; |
|||
word-break: break-word; |
|||
} |
|||
|
|||
thead th { |
|||
background-color: #003366 !important; |
|||
color: white !important; |
|||
} |
|||
|
|||
.report-container { |
|||
background: #fff; |
|||
padding: 15px; |
|||
border-radius: 8px; |
|||
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05); |
|||
} |
|||
|
|||
.dataTables_scrollBody { |
|||
overflow-x: auto !important; |
|||
overflow-y: auto !important; |
|||
white-space: nowrap; |
|||
touch-action: pan-x pan-y; |
|||
cursor: grab; |
|||
} |
|||
|
|||
.dataTables_scrollBody:active { |
|||
cursor: grabbing; |
|||
} |
|||
|
|||
.dataTables_wrapper { |
|||
overflow-x: auto !important; |
|||
} |
|||
|
|||
.dataTables_scrollHeadInner table, |
|||
.report-container table.dataTable { |
|||
min-width: 2400px !important; |
|||
width: 100% !important; |
|||
} |
|||
|
|||
.dataTables_scrollBody::-webkit-scrollbar { |
|||
height: 8px; |
|||
width: 8px; |
|||
} |
|||
|
|||
.dataTables_scrollBody::-webkit-scrollbar-track { |
|||
background: #f1f1f1; |
|||
border-radius: 4px; |
|||
} |
|||
|
|||
.dataTables_scrollBody::-webkit-scrollbar-thumb { |
|||
background: #c1c1c1; |
|||
border-radius: 4px; |
|||
} |
|||
|
|||
.dataTables_scrollBody::-webkit-scrollbar-thumb:hover { |
|||
background: #a8a8a8; |
|||
} |
|||
|
|||
.swal2-container.swal2-custom-zindex { |
|||
z-index: 1070 !important; |
|||
} |
|||
|
|||
/* Ensure columns don't squish */ |
|||
#detailDataTable th { |
|||
max-width: 150px; |
|||
} |
|||
</style> |
|||
</head> |
|||
|
|||
<body> |
|||
|
|||
<div class="container-fluid py-4"> |
|||
<div class="page-header-title d-flex justify-content-between align-items-center"> |
|||
<a href="/commissionerreview/fooddistributionreport" class="btn btn-secondary"><i |
|||
class="fa-solid fa-arrow-left"></i> Back to Abstract</a> |
|||
<h4 class="mb-0 mx-auto">Food Distribution Detailed Report</h4> |
|||
<div style="width: 100px;"></div> |
|||
</div> |
|||
|
|||
<!-- Filter Section --> |
|||
<div class="filter-section d-flex justify-content-center align-items-end gap-3 flex-wrap mt-3"> |
|||
<div> |
|||
<label for="hubId" class="form-label fw-bold">Kitchen/Hub:</label> |
|||
<select id="hubId" class="form-select"> |
|||
<option value="">All Kitchens</option> |
|||
</select> |
|||
</div> |
|||
<div> |
|||
<label for="shiftId" class="form-label fw-bold">Shift:</label> |
|||
<select id="shiftId" class="form-select"> |
|||
<option value="">All Shifts</option> |
|||
</select> |
|||
</div> |
|||
<div> |
|||
<label for="fromDate" class="form-label fw-bold">From Date:</label> |
|||
<input type="date" id="fromDate" class="form-control"> |
|||
</div> |
|||
<div> |
|||
<label for="toDate" class="form-label fw-bold">To Date:</label> |
|||
<input type="date" id="toDate" class="form-control"> |
|||
</div> |
|||
<div> |
|||
<button id="btnSearch" class="btn btn-primary px-4"><i class="fa-solid fa-search"></i> Search</button> |
|||
</div> |
|||
</div> |
|||
|
|||
<div class="report-container"> |
|||
<table id="detailDataTable" class="table table-striped table-bordered display nowrap" style="width:100%;"> |
|||
<thead> |
|||
<tr> |
|||
<th class="text-center">S.No</th> |
|||
<th class="text-center">Audit Date</th> |
|||
<th class="text-center">Shift</th> |
|||
<th class="text-center">Zone</th> |
|||
<th class="text-center">Ward</th> |
|||
<th class="text-center">Address</th> |
|||
<th class="text-center">Audit Category</th> |
|||
<th class="text-center">Question</th> |
|||
<th class="text-center">Answer</th> |
|||
<th class="text-center">Kitchen SI Name</th> |
|||
<th class="text-center">Raised By</th> |
|||
<th class="text-center">PMC Remarks</th> |
|||
<th class="text-center">PMC Image/Video Viewer</th> |
|||
<th class="text-center">FS Status</th> |
|||
<th class="text-center">FS Challenged By</th> |
|||
<th class="text-center">FS Remarks</th> |
|||
<th class="text-center">FS Image/Video Viewer</th> |
|||
<th class="text-center">CE Status</th> |
|||
<th class="text-center">CE Remarks</th> |
|||
<th class="text-center">CE Updated By</th> |
|||
<th class="text-center">Penalty Amount</th> |
|||
</tr> |
|||
</thead> |
|||
<tbody> |
|||
<!-- Populated via JS --> |
|||
</tbody> |
|||
</table> |
|||
</div> |
|||
|
|||
<!-- Media Modal --> |
|||
<div class="modal fade" id="mediaModal" tabindex="-1" aria-labelledby="mediaModalLabel" aria-hidden="true" |
|||
style="z-index: 1060;"> |
|||
<div class="modal-dialog modal-lg modal-dialog-centered"> |
|||
<div class="modal-content"> |
|||
<div class="modal-header"> |
|||
<h5 class="modal-title" id="mediaModalLabel">Media Viewer</h5> |
|||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> |
|||
</div> |
|||
<div class="modal-body text-center" id="mediaModalBody"> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
|
|||
<!-- Scripts --> |
|||
<script src="https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.min.js"></script> |
|||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/js/bootstrap.bundle.min.js"></script> |
|||
|
|||
<!-- DataTables JS --> |
|||
<script src="https://cdn.datatables.net/1.13.4/js/jquery.dataTables.min.js"></script> |
|||
<script src="https://cdn.datatables.net/buttons/2.3.6/js/dataTables.buttons.min.js"></script> |
|||
<script src="https://cdn.datatables.net/buttons/2.3.6/js/buttons.html5.min.js"></script> |
|||
<script src="https://cdn.datatables.net/buttons/2.3.6/js/buttons.print.min.js"></script> |
|||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.1.3/jszip.min.js"></script> |
|||
<script src="https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.2.7/pdfmake.min.js"></script> |
|||
<script src="https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.2.7/vfs_fonts.js"></script> |
|||
|
|||
<!-- SweetAlert --> |
|||
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script> |
|||
|
|||
<script th:inline="none"> |
|||
var dataTable = null; |
|||
|
|||
$(document).ready(function () { |
|||
// Set default dates to yesterday |
|||
var yesterday = new Date(); |
|||
yesterday.setDate(yesterday.getDate() - 1); |
|||
var yyyy = yesterday.getFullYear(); |
|||
var mm = String(yesterday.getMonth() + 1).padStart(2, '0'); |
|||
var dd = String(yesterday.getDate()).padStart(2, '0'); |
|||
var defaultDate = yyyy + '-' + mm + '-' + dd; |
|||
|
|||
$('#fromDate').val(defaultDate); |
|||
$('#toDate').val(defaultDate); |
|||
$('#toDate').attr('min', defaultDate); |
|||
|
|||
$('#fromDate').on('change', function () { |
|||
var selectedDate = $(this).val(); |
|||
$('#toDate').attr('min', selectedDate); |
|||
if ($('#toDate').val() < selectedDate) { |
|||
$('#toDate').val(selectedDate); |
|||
} |
|||
}); |
|||
|
|||
// Load Hubs |
|||
$.ajax({ |
|||
url: '/commissionerreview/api/fooddistribution/hubs', |
|||
method: 'GET', |
|||
success: function (res) { |
|||
if (res.status === 'success') { |
|||
res.data.forEach(function (hub) { |
|||
$('#hubId').append('<option value="' + hub.hub_id + '">' + hub.hub_name + '</option>'); |
|||
}); |
|||
} |
|||
} |
|||
}); |
|||
|
|||
// Load Shifts |
|||
$.ajax({ |
|||
url: '/commissionerreview/api/fooddistribution/shifts', |
|||
method: 'GET', |
|||
success: function (res) { |
|||
if (res.status === 'success') { |
|||
res.data.forEach(function (shift) { |
|||
$('#shiftId').append('<option value="' + shift.shiftid + '">' + shift.shift_name + '</option>'); |
|||
}); |
|||
} |
|||
} |
|||
}); |
|||
|
|||
// Init DataTable |
|||
dataTable = $('#detailDataTable').DataTable({ |
|||
autoWidth: false, |
|||
columnDefs: [ |
|||
{ width: "60px", targets: 0 }, |
|||
{ width: "120px", targets: 1 }, |
|||
{ width: "60px", targets: 2 }, |
|||
{ width: "60px", targets: 3 }, |
|||
{ width: "60px", targets: 4 }, |
|||
{ width: "200px", targets: 5 }, |
|||
{ width: "180px", targets: 6 }, |
|||
{ width: "180px", targets: 7 }, |
|||
{ width: "120px", targets: 8 }, |
|||
{ width: "180px", targets: 9 }, |
|||
{ width: "150px", targets: 10 }, |
|||
{ width: "220px", targets: 11 }, |
|||
{ width: "150px", targets: 12 }, |
|||
{ width: "120px", targets: 13 }, |
|||
{ width: "150px", targets: 14 }, |
|||
{ width: "220px", targets: 15 }, |
|||
{ width: "150px", targets: 16 }, |
|||
{ width: "120px", targets: 17 }, |
|||
{ width: "220px", targets: 18 }, |
|||
{ width: "150px", targets: 19 }, |
|||
{ width: "150px", targets: 20 } |
|||
], |
|||
responsive: false, |
|||
scrollX: true, |
|||
scrollY: "60vh", |
|||
scrollCollapse: true, |
|||
searching: true, |
|||
paging: true, |
|||
info: true, |
|||
ordering: false, |
|||
dom: '<"d-flex justify-content-between align-items-center mb-3"lfB>rtip', |
|||
lengthMenu: [[10, 50, 100, -1], [10, 50, 100, "All"]], |
|||
buttons: [ |
|||
{ |
|||
extend: 'excelHtml5', |
|||
text: '<i class="fa-solid fa-file-excel"></i> Excel', |
|||
className: 'btn btn-success btn-sm me-2', |
|||
title: function () { |
|||
return 'Food Distribution Detailed Report - ' + $('#hubId option:selected').text(); |
|||
}, |
|||
filename: function () { |
|||
var kitchen = $('#hubId option:selected').text().replace(/[^a-zA-Z0-9]/g, '_'); |
|||
return 'Detailed_Food_Distribution_' + kitchen + '_' + ($('#fromDate').val() || 'All') + '_to_' + ($('#toDate').val() || 'All'); |
|||
}, |
|||
exportOptions: { |
|||
format: { |
|||
body: function (data, row, column, node) { |
|||
if (typeof data === 'string' && data.indexOf('showMedia') !== -1) { |
|||
var match = data.match(/showMedia\('([^']+)'/); |
|||
if (match) return match[1]; |
|||
} |
|||
if (typeof data === 'string' && data.indexOf('data-fulltext') !== -1) { |
|||
var match = data.match(/data-fulltext="([^"]+)"/); |
|||
if (match) return decodeURIComponent(match[1]); |
|||
} |
|||
var div = document.createElement("div"); |
|||
div.innerHTML = data; |
|||
return div.textContent || div.innerText || ""; |
|||
} |
|||
} |
|||
} |
|||
}, |
|||
{ |
|||
extend: 'pdfHtml5', |
|||
text: '<i class="fa-solid fa-file-pdf"></i> PDF', |
|||
className: 'btn btn-danger btn-sm', |
|||
orientation: 'landscape', |
|||
pageSize: 'A0', // Set to A0 so the rows don't get cut due to extreme width |
|||
title: function () { |
|||
return 'Food Distribution Detailed Report - ' + $('#hubId option:selected').text(); |
|||
}, |
|||
filename: function () { |
|||
var kitchen = $('#hubId option:selected').text().replace(/[^a-zA-Z0-9]/g, '_'); |
|||
return 'Detailed_Food_Distribution_' + kitchen + '_' + ($('#fromDate').val() || 'All') + '_to_' + ($('#toDate').val() || 'All'); |
|||
}, |
|||
exportOptions: { |
|||
format: { |
|||
body: function (data, row, column, node) { |
|||
if (typeof data === 'string' && data.indexOf('showMedia') !== -1) { |
|||
var match = data.match(/showMedia\('([^']+)'/); |
|||
if (match) return match[1]; |
|||
} |
|||
if (typeof data === 'string' && data.indexOf('data-fulltext') !== -1) { |
|||
var match = data.match(/data-fulltext="([^"]+)"/); |
|||
if (match) return decodeURIComponent(match[1]); |
|||
} |
|||
var div = document.createElement("div"); |
|||
div.innerHTML = data; |
|||
return div.textContent || div.innerText || ""; |
|||
} |
|||
} |
|||
}, |
|||
customize: function (doc) { |
|||
doc.styles.tableHeader.fontSize = 12; |
|||
doc.defaultStyle.fontSize = 10; |
|||
// Prevent breaking cells across pages |
|||
doc.content[1].table.dontBreakRows = true; |
|||
} |
|||
} |
|||
] |
|||
}); |
|||
|
|||
$('#btnSearch').click(function () { |
|||
loadDetailedReport(); |
|||
}); |
|||
|
|||
// Load data initially |
|||
loadDetailedReport(); |
|||
}); |
|||
|
|||
function loadDetailedReport() { |
|||
var fromDate = $('#fromDate').val() || ''; |
|||
var toDate = $('#toDate').val() || ''; |
|||
var hubId = $('#hubId').val() || ''; |
|||
var shiftId = $('#shiftId').val() || ''; |
|||
|
|||
Swal.fire({ title: 'Loading...', allowOutsideClick: false, didOpen: function () { Swal.showLoading(); } }); |
|||
|
|||
$.ajax({ |
|||
url: '/commissionerreview/api/fooddistribution/complianceDetails', |
|||
method: 'GET', |
|||
data: { |
|||
fromDate: fromDate, |
|||
toDate: toDate, |
|||
hubId: hubId, |
|||
shiftId: shiftId |
|||
}, |
|||
success: function (res) { |
|||
Swal.close(); |
|||
if (res.status === 'success') { |
|||
populateTable(res.data); |
|||
} else { |
|||
Swal.fire('Error', 'Failed to load detailed data.', 'error'); |
|||
} |
|||
}, |
|||
error: function () { |
|||
Swal.close(); |
|||
Swal.fire('Error', 'API error loading detailed data.', 'error'); |
|||
} |
|||
}); |
|||
} |
|||
|
|||
function populateTable(data) { |
|||
dataTable.clear(); |
|||
data.forEach(function (item, index) { |
|||
var ext = item.videoLink ? item.videoLink.split('.').pop().toLowerCase() : ''; |
|||
var isVideo = ['mp4', 'mov', 'avi', 'webm', 'mkv'].includes(ext); |
|||
|
|||
var imgBtn = '-'; |
|||
if (item.videoLink && item.videoLink.indexOf('null') === -1) { |
|||
imgBtn = '<button onclick="showMedia(\'' + item.videoLink + '\', ' + isVideo + ')" class="btn btn-sm btn-info text-white"><i class="fa fa-' + (isVideo ? 'video' : 'image') + '"></i> View</button>'; |
|||
} |
|||
|
|||
var fsExt = item.fsVideoLink ? item.fsVideoLink.split('.').pop().toLowerCase() : ''; |
|||
var isFsVideo = ['mp4', 'mov', 'avi', 'webm', 'mkv'].includes(fsExt); |
|||
|
|||
var fsImgBtn = '-'; |
|||
if (item.fsVideoLink && item.fsVideoLink.indexOf('null') === -1) { |
|||
fsImgBtn = '<button onclick="showMedia(\'' + item.fsVideoLink + '\', ' + isFsVideo + ')" class="btn btn-sm btn-info text-white"><i class="fa fa-' + (isFsVideo ? 'video' : 'image') + '"></i> View</button>'; |
|||
} |
|||
|
|||
var fsStsStr = (item.fsStatus || '').toLowerCase(); |
|||
var ceStsStr = (item.chief_engineer_status || '').toLowerCase(); |
|||
var pAmt = parseInt(item.penalty_amt) || 0; |
|||
var finalPenalty = pAmt; |
|||
|
|||
if (item.english_name === 'Issue Found') { |
|||
if (fsStsStr === 'challenge' && ceStsStr === 'reject') { |
|||
finalPenalty = pAmt; |
|||
} else if (fsStsStr === 'accept') { |
|||
finalPenalty = pAmt; |
|||
} else if (fsStsStr === 'challenge' && ceStsStr === 'accept') { |
|||
finalPenalty = '-'; |
|||
} else if (fsStsStr === 'challenge' && (ceStsStr === '' || ceStsStr === '-')) { |
|||
finalPenalty = 'Pending'; |
|||
} |
|||
} else { |
|||
finalPenalty = '-'; |
|||
} |
|||
|
|||
dataTable.row.add([ |
|||
index + 1, |
|||
item.auditDate || '-', |
|||
item.shift || '-', |
|||
item.zone || '-', |
|||
item.ward || '-', |
|||
item.address || '-', |
|||
item.audit_category || '-', |
|||
item.q_english || '-', |
|||
item.english_name || '-', |
|||
item.name || '-', |
|||
item.raisedBy || '-', |
|||
formatRemark(item.pmcRemarks, 'PMC Remarks'), |
|||
imgBtn, |
|||
item.fsStatus || '-', |
|||
item.fsChallengedBy || '-', |
|||
formatRemark(item.fsRemarks, 'FS Remarks'), |
|||
fsImgBtn, |
|||
item.chief_engineer_status || '-', |
|||
formatRemark(item.chief_engineer_remarks, 'CE Remarks'), |
|||
item.chief_engineer || '-', |
|||
finalPenalty |
|||
]); |
|||
}); |
|||
dataTable.draw(); |
|||
setTimeout(function () { |
|||
dataTable.columns.adjust().draw(); |
|||
}, 300); |
|||
} |
|||
|
|||
function formatRemark(text, title) { |
|||
if (!text || text === '-' || String(text).trim() === '' || String(text) === 'null') { |
|||
return '-'; |
|||
} |
|||
var str = String(text); |
|||
if (str.length > 100) { |
|||
var truncated = $('<div>').text(str.substring(0, 100) + '...').html(); |
|||
var encodedText = encodeURIComponent(str); |
|||
return '<span class="text-primary fw-bold" style="cursor:pointer; text-decoration:underline;" onclick="showFullRemark(\'' + title + '\', \'' + encodedText + '\')" title="Click to view full remark" data-fulltext="' + encodedText + '">' + truncated + '</span>'; |
|||
} |
|||
return $('<div>').text(str).html(); |
|||
} |
|||
|
|||
function showFullRemark(title, encodedText) { |
|||
var text = decodeURIComponent(encodedText); |
|||
Swal.fire({ |
|||
title: title, |
|||
html: '<div style="text-align: left; white-space: pre-wrap; font-size: 18px; max-height: 400px; overflow-y: auto; padding: 10px; background: #f8f9fa; border-radius: 5px; border: 1px solid #dee2e6;">' + $('<div>').text(text).html() + '</div>', |
|||
width: '600px', |
|||
confirmButtonText: 'Close', |
|||
customClass: { |
|||
popup: 'swal2-custom-zindex' |
|||
} |
|||
}); |
|||
} |
|||
|
|||
function showMedia(url, isVideo) { |
|||
var mediaHtml = ''; |
|||
if (isVideo) { |
|||
mediaHtml = '<video width="100%" controls controlsList="nodownload" disablePictureInPicture><source src="' + url + '">Your browser does not support the video tag.</video>'; |
|||
} else { |
|||
mediaHtml = '<img src="' + url + '" style="max-width: 100%; height: auto; pointer-events: none; user-select: none;" oncontextmenu="return false;" />'; |
|||
} |
|||
$('#mediaModalBody').html(mediaHtml); |
|||
$('#mediaModal').modal('show'); |
|||
|
|||
$('#mediaModal').off('hidden.bs.modal').on('hidden.bs.modal', function () { |
|||
$('#mediaModalBody').empty(); |
|||
}); |
|||
} |
|||
|
|||
// Drag scroll functionality |
|||
let isDown = false; |
|||
let startX; |
|||
let scrollLeft; |
|||
|
|||
$(document).on('mousedown', '.dataTables_scrollBody', function (e) { |
|||
isDown = true; |
|||
$(this).css('cursor', 'grabbing'); |
|||
startX = e.pageX - this.offsetLeft; |
|||
scrollLeft = this.scrollLeft; |
|||
}); |
|||
|
|||
$(document).on('mouseleave', '.dataTables_scrollBody', function () { |
|||
isDown = false; |
|||
$(this).css('cursor', ''); |
|||
}); |
|||
|
|||
$(document).on('mouseup', '.dataTables_scrollBody', function () { |
|||
isDown = false; |
|||
$(this).css('cursor', ''); |
|||
}); |
|||
|
|||
$(document).on('mousemove', '.dataTables_scrollBody', function (e) { |
|||
if (!isDown) return; |
|||
e.preventDefault(); |
|||
const x = e.pageX - this.offsetLeft; |
|||
const walk = (x - startX) * 1.5; |
|||
this.scrollLeft = scrollLeft - walk; |
|||
}); |
|||
|
|||
// Touchpad scroll mapping support |
|||
$(document).on('wheel', '.dataTables_scrollBody', function (e) { |
|||
const el = this; |
|||
const deltaX = e.originalEvent.deltaX; |
|||
const deltaY = e.originalEvent.deltaY; |
|||
|
|||
const canScrollY = el.scrollHeight > Math.ceil(el.clientHeight) + 5; |
|||
const canScrollX = el.scrollWidth > Math.ceil(el.clientWidth) + 5; |
|||
|
|||
if (Math.abs(deltaX) > Math.abs(deltaY)) { |
|||
el.scrollLeft += deltaX; |
|||
e.preventDefault(); |
|||
} |
|||
else if (!canScrollY && canScrollX && Math.abs(deltaY) > 0) { |
|||
el.scrollLeft += deltaY; |
|||
e.preventDefault(); |
|||
} |
|||
}); |
|||
</script> |
|||
</body> |
|||
|
|||
</html> |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue