Travel Photography Gear Planner

Travel Photography Gear Planner

Plan Your Shoot

Recommended Gear Checklist

Select a destination and style, then click "Generate" to see recommendations.

My Gear Inventory

Add New Gear

Item Category Action

Final Packing List

No items selected for packing. Go to the Gear Planner to make your selections.

'; return; } const packedGear = myGearInventory.filter(item => packedItems.has(item.id)); const categories = [...new Set(packedGear.map(item => item.category))]; categories.forEach(category => { const itemsInCategory = packedGear.filter(item => item.category === category); if (itemsInCategory.length > 0) { const categoryDiv = document.createElement('div'); categoryDiv.className = 'checklist-category'; let itemsHTML = `

${category}

`; itemsInCategory.forEach(item => { itemsHTML += `
`; }); categoryDiv.innerHTML = itemsHTML; finalPackingListContainer.appendChild(categoryDiv); } }); } // --- EVENT HANDLERS & PUBLIC FUNCTIONS --- /** * Adds a new item to the gear inventory. */ window.addGearItem = function() { const nameInput = document.getElementById('gear-name'); const categoryInput = document.getElementById('gear-category'); if (!nameInput.value || !categoryInput.value) { console.warn("Please provide both a name and category for the gear."); return; } const newItem = { id: Date.now(), name: nameInput.value, category: categoryInput.value }; myGearInventory.push(newItem); renderInventoryTable(); nameInput.value = ''; } /** * Removes an item from the gear inventory. * @param {number} id - The ID of the item to remove. */ window.removeGearItem = function(id) { myGearInventory = myGearInventory.filter(item => item.id !== id); packedItems.delete(id); // Also remove from packed list if it was there renderInventoryTable(); generateChecklist(); // Regenerate checklist to reflect removal renderFinalPackingList(); } /** * Handles tab switching logic. */ window.openTab = function(evt, tabName) { if (tabName === 'packing') { renderFinalPackingList(); } const tabContents = document.getElementsByClassName("tab-content"); Array.from(tabContents).forEach(tab => tab.style.display = "none"); const tabButtons = document.getElementsByClassName("tab-btn"); Array.from(tabButtons).forEach(btn => btn.classList.remove("active")); const tabToShow = document.getElementById(tabName); if (tabToShow) tabToShow.style.display = "block"; if (evt) { evt.currentTarget.classList.add("active"); } else { const btnToActivate = Array.from(tabButtons).find(btn => btn.getAttribute('onclick').includes(`'${tabName}'`)); if (btnToActivate) btnToActivate.classList.add("active"); } updateNavButtons(); } /** * Handles Next/Previous button clicks. */ window.navigateTabs = function(direction) { const tabs = Array.from(document.querySelectorAll('.tab-btn')); const activeTabIndex = tabs.findIndex(tab => tab.classList.contains('active')); let newIndex = (direction === 'next') ? (activeTabIndex + 1) % tabs.length : (activeTabIndex - 1 + tabs.length) % tabs.length; tabs[newIndex].click(); } /** * Updates the visibility of Next/Previous buttons. */ function updateNavButtons() { const tabs = Array.from(document.querySelectorAll('.tab-btn')); const activeTabIndex = tabs.findIndex(tab => tab.classList.contains('active')); const prevBtn = document.getElementById('prev-btn'); const nextBtn = document.getElementById('next-btn'); if (!prevBtn || !nextBtn) return; prevBtn.style.visibility = activeTabIndex === 0 ? 'hidden' : 'visible'; nextBtn.style.visibility = activeTabIndex === tabs.length - 1 ? 'hidden' : 'visible'; } /** * PDF Download Functionality. */ if(downloadPdfBtn) { downloadPdfBtn.addEventListener('click', function() { const { jsPDF } = window.jspdf; const contentToDownload = document.getElementById('packing-list-to-download'); if (!contentToDownload) { console.error("PDF content area not found."); return; } html2canvas(contentToDownload, { scale: 2, useCORS: true }) .then(canvas => { const imgData = canvas.toDataURL('image/png'); const pdf = new jsPDF({ orientation: 'p', unit: 'mm', format: 'a4' }); const pdfWidth = pdf.internal.pageSize.getWidth(); const imgProps = pdf.getImageProperties(imgData); const imgHeight = (imgProps.height * pdfWidth) / imgProps.width; pdf.addImage(imgData, 'PNG', 0, 0, pdfWidth, imgHeight); pdf.save('Photography-Packing-List.pdf'); }).catch(err => { console.error("Error generating PDF:", err); }); }); } // --- INITIALIZATION --- function initializeTool() { renderInventoryTable(); updateNavButtons(); } initializeTool(); });
Scroll to Top