Make hash section working

#89
by mishig HF staff - opened
dist/main.bundle.js CHANGED
@@ -5544,14 +5544,133 @@ function _loadFragments() {
5544
  return _loadFragments.apply(this, arguments);
5545
  }
5546
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5547
  ;// ./src/index.js
5548
  // import { plotClusters } from './clusters'
5549
 
5550
 
 
5551
  document.addEventListener("DOMContentLoaded", function () {
5552
  console.log("DOMContentLoaded");
5553
  loadFragments();
5554
  init_memory_plot();
 
5555
  }, {
5556
  once: true
5557
  });
 
5544
  return _loadFragments.apply(this, arguments);
5545
  }
5546
 
5547
+ ;// ./src/syncHFSpacesURLHash.js
5548
+ var queryArg = "section";
5549
+ function syncHFSpacesURLHash() {
5550
+ // Handle explicit section requests (don't update hash automatically on load)
5551
+ var hasExplicitRequest = handleExplicitSectionRequest();
5552
+
5553
+ // Set up hash change monitoring
5554
+ updateHashBasedOnHashChange();
5555
+
5556
+ // Always set up scroll monitoring to update hash during scrolling
5557
+ setupScrollMonitoring();
5558
+
5559
+ // If no explicit request, we don't update the hash on initial load
5560
+ // The hash will only start updating when the user scrolls
5561
+ }
5562
+ function handleExplicitSectionRequest() {
5563
+ // Check for section parameter in URL
5564
+ var urlParams = new URLSearchParams(window.location.search);
5565
+ var sectionId = urlParams.get(queryArg);
5566
+
5567
+ // If we have an explicit section request
5568
+ if (sectionId) {
5569
+ var targetElement = document.getElementById(sectionId);
5570
+ if (targetElement) {
5571
+ // Slight delay to ensure the browser doesn't try to do its own scrolling first
5572
+ setTimeout(function () {
5573
+ targetElement.scrollIntoView();
5574
+ history.replaceState(null, null, "#".concat(sectionId));
5575
+ }, 100);
5576
+ }
5577
+ return true;
5578
+ }
5579
+
5580
+ // No explicit section parameter found
5581
+ return false;
5582
+ }
5583
+ function setupScrollMonitoring() {
5584
+ // Variables to manage throttling
5585
+ var isScrolling = false;
5586
+ var lastKnownScrollPosition = 0;
5587
+ var initialScroll = true;
5588
+
5589
+ // Add the scroll event listener
5590
+ window.addEventListener('scroll', function () {
5591
+ lastKnownScrollPosition = window.scrollY;
5592
+ if (!isScrolling) {
5593
+ window.requestAnimationFrame(function () {
5594
+ // Skip the first scroll event which might be browser's automatic scroll
5595
+ // to a hash on page load
5596
+ if (initialScroll) {
5597
+ initialScroll = false;
5598
+ } else {
5599
+ updateHashBasedOnScroll(lastKnownScrollPosition);
5600
+ }
5601
+ isScrolling = false;
5602
+ });
5603
+ }
5604
+ isScrolling = true;
5605
+ });
5606
+ }
5607
+
5608
+ // Function to update the URL hash based on scroll position
5609
+ function updateHashBasedOnScroll(scrollPosition) {
5610
+ var closestHeading = findClosestHeading(scrollPosition);
5611
+
5612
+ // Update the URL hash if we found a closest element
5613
+ if (closestHeading && closestHeading.id) {
5614
+ // Only update if the hash is different to avoid unnecessary operations
5615
+ if (window.location.hash !== "#".concat(closestHeading.id)) {
5616
+ silentlyUpdateHash(closestHeading.id);
5617
+ postMessageToHFSpaces(closestHeading.id);
5618
+ }
5619
+ }
5620
+ }
5621
+
5622
+ // Find the closest heading to the current scroll position
5623
+ function findClosestHeading(scrollPosition) {
5624
+ // Get only heading elements with IDs that we want to track
5625
+ var headingsWithIds = Array.from(document.querySelectorAll('h1[id], h2[id], h3[id], h4[id], h5[id], h6[id]'));
5626
+
5627
+ // Skip if there are no headings with IDs
5628
+ if (headingsWithIds.length === 0) return null;
5629
+
5630
+ // Find the element closest to the middle of the viewport
5631
+ var closestHeading = null;
5632
+ var closestDistance = Infinity;
5633
+ var viewportMiddle = scrollPosition + window.innerHeight / 2;
5634
+
5635
+ // Iterate through all headings to find the closest one
5636
+ headingsWithIds.forEach(function (heading) {
5637
+ var headingTop = heading.getBoundingClientRect().top + scrollPosition;
5638
+ var distance = Math.abs(headingTop - viewportMiddle);
5639
+ if (distance < closestDistance) {
5640
+ closestDistance = distance;
5641
+ closestHeading = heading;
5642
+ }
5643
+ });
5644
+ return closestHeading;
5645
+ }
5646
+
5647
+ // Update hash without triggering scroll or other side effects
5648
+ function silentlyUpdateHash(id) {
5649
+ history.replaceState(null, null, "#".concat(id));
5650
+ }
5651
+ function updateHashBasedOnHashChange() {
5652
+ window.addEventListener('hashchange', function () {
5653
+ var elementId = window.location.hash.slice(1);
5654
+ postMessageToHFSpaces(elementId);
5655
+ });
5656
+ }
5657
+ function postMessageToHFSpaces(elementId) {
5658
+ var parentOrigin = "https://huggingface.co";
5659
+ window.parent.postMessage({
5660
+ queryString: "".concat(queryArg, "=").concat(elementId)
5661
+ }, parentOrigin);
5662
+ }
5663
+
5664
  ;// ./src/index.js
