150 votes

Insérer des points de suspension (...) dans la balise HTML si content trop large

J'ai une page web avec un élastique de mise en page que l'évolution de sa largeur si la fenêtre du navigateur est redimensionnée.

Dans cette disposition, il y a des titres (h2) qui ont une longueur variable (qui était en fait les gros titres de blogposts que je n'ai pas le contrôle). Actuellement - si ils sont plus large que la fenêtre - ils sont répartis en deux lignes.

Est-il un élégant, testé (cross-browser) solution - par exemple avec jQuery - qui raccourcit le innerHTML de ce titre tag et ajoute "..." si le texte serait trop large pour tenir dans une seule ligne à l'écran en cours/conteneur largeur?

183voto

Simon Lieschke Points 7351

Le code CSS suivant seule solution pour tronquer un texte sur une seule ligne fonctionne avec tous les browers énumérés à http://www.caniuse.com de l'écriture à l'exception de Firefox 6.0. Notez que JavaScript est totalement inutile, sauf si vous avez besoin de support emballage de texte multiligne ou des versions antérieures de Firefox.

.ellipsis {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    -o-text-overflow: ellipsis;
}

Si vous avez besoin de support pour les versions antérieures de Firefox découvrez ma réponse à cette autre question.

120voto

alex Points 1298

J'ai une solution qui fonctionne avec FF3, Safari et IE6 + avec un texte simple et multiligne

 .ellipsis {
	white-space: nowrap;
	overflow: hidden;
}

.ellipsis.multiline {
	white-space: normal;
}

<div class="ellipsis" style="width: 100px; border: 1px solid black;">Lorem ipsum dolor sit amet, consectetur adipisicing elit</div>
<div class="ellipsis multiline" style="width: 100px; height: 40px; border: 1px solid black; margin-bottom: 100px">Lorem ipsum dolor sit amet, consectetur adipisicing elit</div>

<script type="text/javascript" src="/js/jquery.ellipsis.js"></script>
<script type="text/javascript">
$(".ellipsis").ellipsis();
</script>
 

jquery.ellipsis.js

 (function($) {
	$.fn.ellipsis = function()
	{
		return this.each(function()
		{
			var el = $(this);

			if(el.css("overflow") == "hidden")
			{
				var text = el.html();
				var multiline = el.hasClass('multiline');
				var t = $(this.cloneNode(true))
					.hide()
					.css('position', 'absolute')
					.css('overflow', 'visible')
					.width(multiline ? el.width() : 'auto')
					.height(multiline ? 'auto' : el.height())
					;

				el.after(t);

				function height() { return t.height() > el.height(); };
				function width() { return t.width() > el.width(); };

				var func = multiline ? height : width;

				while (text.length > 0 && func())
				{
					text = text.substr(0, text.length - 1);
					t.html(text + "...");
				}

				el.html(t.html());
				t.remove();
			}
		});
	};
})(jQuery);
 

40voto

Adam Tegen Points 8563

J'ai construit ce code à l'aide d'un certain nombre d'autres postes, avec les améliorations suivantes:

  1. Il utilise le binaire de recherche pour trouver la longueur du texte qui est juste à droite.
  2. Il traite les cas où les points de suspension d'élément(s) sont initialement masqué par la mise en place d'un one-shot show événement qui re-fonctionne sur le bouton de sélection de code lorsque l'élément est affiché pour la première fois. C'est pratique pour les maître-détail de la vue ou de l'arborescence où certains éléments ne sont pas initialement affiché.
  3. Il peut éventuellement ajoute un attribut title avec le texte original pour un hoverover effet.
  4. Ajouté display: block pour le style, de sorte que les travées de travail
  5. Il utilise le caractère de points de suspension au lieu de 3 périodes.
  6. Il s'est auto-exécute le script pour rien .bouton de sélection de la classe

CSS:

.ellipsis {
        white-space: nowrap;
        overflow: hidden;
        display: block;
}

.ellipsis.multiline {
        white-space: normal;
}

jquery.ellipsis.js

(function ($) {

    // this is a binary search that operates via a function
    // func should return < 0 if it should search smaller values
    // func should return > 0 if it should search larger values
    // func should return = 0 if the exact value is found
    // Note: this function handles multiple matches and will return the last match
    // this returns -1 if no match is found
    function binarySearch(length, func) {
        var low = 0;
        var high = length - 1;
        var best = -1;
        var mid;

        while (low <= high) {
            mid = ~ ~((low + high) / 2); //~~ is a fast way to convert something to an int
            var result = func(mid);
            if (result < 0) {
                high = mid - 1;
            } else if (result > 0) {
                low = mid + 1;
            } else {
                best = mid;
                low = mid + 1;
            }
        }

        return best;
    }

    // setup handlers for events for show/hide
    $.each(["show", "toggleClass", "addClass", "removeClass"], function () {

        //get the old function, e.g. $.fn.show   or $.fn.hide
        var oldFn = $.fn[this];
        $.fn[this] = function () {

            // get the items that are currently hidden
            var hidden = this.find(":hidden").add(this.filter(":hidden"));

            // run the original function
            var result = oldFn.apply(this, arguments);

            // for all of the hidden elements that are now visible
            hidden.filter(":visible").each(function () {
                // trigger the show msg
                $(this).triggerHandler("show");
            });

            return result;
        };
    });

    // create the ellipsis function
    // when addTooltip = true, add a title attribute with the original text
    $.fn.ellipsis = function (addTooltip) {

        return this.each(function () {
            var el = $(this);

            if (el.is(":visible")) {

                if (el.css("overflow") === "hidden") {
                    var content = el.html();
                    var multiline = el.hasClass('multiline');
                    var tempElement = $(this.cloneNode(true))
                        .hide()
                        .css('position', 'absolute')
                        .css('overflow', 'visible')
                        .width(multiline ? el.width() : 'auto')
                        .height(multiline ? 'auto' : el.height())
                    ;

                    el.after(tempElement);

                    var tooTallFunc = function () {
                        return tempElement.height() > el.height();
                    };

                    var tooWideFunc = function () {
                        return tempElement.width() > el.width();
                    };

                    var tooLongFunc = multiline ? tooTallFunc : tooWideFunc;

                    // if the element is too long...
                    if (tooLongFunc()) {

                        var tooltipText = null;
                        // if a tooltip was requested...
                        if (addTooltip) {
                            // trim leading/trailing whitespace
                            // and consolidate internal whitespace to a single space
                            tooltipText = $.trim(el.text()).replace(/\s\s+/g, ' ');
                        }

                        var originalContent = content;

                        var createContentFunc = function (i) {
                            content = originalContent.substr(0, i);
                            tempElement.html(content + "…");
                        };

                        var searchFunc = function (i) {
                            createContentFunc(i);
                            if (tooLongFunc()) {
                                return -1;
                            }
                            return 0;
                        };

                        var len = binarySearch(content.length - 1, searchFunc);

                        createContentFunc(len);

                        el.html(tempElement.html());

                        // add the tooltip if appropriate
                        if (tooltipText !== null) {
                            el.attr('title', tooltipText);
                        }
                    }

                    tempElement.remove();
                }
            }
            else {
                // if this isn't visible, then hook up the show event
                el.one('show', function () {
                    $(this).ellipsis(addTooltip);
                });
            }
        });
    };

    // ellipsification for items with an ellipsis
    $(document).ready(function () {
        $('.ellipsis').ellipsis(true);
    });

} (jQuery));

20voto

Mikey G Points 1860

J'ai réécrit le code de la première réponse à quelques reprises, et je pense que ce devrait être le plus rapide.

Il trouve d'abord une "Estimation" de la longueur du texte, puis ajoute ou supprime un caractère jusqu'à ce que la largeur est correct.

Je n'ai pas testé avec multilines.

La logique qu'il utilise est indiqué ci-dessous:

enter image description here

Après une "estimation" de la longueur du texte est trouvé, les personnages sont ajoutés ou supprimés jusqu'à ce que la largeur désirée est atteinte.

Je suis sûr qu'il a besoin de quelques ajustements, mais voici le code:

(function ($) {
    $.fn.ellipsis = function () {
        return this.each(function () {
            var el = $(this);

            if (el.css("overflow") == "hidden") {
                var text = el.html().trim();
                var t = $(this.cloneNode(true))
                                        .hide()
                                        .css('position', 'absolute')
                                        .css('overflow', 'visible')
                                        .width('auto')
                                        .height(el.height())
                                        ;
                el.after(t);

                function width() { return t.width() > el.width(); };

                if (width()) {

                    var myElipse = "....";

                    t.html(text);

                    var suggestedCharLength = (text.length * el.width() / t.width()) - myElipse.length;

                    t.html(text.substr(0, suggestedCharLength) + myElipse);

                    var x = 1;
                    if (width()) {
                        while (width()) {
                            t.html(text.substr(0, suggestedCharLength - x) + myElipse);
                            x++;
                        }
                    }
                    else {
                        while (!width()) {
                            t.html(text.substr(0, suggestedCharLength + x) + myElipse);
                            x++;
                        }
                        x--;
                        t.html(text.substr(0, suggestedCharLength + x) + myElipse);
                    }

                    el.html(t.html());
                    t.remove();
                }
            }
        });
    };
})(jQuery);

18voto

Jeremy Horn Points 151

J'ai fait un plugin jQuery vraiment sympa pour gérer toutes les variétés de points de suspension de texte, celui appelé ThreeDots @ http://tpgblog.com/threedots

Il est beaucoup plus flexible que les approches CSS et prend en charge des comportements et des interactions beaucoup plus avancés et personnalisables.

Prendre plaisir.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X