'Limiting the number of characters in a div has specific class

I have some set of div which has a class name. Here I want to control/limit the number of characters to be displayed in the div based on the class name using JavaScript. How can I fix this?



Solution 1:[1]

Use the substring() method in JavaScript. Details on usage are in JavaScript String substring().

If you are using jQuery, select by the class and run the sub string method.

Solution 2:[2]

A version that honours existing child elements

I came across this Q&A, but I was looking for something that would handle child elements correctly, rather than just a sub-string slice. For those that may need this, here is what I put together.

Basically it recursively steps through child elements, clones and appends them to a new container — all the while totaling up the number of "words" it finds (i.e., text content split by spaces).

http://jsfiddle.net/D8LEx/2/

Once it reaches its word limit, it will stop processing/appending new nodes. If the content of the final text node will breach the word limit, the node's text value is sliced to meet the requirement.

The code expects the class name provided to be the containing element of mainly text nodes with some other elements mixed in. For example, wrapping-element would be the element to target:

<p class="wrapping-element">
  Rude alert! An electrical fire has knocked out my voice-recognition unicycle!
  Many Wurlitzers are <strong>missing from my database!</strong>
  <a href="#shop">Abandon shop!</a>
  This is not a <i>daffodil!</i>
</p>

The code

I've tried to keep this a succinct as possible. It works in all modern browsers — mainly those that support getElementsByClassName and cloneNode:

var wordlimit = (function(){
  var clonempty = function( elm ){
    var doppel = elm.cloneNode();
        doppel.innerHTML = '';
    return doppel;
  };
  var wordsmith = function( elm, out, opts ){
    var i, l, kids = elm.childNodes, kid, txt, wrd, tnd;
    for (i=0, l=kids.length; i<l && opts && opts.limit; i++) {
      if ( (kid = kids[i]) && kid.nodeType === 1 ) {
        wordsmith( kid, out.appendChild( clonempty(kid) ), opts );
      }
      else if ( kid && kid.nodeType === 3 ) {
        txt = kid.nodeValue;
        wrd = txt.replace(/^\s+|\s+$/g, '').split(' ');
        if ( wrd.length >= opts.limit ) {
          tnd = document.createTextNode( wrd.slice(0, opts.limit).join(' ') );
          out.appendChild( tnd );
          opts.limit -= wrd.length;
          if ( opts.limit < 0 && opts.ellipsis ) {
            out.appendChild( document.createTextNode('...') );
          }
          opts.limit = 0;
        }
        else {
          opts.limit -= wrd.length;
          out.appendChild( document.createTextNode(txt) );
        }
      }
    }
    return out;
  }
  return function(classname, limit, ellipsis){
    var i, l, elms = document.getElementsByClassName(classname), elm, out;
    for (i=0, l=elms.length; i<l; i++) {
      elm = elms[i];
      out = wordsmith( elm, clonempty(elm), {
        limit: limit,
        ellipsis: ellipsis
      });
      elm.parentNode.insertBefore( out, elm );
      elm.parentNode.removeChild( elm );
    }
  };
})();

Usage

To call it is quite simply:

wordlimit(class-name :string, word-limit :int, add-ellipsis :boolean)

So:

wordlimit('wrapping-element', 40, true)

Disclaimer

The above could be improved to support complex CSS selectors, or just allow the provision of the actual element(s) to work with. The current version does support multiple elements with the specified class name.

Please note: This code will remove the original element, and replace with a newly fashioned clone. Because the code relies on cloneNode, any event listeners that are already in place will be lost, as per this snippet from the linked MDN page:

Cloning a node copies all of its attributes and their values, including intrinsic (in–line) listeners. It does not copy event listeners added using addEventListener() or those assigned to element properties (e.g. node.onclick = fn).

It goes without saying that any existing live element references to the elements being modified by this code will also be broken. [Why mention it then? Ed.]

I had no need to worry about keeping the existing elements, but if you require this it should be quite simple to rewrite the code to work on existing elements; rather than clone and destroy.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Peter Mortensen
Solution 2 Peter Mortensen