﻿var TextRuler = function() {
    var RulerID = "TextRuler_" + Math.random();
    var MaxLength = 0;
    var MaxHeight = 0;
    var FailsafeCount = 250;

    var Ellipsis = "...";

    var Lines = 1;

    this.SetLines = function(value) {
        Lines = value;
    }

    TextRuler.prototype.SetEllipsis = function(value) {
        if (value) {
            Ellipsis = value;
        }
    }

    this.TestLength = function(text, container, HTMLContainer, family, size, style, weight) {
        if (HTMLContainer) {
            if (!document.getElementById(HTMLContainer.id)) {
                var TempDiv = document.createElement("div");
                TempDiv.style.position = "absolute";
                TempDiv.style.top = "-1000px";
                TempDiv.style.left = "-1000px";
                TempDiv.style.visibility = "hidden";

                TempDiv.id = RulerID + "_" + HTMLContainer.id;

                TempDiv.appendChild(HTMLContainer);
                document.body.appendChild(TempDiv);

                if (!family) {
                    if (HTMLContainer.style.fontFamily) {
                        family = HTMLContainer.style.fontFamily;
                    }
                    else if (HTMLContainer.currentStyle) {
                        family = HTMLContainer.currentStyle.fontFamily;
                    }
                }

                if (!size) {
                    if (HTMLContainer.style.fontSize) {
                        size = HTMLContainer.style.fontSize;
                    }
                    else if (HTMLContainer.currentStyle) {
                        size = HTMLContainer.currentStyle.fontSize;
                    }
                }

                if (!style) {
                    if (HTMLContainer.style.fontStyle) {
                        style = HTMLContainer.style.fontStyle;
                    }
                    else if (HTMLContainer.currentStyle) {
                        style = HTMLContainer.currentStyle.fontStyle;
                    }
                }

                if (!weight) {
                    if (HTMLContainer.style.fontWeight) {
                        weight = HTMLContainer.style.fontWeight;
                    }
                    else if (HTMLContainer.currentStyle) {
                        weight = HTMLContainer.currentStyle.fontWeight;
                    }
                }

                TempDiv.parentNode.removeChild(TempDiv);
            }
        }
        else {
            if (!document.getElementById(container.id)) {
                var TempDiv = document.createElement("div");
                TempDiv.style.position = "absolute";
                TempDiv.style.top = "-1000px";
                TempDiv.style.left = "-1000px";
                TempDiv.style.visibility = "hidden";

                TempDiv.id = RulerID + "_" + container.id;

                TempDiv.appendChild(container);
                document.body.appendChild(TempDiv);

                if (!family) {
                    if (container.style.fontFamily) {
                        family = container.style.fontFamily;
                    }
                    else if (container.currentStyle) {
                        family = container.currentStyle.fontFamily;
                    }
                }

                if (!size) {
                    if (container.style) {
                        size = container.style.fontSize;
                    }
                    else if (container.currentStyle) {
                        size = container.currentStyle.fontSize;
                    }
                }

                if (!style) {
                    if (container.style) {
                        style = container.style.fontStyle;
                    }
                    else if (container.currentStyle) {
                        style = container.currentStyle.fontStyle;
                    }
                }

                if (!weight) {
                    if (container.style) {
                        weight = container.style.fontWeight;
                    }
                    else if (container.currentStyle) {
                        weight = container.currentStyle.fontWeight;
                    }
                }

                TempDiv.parentNode.removeChild(TempDiv);
            }
            else {
                if (!family) {
                    if (container.style.fontFamily) {
                        family = container.style.fontFamily;
                    }
                    else if (container.currentStyle) {
                        family = container.currentStyle.fontFamily;
                    }
                }

                if (!size) {
                    if (container.style) {
                        size = container.style.fontSize;
                    }
                    else if (container.currentStyle) {
                        size = container.currentStyle.fontSize;
                    }
                }

                if (!style) {
                    if (container.style) {
                        style = container.style.fontStyle;
                    }
                    else if (container.currentStyle) {
                        style = container.currentStyle.fontStyle;
                    }
                }

                if (!weight) {
                    if (container.style) {
                        weight = container.style.fontWeight;
                    }
                    else if (container.currentStyle) {
                        weight = container.currentStyle.fontWeight;
                    }
                }
            }
        }

        CreateRuler(text, container, family, size, style, weight);

        if (HTMLContainer) {
            LengthChecker(text, HTMLContainer);
        }
        else {
            LengthChecker(text, container);
        }

        DestroyRuler();
    }

    var LengthChecker = function(text, container) {
        if (document.getElementById(RulerID)) {
            var originalText = text;
            var sampleText = text;

            var Ruler = document.getElementById(RulerID);

            if (Lines > 1) {
                Ruler.textArea.innerHTML = sampleText;

                if (parseInt(Ruler.offsetHeight) > parseInt(MaxHeight)) {
                    var FailsafeCounter = 0;

                    //Ruler.textArea.innerHTML = sampleText;

                    var x = (Ruler.textArea.offsetWidth * Lines);
                    var y = parseInt(MaxLength) * Lines;
                    var z = sampleText.length;

                    var charsToRemove = Math.floor((z * (x - y)) / x);
                    //var charsToRemove = z - Math.floor((z * y) / x) - 1;

                    sampleText = sampleText.substr(0, sampleText.length - charsToRemove);

                    sampleText = sampleText.replace(/\&/g, "&amp;");
                    sampleText = sampleText.replace(/\</g, "&lt;");
                    sampleText = sampleText.replace(/\>/g, "&gt;");

                    Ruler.textArea.innerHTML = sampleText + Ellipsis;

                    var OldWidth = 0;
                    var OldHeight = 0;

                    while (parseInt(Ruler.textArea.offsetHeight) > parseInt(MaxHeight) && FailsafeCounter < FailsafeCount) {
                        OldLength = sampleText.length;

                        sampleText = sampleText.replace(/\&amp\;/g, "&");
                        sampleText = sampleText.replace(/\&lt\;/g, "<");
                        sampleText = sampleText.replace(/\&gt\;/g, ">");

                        sampleText = sampleText.substring(0, sampleText.length - Ellipsis.length - 1) + Ellipsis;

                        sampleText = sampleText.replace(/\&/g, "&amp;");
                        sampleText = sampleText.replace(/\</g, "&lt;");
                        sampleText = sampleText.replace(/\>/g, "&gt;");

                        Ruler.textArea.innerHTML = sampleText;

                        if (OldLength == sampleText.length) {
                            FailsafeCounter++;
                        }
                    }

                    container.innerHTML = sampleText;

                    if (container.tagName.toLowerCase() == "td" || container.tagName.toLowerCase() == "table" || container.tagName.toLowerCase() == "div") {
                        container.title = originalText;
                    }
                    else {
                        container.alt = originalText;
                    }

                }
                else {
                    container.innerHTML = sampleText;
                }
            }
            else {
                Ruler.innerHTML = sampleText;

                if (parseInt(Ruler.offsetWidth) > parseInt(MaxLength)) {
                    var FailsafeCounter = 0;

                    //Ruler.innerHTML = sampleText;

                    var x = Ruler.offsetWidth;
                    var y = parseInt(MaxLength);
                    var z = sampleText.length;

                    var charsToRemove = Math.floor((z * (x - y)) / x);
                    //var charsToRemove = z - Math.floor((z * y) / x) - 1;

                    sampleText = sampleText.substr(0, sampleText.length - charsToRemove);

                    sampleText = sampleText.replace(/\&/g, "&amp;");
                    sampleText = sampleText.replace(/\</g, "&lt;");
                    sampleText = sampleText.replace(/\>/g, "&gt;");

                    Ruler.innerHTML = sampleText + Ellipsis;

                    var OldWidth = 0;

                    while (parseInt(Ruler.offsetWidth) > parseInt(MaxLength) && FailsafeCounter < FailsafeCount) {
                        OldWidth = Ruler.offsetWidth;

                        sampleText = sampleText.replace(/\&amp\;/g, "&");
                        sampleText = sampleText.replace(/\&lt\;/g, "<");
                        sampleText = sampleText.replace(/\&gt\;/g, ">");

                        sampleText = sampleText.substring(0, sampleText.length - Ellipsis.length - 1) + Ellipsis;

                        sampleText = sampleText.replace(/\&/g, "&amp;");
                        sampleText = sampleText.replace(/\</g, "&lt;");
                        sampleText = sampleText.replace(/\>/g, "&gt;");

                        Ruler.innerHTML = sampleText;

                        if (OldWidth == Ruler.offsetWidth) {
                            FailsafeCounter++;
                        }
                    }

                    container.style.whiteSpace = "nowrap";

                    container.innerHTML = sampleText;

                    if (container.tagName.toLowerCase() == "td" || container.tagName.toLowerCase() == "table" || container.tagName.toLowerCase() == "div")
                        container.title = originalText;
                    else
                        container.alt = originalText;
                }
                else {
                    container.innerHTML = sampleText;
                }
            }
        }
    }

    var CreateRuler = function(text, container, family, size, style, weight) {
        if (!container) return;

        var Ruler = document.createElement("div");
        Ruler.style.visibility = "hidden";
        Ruler.style.position = "absolute";
        Ruler.style.left = "-500px";
        Ruler.style.top = "-500px";
        Ruler.id = RulerID;

        if (container.style.width)
            MaxLength = parseInt(container.style.width);
        else if (container.currentStyle && container.currentStyle.width)
            MaxLength = parseInt(container.currentStyle.width);
        else
            MaxLength = parseInt(container.offsetWidth);

        if (family)
            Ruler.style.fontFamily = family;

        if (size)
            Ruler.style.fontSize = size;

        if (style)
            Ruler.style.fontStyle = style;

        if (weight)
            Ruler.style.fontWeight = weight;

        document.body.appendChild(Ruler);

        if (Lines > 1) {
            Ruler.style.whiteSpace = "nowrap";

            var sampleText = "...";

            sampleText = sampleText.replace(/\&/g, "&amp;");
            sampleText = sampleText.replace(/\</g, "&lt;");
            sampleText = sampleText.replace(/\>/g, "&gt;");

            Ruler.innerHTML = sampleText;

            var LinesOffset = Lines;
            if (LinesOffset <= 0) LinesOffset = 1;

            MaxHeight = (parseInt(Ruler.offsetHeight) * LinesOffset) + "px";
            Ruler.style.width = MaxLength + "px";

            Ruler.innerHTML = "";
            Ruler.style.whiteSpace = "";

            var RulerTable = document.createElement("table");
            RulerTable.border = "0";
            RulerTable.cellSpacing = "0";
            RulerTable.cellPadding = "0";
            RulerTable.style.width = MaxLength + "px";
            RulerTable.style.tableLayout = "fixed";
            RulerTable.style.wordWrap = "break-word";

            var RulerTR = document.createElement("tr");

            var RulerTD = document.createElement("td");
            RulerTD.align = "left";
            RulerTD.vAlign = "top";

            RulerTR.appendChild(RulerTD);

            addTableRows(RulerTable, [RulerTR]);

            Ruler.appendChild(RulerTable);

            Ruler.textArea = RulerTD;
        }
        else {
            Ruler.style.whiteSpace = "nowrap";
        }
    }

    var DestroyRuler = function() {
        if (document.getElementById(RulerID)) {
            var Ruler = document.getElementById(RulerID);

            Ruler.parentNode.removeChild(Ruler);
        }
    }

    var DotSize = function(fontSize) {
        if (fontSize && !isNaN(fontSize)) {
            var y = Math.ceil((parseInt(fontSize) - 5) / 4) + 1;
            if (y < 1) y = 1;

            return y;
        }

        return 1;
    }
}
