Editor.vue 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. <template>
  2. <div class="slide show-mode">
  3. <template v-for="page in pages">
  4. <editing-page-vue :key="page.frontendId" :page="page"></editing-page-vue>
  5. </template>
  6. <div v-show="false">{{ focus }}</div>
  7. </div>
  8. </template>
  9. <script>
  10. import { mapState } from 'vuex'
  11. import EditingPageVue from './EditingPage.vue'
  12. import { USE_FOCUS, INIT_BY_DEFAULT } from '../../store/types/editor-types'
  13. export default {
  14. name: 'editor',
  15. components: {
  16. EditingPageVue
  17. },
  18. computed: {
  19. ...mapState({
  20. items: state => state.editor.items
  21. }),
  22. pages() {
  23. const items = this.$store.state.editor.items
  24. if (items.length === 0) {
  25. this.$nextTick(() => {
  26. this.$store.commit(
  27. INIT_BY_DEFAULT,
  28. this.$store.state.editor.slideInfo
  29. )
  30. })
  31. }
  32. const pages = []
  33. let lastIndex = 0
  34. let times = 0
  35. items.forEach((item, index) => {
  36. if (item.content === '====') {
  37. pages.push({ items: [...items].slice(lastIndex, index + 1) })
  38. lastIndex = index + 1
  39. }
  40. times = index
  41. })
  42. if (times !== items.length) {
  43. const page = { items: [...items].slice(lastIndex) }
  44. pages.push(page)
  45. }
  46. return pages
  47. },
  48. focus() {
  49. const res = this.$store.state.editor.focus
  50. res !== null &&
  51. this.$nextTick(() => {
  52. this.checkFocus()
  53. })
  54. return this.$store.state.editor.focus
  55. }
  56. },
  57. methods: {
  58. checkFocus() {
  59. if (this.focus !== null) {
  60. if (this.focus.focusId) {
  61. this.$nextTick(() => {
  62. const item = document.getElementById(this.focus.focusId)
  63. item.focus()
  64. const offset = this.focus.offset
  65. const computeResult = this.computeContainerAndOffset(item, offset)
  66. const range = document.getSelection().getRangeAt(0)
  67. range.setStart(computeResult.container, computeResult.offset)
  68. range.collapse()
  69. this.$store.commit(USE_FOCUS)
  70. })
  71. }
  72. }
  73. },
  74. computeContainerAndOffset(item, offset) {
  75. // todo test
  76. if (offset === 0) {
  77. return { container: item, offset: 0 }
  78. }
  79. let restOffset = offset
  80. if (item.hasChildNodes()) {
  81. for (const node of item.childNodes) {
  82. if (node.length > restOffset) {
  83. return {
  84. container: node,
  85. offset: restOffset
  86. }
  87. } else {
  88. restOffset -= node.length
  89. }
  90. }
  91. } else {
  92. return { container: item, offset: 0 }
  93. }
  94. // default return value is the end of this element
  95. // notice that when the element is not Text, offset 1 means the end of element
  96. return {
  97. container: item,
  98. offset: 1
  99. }
  100. }
  101. }
  102. }
  103. </script>
  104. <style lang="scss" scoped>
  105. @import '@/common/reset.scss';
  106. @import '@/common/mode-common.scss';
  107. @import '@/common/show-mode.scss';
  108. @import '@/common/read-mode.scss';
  109. </style>