PageSourceSearch

https://komekaigi.dev/2025/js/individual_sponsors.js

js komekaigi.dev collected 2026-09-26 04:37:35 UTC 3,538 bytes, 112 lines download raw bytes

1/**
2 * KomeKaigi 個人スポンサー表示機能
3 */
4(function(window, document) {
5    'use strict';
6
7    // 設定
8    const CONFIG = {
9        JSON_URL: 'data/individual_sponsors.json',
10        IMAGE_BASE_PATH: 'assets/images/individual_sponsors/',
11        SECTION_ID: 'individual-sponsors',
12        CONTENT_ID: 'individual-sponsors-content'
13    };
14
15    /**
16     * 個人スポンサーセクションを非表示にする
17     */
18    function hideIndividualSponsorsSection() {
19        const section = document.getElementById(CONFIG.SECTION_ID);
20        if (section) {
21            section.style.display = 'none';
22        }
23    }
24
25    /**
26     * 個人スポンサーデータを取得して表示
27     */
28    async function loadIndividualSponsors() {
29        const contentElement = document.getElementById(CONFIG.CONTENT_ID);
30        if (!contentElement) return;
31
32        try {
33            const response = await fetch(CONFIG.JSON_URL);
34            if (!response.ok) {
35                throw new Error(`HTTP error! status: ${response.status}`);
36            }
37            const sponsors = await response.json();
38
39            if (sponsors.length === 0) {
40                hideIndividualSponsorsSection();
41                return;
42            }
43
44            renderIndividualSponsorsList(sponsors, contentElement);
45
46        } catch (error) {
47            console.error('個人スポンサーデータの取得エラー:', error);
48            contentElement.innerHTML = '';
49            hideIndividualSponsorsSection();
50        }
51    }
52
53    /**
54     * 個人スポンサーリストをレンダリング
55     * @param {Array} sponsors - 個人スポンサーの配列
56     * @param {HTMLElement} container - 表示先のコンテナ要素
57     */
58    function renderIndividualSponsorsList(sponsors, container) {
59        const sectionTitle = `
60            <div class="text-center mb-8">
61                <h4 class="text-2xl font-semibold text-primary">
62                    個人スポンサー
63                </h4>
64            </div>
65        `;
66
67        const sponsorsHTML = `
68            <div class="staff-grid">
69                ${sponsors.map(sponsor => createIndividualSponsorCard(sponsor)).join('')}
70            </div>
71        `;
72
73        container.innerHTML = sectionTitle + sponsorsHTML;
74    }
75
76    /**
77     * 個人スポンサーカードを作成
78     * @param {Object} sponsor - 個人スポンサーのデータ
79     * @returns {string} HTMLテキスト
80     */
81    function createIndividualSponsorCard(sponsor) {
82        const imagePath = `${CONFIG.IMAGE_BASE_PATH}${sponsor.image}`;
83        const hasLink = sponsor.url && sponsor.url.trim() !== '';
84
85        const cardContent = `
86            <div class="staff-member">
87                <div class="staff-avatar-wrapper">
88                    <img src="${escapeHtml(imagePath)}"
89                         alt="${escapeHtml(sponsor.name)}"
90                         class="staff-avatar"
91                         loading="lazy">
92                </div>
93                <div class="staff-name">
94                    ${escapeHtml(sponsor.name)}
95                </div>
96            </div>
97        `;
98
99        return hasLink
100            ? `<a href="${escapeHtml(sponsor.url)}"
101                  target="_blank"
102                  rel="noopener noreferrer"
103                  class="staff-link">
104                  ${cardContent}
105               </a>`
106            : cardContent;
107    }
108
109    // 初期化
110    document.addEventListener('DOMContentLoaded', loadIndividualSponsors);
111
112})(window, document);

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.