1/** 2 * Component Loader â CRITICAL FILE 3 * 4 * This is the SINGLE SOURCE OF TRUTH for the site header and footer HTML. 5 * The files components/header/header.html and components/footer/footer.html 6 * are reference copies ONLY â this file contains the live HTML that gets 7 * injected at runtime into every page. 8 * 9 * What this file does: 10 * 1. Injects header HTML into #header-placeholder 11 * 2. Injects footer HTML into #footer-placeholder 12 * 3. Replaces {{BASE}} placeholders with correct relative paths 13 * 4. Builds breadcrumb navigation from data-breadcrumb attribute 14 * 5. Loads Google Translate widget 15 * 6. Manages login button visibility (homepage only) 16 * 7. Shows correct footer badges (homepage vs other pages) 17 * 8. Provides NAV_HIGHLIGHT_RULES for active nav link highlighting 18 * 9. Dispatches 'componentsLoaded' event when done 19 * 20 * To modify header/footer: Edit the headerHTML/footerHTML template strings below. 21 * To add breadcrumbs to a page: Add data-breadcrumb="Label::URL|..." to #header-placeholder. 22 */ 23 24(function() { 25 'use strict'; 26 27 // Header HTML template 28 const headerHTML = ` 29<!-- Header Component - Smithsonian Magazine Style (Black/White/Yellow) --> 30<header class="site-header" id="site-header" role="banner"> 31 <!-- Slogan Strip --> 32 <div class="header-slogan"> 33 <div class="container"> 34 <span class="header-slogan__text">Paleophilatelie <span class="header-slogan__separator">–</span> the place where Paleontology and Paleoanthropology meet Philately</span> 35 </div> 36 </div> 37 <!-- Top Black Bar with Logo and Navigation --> 38 <div class="header-top"> 39 <div class="container"> 40 <div class="header-top__content"> 41 <!-- Logo --> 42 <a href="{{BASE}}index.html" class="site-logo" aria-label="Paleophilatelie Home"> 43 <img src="{{BASE}}images/others/paleophilatelie-logo.png" alt="Paleophilatelie Logo" class="site-logo__image" width="70" height="88"> 44 <span class="site-logo__text">Paleophilatelie</span> 45 </a> 46 47 <!-- Main Navigation --> 48 <nav class="main-nav" id="main-nav" role="navigation" aria-label="Main navigation"> 49 <!-- Mobile Close Button --> 50 <button class="main-nav__close" id="nav-close" aria-label="Close menu"> 51 <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> 52 <path d="M18 6L6 18M6 6l12 12"/> 53 </svg> 54 </button> 55 <ul class="nav-list"> 56 <!-- Home --> 57 <li class="nav-item"> 58 <a href="{{BASE}}index.html" class="nav-link">Home</a> 59 </li> 60 61 <!-- Catalogue with Dropdown --> 62 <li class="nav-item has-dropdown"> 63 <a href="{{BASE}}phil_catalogue_main.html" class="nav-link">Catalogue</a> 64 <ul class="nav-dropdown"> 65 <li><a href="{{BASE}}country/index.html" class="nav-dropdown__link">Country</a></li> 66 <li><a href="{{BASE}}year/index.html" class="nav-dropdown__link">Date of Issue</a></li> 67 68 <li class="has-subdropdown"> 69 <a href="{{BASE}}description/index.html" class="nav-dropdown__link">Descriptions</a> 70 <ul class="nav-subdropdown"> 71 <li><a href="{{BASE}}description/stamps/index.html" class="nav-subdropdown__link">Official Stamps â Primary Topics</a></li> 72 <li><a href="{{BASE}}description/stamps/personalized/index.html" class="nav-subdropdown__link">Personalized Stamps â Primary Topics</a></li> 73 <li><a href="{{BASE}}description/stamps/others/index.html" class="nav-subdropdown__link">Official Stamps â Associated Topics</a></li> 74 <li><a href="{{BASE}}description/pm/index.html" class="nav-subdropdown__link">Postmarks â Primary Topics</a></li> 75 <li><a href="{{BASE}}description/ps/others/index.html" class="nav-subdropdown__link">Postal Stationery â Associated Topics</a></li> 76 <li><a href="{{BASE}}description/covers/index.html" class="nav-subdropdown__link">Commemorative Covers â Primary Topics</a></li> 77 </ul> 78 </li> 79 80 81 <li class="has-subdropdown"> 82 <a href="{{BASE}}check_list.html" class="nav-dropdown__link">Check List</a> 83 <ul class="nav-subdropdown"> 84 <li><a href="{{BASE}}images/checklist_stamps.html" class="nav-subdropdown__link">Stamps</a></li> 85 <li><a href="{{BASE}}images/checklist_pm.html" class="nav-subdropdown__link">Postmarks</a></li> 86 </ul> 87 </li> 88 89 <li><a href="{{BASE}}legend.html" class="nav-dropdown__link">Legend</a></li> 90 <li><a href="{{BASE}}phil_glossary.html" class="nav-dropdown__link">Glossary</a></li> 91 </ul> 92 </li> 93 94 <!-- Gallery with Dropdown --> 95 <li class="nav-item has-dropdown"> 96 <a href="{{BASE}}images/index.html" class="nav-link">Gallery</a> 97 <ul class="nav-dropdown"> 98 99 <li class="has-subdropdown"> 100 <a href="{{BASE}}images/stamps_gallery.html" class="nav-dropdown__link">Postage Stamps</a> 101 <ul class="nav-subdropdown"> 102 <li><a href="{{BASE}}images/stamps.html" class="nav-subdropdown__link">Primary Topics</a></li> 103 <li><a href="{{BASE}}images/stamps_others.html" class="nav-subdropdown__link">Associated Topics</a></li> 104 <li><a href="{{BASE}}images/stamps_used.html" class="nav-subdropdown__link">Circulated examples â Primary Topics</a></li> 105 <li><a href="{{BASE}}images/stamps_others_used.html" class="nav-subdropdown__link">Circulated examples â Associated Topics</a></li> 106 </ul> 107 </li> 108 109 <li class="has-subdropdown"> 110 <a href="{{BASE}}images/fdc_gallery.html" class="nav-dropdown__link">First Day Covers</a> 111 <ul class="nav-subdropdown"> 112 <li><a href="{{BASE}}images/fdc.html" class="nav-subdropdown__link">Primary Topics</a></li> 113 <li><a href="{{BASE}}images/fdc_others.html" class="nav-subdropdown__link">Associated Topics</a></li> 114 <li><a href="{{BASE}}images/fdc_used.html" class="nav-subdropdown__link">Circulated examples â Primary Topics</a></li> 115 <li><a href="{{BASE}}images/fdc_others_used.html" class="nav-subdropdown__link">Circulated examples â Associated Topics</a></li> 116 </ul> 117 </li> 118 119 120 <li class="has-subdropdown"> 121 <a href="{{BASE}}images/pm_gallery.html" class="nav-dropdown__link">Postmarks</a> 122 <ul class="nav-subdropdown"> 123 <li><a href="{{BASE}}images/pm.html" class="nav-subdropdown__link">Primary Topics</a></li> 124 <li><a href="{{BASE}}images/pm_others.html" class="nav-subdropdown__link">Associated Topics</a></li> 125 <li><a href="{{BASE}}images/pm_used.html" class="nav-subdropdown__link">Circulated examples â Primary Topics</a></li> 126 <li><a href="{{BASE}}images/pm_others_used.html" class="nav-subdropdown__link">Circulated examples â Associated Topics</a></li> 127 </ul> 128 </li> 129 130 131 132 <li class="has-subdropdown"> 133 <a href="{{BASE}}images/ps_gallery.html" class="nav-dropdown__link">Postal Stationeries</a> 134 135 <ul class="nav-subdropdown"> 136 <li><a href="{{BASE}}images/ps.html" class="nav-subdropdown__link">Primary Topics</a></li> 137 <li><a href="{{BASE}}images/ps_others.html" class="nav-subdropdown__link">Associated Topics</a></li> 138 <li><a href="{{BASE}}images/ps_used.html" class="nav-subdropdown__link">Circulated examples â Primary Topics</a></li> 139 <li><a href="{{BASE}}images/ps_others_used.html" class="nav-subdropdown__link">Circulated examples â Associated Topics</a></li> 140 </ul> 141 </li> 142 143 144 <li><a href="{{BASE}}exhibitions/index.html" class="nav-dropdown__link">Exhibits</a></li> 145 </ul> 146 </li> 147 148 <!-- Topics with Dropdown --> 149 <li class="nav-item has-dropdown"> 150 <a href="{{BASE}}topics/index.html" class="nav-link">Topics</a> 151 <ul class="nav-dropdown"> 152 <li class="has-subdropdown"> 153 <a href="{{BASE}}topics/paleo/index.html" class="nav-dropdown__link">Paleontology</a> 154 <ul class="nav-subdropdown"> 155 <li><a href="{{BASE}}topics/paleo/paleontologist.html" class="nav-subdropdown__link">Paleontologists</a></li> 156 <li><a href="{{BASE}}topics/paleo/contributors.html" class="nav-subdropdown__link">Contributors</a></li> 157 <li><a href="{{BASE}}topics/paleo/museums.html" class="nav-subdropdown__link">Museums</a></li> 158 <li><a href="{{BASE}}topics/paleo/sites.html" class="nav-subdropdown__link">Fossil Sites</a></li> 159 <li><a href="{{BASE}}topics/paleo/vertebrate/index.html" class="nav-subdropdown__link">Vertebrate</a></li> 160 </ul> 161 </li> 162 <li class="has-subdropdown"> 163 <a href="{{BASE}}topics/anthro/index.html" class="nav-dropdown__link">Paleoanthropology</a> 164 <ul class="nav-subdropdown"> 165 <li><a href="{{BASE}}topics/anthro/antropologist.html" class="nav-subdropdown__link">Paleoanthropologists</a></li> 166 <li><a href="{{BASE}}topics/anthro/contributors.html" class="nav-subdropdown__link">Contributors</a></li> 167 <li><a href="{{BASE}}topics/anthro/museums.html" class="nav-subdropdown__link">Museums</a></li> 168 <li><a href="{{BASE}}topics/anthro/sites.html" class="nav-subdropdown__link">Fossil Sites</a></li> 169 </ul> 170 </li> 171 </ul> 172 </li> 173 174 175 176 <li class="nav-item has-dropdown"> 177 <a href="{{BASE}}articles/index.html" class="nav-link">Resources</a> 178 <ul class="nav-dropdown"> 179 <li><a href="{{BASE}}articles/index.html" class="nav-dropdown__link">Articles</a></li> 180 <li><a href="{{BASE}}description/letters/index.html" class="nav-dropdown__link">Letters</a></li> 181 182 <li><a href="{{BASE}}media/books.html" class="nav-dropdown__link">Books</a></li> 183 <li><a href="{{BASE}}media/paleoart.html" class="nav-dropdown__link">Paleoart</a></li> 184 <li><a href="{{BASE}}media/videos.html" class="nav-dropdown__link">Videos</a></li> 185 <li class="has-subdropdown"> 186 <a href="{{BASE}}links.html" class="nav-dropdown__link">Links</a> 187 <ul class="nav-subdropdown"> 188 <li><a href="{{BASE}}links_paleo.html" class="nav-dropdown__link">Paleontology</a></li> 189 <li><a href="{{BASE}}links.html" class="nav-dropdown__link">Philately</a></li> 190 <li><a href="{{BASE}}links_postal_resources.html" class="nav-dropdown__link">Postal Resources</a></li> 191 <li><a href="{{BASE}}links_forums.html" class="nav-dropdown__link">Forums</a></li> 192 </ul> 193 </li> 194 </ul> 195 </li> 196 197 198 <!-- About with Dropdown --> 199 <li class="nav-item has-dropdown"> 200 <a href="{{BASE}}about_website.html" class="nav-link">About</a> 201 <ul class="nav-dropdown"> 202 <li><a href="{{BASE}}about.html" class="nav-dropdown__link">About Author</a></li> 203 <li><a href="{{BASE}}about_website.html" class="nav-dropdown__link">About Website</a></li> 204 <li><a href="{{BASE}}awards.html" class="nav-dropdown__link">Website's Awards</a></li> 205 <li><a href="{{BASE}}news.html" class="nav-dropdown__link">Website's News</a></li> 206 <li><a href="{{BASE}}about_how-to-help.html" class="nav-dropdown__link">How to Help</a></li> 207 <li><a href="{{BASE}}contact.html" class="nav-dropdown__link">Contact</a></li> 208 <li><a href="{{BASE}}sitemap.html" class="nav-dropdown__link">Sitemap</a></li> 209 </ul> 210 </li> 211 212 <!-- MK Private Area with Dropdown (only shown inside /mk/) --> 213 <li class="nav-item has-dropdown nav-item--mk"> 214 <a href="{{BASE}}mk/index.html" class="nav-link">Private</a> 215 <ul class="nav-dropdown"> 216 <li><a href="{{BASE}}mk/dealers.html" class="nav-dropdown__link">Dealers</a></li> 217 <li><a href="{{BASE}}mk/keywords_persons.html" class="nav-dropdown__link">Keywords</a></li> 218 <li><a href="{{BASE}}mk/wishlist.html" class="nav-dropdown__link">Wishlist</a></li> 219 <li><a href="{{BASE}}mk/my_links.html" class="nav-dropdown__link">My Links</a></li> 220 <li><a href="{{BASE}}mk/publications.html" class="nav-dropdown__link">Publications</a></li> 221 </ul> 222 </li> 223 224 <!-- Login (homepage only) --> 225 <li class="nav-item nav-item--login"> 226 <a href="{{BASE}}mk/index.html" class="nav-link">Login</a> 227 </li> 228 </ul> 229 </nav> 230 231 <!-- Mobile Menu Toggle --> 232 <button class="menu-toggle" id="menu-toggle" aria-label="Toggle navigation menu" aria-expanded="false">
233 <span class="menu-toggle__bar"></span> 234 <span class="menu-toggle__bar"></span> 235 <span class="menu-toggle__bar"></span> 236 </button> 237 </div> 238 </div> 239 </div> 240 241 <!-- Second Bar: Google Translate and FreeFind Search --> 242 <div class="header-toolbar"> 243 <div class="container"> 244 <div class="header-toolbar__content"> 245 <!-- Left column: Translate --> 246 <div class="header-toolbar__left"> 247 <div id="google_translate_element"></div> 248 </div> 249 250 <!-- Right column: Search Form --> 251 <div class="header-search-wrapper"> 252 <form action="https://search.freefind.com/find.html" method="get" accept-charset="UTF-8" class="header-search-form"> 253 <input type="hidden" name="si" value="14323397"> 254 <input type="hidden" name="pid" value="r"> 255 <input type="text" name="query" class="header-search-input" placeholder="Search stamps, countries, years..." aria-label="Search" autocomplete="off"> 256 <button type="submit" class="header-search-button" aria-label="Search"> 257 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> 258 <circle cx="11" cy="11" r="8"></circle> 259 <line x1="21" y1="21" x2="16.65" y2="16.65"></line> 260 </svg> 261 </button> 262 </form> 263 <div class="header-search-links"> 264 <a href="https://www.freefind.com/searchtipspop.html" target="_blank" rel="noopener noreferrer" class="header-search-links__item">search tips</a> 265 <span class="header-search-credit"><a href="https://www.freefind.com" target="_blank" rel="noopener noreferrer">search engine</a> by <a href="https://www.freefind.com" target="_blank" rel="noopener noreferrer">freefind</a></span> 266 <a href="https://search.freefind.com/find.html?si=14323397&pid=a" class="header-search-links__item">advanced search</a> 267 </div> 268 </div> 269 270 <!-- Sticky Toggle --> 271 <label class="toolbar-sticky-toggle" title="Pin toolbar to top"> 272 <input type="checkbox" id="toolbar-sticky-checkbox"> 273 <span class="toolbar-sticky-toggle__pin"> 274 <svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor"> 275 <path d="M16 3a1 1 0 0 1 .117 1.993L16 5h-.39l-1.45 4.36A3.5 3.5 0 0 1 16 12.5V14h-3v7l-1 1-1-1v-7H8v-1.5a3.5 3.5 0 0 1 1.84-3.14L8.39 5H8a1 1 0 0 1-.117-1.993L8 3h8z"/> 276 </svg> 277 </span> 278 </label> 279 </div> 280 <div id="header-breadcrumb-slot"></div> 281 </div> 282 </div> 283 284 <!-- Search Overlay --> 285 <div class="search-overlay" id="search-overlay"> 286 <div class="search-overlay-content"> 287 <form action="https://search.freefind.com/find.html" method="get" accept-charset="UTF-8"> 288 <input type="hidden" name="si" value="14323397"> 289 <input type="hidden" name="pid" value="r"> 290 <input type="text" name="query" class="search-overlay-input" placeholder="Search stamps, countries, years..." aria-label="Search" autocomplete="off"> 291 </form> 292 </div> 293 <button class="search-overlay-close" id="search-close" aria-label="Close search">×</button> 294 </div> 295</header> 296`; 297 298 // Footer HTML template 299 const footerHTML = ` 300<!-- Site Footer Component --> 301<footer class="site-footer" id="site-footer"> 302 <!-- Main Footer --> 303 <div class="footer-main"> 304 <div class="container"> 305 <div class="footer-grid"> 306 <!-- About Column --> 307 <div class="footer-col footer-col--about"> 308 <a href="{{BASE}}index.html" class="footer-logo"> 309 <img src="{{BASE}}images/others/paleophilatelie-logo.png" alt="Paleophilatelie" class="footer-logo__image" width="70" height="88">
310 <span class="footer-logo__text">Paleophilatelie<span class="footer-logo__tld">.eu</span></span> 311 </a> 312 <p class="footer-about"> 313 The place where Paleontology and Paleoanthropology meets Philately. 314 Explore the world's most comprehensive collection of prehistoric life on stamps. 315 </p> 316 <div class="footer-social"> 317 <a href="mailto:[email protected]" class="footer-social__link" aria-label="Email"> 318 <svg width="20" height="20" viewBox="0 0 24 24" fill="currentColor"> 319 <path d="M20 4H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm0 4l-8 5-8-5V6l8 5 8-5v2z"/> 320 </svg> 321 </a> 322 <a href="https://x.com/PaleoPhilatelis" class="footer-social__link" aria-label="Follow us on X" target="_blank" rel="noopener noreferrer"> 323 <svg width="20" height="20" viewBox="0 0 24 24" fill="currentColor"> 324 <path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z"/> 325 </svg> 326 </a> 327 </div> 328 <div class="footer-badges footer-badges--other"> 329 <a href="{{BASE}}images/others/qrcode_www.paleophilatelie.eu.png"> 330 <img src="{{BASE}}images/others/qrcode_www.paleophilatelie.eu.png" 331 alt="QR code of PaleoPhilatelie.eu website" 332 class="footer-badges__img" 333 loading="lazy"> 334 </a> 335 <a href="{{BASE}}images/others/logo_qr_code_fb.png" rel="noopener noreferrer"> 336 <img src="{{BASE}}images/others/logo_qr_code_fb.png" 337 alt="QR code of Paleophilately Facebook group" 338 class="footer-badges__img" 339 loading="lazy"> 340 </a> 341 </div> 342 <div class="footer-badges footer-badges--facebook"> 343 <a href="https://www.facebook.com/groups/889825297731726/" target="_blank" rel="noopener noreferrer"> 344 <img src="{{BASE}}images/others/facebook.jpg" 345 alt="PaleoPhilatelie.eu on Facebook - Welcome to join !" 346 title="PaleoPhilatelie.eu on Facebook - Welcome to join !" 347 class="footer-badges__img footer-badges__img--facebook" 348 loading="lazy"> 349 </a> 350 </div> 351 <!-- 352 <div class="footer-badges footer-badges--homepage"> 353 <a href="https://www.pwmo.org/" target="_blank" rel="noopener noreferrer"> 354 <img src="{{BASE}}images/others/pwo-logo.gif" 355 alt="Philatelic Webmasters Organization" 356 class="footer-badges__img_pwo" 357 loading="lazy"> 358 </a> 359 </div> 360 --> 361 </div> 362 363 <!-- Catalogue Column --> 364 <div class="footer-col"> 365 <h3 class="footer-col__title">Catalogue</h3> 366 <ul class="footer-links"> 367 <li><a href="{{BASE}}country/index.html">Country</a></li> 368 <li><a href="{{BASE}}year/index.html">Year</a></li> 369 <li><a href="{{BASE}}images/checklist_stamps.html">Checklist</a></li> 370 <li><a href="{{BASE}}description/index.html">Descriptions</a></li> 371 372 <!-- 373 </ul> 374 <h4 class="footer-col__subtitle"><a href="{{BASE}}description/index.html">Descriptions</a></h4> 375 <ul class="footer-links footer-links--nested"> 376 <li><a href="{{BASE}}description/stamps/index.html" >Official Stamps â Primary Topics</a></li> 377 <li><a href="{{BASE}}description/stamps/personalized/index.html" >Personalized Stamps â Primary Topics</a></li> 378 <li><a href="{{BASE}}description/stamps/others/index.html" >Official Stamps â Associated Topics:</a></li> 379 <li><a href="{{BASE}}description/pm/index.html" >Postmarks â Primary Topics</a></li> 380 <li><a href="{{BASE}}description/ps/others/index.html" >Postal Stationery â Associated Topics</a></li> 381 <li><a href="{{BASE}}description/covers/index.html" >Commemorative Covers â Primary Topics</a></li> 382 </ul> 383 <ul class="footer-links"> 384 --> 385 386 <li><a href="{{BASE}}legend.html">Legend</a></li> 387 <li><a href="{{BASE}}phil_glossary.html">Glossary</a></li> 388 </ul> 389 </div> 390 391 <!-- Gallery Column --> 392 <div class="footer-col"> 393 <h3 class="footer-col__title">Gallery</h3> 394 <ul class="footer-links"> 395 <li><a href="{{BASE}}images/stamps_gallery.html">Stamps</a></li> 396 <li><a href="{{BASE}}images/ps.html">Postal Stationeries</a></li> 397 <li><a href="{{BASE}}images/fdc.html">FDC</a></li> 398 <li><a href="{{BASE}}images/pm.html">Postmarks</a></li> 399 <li><a href="{{BASE}}exhibitions/index.html">Exhibits</a></li> 400 </ul> 401 </div> 402 403 <!-- Topics Column --> 404 <div class="footer-col"> 405 <h3 class="footer-col__title">Topics</h3> 406 <h4 class="footer-col__subtitle"><a href="{{BASE}}topics/paleo/index.html">Paleontology</a></h4> 407 <ul class="footer-links footer-links--nested"> 408 <li><a href="{{BASE}}topics/paleo/paleontologist.html">Paleontologists</a></li> 409 <li><a href="{{BASE}}topics/paleo/contributors.html">Contributors</a></li> 410 <li><a href="{{BASE}}topics/paleo/museums.html">Museums</a></li> 411 <li><a href="{{BASE}}topics/paleo/sites.html">Fossil Sites</a></li> 412 <li><a href="{{BASE}}topics/paleo/vertebrate/index.html">Vertebrate</a></li> 413 </ul> 414 <h4 class="footer-col__subtitle"><a href="{{BASE}}topics/anthro/index.html">Paleoanthropology</a></h4> 415 <ul class="footer-links footer-links--nested"> 416 <li><a href="{{BASE}}topics/anthro/antropologist.html">Paleoanthropologists</a></li> 417 <li><a href="{{BASE}}topics/anthro/contributors.html">Contributors</a></li> 418 <li><a href="{{BASE}}topics/anthro/museums.html">Museums</a></li> 419 <li><a href="{{BASE}}topics/anthro/sites.html">Fossil Sites</a></li> 420 </ul> 421 </div> 422 423 <!-- Resources Column --> 424 <div class="footer-col"> 425 <h3 class="footer-col__title">Resources</h3> 426 <ul class="footer-links"> 427 <li><a href="{{BASE}}articles/index.html">Articles</a></li> 428 <li><a href="{{BASE}}media/books.html">Books</a></li> 429 <li><a href="{{BASE}}media/paleoart.html">Paleoart</a></li> 430 <li><a href="{{BASE}}media/videos.html">Videos</a></li> 431 </u> 432 433 <h4 class="footer-col__subtitle"><a href="{{BASE}}links.html">Links</a></h4> 434 <ul class="footer-links footer-links--nested"> 435 <li><a href="{{BASE}}links_paleo.html">Paleontology</a></li> 436 <li><a href="{{BASE}}links.html">Philately</a></li> 437 <li><a href="{{BASE}}links_postal_resources.html">Postal Resources</a></li> 438 <li><a href="{{BASE}}links_forums.html">Forums</a></li> 439 </ul> 440 </div> 441 442 <!-- About Column --> 443 <div class="footer-col"> 444 <h3 class="footer-col__title">About</h3> 445 <ul class="footer-links"> 446 <li><a href="{{BASE}}about_website.html">Website</a></li> 447 <li><a href="{{BASE}}about.html">Author</a></li> 448 <li><a href="{{BASE}}awards.html">Awards</a></li> 449 <li><a href="{{BASE}}news.html">News</a></li> 450 <li><a href="{{BASE}}about_how-to-help.html">How to Help</a></li> 451 <li><a href="{{BASE}}contact.html">Contact</a></li> 452 <li><a href="{{BASE}}sitemap.html">Sitemap</a></li> 453 </ul> 454 </div> 455 </div> 456 </div> 457 </div> 458 459 <!-- Footer Bottom --> 460 <div class="footer-bottom"> 461 <div class="container"> 462 <div class="footer-bottom__content"> 463 <p class="footer-copyright"> 464 © 2010–<span id="currentYear"></span> Paleophilatelie. All rights reserved. Contact for any issue: <a href="mailto:[email protected]">[email protected]</a> 465 </p> 466 <div class="footer-bottom__links"> 467 <a href="{{BASE}}sitemap.html">Sitemap</a>
468 <span class="footer-bottom__divider">|</span> 469 <a href="{{BASE}}legend.html">Legend</a> 470 <span class="footer-bottom__divider">|</span> 471 <a href="{{BASE}}phil_glossary.html">Glossary</a> 472 </div> 473 </div> 474 <p class="footer-developer"> 475 Designed & Developed by <a href="https://softechinfra.com" target="_blank" rel="noopener noreferrer">SoftechInfra</a> 476 </p> 477 </div> 478 </div> 479 480 <!-- Back to Top Button --> 481 <button class="back-to-top" id="back-to-top" aria-label="Back to top"> 482 <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> 483 <path d="M18 15l-6-6-6 6"/> 484 </svg> 485 </button> 486</footer> 487`; 488 489 // ===== Centralized Navigation Highlighting Config ===== 490 // Each rule maps a page (by exact path or prefix) to the nav hrefs that should be highlighted. 491 // nav array: [top-level href, dropdown href, subdropdown href] â only include what applies. 492 // Exact paths are checked before prefixes (order matters within each type). 493 window.NAV_HIGHLIGHT_RULES = [ 494 // HOME 495 { path: "index.html", nav: ["index.html"] }, 496 497 // CATALOGUE (top-level href: phil_catalogue_main.html) 498 { path: "phil_catalogue_main.html", nav: ["phil_catalogue_main.html"] }, 499 { path: "phil_catalogue_framed.html", nav: ["phil_catalogue_main.html"] }, 500 { path: "phil_catalogue_trends.html", nav: ["phil_catalogue_main.html", "phil_catalogue_trends.html"] }, 501 502 { path: "checklist.html", nav: ["phil_catalogue_main.html", "check_list.html"] }, 503 { path: "images/checklist_stamps.html", nav: ["phil_catalogue_main.html", "check_list.html", "images/checklist_stamps.html"] }, 504 { path: "images/checklist_pm.html", nav: ["phil_catalogue_main.html", "check_list.html", "images/checklist_pm.html"] }, 505 506 { path: "legend.html", nav: ["phil_catalogue_main.html", "legend.html"] }, 507 { path: "phil_glossary.html", nav: ["phil_catalogue_main.html", "phil_glossary.html"] }, 508 { prefix: "country/", nav: ["phil_catalogue_main.html", "country/index.html"] }, 509 { prefix: "year/", nav: ["phil_catalogue_main.html", "year/index.html"] }, 510 511 { path: "description/index.html", nav: ["phil_catalogue_main.html", "description/index.html"] }, 512 { prefix: "description/stamps/personalized/", nav: ["phil_catalogue_main.html", "description/index.html", "description/stamps/personalized/index.html"] }, 513 { prefix: "description/stamps/others/", nav: ["phil_catalogue_main.html", "description/index.html", "description/stamps/others/index.html"] }, 514 { prefix: "description/stamps/", nav: ["phil_catalogue_main.html", "description/index.html", "description/stamps/index.html"] }, 515 { prefix: "description/pm/", nav: ["phil_catalogue_main.html", "description/index.html", "description/pm/index.html"] }, 516 { prefix: "description/ps/", nav: ["phil_catalogue_main.html", "description/index.html", "description/ps/others/index.html"] }, 517 { prefix: "description/covers/", nav: ["phil_catalogue_main.html", "description/index.html", "description/covers/index.html"] }, 518 519 // GALLERY (top-level href: images/index.html) 520 { path: "images/index.html", nav: ["images/index.html"] }, 521 522 // { path: "images/stamps_gallery.html", nav: ["images/stamps_gallery.html"] }, 523 { prefix: "images/stamps_gallery.html", nav: ["images/index.html", "images/stamps_gallery.html"] }, 524 525 { prefix: "images/stamps.html", nav: ["images/index.html", "images/stamps_gallery.html", "images/stamps.html"] }, 526 { prefix: "images/stamps_used.html", nav: ["images/index.html", "images/stamps_gallery.html", "images/stamps_used.html"] }, 527 { prefix: "images/stamps_others.html", nav: ["images/index.html", "images/stamps_gallery.html", "images/stamps_others.html"] }, 528 { prefix: "images/stamps_others_used.html", nav: ["images/index.html", "images/stamps_gallery.html", "images/stamps_others_used.html"] }, 529 530 { prefix: "images/ps.html", nav: ["images/index.html", "images/ps_gallery.html", "images/ps.html"] }, 531 { prefix: "images/ps_used.html", nav: ["images/index.html", "images/ps_gallery.html", "images/ps_used.html"] }, 532 { prefix: "images/ps_others.html", nav: ["images/index.html", "images/ps_gallery.html", "images/ps_others.html"] }, 533 { prefix: "images/ps_others_used.html", nav: ["images/index.html", "images/ps_gallery.html", "images/ps_others_used.html"] }, 534 535 { prefix: "images/fdc_gallery.html", nav: ["images/index.html", "images/fdc_gallery.html"] }, 536 { prefix: "images/fdc.html", nav: ["images/index.html", "images/fdc_gallery.html", "images/fdc.html"] }, 537 { prefix: "images/fdc_used.html", nav: ["images/index.html", "images/fdc_gallery.html", "images/fdc_used.html"] }, 538 { prefix: "images/fdc_others.html", nav: ["images/index.html", "images/fdc_gallery.html", "images/fdc_others.html"] }, 539 { prefix: "images/fdc_others_used.html", nav: ["images/index.html", "images/fdc_gallery.html", "images/fdc_others_used.html"] }, 540 541 542 { prefix: "images/pm.html", nav: ["images/index.html", "images/pm_gallery.html", "images/pm.html"] }, 543 { prefix: "images/pm_used.html", nav: ["images/index.html", "images/pm_gallery.html", "images/pm_used.html"] }, 544 { prefix: "images/pm_others.html", nav: ["images/index.html", "images/pm_gallery.html", "images/pm_others.html"] }, 545 { prefix: "images/pm_others_used.html", nav: ["images/index.html", "images/pm_gallery.html", "images/pm_others_used.html"] }, 546 547 { prefix: "exhibitions/", nav: ["images/index.html", "exhibitions/index.html"] }, 548 549 // TOPICS > PALEONTOLOGY 550 { path: "topics/index.html", nav: ["topics/index.html"] }, 551 { path: "topics/paleo/index.html", nav: ["topics/index.html", "topics/paleo/index.html"] }, 552 { path: "topics/paleo/paleontologist.html", nav: ["topics/index.html", "topics/paleo/index.html", "topics/paleo/paleontologist.html"] }, 553 { path: "topics/paleo/contributors.html", nav: ["topics/index.html", "topics/paleo/index.html", "topics/paleo/contributors.html"] }, 554 { path: "topics/paleo/museums.html", nav: ["topics/index.html", "topics/paleo/index.html", "topics/paleo/museums.html"] }, 555 { path: "topics/paleo/sites.html", nav: ["topics/index.html", "topics/paleo/index.html", "topics/paleo/sites.html"] }, 556 { prefix: "topics/paleo/vertebrate/", nav: ["topics/index.html", "topics/paleo/index.html", "topics/paleo/vertebrate/index.html"] }, 557 { prefix: "topics/paleo/", nav: ["topics/index.html", "topics/paleo/index.html"] }, 558 559 // TOPICS > PALEOANTHROPOLOGY 560 { path: "topics/anthro/index.html", nav: ["topics/index.html", "topics/anthro/index.html"] }, 561 { path: "topics/anthro/antropologist.html", nav: ["topics/index.html", "topics/anthro/index.html", "topics/anthro/antropologist.html"] }, 562 { path: "topics/anthro/contributors.html", nav: ["topics/index.html", "topics/anthro/index.html", "topics/anthro/contributors.html"] }, 563 { path: "topics/anthro/museums.html", nav: ["topics/index.html", "topics/anthro/index.html", "topics/anthro/museums.html"] }, 564 { path: "topics/anthro/sites.html", nav: ["topics/index.html", "topics/anthro/index.html", "topics/anthro/sites.html"] }, 565 { prefix: "topics/anthro/", nav: ["topics/index.html", "topics/anthro/index.html"] }, 566 567 // RESOURCES (top-level href: articles/index.html) 568 { prefix: "articles/", nav: ["articles/index.html"] }, 569 { path: "links_paleo.html", nav: ["articles/index.html", "links_paleo.html"] }, 570 571 { prefix: "description/letters/", nav: ["articles/index.html", "description/letters/index.html"] }, 572 573 { path: "links.html", nav: ["articles/index.html", "links.html"] }, 574 { path: "links_postal_resources.html", nav: ["articles/index.html", "links_postal_resources.html"] }, 575 { path: "links_forums.html", nav: ["articles/index.html", "links_forums.html"] }, 576 { path: "media/books.html", nav: ["articles/index.html", "media/books.html"] }, 577 { path: "media/paleoart.html", nav: ["articles/index.html", "media/paleoart.html"] }, 578 { path: "media/videos.html", nav: ["articles/index.html", "media/videos.html"] }, 579 { prefix: "media/", nav: ["articles/index.html"] }, 580 581 // ABOUT (top-level href: about_website.html) 582 { path: "about_website.html", nav: ["about_website.html"] }, 583 { path: "about.html", nav: ["about_website.html", "about.html"] }, 584 { path: "news.html", nav: ["about_website.html", "news.html"] }, 585 { path: "news_archive.html", nav: ["about_website.html", "news.html"] }, 586 { path: "awards.html", nav: ["about_website.html", "awards.html"] }, 587 { path: "contact.html", nav: ["contact.html"] }, 588 { path: "sitemap.html", nav: ["sitemap.html"] }, 589 { path: "paleophilatelie_site_map.html", nav: ["sitemap.html"] }, 590 { path: "about_how-to-help.html", nav: ["about_website.html", "about_how-to-help.html"] }, 591 592 // LOGIN 593 { prefix: "mk/", nav: ["mk/index.html"] }, 594 ]; 595 596 // Get the site-root-relative path of the current page (e.g. 597 // "country/afghanistan.html"). The folder depth is taken from getBasePath() 598 // (the number of "../" steps back to the site root), so the last N URL 599 // segments give the path relative to root. Works on a server and on a local 600 // file:// copy, and needs no list of folder names. 601 window.getSiteRelativePath = function() { 602 var depth = (getBasePath().match(/\.\.\//g) || []).length; 603 var pathname = window.location.pathname.replace(/\\/g, '/');
604 var segs = pathname.split('/').filter(Boolean); 605 return segs.slice(segs.length - (depth + 1)).join('/') || 'index.html'; 606 }; 607 608 // Find the matching highlight rule for the current page 609 window.getNavHighlightRule = function() { 610 var pagePath = window.getSiteRelativePath().toLowerCase(); 611 var rules = window.NAV_HIGHLIGHT_RULES; 612 // Exact path matches first 613 for (var i = 0; i < rules.length; i++) { 614 if (rules[i].path && pagePath === rules[i].path.toLowerCase()) { 615 return rules[i]; 616 } 617 } 618 // Prefix matches second 619 for (var i = 0; i < rules.length; i++) { 620 if (rules[i].prefix && pagePath.indexOf(rules[i].prefix.toLowerCase()) === 0) { 621 return rules[i]; 622 } 623 } 624 return null; 625 }; 626 627 // Determine the base path for {{BASE}} links. 628 // Derive it from THIS script's own <script src="..."> value. Every page 629 // already references the loader with the correct relative depth 630 // (e.g. "scripts/...", "../scripts/...", "../../scripts/..."), so whatever 631 // comes before "scripts/component-loader.js" is exactly the relative path 632 // back to the site root. This means: 633 // ⢠Works on a live web server AND on a local file:// copy (relative links). 634 // ⢠Needs NO hardcoded list of folder names â new subdirectories, at any 635 // depth, work automatically. 636 function getBasePath() { 637 var scripts = document.getElementsByTagName('script'); 638 for (var i = 0; i < scripts.length; i++) { 639 var src = scripts[i].getAttribute('src') || ''; 640 var m = src.match(/^(.*?)scripts\/component-loader\.js(?:[?#].*)?$/); 641 if (m) { 642 return m[1]; // '', '../', '../../', etc. 643 } 644 } 645 return ''; 646 } 647 648 // Replace base path placeholders in HTML 649 function applyBasePath(html, basePath) { 650 return html.replace(/\{\{BASE\}\}/g, basePath); 651 } 652 653 // Load header component 654 function loadHeader(basePath) { 655 const element = document.getElementById('header-placeholder'); 656 if (!element) return; 657 658 element.innerHTML = applyBasePath(headerHTML, basePath); 659 660 // Show login button only on the root homepage 661 const pageName = window.location.pathname.replace(/\\/g, '/').split('/').pop(); 662 // Root homepage = an index page with no subfolder in its site-relative path 663 const siteRel = window.getSiteRelativePath(); 664 const isHomepage = (pageName === 'index.html' || pageName === 'index.htm' || pageName === '') && siteRel.indexOf('/') === -1; 665 const loginItem = element.querySelector('.nav-item--login'); 666 if (loginItem && !isHomepage) { 667 loginItem.style.display = 'none'; 668 } 669 670 // Show the MK private-area menu only inside the /mk/ section 671 const isMkArea = siteRel.toLowerCase().indexOf('mk/') === 0; 672 const mkItem = element.querySelector('.nav-item--mk'); 673 if (mkItem && !isMkArea) { 674 mkItem.style.display = 'none'; 675 } 676 677 // Build breadcrumb from data attribute 678 var breadcrumbData = element.getAttribute('data-breadcrumb'); 679 var slot = element.querySelector('#header-breadcrumb-slot'); 680 if (breadcrumbData && slot) { 681 var items = breadcrumbData.split('|'); 682 // Filter out any existing "Sitemap" entry â we auto-prepend it 683 items = items.filter(function(item) { 684 return item.split('::')[0].trim().toLowerCase() !== 'sitemap'; 685 }); 686 var lis = items.map(function(item) { 687 var parts = item.split('::'); 688 var label = parts[0]; 689 var url = parts[1]; 690 if (url) { 691 return '<li class="breadcrumb__item"><a href="' + url + '" class="breadcrumb__link">' + label + '</a></li>'; 692 } 693 return '<li class="breadcrumb__item"><span class="breadcrumb__current">' + label + '</span></li>'; 694 }).join(''); 695 var sitemapLink = '<a href="' + basePath + 'sitemap.html" class="breadcrumb__sitemap-link">Sitemap</a>:\u00a0 '; 696 slot.innerHTML = '<nav class="breadcrumb" aria-label="Breadcrumb">' + sitemapLink + '<ol class="breadcrumb__list">' + lis + '</ol></nav>'; 697 } 698 } 699 700 // Load footer component 701 function loadFooter(basePath) { 702 const element = document.getElementById('footer-placeholder'); 703 if (!element) return; 704 705 element.innerHTML = applyBasePath(footerHTML, basePath); 706 707 // Detect homepage and show the appropriate footer badges 708 const path = window.location.pathname; 709 const isHomepage = path === '/' || path.endsWith('/index.html') || path.endsWith('/index.htm') || path === ''; 710 const homepageBadges = element.querySelector('.footer-badges--homepage'); 711 const otherBadges = element.querySelector('.footer-badges--other'); 712 713 if (homepageBadges && otherBadges) { 714 if (isHomepage) { 715 otherBadges.style.display = 'none'; 716 } else { 717 homepageBadges.style.display = 'none'; 718 } 719 } 720 } 721 722 // Load Google Translate script 723 function loadGoogleTranslate() { 724 // Define the callback function globally 725 window.googleTranslateElementInit = function() { 726 new google.translate.TranslateElement({ 727 pageLanguage: 'en', 728 layout: google.translate.TranslateElement.InlineLayout.HORIZONTAL 729 }, 'google_translate_element'); 730 }; 731 732 // Load the script (use https explicitly for file:// protocol compatibility) 733 const script = document.createElement('script'); 734 script.src = 'https://translate.google.com/translate_a/element.js?cb=googleTranslateElementInit'; 735 script.async = true; 736 document.body.appendChild(script); 737 } 738 739 // Main initialization
740 function init() { 741 // Suppress Chrome's built-in translate bar (site has its own translate widget) 742 if (!document.querySelector('meta[name="google"][content="notranslate"]')) { 743 const meta = document.createElement('meta'); 744 meta.name = 'google'; 745 meta.content = 'notranslate'; 746 document.head.appendChild(meta); 747 } 748 749 // Skip header/footer when loaded inside an iframe (e.g. 3-panel navigator) 750 const isInIframe = window !== window.top; 751 752 const basePath = getBasePath(); 753 754 // Load components (skip if inside iframe to avoid double header/footer) 755 if (!isInIframe) { 756 loadHeader(basePath); 757 loadFooter(basePath); 758 759 // Load Google Translate after header is loaded 760 loadGoogleTranslate(); 761 762 // Update copyright year 763 const yearSpan = document.getElementById('currentYear'); 764 if (yearSpan) { 765 yearSpan.textContent = new Date().getFullYear(); 766 } 767 } 768 769 // Dispatch event to notify other scripts that components are loaded 770 document.dispatchEvent(new CustomEvent('componentsLoaded')); 771 } 772 773 // Run when DOM is ready 774 if (document.readyState === 'loading') { 775 document.addEventListener('DOMContentLoaded', init); 776 } else { 777 init(); 778 } 779})();
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.