Browse Source

interaction between texts and toc, alpha version, still buged

Bachir Soussi Chiadmi 4 năm trước cách đây
mục cha
commit
64f38eac6f

+ 14 - 4
assets/css/app.scss

@@ -273,11 +273,17 @@ section[role="main-content"]{
 
     >section{
       div#text{
-        // >h1{
-        //   @include title1blue;
-        // }
+        .infinite-loading-container{
+          height:0;
+          overflow: hidden;
+        }
         div.tei{
-          // >h1{display: none;}
+          border-left: 1px dotted $grisclair;
+          padding-left: 1em;
+          &.active{
+            border-left: 1px dotted $grisfonce;
+          }
+
           >h1{@include title1blue;}
           span.placeName,
           span.objectName,
@@ -329,6 +335,10 @@ section[role="main-content"]{
             &.active,
             &:hover{
               color:$grisfonce;
+              font-weight: 600;
+            }
+            &.loaded{
+              color:$grisfonce;
             }
           }
           h2.toc-title{font-size: 0.882em;}

+ 13 - 0
package-lock.json

@@ -2187,6 +2187,11 @@
         "tweetnacl": "^0.14.3"
       }
     },
+    "bezier-easing": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/bezier-easing/-/bezier-easing-2.1.0.tgz",
+      "integrity": "sha1-wE3+i5JtbsrKGBPWn/F5t8ICXYY="
+    },
     "big.js": {
       "version": "5.2.2",
       "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz",
@@ -11954,6 +11959,14 @@
       "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-3.1.3.tgz",
       "integrity": "sha512-8iSa4mGNXBjyuSZFCCO4fiKfvzqk+mhL0lnKuGcQtO1eoj8nq3CmbEG8FwK5QqoqwDgsjsf1GDuisDX4cdb/aQ=="
     },
+    "vue-scrollto": {
+      "version": "2.18.1",
+      "resolved": "https://registry.npmjs.org/vue-scrollto/-/vue-scrollto-2.18.1.tgz",
+      "integrity": "sha512-JojeVOP1Z50Jt0OCOd61jRRRF8TrNvPAzF4LAKwkTEZnt30mpDd48aDZZOEPD3l6z2PybOyUGFT/FNWfTtFv9w==",
+      "requires": {
+        "bezier-easing": "2.1.0"
+      }
+    },
     "vue-server-renderer": {
       "version": "2.6.10",
       "resolved": "https://registry.npmjs.org/vue-server-renderer/-/vue-server-renderer-2.6.10.tgz",

+ 1 - 0
package.json

@@ -23,6 +23,7 @@
     "vue-infinite-loading": "^2.4.5",
     "vue-meta": "^1.6.0",
     "vue-router": "^3.1.3",
+    "vue-scrollto": "^2.18.1",
     "vuex": "^3.1.1",
     "vuex-router-sync": "^5.0.0"
   },

+ 7 - 2
src/components/Content/EdText.vue

@@ -5,7 +5,9 @@ import Vue from 'vue'
 export default {
   name: 'EdText',
   props: {
-    tei: String
+    tei: String,
+    uuid: String,
+    textid: String
   },
   data: () => ({
     template: null,
@@ -37,7 +39,10 @@ export default {
       this.template.staticRenderFns.map(fn => (this.$options.staticRenderFns.push(fn)))
     },
     buildHtml () {
-      this.html = `<div class="tei">${this.tei}</div>`
+      this.html = `<div` +
+      ` class="tei${this.uuid === this.textid ? ' active' : ''}"` +
+      ` data-uuid="${this.uuid}"` +
+      `>${this.tei}</div>`
       this.parseLinks()
       // console.log('EdText: builded html', this.html)
     },

+ 15 - 3
src/components/Content/EdToc.vue

@@ -5,7 +5,13 @@
         v-for="item in toc"
         :key="item.uuid"
       >
-        <TocItem :item="item" :level="1" :editionid="$route.params.id" />
+        <TocItem
+          :item="item"
+          :level="1"
+          :editionid="$route.params.id"
+          :loadedtextsuuids="loadedtextsuuids"
+          @onClickTocItem="onClickTocItem"
+        />
       </li>
     </ul>
   </section>
@@ -21,11 +27,17 @@ export default {
     TocItem
   },
   props: {
-    toc: Array
+    toc: Array,
+    loadedtextsuuids: Array
   },
   data: () => ({
 
-  })
+  }),
+  methods: {
+    onClickTocItem (uuid) {
+      this.$emit('onClickTocItem', uuid)
+    }
+  }
 }
 </script>
 

