PageSourceSearch

https://nakasota.github.io/js/header.js

js nakasota.github.io collected 2026-10-03 09:39:28 UTC 6,185 bytes, 205 lines download raw bytes

1// ヘッダーの動的生成
2document.addEventListener('DOMContentLoaded', () => {
3    const headerElement = document.querySelector('[data-include="header"]');
4    
5    if (headerElement) {
6        const currentLang = getCurrentLanguage();
7        const headerHTML = `
8            <nav class="main-nav">
9                <div class="nav-container">
10                    <a href="index.html" class="nav-logo">Sota Nakashima</a>
11                    <div class="nav-right">
12                        <ul class="nav-menu">
13                            <li><a href="#profile" data-nav="profile">Profile</a></li>
14                            <li><a href="all_news.html" data-nav="news">News</a></li>
15                            <li><a href="all_publications.html" data-nav="publications">Publications</a></li>
16                            <li><a href="cv.html" data-nav="cv">CV</a></li>
17                            <li><a href="#contact" data-nav="contact">Contact</a></li>
18                        </ul>
19                        <div class="lang-switcher">
20                            <button class="lang-btn ${currentLang === 'ja' ? 'active' : ''}" data-lang="ja">JP</button>
21                            <button class="lang-btn ${currentLang === 'en' ? 'active' : ''}" data-lang="en">EN</button>
22                        </div>
23                    </div>
24                </div>
25            </nav>
26        `;
27        
28        headerElement.innerHTML = headerHTML;
29        
30        // 言語切り替えボタンのイベントリスナーを追加
31        setupLanguageSwitcher();
32        
33        // ナビゲーションメニューの翻訳を適用
34        updateNavMenu();
35        
36        // スタイルを追加
37        addHeaderStyles();
38    }
39});
40
41function getCurrentLanguage() {
42    return localStorage.getItem('preferredLanguage') || 'ja';
43}
44
45function setupLanguageSwitcher() {
46    const langButtons = document.querySelectorAll('.lang-btn');
47    langButtons.forEach(btn => {
48        btn.addEventListener('click', () => {
49            const lang = btn.getAttribute('data-lang');
50            if (typeof switchLanguage === 'function') {
51                switchLanguage(lang);
52                // ボタンのアクティブ状態を更新
53                langButtons.forEach(b => b.classList.remove('active'));
54                btn.classList.add('active');
55                // ナビゲーションメニューを更新
56                updateNavMenu();
57                // ニュースを更新
58                if (typeof updateNewsList === 'function') {
59                    updateNewsList();
60                }
61                // 論文・発表を更新
62                if (typeof updatePublicationsList === 'function') {
63                    updatePublicationsList();
64                }
65                if (typeof updateCvPublicationsList === 'function') {
66                    updateCvPublicationsList();
67                }
68            }
69        });
70    });
71}
72
73function updateNavMenu() {
74    const navItems = {
75        ja: {
76            profile: 'プロフィール',
77            news: 'ニュース',
78            publications: '業績',
79            cv: 'CV',
80            contact: '連絡先'
81        },
82        en: {
83            profile: 'Profile',
84            news: 'News',
85            publications: 'Publications',
86            cv: 'CV',
87            contact: 'Contact'
88        }
89    };
90    
91    const currentLang = getCurrentLanguage();
92    document.querySelectorAll('[data-nav]').forEach(link => {
93        const key = link.getAttribute('data-nav');
94        if (navItems[currentLang] && navItems[currentLang][key]) {
95            link.textContent = navItems[currentLang][key];
96        }
97    });
98}
99
100function addHeaderStyles() {
101    const style = document.createElement('style');
102    style.textContent = `
103        .main-nav {
104            width: 100%;
105        }
106        
107        .nav-container {
108            max-width: 1200px;
109            margin: 0 auto;
110            padding: 0 20px;
111            display: flex;
112            justify-content: space-between;
113            align-items: center;
114        }
115        
116        .nav-logo {
117            font-size: 1.3rem;
118            font-weight: 700;
119            color: #ffffff;
120            text-decoration: none;
121        }
122        
123        .nav-right {
124            display: flex;
125            align-items: center;
126            gap: 30px;
127        }
128        
129        .nav-menu {
130            display: flex;
131            list-style: none;
132            gap: 30px;
133            margin: 0;
134            padding: 0;
135        }
136        
137        .nav-menu a {
138            color: #555;
139            text-decoration: none;
140            font-weight: 500;
141            transition: color 0.3s ease;
142        }
143        
144        .nav-menu a:hover {
145            color: #ffffff;
146        }
147        
148        .lang-switcher {
149            display: flex;
150            gap: 5px;
151            border: 1px solid #ddd;
152            border-radius: 4px;
153            overflow: hidden;
154        }
155        
156        .lang-btn {
157            padding: 6px 12px;
158            background-color: #fff;
159            border: none;
160            cursor: pointer;
161            font-size: 0.85rem;
162            font-weight: 600;
163            color: #666;
164            transition: all 0.3s ease;
165        }
166        
167        .lang-btn:hover {
168            background-color: #f0f0f0;
169        }
170        
171        .lang-btn.active {
172            background-color: #ffffff;
173            color: #fff;
174        }
175        
176        @media (max-width: 768px) {
177            .nav-container {
178                flex-direction: column;
179                gap: 15px;
180                padding: 15px 20px;
181            }
182            
183            .nav-right {
184                flex-direction: column;
185                gap: 15px;
186                width: 100%;
187            }
188            
189            .nav-menu {
190                gap: 15px;
191                flex-wrap: wrap;
192                justify-content: center;
193            }
194            
195            .nav-menu li {
196                font-size: 0.9rem;
197            }
198            
199            .lang-switcher {
200                align-self: center;
201            }
202        }
203    `;
204    document.head.appendChild(style);
205}

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.