﻿(function() {
    Hover = function(t, txt, width) {
        this.t = $(t);
        this.hideHover = function() {
            this.hvr.hide();
            this.t.css('position', 'static');
        };
        this.hvr = $('<div>' + txt + '</div>')
            .addClass('abridged-hover')
            .css({ 'position': 'absolute', 'z-index': '20', 'width': width +'px' })
            .hide()
            .mouseout(Function.createDelegate(this, this.hideHover));
        this.t
            .before(this.hvr)
            .mouseover(Function.createDelegate(this, function() {
                this.t.css('position', 'static');
                this.hvr.show();
            }));
    }

    StringAbridger = function(items, o) {
        var defaults = {
            ellipsis: '(...)'
        };
        this.opt = $.extend({}, defaults, o || {});
        this.STOP_CHARS = ['(', '"'];
        this.CLOSE_CHARS = new Array();
        this.CLOSE_CHARS['('] = ')';
        this.CLOSE_CHARS['"'] = '"';
        this.cleanReg = /( )+/g;
        this.lineFeed = /\n/g;
        this.quot = /\"/g;

        if (!$.isArray(items)) {
            return;
        }
        var md = $('div#strMes:first');
        if (md.size() == 0) {
            md = $('<div id="strMes"></div>').css({ 'position': 'absolute', 'left': '-25000px' });
            $('body').prepend(md);
        }
        this.measureDiv = md;
        var j;
        for (j in items) {
            this.suffix = null;
            this.abridgeString(items[j]);
        }
    }
    $.extend(StringAbridger.prototype, {
        abridgeString: function(i) {
            if (typeof (i) == 'undefined'
                || typeof (i.id) == 'undefined'
                || typeof (i.width) == 'undefined') {
                return;
            }
            this.ellipsis = (typeof (i.ellipsis) == 'undefined' ? this.opt.ellipsis : i.ellipsis);
            this.node = $('#' + i.id + ':first');
            if (this.node.size() == 0) {
                return;
            }
            var lbl = this.node.clone().removeAttr('id');
            this.measureDiv.empty().append(lbl);
            this.lbl = lbl;
            this.text = lbl.html()
							.replace(this.cleanReg, ' ')
            //.replace(this.lineFeed, "<br />")
							.replace(this.quot, "&quot;");

            var words = this.text.split(' ');
            if (typeof (i.preserveLast) != 'undefined' && i.preserveLast > 0) {
                this.suffix = this.wrapSuffix(words.slice(words.length - i.preserveLast, words.length).join(' '));
                words.splice(words.length - i.preserveLast, i.preserveLast);
            }
            if (lbl.width() <= i.width) {
                this.node.html(words.join(' ') + ' ').append(this.suffix);
                return;
            }
            var word = '', abr = '';
            while (word = words.shift()) {
                var ch1 = word.substr(0, 1);
                if ($.inArray(ch1, this.STOP_CHARS) != -1 && (abr + word).length == lbl.length) {
                    var procRes = this.processStopChar(ch1, $.merge(new Array(word), words), abr, i.width);
                    if (!procRes.cont) {
                        return;
                    }
                    abr = procRes.abr;
                    continue;
                }
                if (this.strIsShorter(abr + word, i.width) == false) {
                    break;
                }
                abr += word + ' ';
            }
            this.setAbridgedText(abr, i.boxwidth);
        },
        wrapSuffix: function(s) {
            return $('<span class="abridged-suffix">' + s + '</span>');
        },
        processStopChar: function(sCh, words, base, width) {
            var abr = base;
            var cCh = this.CLOSE_CHARS[sCh];
            while (word = words.shift()) {
                abr += word + ' ';
                if (word.substr(word.length - 1, 1) == cCh) {
                    break;
                }
            }
            var isShorter = this.strIsShorter(abr, width);
            if (!isShorter) {
                this.setAbridgedText(base + ' ');
            }
            return { cont: isShorter, abr: abr };
        },
        setAbridgedText: function(txt, width) {
            this.node.html(txt).append('<span class="ellipsis">' + this.ellipsis + '</span>');
            if (this.suffix != null) {
                this.node.text(this.node.text() + ' ').append(this.suffix);
            }
            this.createHover(width);
        },
        strIsShorter: function(str, maxWidth) {
            this.lbl.html(str).append('<span class="ellipsis">' + this.ellipsis + '</span>');
            if (this.suffix != null) {
                this.lbl.html(this.lbl.text() + ' ').append(this.suffix);
            }
            return (this.lbl.width() <= maxWidth);
        },
        createHover: function(width) {
            new Hover(this.node, this.text, width);
        }
    });
})();
