当我想在多个textareas上加上字数限制上限时,我怎么不重复自己?

时间:2013-08-05 17:02:42

标签: javascript jquery dry

JSFiddle:http://jsfiddle.net/qPvch/62/

我在一个页面中有两个文本框。我希望第一个单词限制上限为5,第二个单词限制上限为6。

HTML:

<textarea name="what" id="five" rows="1" placeholder="limit 5 words"></textarea>
<div class="word_count_5">
Word count: <span>0</span>
</div> 

<textarea name="what" id="six" rows="1" placeholder="limit 6 words"></textarea>
<div class="word_count_6">
Word count: <span>0</span>
</div>  

JQuery的:

var maxWords1 = 5;
jQuery('textarea#five').keypress(function() {
var $this, wordcount;
$this = $(this);
wordcount = $this.val().split(/\b[\s,\.-:;]*/).length;
if (wordcount > maxWords1) {
    jQuery(".word_count_5 span").text("" + maxWords1);
    return false;
  } else {
    return jQuery(".word_count_5 span").text(wordcount);
}
});

var maxWords2 = 6; //REPEATING MYSELF
jQuery('textarea#six').keypress(function() {
var $this, wordcount;
$this = $(this);
wordcount = $this.val().split(/\b[\s,\.-:;]*/).length;
if (wordcount > maxWords2) {
    jQuery(".word_count_6 span").text("" + maxWords2);
    return false;
  } else {
    return jQuery(".word_count_6 span").text(wordcount);
}
});

3 个答案:

答案 0 :(得分:1)

这是一个可能的解决方案。限制只写一次。

HTML:

<textarea name="what" id="five" rows="1" data-limit=5></textarea>
<div class="word_count">
Word count: <span>0</span>
</div> 

<textarea name="what" id="six" rows="1" data-limit=6></textarea>
<div class="word_count">
Word count: <span>0</span>
</div>  

JavaScript:

$('textarea[data-limit]').each(function() {
  var $this=$(this), limit = $this.data('limit');
  $this.attr('placeholder', 'limit '+limit+' words');
  $this.keypress(function(){
     var wordcount = $this.val().split(/\b[\s,\.-:;]*/).length;
     $this.next('.word_count').text(Math.min(wordcount, limit));
     return wordcount<=limit;
  });
});

Demonstration

答案 1 :(得分:1)

将wordcount处理移到一个单独的函数中,并将最大字数传递给它

function checkWordcount($this, maxwords) {
    wordcount = $this.val().split(/\b[\s,\.-:;]*/).length;
    if (wordcount > maxwords) {
        jQuery(".word_count_" + maxwords + " span").text("" + maxwords);
        return false;
      } else {
        return jQuery(".word_count_" + maxwords + " span").text(wordcount);
    }
}

var maxWords1 = 5;
jQuery('textarea#five').keypress(function() {
    var $this, wordcount;
    $this = $(this);
    return checkWordcount($this, maxWords1);
});

答案 2 :(得分:0)

我知道这已经得到了回答,但是我认为我会把这个问题发给其他可能冒出来的人。

请参见下面和codepen.io上的演示:

'use strict';

let WordLimiter = function(el){

  el.constraints = {

    /**
     * Events to listen to
     */
    eventListeners: [
        'keyup',
        'input'
    ],

    events: {
      onWordLimiterCount: new CustomEvent('onWordLimiterCount',{
        detail: {
           value: 0,
           words: []
        }
      })
    },

    limit: null,
    validValue: '',

    /**
     * Checks if the
     * @returns {boolean}
     */
    passed: function(){
      return this.wordCount() <= this.getLimit();
    },

    /**
     * Check if the element has a valid limit
     * @returns {boolean}
     */
    hasLimit: function(){
      return false !== this.getLimit();
    },

    getLimit: function(){
      this.limit = parseInt( this.element.dataset.wordLimit );
      this.limit = isNaN( this.limit ) || this.limit <= 0 ? false : this.limit;
      return this.limit;
    },

    getWords: function(){
      this.words = this.element.value.split(' ');

      /**
       * Removes words that are just empty strings
       */
      this.words = this.words.filter(function (el) {
        return el !== null && el.trim() !== '';
      });
      return this.words;
    },

    /**
     * Gets the word count
     * Also triggers an event that you can hook into
     * @returns {number}
     */
    wordCount: function(){
      this.events.onWordLimiterCount.detail.words = this.getWords();
      this.events.onWordLimiterCount.detail.value = this.getWords().length;
      document.dispatchEvent(this.events.onWordLimiterCount );
      return this.events.onWordLimiterCount.detail.value;
    },

    /**
     * Checks constraints
     * @returns {boolean}
     */
    verify: function(){
      console.clear();

      if( !this.constraints.passed() ){
        console.info( 'FAILED' );

        /**
         * Prevent any further input
         */
        event.preventDefault();
        event.stopPropagation();

        /**
         * Revert back to the last valid input
         * @type {string}
         */
        this.value = this.constraints.validValue;
        return false;
      }

      console.info( 'PASS' );
      this.constraints.validValue = this.value;
      return true;
    },

    /**
     * Scope purposes
     */
    element: el,
  };


  if( !el.constraints.hasLimit() ){
    console.groupCollapsed( 'TextArea does not have a valid limit' );
    console.info( el );
    console.groupEnd();
    return;
  }

  el.constraints.eventListeners.forEach(function(e){
    el.addEventListener(e, el.constraints.verify );
  });

};

/**
 * Looks for all textarea elements with the data-word-limit attribute
 */
document.addEventListener("DOMContentLoaded", function(){
  let textAreas = document.querySelectorAll("textarea[data-word-limit]");

  textAreas.forEach(function(i){
    new WordLimiter(i);
  });

}, true );

let CodePenDemo = {

  init: function(){
    document.addEventListener( 'onWordLimiterCount', function(e){
      document.getElementById('counter').value = e.detail.value;
    })
  },

  setWordLimit: function(){
    document.getElementById('textarea-limited').setAttribute( 'data-word-limit', event.srcElement.value );
  }
};

CodePenDemo.init();
<html>
<head>
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
	<script src="index.js"></script>
</head>
<body class="bg-light">
    <div class="container my-3">
        <h2>TextArea with Word Limit</h2>

        <div class="form-group">
            <label for="word-limit">Word Limit</label>
            <input id="word-limit" type="number" min="1" class="form-control" value="50" onchange="CodePenDemo.setWordLimit();"/>
        </div>
        
        <div class="form-group">
            <label for="textarea-limited">TextArea</label>
            <textarea id="textarea-limited" class="form-control" data-word-limit="50" rows="10" cols="20"></textarea>
        </div>
        
        <div class="form-group">
            <label for="counter">Words Count</label>
            <input type="number" id="counter" class="form-control" />
        </div>
    </div>
</body>
</html>