PageSourceSearch

https://verveacu.com/js/blog-manager.js

js verveacu.com collected 2026-09-24 10:52:23 UTC 4,984 bytes, 153 lines download raw bytes

1/* global jQuery */
2
3/**
4 * Blog Manager
5 * Handles all blog-related functionality including navigation highlighting,
6 * category cross-referencing, and pagination styling.
7 */
8jQuery(function ($) {
9  // ====================================================================
10  // Helper Functions
11  // ====================================================================
12
13  /**
14   * Activates a sidebar link and its parent element
15   */
16  function activateSidebarLink(link) {
17    link.classList.add('active');
18    link.parentElement.classList.add('active');
19  }
20
21  // ====================================================================
22  // Blog Navigation
23  // ====================================================================
24
25  /**
26   * Highlights the current page in blog sidebar navigation
27   */
28  function highlightCurrentPage() {
29    if (!$('body.blog').length) {
30      return;
31    }
32
33    const currentPage = window.location.pathname.split('/').pop();
34    $('.site-sidebar .nav a').each(function () {
35      const href = $(this).attr('href');
36      if (href && href.match(new RegExp('^\\/?' + currentPage))) {
37        $(this).addClass('active');
38        $(this).parent().addClass('active');
39      }
40    });
41  }
42
43  /**
44   * Activates sidebar categories based on blog post categories
45   */
46  function activateBlogPostCategories() {
47    const categoryLinks = document.querySelectorAll('.blog-categories-cross-reference a');
48    const sidebarCategoryLinks = document.querySelectorAll('.site-sidebar .side-nav.categories li a');
49
50    categoryLinks.forEach((categoryLink) => {
51      const categoryHref = categoryLink.getAttribute('href');
52      sidebarCategoryLinks.forEach((sidebarLink) => {
53        if (sidebarLink.getAttribute('href') === categoryHref) {
54          activateSidebarLink(sidebarLink);
55        }
56      });
57    });
58  }
59
60  /**
61   * Activates sidebar category based on category page title
62   */
63  function activateCategoryByTitle() {
64    const categoryTitleElement = document.querySelector('.category-title-cross-reference');
65    if (!categoryTitleElement) {
66      return;
67    }
68
69    const categoryTitle = categoryTitleElement.textContent.trim();
70    const sidebarCategoryLinks = document.querySelectorAll('.site-sidebar .side-nav.categories li a');
71
72    sidebarCategoryLinks.forEach((sidebarLink) => {
73      if (sidebarLink.textContent.trim() === categoryTitle) {
74        activateSidebarLink(sidebarLink);
75      }
76    });
77  }
78
79  // ====================================================================
80  // Blog Feed
81  // ====================================================================
82
83  /**
84   * Adds spotlight class to the first blog feed wrapper
85   */
86  function highlightFirstBlogPost() {
87    const spotlightFeed = document.querySelector('.blog-feed-wrapper');
88    if (spotlightFeed) {
89      spotlightFeed.classList.add('spotlight');
90    }
91  }
92
93  /**
94   * Moves the first blog post to a new spotlight wrapper on category pages
95   */
96  function spotlightFirstCategoryPost() {
97    const feedWrapper = document.querySelector('.blog-feed-wrapper');
98    if (!feedWrapper) {
99      return;
100    }
101
102    const firstPost = feedWrapper.querySelector('.blog-feed-post');
103    if (!firstPost) {
104      return;
105    }
106
107    // Create new wrapper with spotlight class
108    const spotlightWrapper = document.createElement('div');
109    spotlightWrapper.className = 'blog-feed-wrapper spotlight';
110
111    // Move first post to new wrapper
112    spotlightWrapper.appendChild(firstPost);
113
114    // Update image src to use full-size image instead of resized version
115    const img = firstPost.querySelector('img');
116    if (img && img.src) {
117      const srcUrl = new URL(img.src);
118      const imgParam = srcUrl.searchParams.get('img');
119      if (imgParam) {
120        img.src = imgParam;
121      }
122    }
123
124    // Insert new wrapper before the original wrapper
125    feedWrapper.parentNode.insertBefore(spotlightWrapper, feedWrapper);
126  }
127
128  // ====================================================================
129  // Initialization
130  // ====================================================================
131
132  // Style pagination buttons
133  $('.pagination a, .pagination > li > span').addClass('btn btn-custom btn-primary');
134
135  // Highlight current page in navigation
136  highlightCurrentPage();
137
138  // Blog feed specific functionality
139  if (document.body.classList.contains('blog') && document.body.classList.contains('feed')) {
140    highlightFirstBlogPost();
141  }
142
143  // Blog post specific functionality
144  if (document.body.classList.contains('blog') && document.body.classList.contains('post')) {
145    activateBlogPostCategories();
146  }
147
148  // Blog category page specific functionality
149  if (document.body.classList.contains('blog') && document.body.classList.contains('category')) {
150    activateCategoryByTitle();
151    spotlightFirstCategoryPost();
152  }
153});

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.