dotdotdot.js 中文特殊字符

在使用jquery.dotdotdot.min.js插件时,你会发现如果文本是中文的特殊字符,此时就无法解析了,因为需要配置插件wap属性,如下代码:

$(".descript").dotdotdot({
                    wrap: 'letter' //注:中文必须改为letter
                });
默认的配置是:word  ,所以需要考虑中文的特殊性。

dotdotdot.js 源码:

/*
 *	jQuery dotdotdot 1.8.3
 *
 *	Copyright (c) Fred Heusschen
 *	www.frebsite.nl
 *
 *	Plugin website:
 *	dotdotdot.frebsite.nl
 *
 *	Licensed under the MIT license.
 *	http://en.wikipedia.org/wiki/MIT_License
 */

(function($, undef) {
    'use strict';
    if ($.fn.dotdotdot) {
        return;
    }

    $.fn.dotdotdot = function(o) {
        if (this.length === 0) {
            $.fn.dotdotdot.debug('No element found for "' + this.selector + '".');
            return this;
        }
        if (this.length > 1) {
            return this.each(
                function() {
                    $(this).dotdotdot(o);
                }
            );
        }

        var $dot = this;
        var orgContent = $dot.contents();

        if ($dot.data('dotdotdot')) {
            $dot.trigger('destroy.dot');
        }

        $dot.data('dotdotdot-style', $dot.attr('style') || '');
        $dot.css('word-wrap', 'break-word');
        if ($dot.css('white-space') === 'nowrap') {
            $dot.css('white-space', 'normal');
        }

        $dot.bind_events = function() {
            $dot.bind(
                'update.dot',
                function(e, c) {
                    $dot.removeClass("is-truncated");
                    e.preventDefault();
                    e.stopPropagation();

                    switch (typeof opts.height) {
                        case 'number':
                            opts.maxHeight = opts.height;
                            break;

                        case 'function':
                            opts.maxHeight = opts.height.call($dot[0]);
                            break;

                        default:
                            opts.maxHeight = getTrueInnerHeight($dot);
                            break;
                    }

                    opts.maxHeight += opts.tolerance;

                    if (typeof c != 'undefined') {
                        if (typeof c == 'string' || ('nodeType' in c && c.nodeType === 1)) {
                            c = $('<div />').append(c).contents();
                        }
                        if (c instanceof $) {
                            orgContent = c;
                        }
                    }

                    $inr = $dot.wrapInner('<div class="dotdotdot" />').children();
                    $inr.contents()
                        .detach()
                        .end()
                        .append(orgContent.clone(true))
                        .find('br')
                        .replaceWith('  <br />  ')
                        .end()
                        .css({
                            'height': 'auto',
                            'width': 'auto',
                            'border': 'none',
                            'padding': 0,
                            'margin': 0
                        });

                    var after = false,
                        trunc = false;

                    if (conf.afterElement) {
                        after = conf.afterElement.clone(true);
                        after.show();
                        conf.afterElement.detach();
                    }

                    if (test($inr, opts)) {
                        if (opts.wrap == 'children') {
                            trunc = children($inr, opts, after);
                        } else {
                            trunc = ellipsis($inr, $dot, $inr, opts, after);
                        }
                    }
                    $inr.replaceWith($inr.contents());
                    $inr = null;

                    if ($.isFunction(opts.callback)) {
                        opts.callback.call($dot[0], trunc, orgContent);
                    }

                    conf.isTruncated = trunc;
                    return trunc;
                }

            ).bind(
                'isTruncated.dot',
                function(e, fn) {
                    e.preventDefault();
                    e.stopPropagation();

                    if (typeof fn == 'function') {
                        fn.call($dot[0], conf.isTruncated);
                    }
                    return conf.isTruncated;
                }

            ).bind(
                'originalContent.dot',
                function(e, fn) {
                    e.preventDefault();
                    e.stopPropagation();

                    if (typeof fn == 'function') {
                        fn.call($dot[0], orgContent);
                    }
                    return orgContent;
                }

            ).bind(
                'destroy.dot',
                function(e) {
                    e.preventDefault();
                    e.stopPropagation();

                    $dot.unwatch()
                        .unbind_events()
                        .contents()
                        .detach()
                        .end()
                        .append(orgContent)
                        .attr('style', $dot.data('dotdotdot-style') || '')
                        .removeClass('is-truncated')
                        .data('dotdotdot', false);
                }
            );
            return $dot;
        }; //	/bind_events

        $dot.unbind_events = function() {
            $dot.unbind('.dot');
            return $dot;
        }; //	/unbind_events

        $dot.watch = function() {
            $dot.unwatch();
            if (opts.watch == 'window') {
                var $window = $(window),
                    _wWidth = $window.width(),
                    _wHeight = $window.height();

                $window.bind(
                    'resize.dot' + conf.dotId,
                    function() {
                        if (_wWidth != $window.width() || _wHeight != $window.height() || !opts.windowResizeFix) {
                            _wWidth = $window.width();
                            _wHeight = $window.height();

                            if (watchInt) {
                                clearInterval(watchInt);
                            }
                            watchInt = setTimeout(
                                function() {
                                    $dot.trigger('update.dot');
                                }, 100
                            );
                        }
                    }
                );
            } else {
                watchOrg = getSizes($dot);
                watchInt = setInterval(
                    function() {
                        if ($dot.is(':visible')) {
                            var watchNew = getSizes($dot);
                            if (watchOrg.width != watchNew.width ||
                                watchOrg.height != watchNew.height) {
                                $dot.trigger('update.dot');
                                watchOrg = watchNew;
                            }
                        }
                    }, 500
                );
            }
            return $dot;
        };
        $dot.unwatch = function() {
            $(window).unbind('resize.dot' + conf.dotId);
            if (watchInt) {
                clearInterval(watchInt);
            }
            return $dot;
        };

        var opts = $.extend(true, {}, $.fn.dotdotdot.defaults, o),
            conf = {},
            watchOrg = {},
            watchInt = null,
            $inr = null;


        if (!(opts.lastCharacter.remove instanceof Array)) {
            opts.lastCharacter.remove = $.fn.dotdotdot.defaultArrays.lastCharacter.remove;
        }
        if (!(opts.lastCharacter.noEllipsis instanceof Array)) {
            opts.lastCharacter.noEllipsis = $.fn.dotdotdot.defaultArrays.lastCharacter.noEllipsis;
        }


        conf.afterElement = getElement(opts.after, $dot);
        conf.isTruncated = false;
        conf.dotId = dotId++;


        $dot.data('dotdotdot', true)
            .bind_events()
            .trigger('update.dot');

        if (opts.watch) {
            $dot.watch();
        }

        return $dot;
    };


    //	public
    $.fn.dotdotdot.defaults = {
        'ellipsis': '... ',
        'wrap': 'word',
        'fallbackToLetter': true,
        'lastCharacter': {},
        'tolerance': 0,
        'callback': null,
        'after': null,
        'height': null,
        'watch': false,
        'windowResizeFix': true,
        'maxLength': null
    };
    $.fn.dotdotdot.defaultArrays = {
        'lastCharacter': {
            'remove': [' ', '\u3000', ',', ';', '.', '!', '?'],
            'noEllipsis': []
        }
    };
    $.fn.dotdotdot.debug = function(msg) {};


    //	private
    var dotId = 1;

    function children($elem, o, after) {
        var $elements = $elem.children(),
            isTruncated = false;

        $elem.empty();

        for (var a = 0, l = $elements.length; a < l; a++) {
            var $e = $elements.eq(a);
            $elem.append($e);
            if (after) {
                $elem.append(after);
            }
            if (test($elem, o)) {
                $e.remove();
                isTruncated = true;
                break;
            } else {
                if (after) {
                    after.detach();
                }
            }
        }
        return isTruncated;
    }

    function ellipsis($elem, $d, $i, o, after) {
        var isTruncated = false;

        //	Don't put the ellipsis directly inside these elements
        var notx = 'a, table, thead, tbody, tfoot, tr, col, colgroup, object, embed, param, ol, ul, dl, blockquote, select, optgroup, option, textarea, script, style';

        //	Don't remove these elements even if they are after the ellipsis
        var noty = 'script, .dotdotdot-keep';

        $elem
            .contents()
            .detach()
            .each(
                function() {

                    var e = this,
                        $e = $(e);

                    if (typeof e == 'undefined') {
                        return true;
                    } else if ($e.is(noty)) {
                        $elem.append($e);
                    } else if (isTruncated) {
                        return true;
                    } else {
                        $elem.append($e);
                        if (after && !$e.is(o.after) && !$e.find(o.after).length) {
                            $elem[$elem.is(notx) ? 'after' : 'append'](after);
                        }
                        if (test($i, o)) {
                            if (e.nodeType == 3) // node is TEXT
                            {
                                isTruncated = ellipsisElement($e, $d, $i, o, after);
                            } else {
                                isTruncated = ellipsis($e, $d, $i, o, after);
                            }
                        }

                        if (!isTruncated) {
                            if (after) {
                                after.detach();
                            }
                        }
                    }
                }
            );
        $d.addClass("is-truncated");
        return isTruncated;
    }

    function ellipsisElement($e, $d, $i, o, after) {
        var e = $e[0];

        if (!e) {
            return false;
        }

        var txt = getTextContent(e),
            space = (txt.indexOf(' ') !== -1) ? ' ' : '\u3000',
            separator = (o.wrap == 'letter') ? '' : space,
            textArr = txt.split(separator),
            position = -1,
            midPos = -1,
            startPos = 0,
            endPos = textArr.length - 1;


        //	Only one word
        if (o.fallbackToLetter && startPos === 0 && endPos === 0) {
            separator = '';
            textArr = txt.split(separator);
            endPos = textArr.length - 1;
        }

        if (o.maxLength) {
            txt = addEllipsis(txt.trim().substr(0, o.maxLength), o);
            setTextContent(e, txt);
        } else {

            while (startPos <= endPos && !(startPos === 0 && endPos === 0)) {
                var m = Math.floor((startPos + endPos) / 2);
                if (m == midPos) {
                    break;
                }
                midPos = m;

                setTextContent(e, textArr.slice(0, midPos + 1).join(separator) + o.ellipsis);

                $i.children().each(function() {
                    $(this).toggle().toggle();
                });

                if (!test($i, o)) {
                    position = midPos;
                    startPos = midPos;
                } else {
                    endPos = midPos;

                    //	Fallback to letter
                    if (o.fallbackToLetter && startPos === 0 && endPos === 0) {
                        separator = '';
                        textArr = textArr[0].split(separator);
                        position = -1;
                        midPos = -1;
                        startPos = 0;
                        endPos = textArr.length - 1;
                    }
                }
            }

            if (position != -1 && !(textArr.length === 1 && textArr[0].length === 0)) {
                txt = addEllipsis(textArr.slice(0, position + 1).join(separator), o);
                setTextContent(e, txt);
            } else {
                var $w = $e.parent();
                $e.detach();

                var afterLength = (after && after.closest($w).length) ? after.length : 0;

                if ($w.contents().length > afterLength) {
                    e = findLastTextNode($w.contents().eq(-1 - afterLength), $d);
                } else {
                    e = findLastTextNode($w, $d, true);
                    if (!afterLength) {
                        $w.detach();
                    }
                }
                if (e) {
                    txt = addEllipsis(getTextContent(e), o);
                    setTextContent(e, txt);
                    if (afterLength && after) {
                        var $parent = after.parent();

                        $(e).parent().append(after);

                        if (!$.trim($parent.html())) {
                            $parent.remove();
                        }
                    }
                }
            }
        }

        return true;
    }

    function test($i, o) {
        return ($i.innerHeight() > o.maxHeight || (o.maxLength && $i.text().trim().length > o.maxLength));
    }

    function addEllipsis(txt, o) {
        while ($.inArray(txt.slice(-1), o.lastCharacter.remove) > -1) {
            txt = txt.slice(0, -1);
        }
        if ($.inArray(txt.slice(-1), o.lastCharacter.noEllipsis) < 0) {
            txt += o.ellipsis;
        }
        return txt;
    }

    function getSizes($d) {
        return {
            'width': $d.innerWidth(),
            'height': $d.innerHeight()
        };
    }

    function setTextContent(e, content) {
        if (e.innerText) {
            e.innerText = content;
        } else if (e.nodeValue) {
            e.nodeValue = content;
        } else if (e.textContent) {
            e.textContent = content;
        }

    }

    function getTextContent(e) {
        if (e.innerText) {
            return e.innerText;
        } else if (e.nodeValue) {
            return e.nodeValue;
        } else if (e.textContent) {
            return e.textContent;
        } else {
            return "";
        }
    }

    function getPrevNode(n) {
        do {
            n = n.previousSibling;
        }
        while (n && n.nodeType !== 1 && n.nodeType !== 3);

        return n;
    }

    function findLastTextNode($el, $top, excludeCurrent) {
        var e = $el && $el[0],
            p;
        if (e) {
            if (!excludeCurrent) {
                if (e.nodeType === 3) {
                    return e;
                }
                if ($.trim($el.text())) {
                    return findLastTextNode($el.contents().last(), $top);
                }
            }
            p = getPrevNode(e);
            while (!p) {
                $el = $el.parent();
                if ($el.is($top) || !$el.length) {
                    return false;
                }
                p = getPrevNode($el[0]);
            }
            if (p) {
                return findLastTextNode($(p), $top);
            }
        }
        return false;
    }

    function getElement(e, $i) {
        if (!e) {
            return false;
        }
        if (typeof e === 'string') {
            e = $(e, $i);
            return (e.length) ?
                e :
                false;
        }
        return !e.jquery ?
            false :
            e;
    }

    function getTrueInnerHeight($el) {
        var h = $el.innerHeight(),
            a = ['paddingTop', 'paddingBottom'];

        for (var z = 0, l = a.length; z < l; z++) {
            var m = parseInt($el.css(a[z]), 10);
            if (isNaN(m)) {
                m = 0;
            }
            h -= m;
        }
        return h;
    }


    //	override jQuery.html
    var _orgHtml = $.fn.html;
    $.fn.html = function(str) {
        if (str != undef && !$.isFunction(str) && this.data('dotdotdot')) {
            return this.trigger('update', [str]);
        }
        return _orgHtml.apply(this, arguments);
    };


    //	override jQuery.text
    var _orgText = $.fn.text;
    $.fn.text = function(str) {
        if (str != undef && !$.isFunction(str) && this.data('dotdotdot')) {
            str = $('<div />').text(str).html();
            return this.trigger('update', [str]);
        }
        return _orgText.apply(this, arguments);
    };


})(jQuery);

