PageSourceSearch

https://www.galls.com/css/blog_assets/blog.js?v=11

js galls.com collected 2026-09-24 19:39:51 UTC 14,502 bytes, 411 lines download raw bytes

1
2/* =============== DOCUMENT READY =============== */
3let skipScrollingAnimation = false;
4$(document).ready(function () {
5	/*Generate Blogs html from Json Data*/
6	jsontoHtml();
7    /* Generate JumpTo Section */
8    if ($('.samBlog_PDP').length > 0 && $('.samBlog_PDP_Bio').length < 1) {
9        // Collect all <h2> elements
10        var headings = $('.samBlog_PDP_Article_Section h2');
11
12        // Loop through each <h2> element
13        headings.each(function(index) {
14            var heading = $(this);
15
16            // Generate a unique ID for each <h2> if it doesn't already have one
17            var id = heading.attr('id') || 'heading-' + index;
18            heading.attr('id', id);
19
20            // Create an <li> tag containing an <a> tag pointing to the <h2>'s ID
21            var link = $('<a></a>')
22                .attr('href', '#' + id)
23                .text(heading.text());
24
25            var listItem = $('<div class="jumpto_list"></div>').append(link);
26
27            // Add the <li> to the container
28            $(".samBlog_JumpTo .jumpto_list_container").append(listItem);
29        });
30
31        // Smooth scrolling effect for the links
32        $('.samBlog_JumpTo a').on('click', function(event) {
33            event.preventDefault(); // Prevent the default anchor click behavior
34
35            var targetId = $(this).attr('href');
36            var target = $(targetId);
37            var adjustTopScroll = 100; //Mobile
38
39            if (screen.width > 991) {
40                adjustTopScroll = 150;  //Desktop
41            }
42            
43            if (target.length) {
44                $('html, body').animate({
45                    scrollTop: target.offset().top - adjustTopScroll
46                }, 300);
47            }
48        });
49
50    }
51
52
53
54    /* Toggle JumpTo Section (Author Page Only) */
55    $(".samBlog.samBlog_PDP_Bio .jumpto_title").on("click", function () {
56        $(".samBlog.samBlog_PDP_Bio .jumpto_list").slideToggle();
57        $(".samBlog.samBlog_PDP_Bio .samBlog_JumpTo").toggleClass('collapsed');
58    });
59    if (screen.width < 992) {
60        /* Collapsed by default on mobile */
61        $(".samBlog.samBlog_PDP_Bio .jumpto_list").slideToggle(0); 
62        $(".samBlog.samBlog_PDP_Bio .samBlog_JumpTo").toggleClass('collapsed');
63        /* end */
64    }
65    /* end */
66
67    /* Toggle Sticky JumpTo_Sticky Section (PDP Only) */
68    $(".samBlog_JumpTo_Sticky .jumpto_title").click(function (event) {
69        event.stopPropagation();
70        $(".samBlog_JumpTo_Sticky").toggleClass("expand");
71    });
72
73    
74    /* Instant Search and Pagination */
75    // Store a reference to all items for global search
76    const allItems = $(".samIS_Product_Grid").children().clone();
77
78    // Search Functionality
79    $(".samIS_SearchInput").on("keyup", function () {
80        const searchTerm = $(this).val().toLowerCase();
81    
82        // Filter items based on the search term
83        const filteredItems = allItems.filter(function () {
84            const keyword = $(this).data("keyword").toLowerCase();
85            return keyword.includes(searchTerm);
86        });
87    
88        // Update the total number of items found
89        $(".samIS_SearchTotal").text(`${filteredItems.length} articles found`);
90        // if (searchTerm == '') {
91        //     $(".samIS_SearchTotal").text('');
92        // }
93    
94        /* Reset Pagination with filtered items (itemsOverride) from Instant Search */
95        samPagination_Start({
96            gridSelector: ".samIS_Product_Grid",
97            paginationContainerSelector: ".samPaginationContainer",
98            itemsPerPage: 6,
99            dateSelector: ".samIS_Product_Date",
100            viewAllBtnSelector: ".samPC_ViewAllBtn",
101            prevBtnSelector: ".samPC_PrevBtn",
102            nextBtnSelector: ".samPC_NextBtn",
103            pageNumberContainerSelector: ".samPC_PageNumber",
104            itemsOverride: filteredItems, // Pass the filtered items for rendering from the Instant Search function
105        });
106    
107        skipScrollingAnimation = true;
108        samAddLazyLoadToImg(); // Add Lazy Load;
109    });
110
111    /* 
112        - Initialize Pagination on page load
113        - itemsOverride is null because No Instant Search on page load
114    */
115    samPagination_Start({
116        gridSelector: ".samIS_Product_Grid",
117        paginationContainerSelector: ".samPaginationContainer",
118        itemsPerPage: 6,
119        dateSelector: ".samIS_Product_Date",
120        viewAllBtnSelector: ".samPC_ViewAllBtn",
121        prevBtnSelector: ".samPC_PrevBtn",
122        nextBtnSelector: ".samPC_NextBtn",
123        pageNumberContainerSelector: ".samPC_PageNumber",
124    });
125    /* end */
126
127
128
129    /* Read Length Calcuation (PDP Only)*/
130    if ($('.samBlog_PDP').length > 0) {
131        // Get all paragraph texts
132        const paragraphTexts = $('p').map(function () {
133            return $(this).text(); // Extract text content
134        }).get(); // Convert jQuery object to a plain array
135
136        // Calculate reading time
137        let readingTime = samBlog_CalculateReadingTime(paragraphTexts);
138        readingTime = readingTime.toString().split('.')[0];
139        if ($('.samBlog_Read_Duration').length > 0) {
140            
141            if (readingTime.indexOf("seconds") >= 0) {
142                $('.samBlog_Read_Duration').html('Less than a minute read');
143            } else {
144                $('.samBlog_Read_Duration').html(readingTime + ' min read');
145            }
146        }
147    }
148    /* end */
149
150
151    samAddLazyLoadToImg();  //Add Lazy Load;
152    
153
154});
155/* =============== END DOCUMENT READY =============== */
156
157
158
159function samPagination_Start({
160    gridSelector,
161    paginationContainerSelector,
162    itemsPerPage,
163    dateSelector,
164    viewAllBtnSelector,
165    prevBtnSelector,
166    nextBtnSelector,
167    pageNumberContainerSelector,
168    itemsOverride = null, // Allow overriding items for search
169}) {
170    const grid = $(gridSelector);
171    const paginationContainer = $(paginationContainerSelector);
172    const viewAllBtn = $(viewAllBtnSelector);
173    const prevBtn = $(prevBtnSelector);
174    const nextBtn = $(nextBtnSelector);
175    const pageNumberContainer = $(pageNumberContainerSelector);
176
177    // Use overridden items if provided, otherwise use all items from the grid
178    const items = itemsOverride || $(gridSelector).children();
179    const sortedItems = items.sort((a, b) => {
180        const dateA = new Date($(a).find(dateSelector).text().replace("Publish: ", ""));
181        const dateB = new Date($(b).find(dateSelector).text().replace("Publish: ", ""));
182        return dateB - dateA; // Descending
183    });
184
185    let currentPage = 1;
186    const totalPages = Math.ceil(sortedItems.length / itemsPerPage);
187
188    function renderItems(page) {
189        grid.empty();
190        const start = (page - 1) * itemsPerPage;
191        const end = start + itemsPerPage;
192
193        const fragment = document.createDocumentFragment();
194        sortedItems.slice(start, end).each(function () {
195            fragment.appendChild(this);
196        });
197        grid.append(fragment);
198    }
199
200    function renderPagination() {
201        pageNumberContainer.empty();
202
203        // Disable buttons if on first or last page
204        prevBtn.prop("disabled", currentPage === 1);
205        nextBtn.prop("disabled", currentPage === totalPages);
206
207        if (totalPages <= 5) {
208            for (let i = 1; i <= totalPages; i++) {
209                pageNumberContainer.append(
210                    `<button class="btn btn-secondary btn-sm page-number${i === currentPage ? " active" : ""}" data-page="${i}">${i}</button>`
211                );
212            }
213        } else {
214            const startPage = Math.max(currentPage - 2, 1);
215            const endPage = Math.min(startPage + 4, totalPages);
216
217            if (startPage > 1) {
218                pageNumberContainer.append(`<button class="btn btn-secondary btn-sm page-number" data-page="1">1</button>`);
219                if (startPage > 2) {
220                    pageNumberContainer.append('<span class="dots">...</span>');
221                }
222            }
223
224            for (let i = startPage; i <= endPage; i++) {
225                pageNumberContainer.append(
226                    `<button class="btn btn-secondary btn-sm page-number${i === currentPage ? " active" : ""}" data-page="${i}">${i}</button>`
227                );
228            }
229
230            if (endPage < totalPages) {
231                if (endPage < totalPages - 1) {
232                    pageNumberContainer.append('<span class="dots">...</span>');
233                }
234                pageNumberContainer.append(
235                    `<button class="btn btn-secondary btn-sm page-number" data-page="${totalPages}">${totalPages}</button>`
236                );
237            }
238        }
239
240        samAddLazyLoadToImg(); // Add Lazy Load;
241
242    }
243
244    function scrollToGrid() {
245        
246        /* Skip scrolling if search function is used */
247        var scrollDelay = 300;
248        if (skipScrollingAnimation == true) {
249            scrollDelay = 0;
250        } 
251
252        // console.log("TEST: " + scrollDelay);
253        showWait("B"); 
254        $("html, body").animate(
255            { scrollTop: grid.offset().top - 220 },
256            scrollDelay,
257            "swing",
258            function () {
259                hideWait(); 
260            }
261        );
262
263    }
264
265    pageNumberContainer.on("click", ".page-number", function () {
266        currentPage = parseInt($(this).data("page"), 10);
267        renderItems(currentPage);
268        renderPagination();
269        scrollToGrid();
270    });
271
272    prevBtn.click(function () {
273        if (currentPage > 1) {
274            currentPage--;
275            renderItems(currentPage);
276            renderPagination();
277            scrollToGrid();
278        }
279    });
280
281    nextBtn.click(function () {
282        if (currentPage < totalPages) {
283            currentPage++;
284            renderItems(currentPage);
285            renderPagination();
286            scrollToGrid();
287        }
288    });
289
290    viewAllBtn.click(function () {
291        grid.empty();
292        grid.append(sortedItems); // Show all items
293        paginationContainer.hide(); // Hide pagination
294        scrollToGrid();
295    });
296
297    // Initialize
298    renderItems(currentPage);
299    renderPagination();
300}
301
302function samBlog_ToggleMenu() {
303    const menu = document.querySelector('.samBlog_Navigation .menu');
304    menu.style.display = menu.style.display === 'flex' ? 'none' : 'flex';
305}
306
307
308function samBlog_CalculateReadingTime(texts) {
309    const wordsPerMinute = 200; // Words per minute
310    let totalWords = 0;
311
312    // Loop through the array of texts and count words
313    texts.forEach(function (text) {
314        const wordCount = text.trim().split(/\s+/).length; // Count words
315        totalWords += wordCount;
316    });
317
318    // Calculate the reading time in minutes
319    const readingTime = totalWords / wordsPerMinute;
320
321    // Format the reading time (e.g., "1.5 minutes" or "1 minute")
322    const formattedReadingTime =
323        readingTime < 1
324            ? Math.ceil(readingTime * 60) + ' seconds'
325            : readingTime.toFixed(1) + ' minutes';
326
327    return formattedReadingTime;
328}
329function jsontoHtml(){
330  	if ($('.samBlog_PDP').length > 0) {return;}//Don't Execute on PDP!
331	if($('#json-blogs').length<1){return;}
332	if($('#json-categs').length<1){return;}
333  	const jsonData = document.getElementById("json-blogs").textContent;
334      const blogs = JSON.parse(jsonData);
335  showWait();
336  				if(blogs.length <  1)  $('.samIS_SearchTotal').html('No articles Found');
337  				if(blogs.length == 1)  $('.samIS_SearchTotal').html(blogs.length + ' article');
338  				if(blogs.length >  1)  $('.samIS_SearchTotal').html(blogs.length + ' articles');
339  $('#blogsList').html('');
340  const categsData = document.getElementById("json-categs").textContent;
341      const categories = JSON.parse(categsData);
342  for (const blog of blogs) {
343  					 
344  	  // Get the template
345  	 var template = $('#blogTemplate').html();
346  	  // Clone the template
347  	  var clonedItem = $(template);
348  
349  	  // Adjust content of the cloned item
350  	  clonedItem.find('img').attr('src', $("#imgpath").val()+ '/' + blog.img);
351  	  clonedItem.find('img').attr('data-original', $("#imgpath").val()+ '/' + blog.img);
352  	  clonedItem.find('a').attr('href',buildCategoryUrl(categories,blog.bcno)+'/'+blog.url);
353  	  clonedItem.find('h5').text(blog.titl);
354  	  clonedItem.find('p').text(blog.metd);
355  	  clonedItem.attr('data-keyword',blog.titl+' '+blog.metd);
356  		// Get current date
357  	try{
358  		var dateString = blog.pbdt.toString();
359  		
360  		// Extract the parts of the date
361  		var year = dateString.substring(0, 4);
362  		var month = dateString.substring(4, 6) - 1;  // Months are 0-indexed, so subtract 1
363  		var day = dateString.substring(6, 8);
364  		var date = new Date(year, month, day);
365  		var formattedDate = new Intl.DateTimeFormat('en-US', {
366  		  month: 'long',  // Full month name (e.g., "February")
367  		  day: '2-digit', // 2-digit day (e.g., "04")
368  		  year: 'numeric' // Full year (e.g., "2025")
369  		}).format(date);
370  	  clonedItem.find('span').text("Published: " +formattedDate);
371  	}catch(e){
372  		clonedItem.find('span').text("Published: " +blog.pbdt);
373  	}
374  	  $('#blogsList').append(clonedItem);
375  	 
376  }
377  
378  //Paint categories:  
379  	let middlemenu = $("#blogmiddlemenu");
380  	let parentCatg = $("#parentCategory").val();
381 
382  $( "#blogCategories" ).hide();
383  for (const categ of categories) {
384  	if(categ.bcnp==parentCatg || categ.bcnp==null && parentCatg==''){
385  	
386		middlemenu.append('<a href="'+buildCategoryUrl(categories,categ.bcno)+
387  				 '" class="btn btn-secondary btn-sm"><span>'+categ.desc+'</span></a>');
388		$( "#blogCategories" ).show();
389  	}
390  }
391  
392   hideWait();
393  }
394  
395  function buildCategoryUrl(categories, bcno) {
396      const categoryMap = new Map(categories.map(cat => [cat.bcno, cat]));
397  
398      let path = [];
399      let current = categoryMap.get(bcno);
400  
401      while (current) {
402          path.unshift(current.url);  // Add category name to the beginning
403          current = categoryMap.get(current.bcnp);  // Move to parent
404      }
405  
406      if(path.length>0)
407          return '/blog/' + path.join('/');  // Construct URL path
408      else
409          return '/blog' ;  // Construct URL path
410  }
411

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.