+ 27 - 10
src/components/Content/TocItem.vue

@@ -8,7 +8,7 @@
       v-if="title"
       class="toc-title"
       :uuid="item.uuid"
-      :class="{active: isActive}"
+      :class="{active: isActive, loaded: isLoaded}"
     >
       <a
         :href="'/edition/'+editionid+'/'+item.uuid"
@@ -25,7 +25,13 @@
       :class="{opened: isOpened}"
     >
       <li v-for="child in children" :key="child.uuid">
-        <TocItem :item="child" :level="nextLevel" :editionid="editionid" />
+        <TocItem
+          :item="child"
+          :level="nextLevel"
+          :editionid="editionid"
+          :loadedtextsuuids="loadedtextsuuids"
+          @onClickTocItem="onClickTocItem"
+        />
       </li>
     </ul>
   </section>
@@ -43,7 +49,8 @@ export default {
   props: {
     item: Object,
     level: Number,
-    editionid: String
+    editionid: String,
+    loadedtextsuuids: Array
   },
   // data: () => ({
   //
@@ -83,6 +90,9 @@ export default {
       } else {
         return false
       }
+    },
+    isLoaded () {
+      return this.loadedtextsuuids.indexOf(this.item.uuid) !== -1
     }
   },
   // beforeCreate () {
@@ -91,13 +101,20 @@ export default {
   methods: {
     onclick (e) {
       console.log('clicked on toc text', this.editionid, e)
-      this.$router.push({
-        name: `editiontext`,
-        params: {
-          id: this.editionid,
-          textid: e.target.getAttribute('uuid')
-        }
-      })
+      // if (this.$route.params.textid !== e.target.getAttribute('uuid')) {
+      //   this.$router.push({
+      //     name: `editiontext`,
+      //     params: {
+      //       id: this.editionid,
+      //       textid: e.target.getAttribute('uuid')
+      //     }
+      //   })
+      // } else {
+      this.$emit('onClickTocItem', e.target.getAttribute('uuid'))
+      // }
+    },
+    onClickTocItem (uuid) {
+      this.$emit('onClickTocItem', uuid)
     }
   }
 

+ 20 - 1
src/components/Layouts/MainContentLayout.vue

@@ -7,7 +7,7 @@
       <slot name="header" />
     </header>
 
-    <section class="col-6">
+    <section ref="scrollablecenter" class="col-6" @scroll.passive="onScrollCenter">
       <slot />
     </section>
 
@@ -25,6 +25,25 @@ export default {
     id: {
       type: String,
       required: true
+    },
+    reftoscrollto: { type: String }
+  },
+  watch: {
+    reftoscrollto: function (newref, oldref) {
+      console.log('reftoscrollto watcher', oldref, newref)
+      this.scrollToRef()
+    }
+  },
+  methods: {
+    onScrollCenter (e) {
+      // console.log('mainLayout onScrollCenter: e', e)
+      this.$emit('onCenterScrolled', e)
+    },
+    scrollToRef () {
+      console.log('scrollToRef', this.reftoscrollto, this.$refs)
+      this.$scrollTo(this.reftoscrollto, 500, {
+        container: this.$refs.scrollablecenter
+      })
     }
   }
 }

+ 3 - 3
src/index.js

@@ -4,6 +4,7 @@ import store from './store'
 // import { sync } from 'vuex-router-sync'
 import Meta from 'vue-meta'
 import InfiniteLoading from 'vue-infinite-loading'
+import VueScrollTo from 'vue-scrollto'
 
 import App from './App'
 
