Spaces:
Running
Running
Commit
·
8bf6976
1
Parent(s):
60e6cb2
update responsive
Browse files- index.html +60 -27
index.html
CHANGED
@@ -526,26 +526,36 @@ https://chatgpt.com/c/67efa5ae-ab80-8005-a7d4-de3ced6ccec4
|
|
526 |
async function init() {
|
527 |
showLoading(); // Show loading message
|
528 |
try {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
529 |
await loadData(); // Load fresh data from server on init
|
530 |
sortTools(currentSort); // Apply default sort
|
531 |
renderTools();
|
532 |
renderVideos();
|
533 |
updateStats();
|
534 |
setupEventListeners();
|
535 |
-
|
536 |
-
|
537 |
-
if (
|
538 |
-
allFilterBtn.
|
|
|
|
|
|
|
539 |
}
|
540 |
} catch (error) {
|
541 |
-
// Handle error during initial load (e.g., network issue)
|
542 |
console.error("Initialization failed:", error);
|
543 |
showError("שגיאה בטעינת הנתונים הראשונית. נסה לרענן את הדף.");
|
544 |
} finally {
|
545 |
-
hideLoading();
|
546 |
}
|
547 |
}
|
548 |
|
|
|
549 |
const speechSynthesis = window.speechSynthesis;
|
550 |
let currentUtterance = null;
|
551 |
|
@@ -730,6 +740,12 @@ https://chatgpt.com/c/67efa5ae-ab80-8005-a7d4-de3ced6ccec4
|
|
730 |
return 0;
|
731 |
});
|
732 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
733 |
|
734 |
// --- Rendering Functions (Unchanged logic, but added hideLoading) ---
|
735 |
function renderTools() {
|
@@ -763,35 +779,36 @@ https://chatgpt.com/c/67efa5ae-ab80-8005-a7d4-de3ced6ccec4
|
|
763 |
<i class="${tool.icon} text-xl"></i>
|
764 |
</div>
|
765 |
<div class="flex-grow">
|
766 |
-
|
767 |
-
|
768 |
-
|
769 |
-
|
770 |
-
<i class="fas fa-volume-up"></i>
|
771 |
-
</button>
|
772 |
-
</div>
|
773 |
-
|
774 |
-
<span class="text-xs px-2 py-1 rounded-full ${getCategoryBadgeColor(tool.category)}">${getCategoryName(tool.category)}</span>
|
775 |
</div>
|
776 |
${tool.isNew ? '<span class="absolute top-2 left-2 bg-green-100 text-green-800 text-xs font-medium px-2.5 py-0.5 rounded-full">חדש!</span>' : ''}
|
777 |
</div>
|
778 |
-
<p class="text-gray-700 mb-4 text-base
|
779 |
<div class="flex justify-between items-center mb-4">
|
780 |
-
<div class="flex items-center gap-
|
781 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
782 |
${tool.video ? `
|
783 |
-
<
|
784 |
-
<i class="fab fa-youtube
|
785 |
-
</
|
786 |
-
}
|
787 |
</div>
|
788 |
</div>
|
789 |
-
<a href="${tool.url}" target="_blank" rel="noopener noreferrer"
|
|
|
790 |
<i class="fas fa-external-link-alt ml-2"></i> ${tool.url !== '#' ? 'גישה לכלי' : 'אין קישור'}
|
791 |
</a>
|
792 |
`;
|
793 |
-
|
794 |
-
|
795 |
toolsContainer.appendChild(toolCard);
|
796 |
});
|
797 |
|
@@ -949,9 +966,11 @@ https://chatgpt.com/c/67efa5ae-ab80-8005-a7d4-de3ced6ccec4
|
|
949 |
// Search input
|
950 |
searchInput.addEventListener('input', (e) => {
|
951 |
currentSearchTerm = e.target.value;
|
|
|
952 |
renderTools();
|
953 |
});
|
954 |
|
|
|
955 |
// Filter buttons
|
956 |
filterButtons.forEach(button => {
|
957 |
button.addEventListener('click', () => {
|
@@ -1013,8 +1032,22 @@ https://chatgpt.com/c/67efa5ae-ab80-8005-a7d4-de3ced6ccec4
|
|
1013 |
});
|
1014 |
|
1015 |
// Sorting stat boxes (Unchanged)
|
1016 |
-
if (topRatedStatBox)
|
1017 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1018 |
|
1019 |
// Refresh buttons - Now primarily resets filters/sort/search and re-renders current data
|
1020 |
// It *could* re-fetch, but init() already does that on load.
|
|
|
526 |
async function init() {
|
527 |
showLoading(); // Show loading message
|
528 |
try {
|
529 |
+
// --- שחזור ערך חיפוש קיים מהאחסון המקומי (אם קיים) ---
|
530 |
+
const savedSearch = localStorage.getItem('searchTerm');
|
531 |
+
if (savedSearch) {
|
532 |
+
searchInput.value = savedSearch;
|
533 |
+
currentSearchTerm = savedSearch;
|
534 |
+
}
|
535 |
+
|
536 |
await loadData(); // Load fresh data from server on init
|
537 |
sortTools(currentSort); // Apply default sort
|
538 |
renderTools();
|
539 |
renderVideos();
|
540 |
updateStats();
|
541 |
setupEventListeners();
|
542 |
+
|
543 |
+
// Set initial active filter button (רק אם אין חיפוש)
|
544 |
+
if (!currentSearchTerm) {
|
545 |
+
const allFilterBtn = document.querySelector('.filter-btn[data-category="all"]');
|
546 |
+
if (allFilterBtn) {
|
547 |
+
allFilterBtn.classList.add('active');
|
548 |
+
}
|
549 |
}
|
550 |
} catch (error) {
|
|
|
551 |
console.error("Initialization failed:", error);
|
552 |
showError("שגיאה בטעינת הנתונים הראשונית. נסה לרענן את הדף.");
|
553 |
} finally {
|
554 |
+
hideLoading();
|
555 |
}
|
556 |
}
|
557 |
|
558 |
+
|
559 |
const speechSynthesis = window.speechSynthesis;
|
560 |
let currentUtterance = null;
|
561 |
|
|
|
740 |
return 0;
|
741 |
});
|
742 |
}
|
743 |
+
function scrollToTools() {
|
744 |
+
const toolsSection = document.getElementById("toolsContainer");
|
745 |
+
if (toolsSection) {
|
746 |
+
toolsSection.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
747 |
+
}
|
748 |
+
}
|
749 |
|
750 |
// --- Rendering Functions (Unchanged logic, but added hideLoading) ---
|
751 |
function renderTools() {
|
|
|
779 |
<i class="${tool.icon} text-xl"></i>
|
780 |
</div>
|
781 |
<div class="flex-grow">
|
782 |
+
<h3 class="text-xl font-semibold">${tool.name}</h3>
|
783 |
+
<span class="text-xs px-2 py-1 rounded-full ${getCategoryBadgeColor(tool.category)}">
|
784 |
+
${getCategoryName(tool.category)}
|
785 |
+
</span>
|
|
|
|
|
|
|
|
|
|
|
786 |
</div>
|
787 |
${tool.isNew ? '<span class="absolute top-2 left-2 bg-green-100 text-green-800 text-xs font-medium px-2.5 py-0.5 rounded-full">חדש!</span>' : ''}
|
788 |
</div>
|
789 |
+
<p class="text-gray-700 mb-4 text-base leading-relaxed min-h-[60px]">${tool.description}</p>
|
790 |
<div class="flex justify-between items-center mb-4">
|
791 |
+
<div class="flex items-center gap-3">
|
792 |
+
${renderRatingStars(tool.rating)}
|
793 |
+
|
794 |
+
<!-- כפתור רמקול -->
|
795 |
+
<button title="הקרא תיאור" onclick="event.stopPropagation(); speakText('${tool.description.replace(/'/g, "\\'")}')" class="text-blue-600 hover:text-blue-800 transition text-xl">
|
796 |
+
<i class="fas fa-volume-up"></i>
|
797 |
+
</button>
|
798 |
+
|
799 |
+
<!-- כפתור יוטיוב -->
|
800 |
${tool.video ? `
|
801 |
+
<button title="צפה בהדרכה" onclick="openVideoModal('${tool.video}')" class="text-red-500 hover:text-red-600 transition text-xl">
|
802 |
+
<i class="fab fa-youtube"></i>
|
803 |
+
</button>` : ''}
|
|
|
804 |
</div>
|
805 |
</div>
|
806 |
+
<a href="${tool.url}" target="_blank" rel="noopener noreferrer"
|
807 |
+
class="inline-block w-full text-center px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition ${tool.url === '#' ? 'opacity-50 cursor-not-allowed' : ''}">
|
808 |
<i class="fas fa-external-link-alt ml-2"></i> ${tool.url !== '#' ? 'גישה לכלי' : 'אין קישור'}
|
809 |
</a>
|
810 |
`;
|
811 |
+
|
|
|
812 |
toolsContainer.appendChild(toolCard);
|
813 |
});
|
814 |
|
|
|
966 |
// Search input
|
967 |
searchInput.addEventListener('input', (e) => {
|
968 |
currentSearchTerm = e.target.value;
|
969 |
+
localStorage.setItem('searchTerm', currentSearchTerm); // שמור בזיכרון הדפדפן
|
970 |
renderTools();
|
971 |
});
|
972 |
|
973 |
+
|
974 |
// Filter buttons
|
975 |
filterButtons.forEach(button => {
|
976 |
button.addEventListener('click', () => {
|
|
|
1032 |
});
|
1033 |
|
1034 |
// Sorting stat boxes (Unchanged)
|
1035 |
+
if (topRatedStatBox) {
|
1036 |
+
topRatedStatBox.addEventListener('click', () => {
|
1037 |
+
sortTools('rating');
|
1038 |
+
renderTools();
|
1039 |
+
scrollToTools(); // גלילה חלקה לתחילת רשימת הכלים
|
1040 |
+
});
|
1041 |
+
}
|
1042 |
+
|
1043 |
+
if (newToolsStatBox) {
|
1044 |
+
newToolsStatBox.addEventListener('click', () => {
|
1045 |
+
sortTools('newest');
|
1046 |
+
renderTools();
|
1047 |
+
scrollToTools(); // גלילה חלקה לתחילת רשימת הכלים
|
1048 |
+
});
|
1049 |
+
}
|
1050 |
+
|
1051 |
|
1052 |
// Refresh buttons - Now primarily resets filters/sort/search and re-renders current data
|
1053 |
// It *could* re-fetch, but init() already does that on load.
|