div simulates textarea text box, input text highly adaptive, and realizes word count and limit

Keywords: JSON Vue

Demand:

The text box can be highly adaptive according to the input content, without scroll bar and variable height. I searched a lot and found that textarea can't meet my needs, scrollheight can't get the actual content height (I used the simple one, maybe I wrote the wrong one; I didn't want to do that with a lot of code, trouble...) , so only div can simulate textarea text box.

Using div to simulate textarea text box, the input text is highly adaptive, and word count and limit are realized. When the number of input words exceeds 65, the statistics will turn red. As a prompt, when div loses focus, the word count will be cut to the maximum limit word count 65.

// Can realize the edit of div imitating text box
contenteditable="true"

In fact, the original real-time limit on the number of words users input, that is, when the number of words users input reaches 65, it is not allowed to input again, and the experience will be better. But when I do this, the cursor in the div will run to the front of the Div. when I input again, the words behind will be cut off. I can't get and locate the cursor, so I can only set the number of words to be cut when blur and focus are lost (of course, the acquisition and location of the cursor should be able to be realized, and small partners with needs can try it on their own).

Design sketch:

               

HTML:

<div class="add-doss-retpl">
    <div>Intentional remarks 
        <span class="c-gy">
            <span :class="addTotal > 65 ? 'hx-red' : ''" > {{addTotal}}</span>
            /65
        </span>
    </div>
    <div class="add-doss-foremark" id="add-doss-foremark" @input="addDossInput($event)" 
     @blur="addDossBlur($event)" contenteditable="true"></div>
</div>

CSS: 

 .add-doss-retpl{
    background-color: #fff;
    padding: 10px;
    .add-doss-foremark{
      width:100%;
      margin: 10px 0;
      border:#e1e1e1 solid 1px;
      padding: 10px 8px;
    }
    .hx-red{
      color:red;
    }
  }

 VUE.js:

<script>
  export default {
    data:function(){
      return {
        addInremark:'', // Intentional remarks
        addTotal:0, // Count the number of words in the input box
      }
    },

    activated:function () {
      this.addInremark = (JSON.parse(sessionStorage.getItem('customerComments')) || JSON.parse(sessionStorage.getItem('customerComments'))=='') ? JSON.parse(sessionStorage.getItem('customerComments')) : (this.$route.query.customerComments?this.$route.query.customerComments:'');
     // Initial value of input box
     document.getElementById('add-doss-foremark').innerHTML = this.addInremark;
      this.getAddTotal();  // word count
    },

    watch:{
       // Listen to intent notes (count & & store)
      'addInremark'(){
         this.getAddTotal();
         sessionStorage.setItem('customerComments', JSON.stringify(this.addInremark));
       },
    },

    beforeRouteEnter(to, from, next){
      if (from.name == "dossCustomer" || from.name == "clientDetail" ) {
         sessionStorage.removeItem('customerComments');    
      }
      next();
    },

    methods:{
      // Monitor intent comment input
      addDossInput(e){this.addInremark = e.target.innerHTML;},
    
      // Monitor intent remarks lose focus
      addDossBlur(e){
        if(e.target.innerHTML.length > 65){
          this.addInremark = e.target.innerHTML.slice(0,65);
          let addRe = document.getElementById('add-doss-foremark');
          addRe.innerHTML = this.addInremark;
        }else {
          this.addInremark = e.target.innerHTML;
         }
      },
      // word count
      getAddTotal(){
        this.addTotal = this.addInremark.length;
      }
    }
  }
</script>

      

 

Posted by methyl_blue on Thu, 07 Nov 2019 13:53:55 -0800