Spaces:
Running
Running
Upload 3 files
Browse files- app.js +89 -0
- page-utils.js +65 -0
- search.js +162 -0
app.js
ADDED
@@ -0,0 +1,89 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
// Script for dynamic content loading
|
2 |
+
document.addEventListener('DOMContentLoaded', function() {
|
3 |
+
// Content container where pages will be loaded
|
4 |
+
const contentContainer = document.getElementById('dynamic-content');
|
5 |
+
if (!contentContainer) return;
|
6 |
+
|
7 |
+
// Function to load page content
|
8 |
+
window.loadPage = function(pageName) {
|
9 |
+
// Add .html extension if not provided
|
10 |
+
if (!pageName.endsWith('.html')) {
|
11 |
+
pageName += '.html';
|
12 |
+
}
|
13 |
+
|
14 |
+
// Fetch the requested page
|
15 |
+
fetch(pageName)
|
16 |
+
.then(response => {
|
17 |
+
if (!response.ok) {
|
18 |
+
throw new Error(`HTTP error! Status: ${response.status}`);
|
19 |
+
}
|
20 |
+
return response.text();
|
21 |
+
})
|
22 |
+
.then(html => {
|
23 |
+
// Extract the content from the HTML (assuming each page has its main content in a div)
|
24 |
+
const parser = new DOMParser();
|
25 |
+
const doc = parser.parseFromString(html, 'text/html');
|
26 |
+
|
27 |
+
// Look for the main content in the page
|
28 |
+
// This assumes each page has its main content within a main tag or a specific div
|
29 |
+
const mainContent = doc.querySelector('main') || doc.querySelector('.min-h-screen');
|
30 |
+
|
31 |
+
if (mainContent) {
|
32 |
+
// Replace the content in the container
|
33 |
+
contentContainer.innerHTML = mainContent.innerHTML;
|
34 |
+
|
35 |
+
// Update the URL without refreshing
|
36 |
+
history.pushState({page: pageName}, '', `?page=${pageName}`);
|
37 |
+
|
38 |
+
// Scroll to top
|
39 |
+
window.scrollTo(0, 0);
|
40 |
+
|
41 |
+
// Update active state in navigation
|
42 |
+
updateActiveNavLink(pageName);
|
43 |
+
} else {
|
44 |
+
contentContainer.innerHTML = '<p>Could not load content. Please try again.</p>';
|
45 |
+
}
|
46 |
+
})
|
47 |
+
.catch(error => {
|
48 |
+
console.error('Error loading page:', error);
|
49 |
+
contentContainer.innerHTML = `<p>Error loading page: ${error.message}</p>`;
|
50 |
+
});
|
51 |
+
|
52 |
+
return false; // Prevent default link behavior
|
53 |
+
};
|
54 |
+
|
55 |
+
// Function to update active state in navigation
|
56 |
+
function updateActiveNavLink(pageName) {
|
57 |
+
// Remove active class from all nav links
|
58 |
+
document.querySelectorAll('.nav-link').forEach(link => {
|
59 |
+
link.classList.remove('active', 'text-accent');
|
60 |
+
link.classList.add('text-gray-600');
|
61 |
+
});
|
62 |
+
|
63 |
+
// Add active class to current page link
|
64 |
+
const activeLink = document.querySelector(`.nav-link[data-page="${pageName.replace('.html', '')}"]`);
|
65 |
+
if (activeLink) {
|
66 |
+
activeLink.classList.add('active', 'text-accent');
|
67 |
+
activeLink.classList.remove('text-gray-600');
|
68 |
+
}
|
69 |
+
}
|
70 |
+
|
71 |
+
// Handle browser back/forward buttons
|
72 |
+
window.addEventListener('popstate', function(event) {
|
73 |
+
if (event.state && event.state.page) {
|
74 |
+
loadPage(event.state.page);
|
75 |
+
} else {
|
76 |
+
// Default to index/home if no state
|
77 |
+
contentContainer.innerHTML = ''; // Reset content
|
78 |
+
location.reload(); // Reload the page to show the default view
|
79 |
+
}
|
80 |
+
});
|
81 |
+
|
82 |
+
// Check URL on page load to see if a specific page was requested
|
83 |
+
const urlParams = new URLSearchParams(window.location.search);
|
84 |
+
const pageParam = urlParams.get('page');
|
85 |
+
|
86 |
+
if (pageParam) {
|
87 |
+
loadPage(pageParam);
|
88 |
+
}
|
89 |
+
});
|
page-utils.js
ADDED
@@ -0,0 +1,65 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
// Script to help transform page content for dynamic loading
|
2 |
+
|
3 |
+
document.addEventListener('DOMContentLoaded', function() {
|
4 |
+
// Process all pages to remove duplicate headers and footers
|
5 |
+
// This is useful for direct page access (non-dynamic loading)
|
6 |
+
|
7 |
+
// Check if this is a standalone page (not loaded via dynamic content)
|
8 |
+
const isStandalonePage = !window.location.href.includes('?page=');
|
9 |
+
if (!isStandalonePage) return; // Only process for direct access
|
10 |
+
|
11 |
+
// For standalone pages, we'll keep their headers and footers
|
12 |
+
// but add a back link to the home page
|
13 |
+
|
14 |
+
// Find any navigation links
|
15 |
+
const navLinks = document.querySelectorAll('header a, nav a');
|
16 |
+
navLinks.forEach(link => {
|
17 |
+
// If it's a home link or empty link
|
18 |
+
if (link.textContent.toLowerCase().includes('home') || link.getAttribute('href') === '#') {
|
19 |
+
// Update it to go back to the main site
|
20 |
+
link.setAttribute('href', 'index.html');
|
21 |
+
link.classList.add('home-link');
|
22 |
+
}
|
23 |
+
});
|
24 |
+
|
25 |
+
// Add specific page styles for standalone view
|
26 |
+
const styleElement = document.createElement('style');
|
27 |
+
styleElement.textContent = `
|
28 |
+
body.standalone-page {
|
29 |
+
max-width: 1200px;
|
30 |
+
margin: 0 auto;
|
31 |
+
padding: 0 20px;
|
32 |
+
}
|
33 |
+
|
34 |
+
.back-to-home {
|
35 |
+
display: inline-block;
|
36 |
+
margin: 1rem 0;
|
37 |
+
padding: 0.5rem 1rem;
|
38 |
+
color: #1a365d;
|
39 |
+
text-decoration: none;
|
40 |
+
font-weight: 500;
|
41 |
+
}
|
42 |
+
|
43 |
+
.back-to-home:hover {
|
44 |
+
text-decoration: underline;
|
45 |
+
}
|
46 |
+
`;
|
47 |
+
document.head.appendChild(styleElement);
|
48 |
+
|
49 |
+
// Check if it's a standalone page (directly accessed, not through dynamic loading)
|
50 |
+
if (isStandalonePage && !document.body.classList.contains('index-page')) {
|
51 |
+
document.body.classList.add('standalone-page');
|
52 |
+
|
53 |
+
// Add a back to home link at the top if it doesn't exist
|
54 |
+
if (!document.querySelector('.back-to-home')) {
|
55 |
+
const mainContent = document.querySelector('main') || document.body.firstElementChild;
|
56 |
+
if (mainContent) {
|
57 |
+
const backLink = document.createElement('a');
|
58 |
+
backLink.href = 'index.html';
|
59 |
+
backLink.className = 'back-to-home';
|
60 |
+
backLink.innerHTML = '<i class="fas fa-arrow-left mr-2"></i> Back to Home';
|
61 |
+
mainContent.parentNode.insertBefore(backLink, mainContent);
|
62 |
+
}
|
63 |
+
}
|
64 |
+
}
|
65 |
+
});
|
search.js
ADDED
@@ -0,0 +1,162 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
// Search functionality for the TN Medical Connect site
|
2 |
+
document.addEventListener('DOMContentLoaded', function() {
|
3 |
+
// Set up search forms
|
4 |
+
const searchForms = document.querySelectorAll('.search-form');
|
5 |
+
|
6 |
+
searchForms.forEach(form => {
|
7 |
+
form.addEventListener('submit', function(e) {
|
8 |
+
e.preventDefault();
|
9 |
+
|
10 |
+
const searchInput = this.querySelector('input[type="text"]');
|
11 |
+
const searchTerm = searchInput.value.trim();
|
12 |
+
|
13 |
+
if (searchTerm) {
|
14 |
+
// Get search category if available (podcasts, research, etc.)
|
15 |
+
const category = this.dataset.category || '';
|
16 |
+
const finalSearchTerm = category ? `${category} ${searchTerm}` : searchTerm;
|
17 |
+
|
18 |
+
// Show loading state
|
19 |
+
const resultsContainer = document.getElementById('search-results');
|
20 |
+
if (resultsContainer) {
|
21 |
+
resultsContainer.innerHTML = '<div class="text-center py-4"><i class="fas fa-spinner fa-spin text-primary text-2xl"></i><p class="mt-2 text-gray-600">Searching...</p></div>';
|
22 |
+
}
|
23 |
+
|
24 |
+
// In a real implementation, this would call a server-side API
|
25 |
+
// For this demo, we'll simulate results after a delay
|
26 |
+
setTimeout(() => {
|
27 |
+
simulateSearchResults(finalSearchTerm, resultsContainer);
|
28 |
+
}, 1000);
|
29 |
+
}
|
30 |
+
});
|
31 |
+
});
|
32 |
+
|
33 |
+
// Function to simulate search results (in a real app, this would call the server)
|
34 |
+
function simulateSearchResults(searchTerm, container) {
|
35 |
+
if (!container) return;
|
36 |
+
|
37 |
+
// Simulate different results based on search term
|
38 |
+
const termLower = searchTerm.toLowerCase();
|
39 |
+
|
40 |
+
if (termLower.includes('podcast') || termLower.includes('audio')) {
|
41 |
+
showPodcastResults(container);
|
42 |
+
} else if (termLower.includes('research') || termLower.includes('paper') || termLower.includes('study')) {
|
43 |
+
showResearchResults(container);
|
44 |
+
} else if (termLower.includes('ai') || termLower.includes('artificial intelligence')) {
|
45 |
+
showAIResults(container);
|
46 |
+
} else {
|
47 |
+
showGeneralResults(container);
|
48 |
+
}
|
49 |
+
}
|
50 |
+
|
51 |
+
// Simulate podcast results
|
52 |
+
function showPodcastResults(container) {
|
53 |
+
container.innerHTML = `
|
54 |
+
<h3 class="text-xl font-semibold text-gray-800 mb-4">Search Results</h3>
|
55 |
+
<div class="grid gap-4 md:grid-cols-2">
|
56 |
+
<div class="p-4 bg-gray-50 border border-gray-200 rounded-lg">
|
57 |
+
<h4 class="text-lg font-medium">Recent Advances in Cardiology</h4>
|
58 |
+
<p class="text-sm text-gray-600">A discussion with Dr. Ramesh about the latest treatments.</p>
|
59 |
+
<audio controls class="mt-2 w-full">
|
60 |
+
<source src="#" type="audio/mpeg">
|
61 |
+
Your browser does not support the audio element.
|
62 |
+
</audio>
|
63 |
+
</div>
|
64 |
+
<div class="p-4 bg-gray-50 border border-gray-200 rounded-lg">
|
65 |
+
<h4 class="text-lg font-medium">Public Health Initiatives in Tamil Nadu</h4>
|
66 |
+
<p class="text-sm text-gray-600">How local communities are benefiting from new programs.</p>
|
67 |
+
<audio controls class="mt-2 w-full">
|
68 |
+
<source src="#" type="audio/mpeg">
|
69 |
+
Your browser does not support the audio element.
|
70 |
+
</audio>
|
71 |
+
</div>
|
72 |
+
</div>
|
73 |
+
`;
|
74 |
+
}
|
75 |
+
|
76 |
+
// Simulate research results
|
77 |
+
function showResearchResults(container) {
|
78 |
+
container.innerHTML = `
|
79 |
+
<h3 class="text-xl font-semibold text-gray-800 mb-4">Research Results</h3>
|
80 |
+
<div class="space-y-4">
|
81 |
+
<div class="p-4 bg-gray-50 border border-gray-200 rounded-lg">
|
82 |
+
<h4 class="text-lg font-medium">Impact of Climate Change on Vector-borne Diseases in South India</h4>
|
83 |
+
<p class="text-sm text-gray-500">Journal of Tropical Medicine • March 2025</p>
|
84 |
+
<p class="text-sm text-gray-600 mt-1">This study examines the correlation between rising temperatures and the spread of dengue and malaria in Tamil Nadu.</p>
|
85 |
+
<a href="#" class="text-primary text-sm hover:underline mt-2 inline-block">Read Abstract</a>
|
86 |
+
</div>
|
87 |
+
<div class="p-4 bg-gray-50 border border-gray-200 rounded-lg">
|
88 |
+
<h4 class="text-lg font-medium">Efficacy of Traditional Medicines in Managing Type 2 Diabetes</h4>
|
89 |
+
<p class="text-sm text-gray-500">Indian Journal of Medical Research • January 2025</p>
|
90 |
+
<p class="text-sm text-gray-600 mt-1">A randomized controlled trial comparing traditional herbal preparations with standard pharmaceutical interventions.</p>
|
91 |
+
<a href="#" class="text-primary text-sm hover:underline mt-2 inline-block">Read Abstract</a>
|
92 |
+
</div>
|
93 |
+
</div>
|
94 |
+
`;
|
95 |
+
}
|
96 |
+
|
97 |
+
// Simulate AI results
|
98 |
+
function showAIResults(container) {
|
99 |
+
container.innerHTML = `
|
100 |
+
<h3 class="text-xl font-semibold text-gray-800 mb-4">AI in Healthcare Results</h3>
|
101 |
+
<div class="space-y-4">
|
102 |
+
<div class="p-4 bg-gray-50 border border-gray-200 rounded-lg">
|
103 |
+
<h4 class="text-lg font-medium">AI-Powered Diagnostic Tools for Rural Healthcare</h4>
|
104 |
+
<p class="text-sm text-gray-600 mt-1">How machine learning is helping bridge the healthcare gap in remote areas of Tamil Nadu.</p>
|
105 |
+
<div class="flex justify-between items-center mt-2">
|
106 |
+
<span class="text-xs text-gray-500">Resource Type: Case Study</span>
|
107 |
+
<a href="#" class="text-primary text-sm hover:underline">View Details</a>
|
108 |
+
</div>
|
109 |
+
</div>
|
110 |
+
<div class="p-4 bg-gray-50 border border-gray-200 rounded-lg">
|
111 |
+
<h4 class="text-lg font-medium">Implementing AI Chatbots in Patient Triage</h4>
|
112 |
+
<p class="text-sm text-gray-600 mt-1">A guide for hospitals looking to adopt AI-powered patient screening systems.</p>
|
113 |
+
<div class="flex justify-between items-center mt-2">
|
114 |
+
<span class="text-xs text-gray-500">Resource Type: Implementation Guide</span>
|
115 |
+
<a href="#" class="text-primary text-sm hover:underline">View Details</a>
|
116 |
+
</div>
|
117 |
+
</div>
|
118 |
+
</div>
|
119 |
+
`;
|
120 |
+
}
|
121 |
+
|
122 |
+
// General mixed results
|
123 |
+
function showGeneralResults(container) {
|
124 |
+
container.innerHTML = `
|
125 |
+
<h3 class="text-xl font-semibold text-gray-800 mb-4">Search Results</h3>
|
126 |
+
<div class="space-y-4">
|
127 |
+
<div class="p-4 bg-gray-50 border border-gray-200 rounded-lg">
|
128 |
+
<h4 class="text-lg font-medium">Upcoming Medical Conferences in Chennai</h4>
|
129 |
+
<p class="text-sm text-gray-600">View the schedule of medical conferences happening in the next 6 months.</p>
|
130 |
+
<a href="#" class="text-primary text-sm hover:underline mt-2 inline-block">View Calendar</a>
|
131 |
+
</div>
|
132 |
+
<div class="p-4 bg-gray-50 border border-gray-200 rounded-lg">
|
133 |
+
<h4 class="text-lg font-medium">Grant Opportunities for Medical Researchers</h4>
|
134 |
+
<p class="text-sm text-gray-600">Current funding opportunities for research in various medical fields.</p>
|
135 |
+
<a href="#" class="text-primary text-sm hover:underline mt-2 inline-block">Browse Grants</a>
|
136 |
+
</div>
|
137 |
+
<div class="p-4 bg-gray-50 border border-gray-200 rounded-lg">
|
138 |
+
<h4 class="text-lg font-medium">Latest Podcast: Healthcare Challenges in 2025</h4>
|
139 |
+
<p class="text-sm text-gray-600">A discussion with leading experts about what to expect this year.</p>
|
140 |
+
<a href="#" class="text-primary text-sm hover:underline mt-2 inline-block">Listen Now</a>
|
141 |
+
</div>
|
142 |
+
</div>
|
143 |
+
`;
|
144 |
+
}
|
145 |
+
|
146 |
+
// Initialize any search fields with the search parameter if present in URL
|
147 |
+
const urlParams = new URLSearchParams(window.location.search);
|
148 |
+
const searchParam = urlParams.get('search');
|
149 |
+
|
150 |
+
if (searchParam) {
|
151 |
+
const searchInputs = document.querySelectorAll('.search-form input[type="text"]');
|
152 |
+
searchInputs.forEach(input => {
|
153 |
+
input.value = searchParam;
|
154 |
+
});
|
155 |
+
|
156 |
+
// Auto-submit the first search form if a search term is provided in URL
|
157 |
+
const firstForm = document.querySelector('.search-form');
|
158 |
+
if (firstForm) {
|
159 |
+
firstForm.dispatchEvent(new Event('submit'));
|
160 |
+
}
|
161 |
+
}
|
162 |
+
});
|