@@ -20,9 +21,6 @@ Vue.use(InfiniteLoading, {
   slots: {
     noMore: '',
     noResult: ''
-  },
-  system: {
-    throttleLimit: 5000
   }
   // system: {
   //   throttleLimit: 50,
@@ -30,6 +28,8 @@ Vue.use(InfiniteLoading, {
   // }
 })
 
+Vue.use(VueScrollTo)
+
 // sync(store, router) // done. Returns an unsync callback fn
 
 new Vue({

+ 53 - 6
src/pages/Edition.vue

@@ -1,5 +1,5 @@
 <template>
-  <MainContentLayout id="edition">
+  <MainContentLayout id="edition" :reftoscrollto="reftoscrollto" @onCenterScrolled="onCenterScrolled">
     <template v-if="!content" #header>
       <span>Loading ...</span>
     </template>
@@ -32,21 +32,32 @@
     <!-- default slot -->
     <div id="text">
       <template v-if="texts.length">
-        <infinite-loading direction="top" @infinite="prevText" />
+        <infinite-loading
+          v-if="center_scrolled"
+          :identifier="textid"
+          direction="top"
+          :distance="inifinite_load_distance"
+          @infinite="prevText"
+        />
         <EdText
           v-for="text in texts"
+          :ref="text.content.uuid"
           :key="text.content.uuid"
           :tei="text.content.tei"
           :uuid="text.content.uuid"
+          :textid="textid"
           @onHoverLink="onHoverLink"
           @onLeaveLink="onLeaveLink"
         />
-        <infinite-loading @infinite="nextText" />
+        <infinite-loading
+          :identifier="textid"
+          @infinite="nextText"
+        />
       </template>
     </div>
 
     <template #nav>
-      <EdToc :toc="toc" />
+      <EdToc :toc="toc" :loadedtextsuuids="textsuuids" @onClickTocItem="onClickTocItem" />
     </template>
   </MainContentLayout>
 </template>
@@ -79,13 +90,19 @@ export default {
     editionid: null,
     textid: null,
     texts: [],
+    textsuuids: [],
     metainfotitle: undefined,
     title: undefined,
     author: undefined,
     texttitle: undefined,
     //
     indexitem: null,
-    tooltip_top: null
+    tooltip_top: null,
+    //
+    next_loaded: false,
+    center_scrolled: false,
+    inifinite_load_distance: 10,
+    reftoscrollto: null
   }),
   computed: {
     ...mapState({
@@ -97,6 +114,7 @@ export default {
     textid: function (newid, oldid) {
       console.log('textid watcher', this, oldid, newid)
       this.texts = []
+      this.textsuuids = []
       this.getTextContent(newid)
     },
     textdata: function (newtxtdata, oldtxtdata) {
@@ -181,11 +199,14 @@ export default {
           console.log('text REST: data', data)
           if (direction === 'next') {
             this.texts.push(data)
+            this.textsuuids.push(data.content.uuid)
           } else {
             this.texts.unshift(data)
+            this.textsuuids.unshift(data.content.uuid)
           }
           if ($state) {
             $state.loaded()
+            this.next_loaded = true
           }
         })
         .catch((error) => {
@@ -193,6 +214,13 @@ export default {
           Promise.reject(error)
         })
     },
+    onCenterScrolled (e) {
+      // console.log('Edition centerScrolled(e)', e.target.scrollTop)
+      if (!this.center_scrolled && e.target.scrollTop > this.inifinite_load_distance * 1.5) {
+        this.center_scrolled = true
+      }
+      this.indexitem = null
+    },
     nextText ($state) {
       console.log('infinite loading nextText()', this.texts[this.texts.length - 1].content.itemAfterUuid, $state)
       if (this.texts[this.texts.length - 1].content.itemAfterUuid) {
@@ -223,17 +251,36 @@ export default {
       REST.get(`/index${item.index.charAt(0).toUpperCase()}${item.index.slice(1)}/${item.uuid}`, {})
         .then(({ data }) => {
           console.log('index tooltip REST: data', data)
-          this.indexitem = data.content
+          if (this.indexitem === 'loading') {
+            this.indexitem = data.content
+          }
         })
         .catch((error) => {
           console.warn('Issue with index tooltip rest', error)
           Promise.reject(error)
           this.indexitem = null
         })
+    },
+    onClickTocItem (uuid) {
+      console.log('Edition onClickTocItem', uuid, this.$refs)
+      if (this.textsuuids.indexOf(uuid) !== -1) {
+        // if already loaded, scroll to uuid
+        this.reftoscrollto = `.tei[data-uuid="${uuid}"]`
+      } else {
+        // if not already loaded, change route
+        this.$router.push({
+          name: `editiontext`,
+          params: {
+            id: this.editionid,
+            textid: uuid
+          }
+        })
+      }
     }
   }
 }
 </script>
 
 <style lang="scss" scoped>
+
 </style>