5665
  // import { plotClusters } from './clusters'
5666
 
5667
 
5668
+
5669
  document.addEventListener("DOMContentLoaded", function () {
5670
  console.log("DOMContentLoaded");
5671
  loadFragments();
5672
  init_memory_plot();
5673
+ syncHFSpacesURLHash();
5674
  }, {
5675
  once: true
5676
  });
dist/main.bundle.js.map CHANGED
The diff for this file is too large to render. See raw diff
 
src/index.js CHANGED
@@ -1,9 +1,11 @@
1
  // import { plotClusters } from './clusters'
2
  import { init_memory_plot } from './memory'
3
  import { loadFragments } from './fragmentLoader'
 
4
 
5
  document.addEventListener("DOMContentLoaded", () => {
6
  console.log("DOMContentLoaded");
7
  loadFragments();
8
  init_memory_plot();
 
9
  }, { once: true });
 
1
  // import { plotClusters } from './clusters'
2
  import { init_memory_plot } from './memory'
3
  import { loadFragments } from './fragmentLoader'
4
+ import { syncHFSpacesURLHash } from './syncHFSpacesURLHash'
5
 
6
  document.addEventListener("DOMContentLoaded", () => {
7
  console.log("DOMContentLoaded");
8
  loadFragments();
9
  init_memory_plot();
10
+ syncHFSpacesURLHash();
11
  }, { once: true });
