TocItem.vue 5.6 KB

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