TocItem.vue 5.7 KB

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