0

I am working on creating a WordPress plugin to snip overflowing multiline text and add "...". It's pretty basic for now, but I am using some for loops and am just wondering if this is the most efficient way to go about doing this without clogging resources.

(function($) {
//Praveen Prasad "HasScrollBar" function adapted http://stackoverflow.com/questions/7341865/checking-if-jquery-is-loaded-using-javascript
$.fn.hasOverflow = function() {
    var elm = $(this);
    var hasOverflow = false; 
    if ( elm.clientHeight < elm.scrollHeight ) {
        hasOverflow = true;
    }
    return hasOverflow;
}
//http://www.mail-archive.com/discuss@jquery.com/msg04261.html
jQuery.fn.reverse = [].reverse;

$(document).ready( function() {

    if (  $('.' + snipClass).length > 0 ) {

        var count = 0;

        for (var i = 0; i < 10000; i++) {
            $('.' + snipClass).each( function () {

                var el = this;

                //Check for overflows
                if ( el.clientHeight < el.scrollHeight) {
                    if ($(this).children().length > 0) { //Handle child elements
                        $("> *", this).reverse().each( function () {
                            for (var j = 0; j < 10000; j++) {  
                                if ( $(this).text() != "" && el.clientHeight < el.scrollHeight ) {
                                    $(this).text($(this).text().substring(0,$(this).text().length - 1));
                                } else {
                                    break;
                                }
                            }  
                        });   
                    } else { //Handle elements with no children
                        $(this).text($(this).text().substring(0,$(this).text().length - 1));
                    }
                } else { //Add '...'
                    count++;
                }

            });

            //Add ... once finished
            if ( count >= $('.' + snipClass).length) {
                $('.' + snipClass).each( function () {
                    var el = this;
                    if ($(this).children().length > 0) { //Handle child elements
                            $("> *", this).reverse().each( function () {
                               if ( $(this).text() != "" ) {
                                   $(this).text($(this).text().substring(0, $(this).text().length - 3) + "...");
                               }
                            });
                        } else { //Handle elements with no children
                            $(this).text($(this).text().substring(0, $(this).text().length - 3) + "...");
                        }
                });
                    break;
            }

        }  
    }
});
}(jQuery));

Brief explanation: "snipClass" is the value from the textfield in the plugin's settings page. If the element in question has a wrapper that is say 200px, but its text overflows it, I keep trimming text letter by letter until it doesn't overflow anymore. I opted to go with for loops rather than intervals, because even with 1s intervals, you could see the text getting removed letter by letter, and it's much faster with the for loop. If the wrapper has any direct children (maybe a tag with

elements), my plugin goes in reverse order to snip text from them until there is no overflow.

Jordan Carter
  • 1,276
  • 3
  • 19
  • 43
  • 1
    If you're looking to improve efficiency, maybe start by caching the result of evaluating jQuery expressions. For example, you call `$(this).text()` ten times. – gyre Dec 11 '16 at 23:50
  • Comparing to `> 0` is seldom required with jQuery as the result is normally 0 or non-zero so if `$('.' + snipClass).length > 0)` becomes just `if ($('.' + snipClass).length)` – iCollect.it Ltd Dec 11 '16 at 23:55
  • You also pass `jQuery` as `$` via your IIFE but still reference jQuery inside the IIFE. – iCollect.it Ltd Dec 11 '16 at 23:56
  • `$(document).ready( function(){...})` is normally replaced with the shorter `$(function(){..})` – iCollect.it Ltd Dec 11 '16 at 23:57
  • As @gyre states you keep reselecting elements and values. For starts `var el = this;` could become `var $el = $(this);` then `var text = $el.text()` – iCollect.it Ltd Dec 11 '16 at 23:58
  • @JordanCarter, this probably belongs on [Code Review](https://codereview.stackexchange.com/) rather than SO. – gyre Dec 12 '16 at 00:21

0 Answers0