/*

## Automatic parsing for CSS classes
Contributed by [Ramil Valitov](https://github.com/rvalitov)

### The idea
You can add one or several CSS classes to HTML elements to automatically invoke "jQuery.dotdotdot functionality" and some extra features. It allows to use jQuery.dotdotdot only by adding appropriate CSS classes without JS programming.

### Available classes and their description
* dot-ellipsis - automatically invoke jQuery.dotdotdot to this element. This class must be included if you plan to use other classes below.
* dot-resize-update - automatically update if window resize event occurs. It's equivalent to option `watch:'window'`.
* dot-timer-update - automatically update at regular intervals using setInterval. It's equivalent to option `watch:true`.
* dot-load-update - automatically update after the window has beem completely rendered. Can be useful if your content is generated dynamically using using JS and, hence, jQuery.dotdotdot can't correctly detect the height of the element before it's rendered completely.
* dot-height-XXX - available height of content area in pixels, where XXX is a number, e.g. can be `dot-height-35` if you want to set maximum height for 35 pixels. It's equivalent to option `height:'XXX'`.

### Usage examples
*Adding jQuery.dotdotdot to element*

	<div class="dot-ellipsis">
	<p>Lorem Ipsum is simply dummy text.</p>
	</div>

*Adding jQuery.dotdotdot to element with update on window resize*

	<div class="dot-ellipsis dot-resize-update">
	<p>Lorem Ipsum is simply dummy text.</p>
	</div>

*Adding jQuery.dotdotdot to element with predefined height of 50px*

	<div class="dot-ellipsis dot-height-50">
	<p>Lorem Ipsum is simply dummy text.</p>
	</div>

*/

jQuery(document).ready(function($) {
    //We only invoke jQuery.dotdotdot on elements that have dot-ellipsis class
    $(".dot-ellipsis").each(function() {
        //Checking if update on window resize required
        var watch_window = $(this).hasClass("dot-resize-update");

        //Checking if update on timer required
        var watch_timer = $(this).hasClass("dot-timer-update");

        //Checking if height set
        var height = 0;
        var classList = $(this).attr('class').split(/\s+/);
        $.each(classList, function(index, item) {
            var matchResult = item.match(/^dot-height-(\d+)$/);
            if (matchResult !== null)
                height = Number(matchResult[1]);
        });

        //Invoking jQuery.dotdotdot
        var x = {};
        if (watch_timer)
            x.watch = true;
        if (watch_window)
            x.watch = 'window';
        if (height > 0)
            x.height = height;
        $(this).dotdotdot(x);
    });
});

//Updating elements (if any) on window.load event
jQuery(window).on('load', function() {
    jQuery(".dot-ellipsis.dot-load-update").trigger("update.dot");
});



评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

低调之人

略表心意,哈哈哈

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值