You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

113 lines
2.8 KiB

  1. <template>
  2. <div class="highlight-container highlight-container--bottom-labels" @mouseup="open">
  3. <entity-item v-for="(chunk, i) in chunks" :key="i" :content="chunk.text" :label="chunk.label" :color="chunk.color" />
  4. </div>
  5. </template>
  6. <script>
  7. import EntityItem from '~/components/EntityItem'
  8. export default {
  9. components: {
  10. EntityItem
  11. },
  12. props: {
  13. content: {
  14. type: String,
  15. default: '',
  16. required: true
  17. },
  18. labels: {
  19. type: Array,
  20. default: () => ([]),
  21. required: true
  22. },
  23. entities: {
  24. type: Array,
  25. default: () => ([]),
  26. required: true
  27. }
  28. },
  29. computed: {
  30. sortedEntities() {
  31. return this.entities.slice().sort((a, b) => a.start_offset - b.start_offset)
  32. },
  33. chunks() {
  34. const chunks = []
  35. const entities = this.sortedEntities
  36. let startOffset = 0
  37. for (const entity of entities) {
  38. // add non-entities to chunks.
  39. chunks.push({
  40. label: null,
  41. color: null,
  42. text: this.content.slice(startOffset, entity.start_offset)
  43. })
  44. startOffset = entity.end_offset
  45. // add entities to chunks.
  46. const label = this.labelObject[entity.label]
  47. chunks.push({
  48. label: label.name,
  49. color: label.color,
  50. text: this.content.slice(entity.start_offset, entity.end_offset)
  51. })
  52. }
  53. // add the rest of text.
  54. chunks.push({
  55. label: null,
  56. color: null,
  57. text: this.content.slice(startOffset, this.content.length)
  58. })
  59. return chunks
  60. },
  61. labelObject() {
  62. const obj = {}
  63. for (const label of this.labels) {
  64. obj[label.id] = label
  65. }
  66. return obj
  67. }
  68. },
  69. methods: {
  70. open() {
  71. let selection
  72. // Modern browsers.
  73. if (window.getSelection) {
  74. selection = window.getSelection()
  75. } else if (document.selection) {
  76. selection = document.selection
  77. }
  78. // If something is selected.
  79. if (selection.rangeCount > 0) {
  80. const range = selection.getRangeAt(0)
  81. const preSelectionRange = range.cloneRange()
  82. preSelectionRange.selectNodeContents(this.$el)
  83. preSelectionRange.setEnd(range.startContainer, range.startOffset)
  84. const start = [...preSelectionRange.toString()].length
  85. const end = start + [...range.toString()].length
  86. alert(start + ' ' + end)
  87. return end
  88. }
  89. }
  90. }
  91. }
  92. </script>
  93. <style scoped>
  94. .highlight-container.highlight-container--bottom-labels {
  95. align-items: flex-start;
  96. }
  97. .highlight-container {
  98. line-height: 42px!important;
  99. display: flex;
  100. flex-wrap: wrap;
  101. white-space: pre-wrap;
  102. cursor: default;
  103. }
  104. .highlight-container.highlight-container--bottom-labels .highlight.bottom {
  105. margin-top: 6px;
  106. }
  107. </style>