Просмотр исходного кода

re-impl blink section header when hash is changed

Yuki Takei 4 лет назад
Родитель
Сommit
899032fabd

+ 6 - 47
packages/app/src/client/legacy/crowi.js

@@ -1,3 +1,5 @@
+const { blinkElem, blinkSectionHeaderAtBoot } = require('../util/blink-section-header');
+
 /* eslint-disable react/jsx-filename-extension */
 require('jquery.cookie');
 
@@ -110,48 +112,6 @@ Crowi.initClassesByOS = function() {
   });
 };
 
-Crowi.findHashFromUrl = function(url) {
-  let match;
-  /* eslint-disable no-cond-assign */
-  if (match = url.match(/#(.+)$/)) {
-    return `#${match[1]}`;
-  }
-  /* eslint-enable no-cond-assign */
-
-  return '';
-};
-
-Crowi.findSectionHeader = function(hash) {
-  if (hash.length === 0) {
-    return;
-  }
-
-  // omit '#'
-  const id = hash.replace('#', '');
-  // don't use jQuery and document.querySelector
-  //  because hash may containe Base64 encoded strings
-  const elem = document.getElementById(id);
-  if (elem != null && elem.tagName.match(/h\d+/i)) { // match h1, h2, h3...
-    return elem;
-  }
-
-  return null;
-};
-
-Crowi.unblinkSelectedSection = function(hash) {
-  const elem = Crowi.findSectionHeader(hash);
-  if (elem != null) {
-    elem.classList.remove('blink');
-  }
-};
-
-Crowi.blinkSelectedSection = function(hash) {
-  const elem = Crowi.findSectionHeader(hash);
-  if (elem != null) {
-    elem.classList.add('blink');
-  }
-};
-
 // window.addEventListener('load', () => {
 //   const { appContainer } = window;
 //   const pageContainer = appContainer.getContainer('PageContainer');
@@ -217,14 +177,13 @@ window.addEventListener('load', () => {
     });
   }
 
-  Crowi.blinkSelectedSection(window.location.hash);
+  blinkSectionHeaderAtBoot();
+
   Crowi.modifyScrollTop();
   Crowi.initClassesByOS();
 });
 
 window.addEventListener('hashchange', (e) => {
-  Crowi.unblinkSelectedSection(Crowi.findHashFromUrl(e.oldURL));
-  Crowi.blinkSelectedSection(Crowi.findHashFromUrl(e.newURL));
   Crowi.modifyScrollTop();
 
   // hash on page
@@ -232,8 +191,8 @@ window.addEventListener('hashchange', (e) => {
     if (window.location.hash === '#edit') {
       Crowi.setCaretLineAndFocusToEditor();
     }
-    else if (window.location.hash === '#hackmd') {
-    }
+    // else if (window.location.hash === '#hackmd') {
+    // }
   }
 });
 

+ 27 - 0
packages/app/src/client/util/blink-section-header.ts

@@ -0,0 +1,27 @@
+let lastBlinkedElem;
+
+export const blinkElem = (elem: HTMLElement): void => {
+  if (lastBlinkedElem != null) {
+    lastBlinkedElem.classList.remove('blink');
+  }
+
+  elem.classList.add('blink');
+  lastBlinkedElem = elem;
+};
+
+export const blinkSectionHeaderAtBoot = (): HTMLElement | undefined => {
+  const { hash } = window.location;
+
+  if (hash.length === 0) {
+    return;
+  }
+
+  // omit '#'
+  const id = hash.replace('#', '');
+  // don't use jQuery and document.querySelector
+  //  because hash may containe Base64 encoded strings
+  const elem = document.getElementById(id);
+  if (elem != null && elem.tagName.match(/h\d+/i)) { // match h1, h2, h3...
+    blinkElem(elem);
+  }
+};

+ 7 - 1
packages/app/src/client/util/smooth-scroll.ts

@@ -14,7 +14,9 @@ export const smoothScrollIntoView = (element: HTMLElement, offsetTop = 0): void
   });
 };
 
-export const addSmoothScrollEvent = (elements: HTMLAnchorElement[]): void => {
+export type SmoothScrollEventCallback = (elem: HTMLElement) => void;
+
+export const addSmoothScrollEvent = (elements: HTMLAnchorElement[], callback?: SmoothScrollEventCallback): void => {
   elements.forEach((link) => {
     const href = link.getAttribute('href');
 
@@ -33,6 +35,10 @@ export const addSmoothScrollEvent = (elements: HTMLAnchorElement[]): void => {
       const targetDom = document.getElementById(elemId);
       if (targetDom != null) {
         smoothScrollIntoView(targetDom, WIKI_HEADER_LINK);
+
+        if (callback != null) {
+          callback(targetDom);
+        }
       }
     });
   });

+ 2 - 1
packages/app/src/components/Page/RevisionRenderer.jsx

@@ -5,6 +5,7 @@ import { withUnstatedContainers } from '../UnstatedUtils';
 import AppContainer from '~/client/services/AppContainer';
 import GrowiRenderer from '~/client/util/GrowiRenderer';
 import { addSmoothScrollEvent } from '~/client/util/smooth-scroll';
+import { blinkElem } from '~/client/util/blink-section-header';
 
 import RevisionBody from './RevisionBody';
 
@@ -46,7 +47,7 @@ class LegacyRevisionRenderer extends React.PureComponent {
 
     const HeaderLink = document.getElementsByClassName('revision-head-link');
     const HeaderLinkArray = Array.from(HeaderLink);
-    addSmoothScrollEvent(HeaderLinkArray);
+    addSmoothScrollEvent(HeaderLinkArray, blinkElem);
 
     const { interceptorManager } = this.props.appContainer;
 

+ 2 - 1
packages/app/src/components/TableOfContents.jsx

@@ -6,6 +6,7 @@ import loggerFactory from '~/utils/logger';
 
 import PageContainer from '~/client/services/PageContainer';
 import { addSmoothScrollEvent } from '~/client/util/smooth-scroll';
+import { blinkElem } from '~/client/util/blink-section-header';
 
 import { withUnstatedContainers } from './UnstatedUtils';
 
@@ -50,7 +51,7 @@ const TableOfContents = (props) => {
   useEffect(() => {
     const tocDom = document.getElementById('revision-toc-content');
     const anchorsInToc = Array.from(tocDom.getElementsByTagName('a'));
-    addSmoothScrollEvent(anchorsInToc);
+    addSmoothScrollEvent(anchorsInToc, blinkElem);
   }, [tocHtml]);
 
   return (