401 lines
16 KiB
JavaScript
Executable File
401 lines
16 KiB
JavaScript
Executable File
/**
|
|
* Copyright 2025-2026 AIIrondev
|
|
*
|
|
* Licensed under the Inventarsystem EULA (Endbenutzer-Lizenzvertrag).
|
|
* See Legal/LICENSE for the full license text.
|
|
* Unauthorized commercial use, SaaS hosting, or removal of branding is prohibited.
|
|
* For commercial licensing inquiries: https://github.com/AIIrondev
|
|
*/
|
|
|
|
// Initialize when document is loaded
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
if (isIOSDevice()) {
|
|
console.log('iOS device detected, applying iOS-specific enhancements');
|
|
applyIOSFixes();
|
|
}
|
|
});
|
|
|
|
// Apply all iOS-specific fixes
|
|
function applyIOSFixes() {
|
|
// Fix file input issues
|
|
fixIOSFileInputs();
|
|
|
|
// Fix form submission
|
|
fixIOSFormSubmission();
|
|
|
|
// Fix image handling
|
|
fixIOSImageHandling();
|
|
|
|
// Fix duplication
|
|
fixIOSDuplication();
|
|
|
|
// Apply CSS fixes
|
|
applyIOSCSSFixes();
|
|
}
|
|
|
|
// Fix iOS file input issues
|
|
function fixIOSFileInputs() {
|
|
// Find all file inputs
|
|
const fileInputs = document.querySelectorAll('input[type="file"]');
|
|
|
|
fileInputs.forEach(input => {
|
|
// Create a touch-friendly wrapper
|
|
const wrapper = document.createElement('div');
|
|
wrapper.className = 'ios-file-input-wrapper';
|
|
wrapper.style.position = 'relative';
|
|
|
|
// Style the original input to be more touch-friendly
|
|
input.style.padding = '20px 0';
|
|
|
|
// Wrap the input
|
|
if (input.parentNode) {
|
|
input.parentNode.insertBefore(wrapper, input);
|
|
wrapper.appendChild(input);
|
|
|
|
// Add a visible button for better touch target
|
|
const fakeButton = document.createElement('div');
|
|
fakeButton.className = 'ios-file-button';
|
|
fakeButton.textContent = 'Wählen Sie Bilder/Videos aus';
|
|
fakeButton.style.display = 'inline-block';
|
|
fakeButton.style.padding = '10px 15px';
|
|
fakeButton.style.backgroundColor = '#4CAF50';
|
|
fakeButton.style.color = 'white';
|
|
fakeButton.style.borderRadius = '4px';
|
|
fakeButton.style.textAlign = 'center';
|
|
fakeButton.style.margin = '10px 0';
|
|
fakeButton.style.fontWeight = 'bold';
|
|
wrapper.appendChild(fakeButton);
|
|
|
|
// Make sure the real input covers the fake button
|
|
input.style.position = 'absolute';
|
|
input.style.top = '0';
|
|
input.style.left = '0';
|
|
input.style.width = '100%';
|
|
input.style.height = '100%';
|
|
input.style.opacity = '0';
|
|
input.style.zIndex = '10';
|
|
}
|
|
|
|
// Add custom event handling
|
|
input.addEventListener('change', function() {
|
|
// Update visual feedback
|
|
const fileCount = this.files ? this.files.length : 0;
|
|
let fileText = fakeButton.textContent;
|
|
|
|
if (fileCount > 0) {
|
|
fileText = `${fileCount} Datei${fileCount !== 1 ? 'en' : ''} ausgewählt`;
|
|
fakeButton.style.backgroundColor = '#2E7D32';
|
|
} else {
|
|
fileText = 'Wählen Sie Bilder/Videos aus';
|
|
fakeButton.style.backgroundColor = '#4CAF50';
|
|
}
|
|
|
|
fakeButton.textContent = fileText;
|
|
});
|
|
});
|
|
}
|
|
|
|
// Fix iOS form submission issues
|
|
function fixIOSFormSubmission() {
|
|
// Find upload forms
|
|
const uploadForms = document.querySelectorAll('form[action*="upload_item"]');
|
|
|
|
uploadForms.forEach(form => {
|
|
// Add an iOS submission handler
|
|
form.addEventListener('submit', function(e) {
|
|
// Only intercept on iOS
|
|
if (!isIOSDevice()) return;
|
|
|
|
e.preventDefault();
|
|
|
|
// Show that we're processing
|
|
const loadingMessage = document.createElement('div');
|
|
loadingMessage.className = 'ios-loading-message';
|
|
loadingMessage.textContent = 'Wird verarbeitet...';
|
|
loadingMessage.style.padding = '10px';
|
|
loadingMessage.style.backgroundColor = '#f0f0f0';
|
|
loadingMessage.style.borderRadius = '5px';
|
|
loadingMessage.style.margin = '10px 0';
|
|
loadingMessage.style.textAlign = 'center';
|
|
form.appendChild(loadingMessage);
|
|
|
|
// Disable the submit button
|
|
const submitButton = form.querySelector('button[type="submit"]');
|
|
if (submitButton) {
|
|
submitButton.disabled = true;
|
|
}
|
|
|
|
// Use timeout to allow UI to update before heavy processing
|
|
setTimeout(() => {
|
|
// Gather form data with special handling for iOS
|
|
const formData = new FormData(form);
|
|
|
|
// Add iOS flag
|
|
formData.append('is_ios', 'true');
|
|
|
|
// Submit with fetch API which works better on iOS
|
|
fetch(form.action, {
|
|
method: 'POST',
|
|
body: formData,
|
|
credentials: 'same-origin'
|
|
})
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
// Remove loading message
|
|
if (loadingMessage.parentNode) {
|
|
loadingMessage.parentNode.removeChild(loadingMessage);
|
|
}
|
|
|
|
// Re-enable submit button
|
|
if (submitButton) {
|
|
submitButton.disabled = false;
|
|
}
|
|
|
|
if (data.success) {
|
|
// Show success and redirect
|
|
alert(data.message || 'Element erfolgreich hinzugefügt');
|
|
|
|
// Redirect to the appropriate page
|
|
if (data.itemId) {
|
|
window.location.href = `/home_admin?highlight_item=${data.itemId}`;
|
|
} else {
|
|
window.location.href = '/home_admin';
|
|
}
|
|
} else {
|
|
// Show error
|
|
alert(data.message || 'Ein Fehler ist aufgetreten');
|
|
}
|
|
})
|
|
.catch(error => {
|
|
console.error('iOS form submission error:', error);
|
|
|
|
// Remove loading message
|
|
if (loadingMessage.parentNode) {
|
|
loadingMessage.parentNode.removeChild(loadingMessage);
|
|
}
|
|
|
|
// Re-enable submit button
|
|
if (submitButton) {
|
|
submitButton.disabled = false;
|
|
}
|
|
|
|
// Show error
|
|
alert('Ein Netzwerkfehler ist aufgetreten. Bitte versuchen Sie es erneut.');
|
|
});
|
|
}, 100);
|
|
});
|
|
});
|
|
}
|
|
|
|
// Fix iOS image handling issues
|
|
function fixIOSImageHandling() {
|
|
// Reduce image preview quality on iOS
|
|
if (typeof ImagePreviewGenerator !== 'undefined') {
|
|
// Override the compression quality for iOS
|
|
const originalCompressImage = ImagePreviewGenerator.prototype._compressImage;
|
|
|
|
if (originalCompressImage) {
|
|
ImagePreviewGenerator.prototype._compressImage = function(dataUrl) {
|
|
// Lower quality for iOS
|
|
this.quality = 0.5;
|
|
this.maxWidth = 600;
|
|
this.maxHeight = 600;
|
|
|
|
return originalCompressImage.call(this, dataUrl);
|
|
};
|
|
}
|
|
}
|
|
|
|
// Fix image preview display
|
|
document.querySelectorAll('.image-preview-container').forEach(container => {
|
|
// Add iOS-specific styling
|
|
container.style.webkitOverflowScrolling = 'touch';
|
|
container.style.maxHeight = '150px';
|
|
container.style.overflow = 'auto';
|
|
});
|
|
}
|
|
|
|
// Fix iOS duplication issues
|
|
function fixIOSDuplication() {
|
|
// Override duplicateItem function
|
|
if (typeof duplicateItem !== 'undefined') {
|
|
const originalDuplicateItem = duplicateItem;
|
|
|
|
duplicateItem = function(itemId) {
|
|
// Use localStorage on iOS instead of sessionStorage
|
|
const useFunction = originalDuplicateItem;
|
|
|
|
useFunction(itemId);
|
|
|
|
// Additional iOS-specific handling
|
|
const checkForSessionData = setInterval(() => {
|
|
const sessionData = sessionStorage.getItem('duplicateItemData');
|
|
if (sessionData) {
|
|
// Copy from sessionStorage to localStorage
|
|
try {
|
|
localStorage.setItem('duplicateItemData', sessionData);
|
|
localStorage.setItem('duplicateItemTimestamp', Date.now().toString());
|
|
console.log('Copied duplicate data to localStorage for iOS reliability');
|
|
} catch (e) {
|
|
console.warn('Failed to copy to localStorage:', e);
|
|
}
|
|
|
|
clearInterval(checkForSessionData);
|
|
}
|
|
}, 100);
|
|
|
|
// Clear interval after 3 seconds regardless
|
|
setTimeout(() => clearInterval(checkForSessionData), 3000);
|
|
};
|
|
}
|
|
|
|
// Fix prefill function
|
|
if (typeof prefillFormWithDuplicateData !== 'undefined') {
|
|
const originalPrefill = prefillFormWithDuplicateData;
|
|
|
|
prefillFormWithDuplicateData = function() {
|
|
// Try to get data from localStorage first
|
|
let data = null;
|
|
try {
|
|
const localData = localStorage.getItem('duplicateItemData');
|
|
if (localData) {
|
|
data = JSON.parse(localData);
|
|
localStorage.removeItem('duplicateItemData');
|
|
localStorage.removeItem('duplicateItemTimestamp');
|
|
console.log('Using duplicate data from localStorage');
|
|
}
|
|
} catch (e) {
|
|
console.warn('Error accessing localStorage:', e);
|
|
}
|
|
|
|
// If we got data from localStorage, manually populate the form
|
|
if (data) {
|
|
console.log('Manually populating form with iOS optimization');
|
|
|
|
// Basic fields
|
|
document.getElementById('name').value = data.name || '';
|
|
document.getElementById('beschreibung').value = data.description || '';
|
|
|
|
// Handle filters with a delay
|
|
setTimeout(() => {
|
|
// Filter 1
|
|
if (data.filter1 && Array.isArray(data.filter1)) {
|
|
data.filter1.forEach((val, idx) => {
|
|
const field = document.getElementById(`filter1-${idx+1}`);
|
|
if (field && val) field.value = val;
|
|
});
|
|
}
|
|
|
|
// Filter 2
|
|
if (data.filter2 && Array.isArray(data.filter2)) {
|
|
data.filter2.forEach((val, idx) => {
|
|
const field = document.getElementById(`filter2-${idx+1}`);
|
|
if (field && val) field.value = val;
|
|
});
|
|
}
|
|
|
|
// Filter 3
|
|
if (data.filter3 && Array.isArray(data.filter3)) {
|
|
data.filter3.forEach((val, idx) => {
|
|
const field = document.getElementById(`filter3-${idx+1}`);
|
|
if (field && val) field.value = val;
|
|
});
|
|
}
|
|
}, 300);
|
|
|
|
// Location
|
|
setTimeout(() => {
|
|
const location = document.getElementById('ort');
|
|
if (location && data.location) location.value = data.location;
|
|
}, 400);
|
|
|
|
// Year and cost
|
|
const year = document.getElementById('anschaffungsjahr');
|
|
if (year && data.year) year.value = data.year;
|
|
|
|
const cost = document.getElementById('anschaffungskosten');
|
|
if (cost && data.cost) cost.value = data.cost;
|
|
|
|
// Handle images - limited for iOS
|
|
const form = document.querySelector('form');
|
|
if (form && data.images && Array.isArray(data.images)) {
|
|
// Add hidden field to indicate duplication
|
|
const isDuplicatingField = document.createElement('input');
|
|
isDuplicatingField.type = 'hidden';
|
|
isDuplicatingField.name = 'is_duplicating';
|
|
isDuplicatingField.value = 'true';
|
|
form.appendChild(isDuplicatingField);
|
|
|
|
// Only use first 3 images on iOS for performance
|
|
const limitedImages = data.images.slice(0, 3);
|
|
|
|
limitedImages.forEach(imageName => {
|
|
const imageField = document.createElement('input');
|
|
imageField.type = 'hidden';
|
|
imageField.name = 'duplicate_images';
|
|
imageField.value = imageName;
|
|
form.appendChild(imageField);
|
|
});
|
|
|
|
// Add a message about limited images
|
|
if (data.images.length > 3) {
|
|
const messageDiv = document.createElement('div');
|
|
messageDiv.style.margin = '10px 0';
|
|
messageDiv.style.padding = '10px';
|
|
messageDiv.style.backgroundColor = '#fff3cd';
|
|
messageDiv.style.borderRadius = '5px';
|
|
messageDiv.style.color = '#856404';
|
|
messageDiv.textContent = `Aus Leistungsgründen werden nur ${limitedImages.length} von ${data.images.length} Bildern verwendet`;
|
|
|
|
const fileInput = document.getElementById('images');
|
|
if (fileInput && fileInput.parentNode) {
|
|
fileInput.parentNode.appendChild(messageDiv);
|
|
} else {
|
|
form.appendChild(messageDiv);
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
// Use original function as fallback
|
|
originalPrefill();
|
|
}
|
|
};
|
|
}
|
|
}
|
|
|
|
// Apply iOS-specific CSS fixes
|
|
function applyIOSCSSFixes() {
|
|
// Create a style element
|
|
const style = document.createElement('style');
|
|
style.textContent = `
|
|
/* Improve touch targets for iOS */
|
|
button, select, input[type="submit"], .ausleihen, .edit-button,
|
|
.delete-button, .duplicate-button, .details-button {
|
|
min-height: 44px !important;
|
|
padding: 10px 15px !important;
|
|
}
|
|
|
|
/* Improve scrolling on iOS */
|
|
.items-container, .filter-options, .modal-content {
|
|
-webkit-overflow-scrolling: touch !important;
|
|
}
|
|
|
|
/* Prevent zoom on inputs */
|
|
input, select, textarea {
|
|
font-size: 16px !important;
|
|
}
|
|
|
|
/* Fix iOS image display */
|
|
.item-image {
|
|
-webkit-transform: translateZ(0);
|
|
}
|
|
|
|
/* Improve form fields on iOS */
|
|
.form-group {
|
|
margin-bottom: 15px !important;
|
|
}
|
|
`;
|
|
|
|
document.head.appendChild(style);
|
|
}
|