src/syncHFSpacesURLHash.js ADDED
@@ -0,0 +1,124 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const queryArg = "section";
2
+
3
+ function syncHFSpacesURLHash() {
4
+ // Handle explicit section requests (don't update hash automatically on load)
5
+ const hasExplicitRequest = handleExplicitSectionRequest();
6
+
7
+ // Set up hash change monitoring
8
+ updateHashBasedOnHashChange();
9
+
10
+ // Always set up scroll monitoring to update hash during scrolling
11
+ setupScrollMonitoring();
12
+
13
+ // If no explicit request, we don't update the hash on initial load
14
+ // The hash will only start updating when the user scrolls
15
+ }
16
+
17
+ function handleExplicitSectionRequest() {
18
+ // Check for section parameter in URL
19
+ const urlParams = new URLSearchParams(window.location.search);
20
+ const sectionId = urlParams.get(queryArg);
21
+
22
+ // If we have an explicit section request
23
+ if (sectionId) {
24
+ const targetElement = document.getElementById(sectionId);
25
+ if (targetElement) {
26
+ // Slight delay to ensure the browser doesn't try to do its own scrolling first
27
+ setTimeout(() => {
28
+ targetElement.scrollIntoView();
29
+ history.replaceState(null, null, `#${sectionId}`);
30
+ }, 100);
31
+ }
32
+ return true;
33
+ }
34
+
35
+ // No explicit section parameter found
36
+ return false;
37
+ }
38
+
39
+ function setupScrollMonitoring() {
40
+ // Variables to manage throttling
41
+ let isScrolling = false;
42
+ let lastKnownScrollPosition = 0;
43
+ let initialScroll = true;
44
+
45
+ // Add the scroll event listener
46
+ window.addEventListener('scroll', function() {
47
+ lastKnownScrollPosition = window.scrollY;
48
+
49
+ if (!isScrolling) {
50
+ window.requestAnimationFrame(function() {
51
+ // Skip the first scroll event which might be browser's automatic scroll
52
+ // to a hash on page load
53
+ if (initialScroll) {
54
+ initialScroll = false;
55
+ } else {
56
+ updateHashBasedOnScroll(lastKnownScrollPosition);
57
+ }
58
+ isScrolling = false;
59
+ });
60
+ }
61
+
62
+ isScrolling = true;
63
+ });
64
+ }
65
+
66
+ // Function to update the URL hash based on scroll position
67
+ function updateHashBasedOnScroll(scrollPosition) {
68
+ const closestHeading = findClosestHeading(scrollPosition);
69
+
70
+ // Update the URL hash if we found a closest element
71
+ if (closestHeading && closestHeading.id) {
72
+ // Only update if the hash is different to avoid unnecessary operations
73
+ if (window.location.hash !== `#${closestHeading.id}`) {
74
+ silentlyUpdateHash(closestHeading.id);
75
+ postMessageToHFSpaces(closestHeading.id);
76
+ }
77
+ }
78
+ }
79
+
80
+ // Find the closest heading to the current scroll position
81
+ function findClosestHeading(scrollPosition) {
82
+ // Get only heading elements with IDs that we want to track
83
+ const headingsWithIds = Array.from(document.querySelectorAll('h1[id], h2[id], h3[id], h4[id], h5[id], h6[id]'));
84
+
85
+ // Skip if there are no headings with IDs
86
+ if (headingsWithIds.length === 0) return null;
87
+
88
+ // Find the element closest to the middle of the viewport
89
+ let closestHeading = null;
90
+ let closestDistance = Infinity;
91
+ const viewportMiddle = scrollPosition + window.innerHeight / 2;
92
+
93
+ // Iterate through all headings to find the closest one
94
+ headingsWithIds.forEach(heading => {
95
+ const headingTop = heading.getBoundingClientRect().top + scrollPosition;
96
+ const distance = Math.abs(headingTop - viewportMiddle);
97
+
98
+ if (distance < closestDistance) {
99
+ closestDistance = distance;
100
+ closestHeading = heading;
101
+ }
102
+ });
103
+
104
+ return closestHeading;
105
+ }
106
+
107
+ // Update hash without triggering scroll or other side effects
108
+ function silentlyUpdateHash(id) {
109
+ history.replaceState(null, null, `#${id}`);
110
+ }
111
+
112
+ function updateHashBasedOnHashChange() {
113
+ window.addEventListener('hashchange', () => {
114
+ const elementId = window.location.hash.slice(1);
115
+ postMessageToHFSpaces(elementId);
116
+ });
117
+ }
118
+
119
+ function postMessageToHFSpaces(elementId) {
120
+ const parentOrigin = "https://huggingface.co";
121
+ window.parent.postMessage({ queryString: `${queryArg}=${elementId}` }, parentOrigin);
122
+ }
123
+
124
+ export { syncHFSpacesURLHash };