TocItem.vue 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. <template>
  2. <section
  3. :uuid="item.uuid"
  4. :level="level"
  5. :type="item.type"
  6. class="tocitem"
  7. :class="{active: isActive, loaded: isLoaded, notitle: noTitle, init_opened: isInitOpened, opened: isOpened}"
  8. >
  9. <component
  10. :is="titlelevel"
  11. v-if="title"
  12. class="toc-title"
  13. :uuid="item.uuid"
  14. :class="{active: isActive, loaded: isLoaded, notitle: noTitle, init_opened: isInitOpened, opened: isOpened}"
  15. >
  16. <a
  17. :href="'/texts/'+editionid+'/'+item.uuid"
  18. :uuid="item.uuid"
  19. @click.prevent="onclick"
  20. @keyup.enter="onclick"
  21. >
  22. {{ title }}
  23. </a>
  24. </component>
  25. <ul
  26. v-if="children.length"
  27. class="toc-list"
  28. :level="level"
  29. :type="item.type"
  30. :class="{init_opened: isInitOpened, opened: isOpened}"
  31. >
  32. <li v-for="child in children" :key="child.uuid">
  33. <TocItem
  34. :item="child"
  35. :level="nextLevel"
  36. :editionid="editionid"
  37. :loadedtextsuuids="loadedtextsuuids"
  38. @onClickTocItem="onClickTocItem"
  39. @onScrollToRef="onScrollToRef"
  40. />
  41. </li>
  42. </ul>
  43. </section>
  44. </template>
  45. <script>
  46. import TocItem from './TocItem'
  47. import { mapState, mapActions } from 'vuex'
  48. export default {
  49. name: 'TocItem',
  50. components: {
  51. TocItem
  52. },
  53. props: {
  54. item: Object,
  55. level: Number,
  56. editionid: String,
  57. loadedtextsuuids: Array
  58. },
  59. data: () => ({
  60. isInitOpened: false,
  61. isOpened: false,
  62. noTitle: false
  63. }),
  64. computed: {
  65. ...mapState({
  66. editionsbyuuid: state => state.Corpus.editionsbyuuid
  67. }),
  68. editionTitle () {
  69. return this.editionsbyuuid[this.editionid].title
  70. },
  71. children () {
  72. // check if children exists and if it is an array
  73. // this shoudn't be necessary
  74. return this.item.children ? Array.isArray(this.item.children) ? this.item.children : [this.item.children] : []
  75. },
  76. title () {
  77. // this shoudn't be necessary
  78. if (this.item.title && Array.isArray(this.item.title)) {
  79. return this.item.title.join(' ')
  80. } else if (this.item.title) {
  81. return this.item.title
  82. } else {
  83. // console.log('TOC no title', this.item)
  84. // return this.item.type
  85. return null
  86. }
  87. },
  88. titlelevel () {
  89. return this.level < 7 ? `h${this.level}` : `span`
  90. },
  91. nextLevel () {
  92. return this.level + 1
  93. },
  94. isActive () {
  95. // console.log('Active', this.$route.params.textid, this.item.uuid)
  96. if (typeof this.$route.params.textid !== 'undefined') {
  97. return this.$route.params.textid === this.item.uuid
  98. } else {
  99. return false
  100. }
  101. },
  102. isLoaded () {
  103. // this is updated when loadedtextsuuids is changing
  104. // but not for isOpened (had to use a watcher + beforeMount)
  105. // don't now why ?
  106. return this.loadedtextsuuids.indexOf(this.item.uuid) !== -1
  107. }
  108. },
  109. watch: {
  110. loadedtextsuuids (n, o) {
  111. // console.log('EdTocItem watch loadedtxtsuuids', o, n)
  112. this.isOpened = this.loadedtextsuuids.some(e => e.indexOf(this.item.uuid) >= 0)
  113. },
  114. isOpened (n, o) {
  115. // console.log('TocItem watch isOpened', o, n)
  116. // if was closed and is opened
  117. if (!o && n) {
  118. this.onOpened()
  119. }
  120. }
  121. },
  122. beforeMount () {
  123. if (typeof this.$route.params.textid !== 'undefined') {
  124. this.isOpened = this.$route.params.textid.indexOf(this.item.uuid) >= 0
  125. }
  126. // if (this.level <= 2 && ['book', 'volume'].indexOf(this.item.type) === -1) {
  127. if (this.level === 1 ||
  128. (this.level === 2 && ['part', 'book', 'volume', 'front', 'body', 'back', 'div'].indexOf(this.item.type) >= 0)
  129. ) {
  130. this.isInitOpened = true
  131. }
  132. if (!this.item.title) {
  133. this.noTitle = true
  134. }
  135. },
  136. methods: {
  137. ...mapActions({
  138. addHistoryItem: 'History/addItem'
  139. }),
  140. onclick (e) {
  141. console.log('clicked on toc text', this.item, e)
  142. this.addHistoryItem({
  143. id: this.editionid,
  144. textid: this.item.uuid,
  145. title: this.item.title,
  146. editionTitle: this.editionTitle
  147. // pages: this.item.pages,
  148. // size: this.item.size
  149. })
  150. this.$emit('onClickTocItem', e.target.getAttribute('uuid'))
  151. },
  152. onClickTocItem (uuid) {
  153. // pass the event to parent
  154. this.$emit('onClickTocItem', uuid)
  155. },
  156. onOpened () {
  157. this.$emit('onScrollToRef', this.item.uuid)
  158. },
  159. onScrollToRef (uuid) {
  160. // pass the event to parent
  161. this.$emit('onScrollToRef', uuid)
  162. }
  163. }
  164. }
  165. </script>
  166. <style lang="scss" scoped>
  167. </style>