PageSourceSearch

https://ucl.edu.pk/js/ucl-footer-blogs.js

js ucl.edu.pk collected 2026-09-24 10:15:22 UTC 3,910 bytes, 94 lines download raw bytes

1/**
2 * UCL Dynamically Populating Footer Blogs
3 * Decoupled from legacy mock DB and hooked to Supabase with dynamic script loading self-healing pattern
4 */
5
6// Helper to inject dependency scripts dynamically
7function loadUCLScript(src) {
8    return new Promise((resolve, reject) => {
9        const scripts = Array.from(document.getElementsByTagName('script'));
10        if (scripts.some(s => s.src && s.src.includes(src))) {
11            resolve();
12            return;
13        }
14        const script = document.createElement('script');
15        script.src = src;
16        script.type = 'text/javascript';
17        script.onload = resolve;
18        script.onerror = (err) => {
19            console.error(`Failed to load script: ${src}`, err);
20            reject(err);
21        };
22        document.body.appendChild(script);
23    });
24}
25
26async function initFooterBlogs() {
27    const footerList = document.getElementById('footer-dynamic-blogs');
28    if (!footerList) return;
29
30    try {
31        // Dynamic dependency loading to support all site static pages elegantly
32        if (typeof supabase === 'undefined') {
33            await loadUCLScript('https://cdn.jsdelivr.net/npm/@supabase/supabase-js@2');
34        }
35        if (typeof window.supabaseClient === 'undefined') {
36            await loadUCLScript('js/modules/supabase-client.js');
37        }
38        if (typeof window.UCLBlogAPI === 'undefined') {
39            await loadUCLScript('js/modules/blog-api.js');
40        }
41
42        const api = window.UCLBlogAPI;
43        if (!api) {
44            throw new Error("UCLBlogAPI is unavailable.");
45        }
46
47        // Fetch the 5 most recent published blogs
48        const latestBlogs = await api.getBlogs({ status: 'published', limit: 5 });
49        
50        if (latestBlogs.length === 0) {
51            footerList.innerHTML = `
52                <li class="menu-item"><a href="#" style="color: #aaa; font-style: italic;">No posts uploaded yet.</a></li>
53                <li class="menu-item" style="margin-top: 15px; border-top: 1px dashed rgba(255,255,255,0.2); padding-top: 10px;">
54                    <a href="blogs.html" style="color: #D22B2B; font-weight: 600; font-size: 15px; transition: color 0.2s; display: inline-flex; align-items: center; gap: 5px;">
55                        View All Blogs <i class="fa fa-long-arrow-right"></i>
56                    </a>
57                </li>
58            `;
59            return;
60        }
61
62        // Dynamically inject list items (Query strings on local file://, pretty paths on live server)
63        footerList.innerHTML = latestBlogs.map(blog => {
64            const detailUrl = window.location.protocol === 'file:' 
65                ? `blog-detail.html?slug=${blog.slug}` 
66                : `/${blog.slug}`;
67            return `
68                <li class="menu-item" style="margin-bottom: 8px;">
69                    <a href="${detailUrl}" style="color: #ffffff; font-size: 15px; transition: color 0.2s; display: inline-block;">
70                        ${blog.title}
71                    </a>
72                </li>
73            `;
74        }).join('') + `
75            <li class="menu-item" style="margin-top: 15px; border-top: 1px dashed rgba(255,255,255,0.2); padding-top: 10px;">
76                <a href="blogs.html" style="color: #D22B2B; font-weight: 600; font-size: 15px; transition: color 0.2s; display: inline-flex; align-items: center; gap: 5px;">
77                    View All Blogs <i class="fa fa-long-arrow-right"></i>
78                </a>
79            </li>
80        `;
81
82    } catch (error) {
83        console.error("UCL Footer Blogs Error:", error);
84        footerList.innerHTML = '<li class="menu-item"><a href="#" style="color: #D22B2B;">Temporary Unavailable</a></li>';
85    }
86}
87
88// Initialize as soon as the DOM is interactive/loaded
89if (document.readyState === 'loading') {
90    document.addEventListener('DOMContentLoaded', initFooterBlogs);
91} else {
92    initFooterBlogs();
93}
94

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.