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

Merge pull request #1745 from weseek/support/1345-reimpl-toc-slimscroll

Support/1345 reimpl toc slimscroll
Yuki Takei 6 лет назад
Родитель
Сommit
d7ac95f4e4

+ 1 - 0
config/logger/config.dev.js

@@ -33,4 +33,5 @@ module.exports = {
   'growi:app': 'debug',
   'growi:services:*': 'debug',
   // 'growi:StaffCredit': 'debug',
+  // 'growi:TableOfContents': 'debug',
 };

+ 1 - 0
package.json

@@ -231,6 +231,7 @@
     "sass-loader": "^8.0.0",
     "simple-load-script": "^1.0.2",
     "socket.io-client": "^2.0.3",
+    "sticky-events": "^3.1.3",
     "style-loader": "^1.0.0",
     "stylelint": "^13.2.0",
     "stylelint-config-recess-order": "^2.0.1",

+ 1 - 1
resource/cdn-manifests.js

@@ -3,7 +3,7 @@ module.exports = {
     {
       name: 'basis',
       // eslint-disable-next-line max-len
-      url: 'https://cdn.jsdelivr.net/combine/npm/emojione@3.1.2,npm/jquery@3.4.0,npm/popper.js@1.15.0,npm/bootstrap@4.4.1/dist/js/bootstrap.min.js,npm/scrollpos-styler@0.7.1',
+      url: 'https://cdn.jsdelivr.net/combine/npm/emojione@3.1.2,npm/jquery@3.4.0,npm/popper.js@1.15.0,npm/bootstrap@4.4.1/dist/js/bootstrap.min.js,npm/scrollpos-styler@0.7.1,npm/jquery-slimscroll@1.3.8/jquery.slimscroll.min.js',
       groups: ['basis'],
       args: {
         integrity: '',

+ 47 - 24
src/client/js/components/TableOfContents.jsx

@@ -1,15 +1,19 @@
 import React from 'react';
 import PropTypes from 'prop-types';
+import loggerFactory from '@alias/logger';
 
 import { withTranslation } from 'react-i18next';
 
 import { debounce } from 'throttle-debounce';
+import StickyEvents from 'sticky-events';
 
 import AppContainer from '../services/AppContainer';
 import PageContainer from '../services/PageContainer';
 
 import { createSubscribedElement } from './UnstatedUtils';
 
+const logger = loggerFactory('growi:TableOfContents');
+
 // get these value with
 //   document.querySelector('.revision-toc').getBoundingClientRect().top
 const DEFAULT_REVISION_TOC_TOP_FOR_GROWI_LAYOUT = 190;
@@ -27,37 +31,54 @@ class TableOfContents extends React.Component {
   constructor(props) {
     super(props);
 
+    this.init = this.init.bind(this);
     this.resetScrollbarDebounced = debounce(100, this.resetScrollbar);
+
+    const { layoutType } = this.props.appContainer.config;
+
+    this.defaultRevisionTocTop = DEFAULT_REVISION_TOC_TOP_FOR_GROWI_LAYOUT;
+    if (layoutType === 'kibela') {
+      this.defaultRevisionTocTop = DEFAULT_REVISION_TOC_TOP_FOR_KIBELA_LAYOUT;
+    }
+  }
+
+  componentDidMount() {
+    this.init();
+    this.resetScrollbar();
   }
 
   componentDidUpdate() {
+    this.resetScrollbar();
+  }
+
+  init() {
     const { layoutType } = this.props.appContainer.config;
     if (layoutType === 'crowi') {
       return;
     }
 
-    let defaultRevisionTocTop = DEFAULT_REVISION_TOC_TOP_FOR_GROWI_LAYOUT;
-    if (layoutType === 'kibela') {
-      defaultRevisionTocTop = DEFAULT_REVISION_TOC_TOP_FOR_KIBELA_LAYOUT;
-    }
-
-    // initialize
-    this.resetScrollbar(defaultRevisionTocTop);
-
     /*
      * set event listener
      */
     // resize
     window.addEventListener('resize', (event) => {
-      this.resetScrollbarDebounced(defaultRevisionTocTop);
+      this.resetScrollbarDebounced(this.defaultRevisionTocTop);
+    });
+
+    // sticky
+    // See: https://github.com/ryanwalters/sticky-events
+    const stickyEvents = new StickyEvents({
+      stickySelector: '#revision-toc',
     });
-    // affix on
-    $('#revision-toc').on('affixed.bs.affix', () => {
-      this.resetScrollbar(this.getCurrentRevisionTocTop());
+    const { stickySelector } = stickyEvents;
+    const elem = document.querySelector(stickySelector);
+    elem.addEventListener(StickyEvents.STUCK, (event) => {
+      logger.debug('StickyEvents.STUCK detected');
+      this.resetScrollbar();
     });
-    // affix off
-    $('#revision-toc').on('affixed-top.bs.affix', () => {
-      this.resetScrollbar(defaultRevisionTocTop);
+    elem.addEventListener(StickyEvents.UNSTUCK, (event) => {
+      logger.debug('StickyEvents.UNSTUCK detected');
+      this.resetScrollbar(this.defaultRevisionTocTop);
     });
   }
 
@@ -67,29 +88,31 @@ class TableOfContents extends React.Component {
     return revisionTocElem.getBoundingClientRect().top;
   }
 
-  resetScrollbar(revisionTocTop) {
+  resetScrollbar(defaultRevisionTocTop) {
     const tocContentElem = document.querySelector('.revision-toc .markdownIt-TOC');
 
     if (tocContentElem == null) {
       return;
     }
 
+    const revisionTocTop = defaultRevisionTocTop || this.getCurrentRevisionTocTop();
     // window height - revisionTocTop - .system-version height
     const viewHeight = window.innerHeight - revisionTocTop - 20;
 
     const tocContentHeight = tocContentElem.getBoundingClientRect().height + 15; // add margin
 
+    logger.debug('viewHeight', viewHeight);
+    logger.debug('tocContentHeight', tocContentHeight);
+
     if (viewHeight < tocContentHeight) {
-      // FIXME: GW-1345
-      // $('#revision-toc-content').slimScroll({
-      //   railVisible: true,
-      //   position: 'right',
-      //   height: viewHeight,
-      // });
+      $('#revision-toc-content').slimScroll({
+        railVisible: true,
+        position: 'right',
+        height: viewHeight,
+      });
     }
     else {
-      // FIXME: GW-1345
-      // $('#revision-toc-content').slimScroll({ destroy: true });
+      $('#revision-toc-content').slimScroll({ destroy: true });
     }
   }
 

+ 0 - 1
src/client/styles/scss/_layout.scss

@@ -87,7 +87,6 @@ header {
 }
 
 .revision-toc {
-  max-width: 250px;
   overflow: hidden;
   font-size: 0.9em;
 

+ 1 - 1
src/client/styles/scss/_layout_growi.scss

@@ -21,7 +21,7 @@
   .revision-toc {
     position: sticky;
     top: calc(46px + 5px);
-    min-width: calc(#{100 / 12 * 2%} - #{$grid-gutter-width}); // width of 2column - padding
+    min-width: 100%;
     margin-top: 5px;
 
     .revision-toc-content {

+ 1 - 1
src/client/styles/scss/_layout_kibela.scss

@@ -104,7 +104,7 @@ body.kibela {
     position: sticky;
     top: calc(60px + 5px);
     right: 10rem;
-    min-width: calc(#{100 / 12 * 2%} - #{$grid-gutter-width}); // width of 2column - padding
+    min-width: 100%;
     margin-top: 40px;
 
     .revision-toc-content {

+ 5 - 0
yarn.lock

@@ -12690,6 +12690,11 @@ stealthy-require@^1.1.1:
   resolved "https://registry.yarnpkg.com/stealthy-require/-/stealthy-require-1.1.1.tgz#35b09875b4ff49f26a777e509b3090a3226bf24b"
   integrity sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=
 
+sticky-events@^3.1.3:
+  version "3.1.3"
+  resolved "https://registry.yarnpkg.com/sticky-events/-/sticky-events-3.1.3.tgz#7b6b4091988b87b9f4e711c7c6532de07ab156dd"
+  integrity sha512-nTm2bDaYTXFHAyQS59mWDRnnno/D8oj3C4JddOdipq6ZRnLLqjj+PeyCSbHPwMVdfvQoKwmMmAztp+YybDhvtA==
+
 stream-browserify@^2.0.1:
   version "2.0.1"
   resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.1.tgz#66266ee5f9bdb9940a4e4514cafb43bb71e5c9db"