views:

74

answers:

5

I'm trying to implement a requirement that requires I set a maximum line length for the contents of a div element. But when I open the page in Firefox, I get an error about a "long-running script" and am asked to Continue, Debug, or Stop Script. I don't understand why this is happening. This is my code:

    <html>
    <head>
        <script type="text/javascript" src="http://code.jquery.com/jquery-1.4.2.min.js"&gt;&lt;/script&gt;
        <script type="text/javascript">

            $.fn.lineCount = function () {
                var lineHeight = this.css("line-height"); // returns "Xpx"
                return document.getElementById(this.attr("id")).offsetHeight / parseInt(lineHeight.substr(0, lineHeight.length - 2));
            };

            $.fn.truncateLineCount = function (countAfterTruncation) {
                while (this.lineCount() > countAfterTruncation) {
                    var text = this.html();
                    this.html(text.substr(0, text.length - 1) + "&hellip;");
                }
            };

            $(function () {
                $("#title").truncateLineCount(3);
            });
        </script>
    </head>

<body>
 <div id="title">
  My MVC Application<br />
  steaks<br />
  are<br />
  awesome
 </div>
</body>
</html>

What gives?

A: 

within your $.fn's your using this instead of the jQuery $(this).. This could be causing an infinite loop in your while () statement.

pharalia
Nope, in a jQuery plugin ($.fn....), this is the jQuery object so no need for $(this)
Vincent Robert
A: 

I think you're using line-height the wrong way. That property only gives you the height of each line in a paragraph, it's used to measure space between two lines, not to count how many lines you have in your paragraph.

You remove text from the content in your truncateLineCount() but lineCount always has the same value, thus the while cycle is never ending...

P.S. Be careful: truncateLineCount also removes html (char by char), not only text.

mamoo
+1  A: 

The default value for the line-height CSS property is normal. This line:

var lineHeight = this.css("line-height"); // returns "Xpx"

Is actually returning "normal", which your code then attempts to parse into an integer, which yields NaN.

http://www.w3.org/TR/CSS2/visudet.html#propdef-line-height

Aside from that, as others have mentioned, your loop removes 1 character and adds another 8 so it will never get any shorter. You should append &hellip; after the loop ends and your line is short enough:

            while (this.lineCount() > countAfterTruncation) {
                this.html(this.html().slice(0, -1));
            }
            this.html(this.html()+"&hellip;");

As an aside, I feel it necessary to add a few pointers for your code:

  • As I mentioned in the comments, you don't need to snip off the px when parsing a string like "12px" with parseInt().
  • Don't use the var keyword inside a loop, this reinitializes the variable on each iteration which, aside from being bad practice, will throw an error in ECMAScript 5th's strict mode.
  • You can use the slice() method with a negative offset for the second parameter instead of using substring() and passing string length - 1.
  • Instead of document.getElementById(this.attr("id")), you can just use this.get(0). this is already an element wrapped by jQuery, you can access the underlying element using the get() method.
  • If you can help it, don't manipulate html()/innerHTML inside loops. The performance is very poor since it invokes the HTML parser on every iteration of the loop.
Andy E
+1  A: 

I don't think your truncate function works.

At each iteration of your while loop, you are removing 1 character but adding 8 more ("&hellip;").

You may want to add the ellipsis after the loop.

Vincent Robert
+1  A: 
this.html(text.substr(0, text.length - 1) + "&hellip;");

this line increases the charater count. it removes last character, but it adds "&hellip;" to end of the line. so the text will never be truncated.

if your text is My MVC Application, after some while loop, it becomes: My MVC Applicatio................

your loop should be:

while (this.lineCount() > countAfterTruncation) {
    var text = this.html();
    this.html(text.substr(0, text.length - 1));
}
this.html(this.html()+"&hellip;");
feridcelik