skip to Main Content

I am trying to record every word from a paragraph of text when it is clicked on. However, I would also like to provide visual feedback to the user when they have clicked on a word. This code has been very helpful. But I don’t seem to be understand how to add a class to it. I’ve marked the areas where my added code is not working:

var book = 'Lorem ipsum dolor sit amet, cu eum eros vitae persequeris, laudem possit nam ex. Labore eloquentiam per an. Sit ex omnesque interpretaris, habeo tantas eos ad, ea eos ludus inciderint. Facete tritani pro ei, vim evertitur liberavisse ex. Ridens indoctum duo cu, est utamur aliquando expetendis ne. Cum nusquam definiebas ex, id esse neglegentur cum, eu libris bonorum volumus vis. Ius et quis omnis graeco, no his nullam perpetua dissentiet. No vix possim scripserit consequuntur, te mnesarchum philosophia sed. Ne mea putent iudicabit, in eam ipsum viris dicunt. Eum amet accommodare ex, sint malis adversarium at qui.'

new Vue({
  el: '#app',
  data: { book: '' },
  methods: {
    doSomething(e) {
      var content = e.target.textContent
      var pos = window.getSelection().anchorOffset
      content = content
        .substring(0, content.indexOf(' ', pos))
        .trim()
      content = content
        .substr(content.lastIndexOf(' ') + 1)
        .replace(/[.,:;!?()+-]/g, '')
        // not working code
        .add('highlight')

      console.log(content)
    }
  },
  created() {
    // load external data
    this.book = book
  }
})
.highlight {
  background-color: yellow;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
  <p @click="doSomething" v-html="book"></p>
</div>

I would like each word to remain highlighted when clicked on. For example, if you click on "Lorem ipsum dolor" all 3 words should be highlighted in yellow. Preferably, if clicked again, they would be unhighlighted too.

2

Answers


  1. Split your text into words using b regex, make each word its own , and then highlight those

    Playground

    <script>
    import { defineComponent } from 'vue'
    
    export default defineComponent({
      data: () => ({
        book: 'Lorem ipsum dolor sit amet, cu eum eros vitae persequeris, laudem possit nam ex. Labore eloquentiam per an. Sit ex omnesque interpretaris, habeo tantas eos ad, ea eos ludus inciderint. Facete tritani pro ei, vim evertitur liberavisse ex. Ridens indoctum duo cu, est utamur aliquando expetendis ne. Cum nusquam definiebas ex, id esse neglegentur cum, eu libris bonorum volumus vis. Ius et quis omnis graeco, no his nullam perpetua dissentiet. No vix possim scripserit consequuntur, te mnesarchum philosophia sed. Ne mea putent iudicabit, in eam ipsum viris dicunt. Eum amet accommodare ex, sint malis adversarium at qui.',
        selectedWord: 'cu'
      }),
      computed: {
        words() {
          // split by `b` - the "word border"
          // [ "Lorem", " ", "ipsum", " ", "dolor", " ", "sit", " ", "amet", ", ", ...]
          return this.book.match(/b.+?b/g)
        }
      },
      methods: {
        select(word) {
          this.selectedWord = word
        },
        isSelected(word) {
          return word.toLowerCase() === this.selectedWord.toLowerCase()
        }
      }
    })
    </script>
    
    <template>
      <input v-model="selectedWord">
      <p>
        <span v-for="w of words" @click="select(w)" :class="{ 'selected-word': isSelected(w) }">
          {{ w }}
        </span>
      </p>
    </template>
    
    <style scoped>
    .selected-word {
      background: yellow;
    }
    </style>
    
    Login or Signup to reply.
  2. I looked at the mentioned stackoverflow answer in your post and came up with the following solution.

    1. Use the solution that adds spans to each word
    2. In the event handler, you can check if there exists any style. For our case, we can check if there is a color property ie event.target.style.color
    3. If it does exist then you know that this has been clicked and you can revert the color to your choice
    4. If it doesn’t exist then you know it’s the first time clicking it and can set the color to your choice
    var page = 'Lorem ipsum dolor sit amet, cu eum eros vitae persequeris, laudem possit nam ex. Labore eloquentiam per an. Sit ex omnesque interpretaris, habeo tantas eos ad, ea eos ludus inciderint. Facete tritani pro ei, vim evertitur liberavisse ex. Ridens indoctum duo cu, est utamur aliquando expetendis ne. Cum nusquam definiebas ex, id esse neglegentur cum, eu libris bonorum volumus vis. Ius et quis omnis graeco, no his nullam perpetua dissentiet. No vix possim scripserit consequuntur, te mnesarchum philosophia sed. Ne mea putent iudicabit, in eam ipsum viris dicunt. Eum amet accommodare ex, sint malis adversarium at qui.'
    
    new Vue({
      el: '#app',
      data: {
        page: ''
      },
      computed: {
        pageContent() {
          return this.page.replace(/b(w+?)b/g, '<span>$1</span>')
        }
      },
      methods: {
        doSomething(e) {
          if (e.target.style.color) {
            //Revert back to black text
            e.target.style = 'color: black;';
          } else {
            //Change text color to yellow
            e.target.style = 'color: yellow;';
          }
          console.log(e.target.textContent);
        }
      },
      created() {
        // load external data
        this.page = page
      }
    })
    <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
    <div id="app">
      <p @click="doSomething" v-html="pageContent"></p>
    </div>
    
    <script src="https://unpkg.com/[email protected]/dist/vue.min.js"></script>

    Note : This code was not thought by me. It was copy-pasted from the above stackoverflow link. Just modified it for the scenario 🙂

    Also, I don’t know jack shit about vue lol

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search