jekyll-theme-satellite 1.0.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/assets/js/main.js DELETED
@@ -1,709 +0,0 @@
1
- document.addEventListener('DOMContentLoaded', function(){
2
- // Loading page
3
- window.addEventListener("load", () => {
4
- var load_div = document.querySelector('#loading');
5
-
6
- if(load_div != null){
7
- setTimeout(function(){
8
- load_div.style.transition = '.75s';
9
- load_div.style.opacity = '0';
10
- load_div.style.visibility = 'hidden';
11
- }, 800);
12
- }
13
- });
14
-
15
- // Lazy image loading
16
- var content = document.querySelector('main');
17
-
18
- if (content){
19
- var images = content.querySelectorAll('img');
20
-
21
- images.forEach((img) => {
22
- img.setAttribute('loading', 'lazy');
23
- });
24
- }
25
-
26
- function loadImage(image) {
27
- var i = new Image();
28
-
29
- i.onload = function() {
30
- image.classList.add('lazy-loaded')
31
- image.src = image.dataset.lazySrc
32
- }
33
-
34
- i.onerror = function() {image.classList.add('lazy-error')}
35
- i.src = image.dataset.lazySrc
36
- }
37
-
38
- function onIntersection(entries) {
39
- for (var e in entries) {
40
- if(entries[e].intersectionRatio <= 0) continue
41
- observer.unobserve(entries[e].target) // Stop watching
42
- loadImage(entries[e].target)
43
- }
44
- }
45
-
46
-
47
-
48
- // navigation (mobile)
49
- var siteNav = document.querySelector('#navigation');
50
- var siteContact = document.querySelector('#contact');
51
- var menuButton = document.querySelector("#btn-nav");
52
-
53
- menuButton.addEventListener('click', function() {
54
- if (menuButton.classList.toggle('nav-open')) {
55
- siteNav.classList.add('nav-open');
56
- siteContact.classList.add('contact-open');
57
- } else {
58
- siteNav.classList.remove('nav-open');
59
- siteContact.classList.remove('contact-open');
60
- }
61
- });
62
-
63
- // kept nav opened
64
- var firstNavs = document.querySelectorAll('#nav-first');
65
- var page_path = window.location.pathname.replace(/%20/g, " ");
66
- var page_tree = page_path.split('/');
67
-
68
- Array.prototype.forEach.call(firstNavs, function (nav_first) {
69
- if (page_tree[1] === nav_first.ariaLabel){
70
- nav_first.classList.add('active');
71
-
72
- var secondNavs = nav_first.querySelectorAll('#nav-second');
73
-
74
- Array.prototype.forEach.call(secondNavs, function (nav_second) {
75
- if (page_tree[2] === nav_second.ariaLabel){
76
- nav_second.classList.toggle('active');
77
-
78
- var thirdNavs = nav_second.querySelectorAll('#nav-third');
79
-
80
- Array.prototype.forEach.call(thirdNavs, function (nav_third) {
81
- if (page_tree[3] === nav_third.ariaLabel){
82
- nav_third.classList.toggle('active');
83
- }
84
- });
85
- }
86
- });
87
- }
88
- });
89
-
90
- // navigation (toogle sub-category)
91
- document.addEventListener('click', function(e){
92
- var target = e.target;
93
-
94
- while (target && !(target.classList && target.classList.contains('nav-list-expander'))) {
95
- target = target.parentNode;
96
- }
97
-
98
- if (target) {
99
- e.preventDefault();
100
- var nav_item = target.parentNode;
101
- target.ariaPressed = nav_item.parentNode.classList.toggle('active');
102
- }
103
- });
104
-
105
- document.querySelectorAll('.nav-item').forEach((nav_item) => {
106
- if (nav_item.parentNode.classList.contains('active')){
107
- nav_item.classList.add('selected');
108
- }
109
- else {
110
- nav_item.classList.remove('selected');
111
- }
112
- });
113
-
114
- // tocbot
115
- //var content = document.querySelector('main');
116
-
117
- if (content){
118
- var headings = content.querySelectorAll('h1, h2');
119
- var headingMap = {};
120
-
121
- Array.prototype.forEach.call(headings, function (heading) {
122
- var id = heading.id ? heading.id : heading.textContent.trim().toLowerCase()
123
- .split(' ').join('-').replace(/[\!\@\#\$\%\^\&\*\(\):]/ig, '');
124
-
125
- headingMap[id] = !isNaN(headingMap[id]) ? ++headingMap[id] : 0;
126
-
127
- if (headingMap[id]) {
128
- heading.id = id + '-' + headingMap[id];
129
- } else {
130
- heading.id = id;
131
- }
132
- })
133
-
134
- tocbot.init({
135
- tocSelector: '.toc-board',
136
- contentSelector: '.inner-content',
137
- headingSelector:'h1, h2',
138
- hasInnerContainers: false
139
- });
140
- }
141
-
142
- // link (for hover effect)
143
- if (content){
144
- var links = content.querySelectorAll('a');
145
-
146
- links.forEach((link) => {
147
- link.setAttribute('data-content', link.innerText);
148
- });
149
- }
150
-
151
- // pagination
152
- const paginationNumbers = document.querySelector("#pagination-numbers");
153
- const paginatedList = document.querySelector(".paginated-list");
154
-
155
- if (paginatedList) {
156
- const listItems = paginatedList.querySelectorAll("li");
157
- const nextButton = document.querySelector("#next-button");
158
- const prevButton = document.querySelector("#prev-button");
159
- const pageKey = "pageKey=" + document.URL;
160
-
161
- const paginationLimit = 5;
162
- const pageCount = Math.ceil(listItems.length / paginationLimit);
163
- let currentPage = 1;
164
-
165
- const disableButton = (button) => {
166
- button.classList.add("disabled");
167
- button.setAttribute("disabled", true);
168
- };
169
-
170
- const enableButton = (button) => {
171
- button.classList.remove("disabled");
172
- button.removeAttribute("disabled");
173
- };
174
-
175
- const handlePageButtonsStatus = () => {
176
- if (currentPage === 1) {
177
- disableButton(prevButton);
178
- } else {
179
- enableButton(prevButton);
180
- }
181
-
182
- if (pageCount === currentPage) {
183
- disableButton(nextButton);
184
- } else {
185
- enableButton(nextButton);
186
- }
187
- };
188
-
189
- const handleActivePageNumber = () => {
190
- document.querySelectorAll(".pagination-number").forEach((button) => {
191
- button.classList.remove("active");
192
-
193
- const pageIndex = Number(button.getAttribute("page-index"));
194
-
195
- if (pageIndex == currentPage) {
196
- button.classList.add("active");
197
- }
198
- });
199
- };
200
-
201
- const appendPageNumber = (index) => {
202
- const pageNumber = document.createElement("button");
203
-
204
- pageNumber.className = "pagination-number";
205
- pageNumber.innerHTML = index;
206
- pageNumber.setAttribute("page-index", index);
207
- pageNumber.setAttribute("aria-label", "Page " + index);
208
-
209
- paginationNumbers.appendChild(pageNumber);
210
- };
211
-
212
- const getPaginationNumbers = () => {
213
- for (let i = 1; i <= pageCount; i++) {
214
- appendPageNumber(i);
215
- }
216
- };
217
-
218
- const setCurrentPage = (pageNum) => {
219
- currentPage = pageNum;
220
-
221
- handleActivePageNumber();
222
- handlePageButtonsStatus();
223
-
224
- const prevRange = (pageNum - 1) * paginationLimit;
225
- const currRange = pageNum * paginationLimit;
226
-
227
- listItems.forEach((item, index) => {
228
- item.classList.add("hidden");
229
-
230
- if (index >= prevRange && index < currRange) {
231
- item.classList.remove("hidden");
232
- }
233
- });
234
-
235
- $('html, body').scrollTop(0);
236
- localStorage.setItem(pageKey, currentPage);
237
- };
238
-
239
- window.addEventListener("load", (event) => {
240
- // Load last visited page number
241
- if (event.persisted
242
- || (window.performance && window.performance.navigation.type == 2)) {
243
- currentPage = localStorage.getItem(pageKey);
244
- }
245
-
246
- getPaginationNumbers();
247
- setCurrentPage(currentPage);
248
-
249
- prevButton.addEventListener("click", () => {
250
- setCurrentPage(currentPage - 1);
251
- });
252
-
253
- nextButton.addEventListener("click", () => {
254
- setCurrentPage(currentPage + 1);
255
- });
256
-
257
- document.querySelectorAll(".pagination-number").forEach((button) => {
258
- const pageIndex = Number(button.getAttribute("page-index"));
259
-
260
- if (pageIndex) {
261
- button.addEventListener("click", () => {
262
- setCurrentPage(pageIndex);
263
- });
264
- }
265
- });
266
- });
267
- }
268
-
269
- // code clipboard copy button
270
- async function copyCode(block) {
271
- let code = block.querySelector("code");
272
- let text = code.innerText;
273
-
274
- await navigator.clipboard.writeText(text);
275
- }
276
-
277
- let blocks = document.querySelectorAll("pre");
278
-
279
- blocks.forEach((block) => {
280
- // only add button if browser supports Clipboard API
281
- if (navigator.clipboard) {
282
- let clip_btn = document.createElement("button");
283
- let clip_img = document.createElement("svg");
284
-
285
- clip_btn.setAttribute('title', "Copy Code");
286
- clip_img.ariaHidden = true;
287
-
288
- block.appendChild(clip_btn);
289
- clip_btn.appendChild(clip_img);
290
-
291
- clip_btn.addEventListener("click", async () => {
292
- await copyCode(block, clip_btn);
293
- });
294
- }
295
- });
296
-
297
- // dark mode
298
- let currentTheme = localStorage.getItem('theme');
299
- let isDarkMode = false;
300
-
301
- if (currentTheme === 'dark'){
302
- isDarkMode = true;
303
- document.body.classList.add('dark-theme');
304
-
305
- const moonIcons = document.querySelectorAll(".ico-dark");
306
- const sunIcons = document.querySelectorAll(".ico-light");
307
-
308
- moonIcons.forEach((ico) => {
309
- ico.classList.add('active');
310
- });
311
-
312
- sunIcons.forEach((ico) => {
313
- ico.classList.add('active');
314
- });
315
-
316
- // Disable highlighter default color theme
317
- document.getElementById("highlight-default").disabled=true;
318
- }
319
- else {
320
- isDarkMode = false;
321
- // Disable highlighter dark color theme
322
- document.getElementById("highlight-dark").disabled=true;
323
- }
324
-
325
- const themeButton = document.querySelectorAll("#btn-brightness");
326
-
327
- themeButton.forEach((btn) => {
328
- btn.addEventListener('click', function() {
329
- const moonIcons = document.querySelectorAll(".btn-dark");
330
- const sunIcons = document.querySelectorAll(".btn-light");
331
-
332
- moonIcons.forEach((ico) => {
333
- ico.classList.toggle('active');
334
- });
335
-
336
- sunIcons.forEach((ico) => {
337
- ico.classList.toggle('active');
338
- });
339
-
340
- document.body.classList.toggle('dark-theme');
341
-
342
- if (isDarkMode){
343
- localStorage.setItem('theme', 'default');
344
- // Disable highlighter dark color theme
345
- document.getElementById("highlight-default").disabled=false;
346
- document.getElementById("highlight-dark").disabled=true;
347
- changeGiscusTheme('light');
348
- isDarkMode = false;
349
- }
350
- else {
351
- localStorage.setItem('theme', 'dark');
352
- // Disable highlighter default color theme
353
- document.getElementById("highlight-default").disabled=true;
354
- document.getElementById("highlight-dark").disabled=false;
355
- changeGiscusTheme('noborder_gray');
356
- isDarkMode = true;
357
- }
358
- });
359
- });
360
-
361
- // Initialize/Change Giscus theme
362
- const commentBox = document.getElementById('giscus');
363
-
364
- if (commentBox) {
365
- var giscusUserInfos = [];
366
- var giscusTheme = "light";
367
-
368
- $.getJSON('/giscus.json', function (data) {
369
- giscusUserInfos = data[0];
370
- })
371
- .done(function() {
372
- console.log('getJSON request succeeded! [giscus.json]');
373
-
374
- if (giscusUserInfos.repo === '') return;
375
-
376
- if (currentTheme === 'dark'){
377
- giscusTheme = "noborder_gray";
378
- }
379
-
380
- let giscusAttributes = {
381
- "src": "https://giscus.app/client.js",
382
- "data-repo": giscusUserInfos.repo,
383
- "data-repo-id": giscusUserInfos.repoId,
384
- "data-category": giscusUserInfos.category,
385
- "data-category-id": giscusUserInfos.categoryId,
386
- "data-mapping": "pathname",
387
- "data-reactions-enabled": "1",
388
- "data-emit-metadata": "1",
389
- "data-theme": giscusTheme,
390
- "data-lang": "en",
391
- "crossorigin": "anonymous",
392
- "async": "",
393
- };
394
-
395
- let giscusScript = document.createElement("script");
396
- Object.entries(giscusAttributes).forEach(([key, value]) => giscusScript.setAttribute(key, value));
397
- document.body.appendChild(giscusScript);
398
- })
399
- .fail(function(jqXHR, textStatus, errorThrown) { console.log('getJSON request failed! [giscus.json] ' + textStatus); })
400
- .always(function() { console.log('getJSON request ended! [giscus.json]'); });
401
-
402
- // Giscus IMetadataMessage event handler
403
- function handleMessage(event) {
404
- if (event.origin !== 'https://giscus.app') return;
405
- if (!(typeof event.data === 'object' && event.data.giscus)) return;
406
-
407
- const giscusData = event.data.giscus;
408
-
409
- if (giscusData && giscusData.hasOwnProperty('discussion')) {
410
- $('#num-comments').text(giscusData.discussion.totalCommentCount);
411
- }
412
- else {
413
- $('#num-comments').text('0');
414
- }
415
- }
416
-
417
- window.addEventListener('message', handleMessage);
418
- }
419
-
420
- function changeGiscusTheme(theme) {
421
- const iframe = document.querySelector('iframe.giscus-frame');
422
- if (!iframe) return;
423
-
424
- const message = {
425
- setConfig: {
426
- theme: theme
427
- }
428
- };
429
-
430
- iframe.contentWindow.postMessage({ giscus: message }, 'https://giscus.app');
431
- }
432
-
433
- // search box
434
- const searchButton = document.querySelectorAll("#btn-search");
435
- const cancelButton = document.querySelector('#btn-clear');
436
- const searchPage = document.querySelector("#search");
437
-
438
- if (searchButton) {
439
- searchButton.forEach((btn) => {
440
- btn.addEventListener('click', function() {
441
- searchPage.classList.add('active');
442
- $('#search-input').focus();
443
- });
444
- });
445
- }
446
-
447
- if (searchPage) {
448
- searchPage.addEventListener('click', function(event) {
449
- const searchBar = document.querySelector(".search-box");
450
- var target = event.target;
451
-
452
- if (searchBar.contains(target))
453
- return;
454
-
455
- searchPage.classList.remove('active');
456
- });
457
- }
458
-
459
- var posts = [];
460
-
461
- $.getJSON('/search.json', function (data) {
462
- posts = data;
463
- })
464
- .done(function() {
465
- console.log('getJSON request succeeded! [search.json]');
466
-
467
- // Related Posts
468
- displayRelatedPosts(posts);
469
- })
470
- .fail(function(jqXHR, textStatus, errorThrown) { console.log('getJSON request failed! [search.json] ' + textStatus); })
471
- .always(function() { console.log('getJSON request ended! [search.json]'); });
472
-
473
- $('#search-input').on('keyup', function () {
474
- var keyword = this.value.toLowerCase();
475
- var searchResult = [];
476
-
477
- if (keyword.length > 0) {
478
- $('#search-result').show();
479
- $('#btn-clear').show();
480
- } else {
481
- $('#search-result').hide();
482
- $('#btn-clear').hide();
483
- }
484
-
485
- $('.result-item').remove();
486
-
487
- for (var i = 0; i < posts.length; i++) {
488
- var post = posts[i];
489
-
490
- if (post.title === 'Home' && post.type == 'category') continue;
491
-
492
- if (post.title.toLowerCase().indexOf(keyword) >= 0
493
- || post.path.toLowerCase().indexOf(keyword) >= 0
494
- || post.tags.toLowerCase().indexOf(keyword) >= 0){
495
- searchResult.push(post);
496
- }
497
- }
498
-
499
- if (searchResult.length === 0) {
500
- $('#search-result').append(
501
- '<li class="result-item"><span class="description">There is no search result.</span></li>'
502
- );
503
-
504
- return;
505
- }
506
-
507
- searchResult.sort(function (a, b) {
508
- if (a.type == 'category') return 1;
509
-
510
- return -1;
511
- });
512
-
513
- for (var i = 0; i < searchResult.length; i++) {
514
- var highlighted_path = highlightKeyword(searchResult[i].path, keyword);
515
-
516
- if (highlighted_path === '')
517
- highlighted_path = "Home";
518
-
519
- if (searchResult[i].type === 'post'){
520
- var highlighted_title = highlightKeyword(searchResult[i].title, keyword);
521
- var highlighted_tags = highlightKeyword(searchResult[i].tags, keyword);
522
-
523
- if (highlighted_tags === '')
524
- highlighted_tags = "none";
525
-
526
- $('#search-result').append(
527
- '<li class="result-item"><a href="' +
528
- searchResult[i].url +
529
- '"><table><thead><tr><th><svg class="ico-book"></svg></th><th>' + highlighted_title +
530
- '</th></tr></thead><tbody><tr><td><svg class="ico-folder"></svg></td><td>' + highlighted_path +
531
- '</td></tr><tr><td><svg class="ico-tags"></svg></td><td>' + highlighted_tags +
532
- '</td></tr><tr><td><svg class="ico-calendar"></svg></td><td>' + searchResult[i].date +
533
- '</td></tr></tbody></table></a></li>'
534
- );
535
- }
536
- else {
537
- $('#search-result').append(
538
- '<li class="result-item"><a href="' +
539
- searchResult[i].url +
540
- '"><table><thead><tr><th><svg class="ico-folder"></svg></th><th>' + highlighted_path +
541
- '</th></tr></thead></table></a></li>'
542
- );
543
- }
544
- }
545
- });
546
-
547
- if (cancelButton) {
548
- cancelButton.addEventListener('click', function() {
549
- $('.result-item').remove();
550
- $('#search-input').val("");
551
- $('#btn-clear').hide();
552
- });
553
- }
554
-
555
- function highlightKeyword(txt, keyword) {
556
- var index = txt.toLowerCase().lastIndexOf(keyword);
557
-
558
- if (index >= 0) {
559
- out = txt.substring(0, index) +
560
- "<span class='highlight'>" +
561
- txt.substring(index, index+keyword.length) +
562
- "</span>" +
563
- txt.substring(index + keyword.length);
564
- return out;
565
- }
566
-
567
- return txt;
568
- }
569
-
570
- // Tag EventListener
571
- document.querySelectorAll('.tag-box').forEach(function(tagButton){
572
- tagButton.addEventListener('click', function() {
573
- const contentID = tagButton.getAttribute('contentID');
574
- searchPage.classList.add('active');
575
-
576
- $('#search-input').val(contentID);
577
- $('#search-input').trigger('keyup');
578
- });
579
- });
580
-
581
- // Related Posts
582
- function displayRelatedPosts(pages){
583
- const refBox = document.getElementById('related-box');
584
-
585
- if (!refBox) return;
586
-
587
- var relatedPosts = [];
588
- var currPost = pages.find(obj => {return obj.url === location.pathname});
589
-
590
- let currTags = currPost.tags.split(', ');
591
- let currCategory = currPost.path.split(' > ').pop();
592
-
593
- for (var i = 0; i < pages.length; i++) {
594
- let page = pages[i];
595
-
596
- if (page.type === 'category') continue;
597
-
598
- if (page.title === currPost.title) continue;
599
-
600
- let tags = page.tags.split(', ');
601
- let category = page.path.split(' > ').pop();
602
- let correlationScore = 0;
603
-
604
- for (var j = 0; j < currTags.length; j++){
605
- if (tags.indexOf(currTags[j]) != -1) correlationScore += 1;
606
- }
607
-
608
- if (category === currCategory) correlationScore += 1;
609
-
610
- if (correlationScore == 0) continue;
611
-
612
- relatedPosts.push({
613
- 'title': page.title,
614
- 'date': page.date,
615
- 'category': category,
616
- 'url': page.url,
617
- 'thumbnail': page.image,
618
- 'score': correlationScore
619
- });
620
- }
621
-
622
- relatedPosts.sort(function (a, b) {
623
- if(a.hasOwnProperty('score')){
624
- return b.score - a.score;
625
- }
626
- });
627
-
628
- if (relatedPosts.length == 0){
629
- $('#related-box').hide();
630
- return;
631
- }
632
-
633
- for (var i = 0; i < Math.min(relatedPosts.length, 6); i++){
634
- let post = relatedPosts[i];
635
- let date = '-';
636
- let category = 'No category';
637
-
638
- if (post.date !== '1900-01-01'){
639
- date = new Date(post.date);
640
- date = date.toLocaleString('en-US', {day: 'numeric', month:'long', year:'numeric'});
641
- }
642
-
643
- if (post.category !== '') category = post.category;
644
-
645
- if (post.thumbnail === ''){
646
- post.thumbnail = "/assets/img/thumbnail/empty.jpg";
647
- }
648
-
649
- $('#related-posts').append(
650
- '<li class="related-item"><a href="' + post.url +
651
- '"><img src="' + post.thumbnail +
652
- '"/><p class="category">' + category +
653
- '</p><p class="title">' + post.title +
654
- '</p><p class="date">' + date +
655
- '</p></a></li>'
656
- );
657
- }
658
- }
659
-
660
- // Page Hits
661
- const pageHits = document.getElementById('page-hits');
662
-
663
- if (pageHits) {
664
- const goatcounterCode = pageHits.getAttribute('usercode');
665
- const requestURL = 'https://'
666
- + goatcounterCode
667
- + '.goatcounter.com/counter/'
668
- + encodeURIComponent(location.pathname)
669
- + '.json';
670
-
671
- var resp = new XMLHttpRequest();
672
- resp.open('GET', requestURL);
673
- resp.onerror = function() { pageHits.innerText = "0"; };
674
- resp.onload = function() { pageHits.innerText = JSON.parse(this.responseText).count; };
675
- resp.send();
676
- }
677
-
678
- // Sweat Scroll
679
- const scroller = new SweetScroll({
680
- /* some options */
681
- });
682
-
683
- // Move to Top
684
- if (document.querySelector('.thumbnail')){
685
- const arrowButton = document.querySelector('.top-arrow');
686
-
687
- setInterval(function(){
688
- var scrollPos = document.documentElement.scrollTop;
689
- console.log(scrollPos);
690
-
691
- if (scrollPos < 512){
692
- arrowButton.classList.remove('arrow-open');
693
- }
694
- else {
695
- arrowButton.classList.add('arrow-open');
696
- }
697
- }, 1000);
698
- }
699
-
700
- // Code highlighter
701
- hljs.highlightAll();
702
-
703
- // Disable code highlights to the plaintext codeblocks
704
- document.querySelectorAll('.language-text, .language-plaintext').forEach(function(codeblock){
705
- codeblock.querySelectorAll('.hljs-keyword, .hljs-meta, .hljs-selector-tag').forEach(function($){
706
- $.outerHTML = $.innerHTML;
707
- });
708
- });
709
- });