Insérer des points de suspension (…) dans la balise HTML si le contenu est trop large

148

J'ai une page Web avec une mise en page élastique qui change sa largeur si la fenêtre du navigateur est redimensionnée.

Dans cette mise en page, il y a des titres ( h2) qui auront une longueur variable (étant en fait des titres de blogs sur lesquels je n'ai pas de contrôle). Actuellement, s'ils sont plus larges que la fenêtre, ils sont divisés en deux lignes.

Existe-t-il une solution élégante et testée (multi-navigateurs) - par exemple avec jQuery - qui raccourcit le fichier innerHTML de cette balise de titre et ajoute "..." si le texte est trop large pour tenir dans une ligne à l'écran actuel / largeur du conteneur?

BlaM
la source
1
Réponse mise à jour 2014: stackoverflow.com/a/22811590/759452
Adrien Be
J'ai créé un plugin basé sur ce fil qui utilise les propriétés CSS white-space et word-wrap pour formater le texte. github.com/nothrem/jQuerySmartEllipsis
Radek Pech

Réponses:

119

J'ai une solution fonctionnant dans FF3, Safari et IE6 + avec du 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);
Alex
la source
22
Bien, j'ai cherché comment gérer le débordement avec plusieurs lignes. Une amélioration: au lieu d'ajouter trois points, ajoutez le caractère points de suspension, «…».
Simon Lieschke
4
Cela fonctionne très bien. Vous devriez publier ceci sur le site jQuery.
Edgar
1
Bien que dans IE, si la fonction d'ellipse est appliquée sur un div qui a juste un lien, après les points de suspension, le lien disparaît. Des conseils à ce sujet?
Chantz
6
Si vous souhaitez voir cela en action, vous pouvez le voir ici (désolé pour le formatage vicieux sur le code du plugin) jsfiddle.net/danesparza/TF6Rb/1
Dan Esparza
22
Pour améliorer les performances, effectuez une recherche binaire au lieu de supprimer 1 caractère à la fois dans la boucle «while». Si 100% du texte ne rentre pas, essayez 50% du texte; puis 75% du texte si 50% correspond, ou 25% si 50% ne correspond pas, etc.
StanleyH
182

La seule solution CSS suivante pour tronquer du texte sur une seule ligne fonctionne avec tous les navigateurs répertoriés sur http://www.caniuse.com dès la rédaction, à l'exception de Firefox 6.0. Notez que JavaScript est totalement inutile, sauf si vous devez prendre en charge l'encapsulation 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 d'assistance pour les versions antérieures de Firefox, consultez ma réponse à cette autre question .

Simon Lieschke
la source
2
C'est des ordres de grandeur plus rapides que l'approche jQuery. Fonctionne très bien dans IE7 + et Chrome.
JDB se souvient toujours de Monica
3
Cela fonctionne aussi bien avec les anciens navigateurs. Nous l'avons utilisé avec succès chez Google en 2004, où nous devions prendre en charge ou dégrader gracieusement sur certains navigateurs vraiment de coin.
ElBel
2
JS Fiddle pour ceux qui veulent l'échantillonner sur un navigateur - jsfiddle.net/r39Ad
Deepak Bala
@DilipRajkumar vous devrez fournir plus de détails, par exemple un exemple de JSFiddle démontrant qu'il ne fonctionne pas dans IE 8.
Simon Lieschke
1
@SharpCoder vous ne le faites pas. L'endroit où le texte se coupe est dicté par la largeur de l'élément le contenant, c'est-à-dire qu'il tronque lorsqu'il déborderait de la largeur de l'élément.
Simon Lieschke
40

J'ai construit ce code en utilisant un certain nombre d'autres articles, avec les améliorations suivantes:

  1. Il utilise une recherche binaire pour trouver la longueur de texte qui est juste.
  2. Il gère les cas où les éléments d'ellipse sont initialement masqués en configurant un événement d'exposition unique qui réexécute le code des points de suspension lorsque l'élément est affiché pour la première fois. Ceci est pratique pour les vues maître-détail ou les vues arborescentes où certains éléments ne sont pas initialement affichés.
  3. Il ajoute éventuellement un attribut de titre avec le texte d'origine pour un effet de survol.
  4. Ajouté display: blockau style, donc les travées fonctionnent
  5. Il utilise le caractère points de suspension au lieu de 3 points.
  6. Il exécute automatiquement le script pour tout avec la classe .ellipsis

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));
Adam Tegen
la source
2
Belle. Bravo pour l'implémentation de ma suggestion de recherche binaire.
StanleyH
2
Juste un petit mot ... cela vaut la peine d'ajouter .css ('max-width', 'none') à la variable tempElement ... De cette façon, vous pouvez utiliser une déclaration max-width dans votre css, ce qui rend le plugin beaucoup plus flexible (du moins pour la plupart des cas d'utilisation que j'ai). Beau travail en tout cas. :)
gordyr
3
Il s'agit d'une mise en œuvre beaucoup plus rapide que la réponse acceptée ci-dessus. Si vous avez plusieurs éléments .ellipsis et que vous faites quelque chose de dynamique avec eux, celui-ci fonctionne beaucoup mieux.
mjvotaw
Pouvez-vous donner un exemple? Ma question est ici: stackoverflow.com/questions/26344520/…
SearchForKnowledge
La recherche binaire est préférable mais pas avec de très petits ensembles de données et dans ce cas, elle entrave les performances par rapport à une recherche linéaire directe telle que indexOf () ... apparemment
user1360809
20

Ma réponse ne prend en charge que le texte sur une seule ligne. Consultez le commentaire de gfullam ci-dessous pour le fork multi-lignes, cela semble assez prometteur.

J'ai réécrit le code de la première réponse plusieurs fois, et je pense que cela devrait être le plus rapide.

Il trouve d'abord une longueur de texte «estimée», puis ajoute ou supprime un caractère jusqu'à ce que la largeur soit correcte.

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

entrez la description de l'image ici

Après avoir trouvé une longueur de texte «estimée», des caractères sont ajoutés ou supprimés jusqu'à ce que la largeur souhaitée soit atteinte.

Je suis sûr qu'il a besoin d'être peaufiné, 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);
Mikey G
la source
3
Votre solution n'est peut-être pas la meilleure, mais elle est très bien expliquée. Et j'aime ce type de logique d'approximation. +1 :)
Flater
2
J'ai bifurqué ceci pour ajouter la prise en charge des zones de texte et de la troncature des ellipses multilignes (verticales): jsfiddle.net/gfullam/j29z7381 (j'aime la logique d'approximation BTW)
gfullam
19

Juste au cas où vous vous retrouveriez ici en 2013 - voici une approche css pure que j'ai trouvée ici: http://css-tricks.com/snippets/css/truncate-string-with-ellipsis/

.truncate {
  width: 250px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

Ça marche bien.

Joseph Juhnke
la source
1
FWIW, text-overflowne fonctionne pas avec des textareaéléments (à partir de 2015). Si vous avez besoin de support, textareavous pouvez y parvenir en modifiant la réponse acceptée ou en utilisant cette fourchette .
gfullam
18

J'ai fait un plugin jQuery vraiment cool pour gérer toutes les variétés d'ellipse de texte est 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.

Jeremy Horn
la source
8

Un plugin jQuery plus flexible vous permettant de conserver un élément après les points de suspension (par exemple un bouton "read-more") et de mettre à jour onWindowResize. Cela fonctionne également autour du texte avec un balisage:

http://dotdotdot.frebsite.nl

Mat
la source
Je viens de tester ce plugin, mais je n'ai pas pu le faire fonctionner. Trunk8 était un meilleur choix pour moi.
Guilherme Garnier
8

Le plugin jQuery trunk8 prend en charge plusieurs lignes et peut utiliser n'importe quel html, pas seulement des caractères d'ellipse, pour le suffixe de troncature: https://github.com/rviscomi/trunk8

Démo ici: http://jrvis.com/trunk8/

Eliot Sykes
la source
ouais mais c'est ancien maintenant. ressemble à ce n'est pas pris en charge?
user2513846
1
Il semble qu'il soit activement soutenu - au moment de la rédaction (mars 2016), les numéros et les PR montrent une activité récente impliquant le créateur du projet.
Eliot Sykes
5

Il existe en fait un moyen assez simple de le faire dans CSS en exploitant le fait qu'IE étend cela avec des supports non standard et FF:after

Vous pouvez également le faire dans JS si vous le souhaitez en inspectant le scrollWidth de la cible et en le comparant à la largeur de ses parents, mais à mon avis, c'est moins robuste.

Edit: c'est apparemment plus développé que je ne le pensais. Le support CSS3 peut bientôt exister, et certaines extensions imparfaites sont disponibles pour que vous puissiez les essayer.

Ce dernier est une bonne lecture.

Annakata
la source
En fait, je préfère la solution JS - car elle n'ajoute "..." que si le texte est plus large que l'espace disponible.
BlaM le
3

J'avais fait quelque chose de similaire pour un client récemment. Voici une version de ce que j'ai fait pour eux (exemple testé dans toutes les dernières versions de navigateur sur Win Vista). Pas parfait sur tout le plateau, mais pourrait être modifié assez facilement.

Démo: http://enobrev.info/ellipsis/

Code:

<html>
    <head>
        <script src="http://www.google.com/jsapi"></script>
        <script>            
            google.load("jquery", "1.2.6");
            google.setOnLoadCallback(function() {
                $('.longtext').each(function() {
                    if ($(this).attr('scrollWidth') > $(this).width()) {
                        $more = $('<b class="more">&hellip;</b>');

                        // add it to the dom first, so it will have dimensions
                        $(this).append($more);

                        // now set the position
                        $more.css({
                            top: '-' + $(this).height() + 'px',
                            left: ($(this).attr('offsetWidth') - $more.attr('offsetWidth')) + 'px'
                        });
                    }
                });
            });
        </script>

        <style>
            .longtext {
                height: 20px;
                width: 300px;
                overflow: hidden;
                white-space: nowrap;
                border: 1px solid #f00;
            }

            .more {
                z-index: 10;
                position: relative;
                display: block;
                background-color: #fff;
                width: 18px;
                padding: 0 2px;
            }
        </style>
    </head>
    <body>
        <p class="longtext">This is some really long text.  This is some really long text.  This is some really long text.  This is some really long text.</p>
    </body>
</html>
enobrev
la source
3

Eh bien, une solution simple, qui n'ajoute pas tout à fait le "...", mais qui empêche le <h2> de se diviser en deux lignes serait d'ajouter ce bit de css:

h2 {
    height:some_height_in_px; /* this is the height of the line */
    overflow:hidden; /* so that the second (or third, fourth, etc.)
                        line is not visible */
}

J'ai réfléchi un peu plus et j'ai trouvé cette solution, vous devez envelopper le contenu textuel de votre balise h2 avec une autre balise (par exemple, une étendue) (ou bien envelopper les h2 avec quelque chose qui a la hauteur donnée) et ensuite vous pouvez utiliser ce type de javascript pour filtrer les mots inutiles:

var elems = document.getElementById('conainter_of_h2s').
                     getElementsByTagName('h2');

    for ( var i = 0, l = elems.length; i < l; i++) {
        var span = elems.item(i).getElementsByTagName('span')[0];
        if ( span.offsetHeight > elems.item(i).offsetHeight ) {
            var text_arr = span.innerHTML.split(' ');
            for ( var j = text_arr.length - 1; j>0 ; j--) {
                delete text_arr[j];
                span.innerHTML = text_arr.join(' ') + '...';
                if ( span.offsetHeight <= 
                                        elems.item(i).offsetHeight ){
                    break;
                }
            }
        }
    }
Ramuns Usovs
la source
En fait, j'ai pensé à l'utiliser comme base pour une solution possible, mais je ne sais pas si - sur cette base - il serait possible de savoir si tout le texte est maintenant affiché ou si j'ai besoin de le raccourcir et d'ajouter " ... ". Le couper aurait l'air bizarre.
BlaM
3

Voici une autre solution JavaScript. Fonctionne très bien et très vite.

https://github.com/dobiatowski/jQuery.FastEllipsis

Testé sur Chrome, FF, IE sous Windows et Mac.

Adam Lukaszczyk
la source
Bien que ce soit moins automatique, j'ai trouvé que c'était une solution plus précise que la réponse d' Adam Tegen . Ce script nécessite que le nombre maximum de lignes de texte soit spécifié au lieu de deviner.
donut
3

Il existe une solution pour le texte multiligne avec du css pur. Cela s'appelle line-clamp, mais cela ne fonctionne que dans les navigateurs Webkit. Il existe cependant un moyen d'imiter cela dans tous les navigateurs modernes (tout ce qui est plus récent que IE8.) De plus, cela ne fonctionnera que sur des arrière-plans solides car vous avez besoin d'une image d'arrière-plan pour masquer les derniers mots de la dernière ligne. Voici comment ça se passe:

Compte tenu de ce html:

<p class="example" id="example-1">
    Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</p>

Voici le CSS:

p {
    position:relative;
    line-height:1.4em;
    height:4.2em;      /* 3 times the line-height to show 3 lines */
}
p::after {
    content:"...";
    font-weight:bold;
    position:absolute;
    bottom:0;
    right:0;
    padding:0 20px 1px 45px;
    background:url(ellipsis_bg.png) repeat-y;
}

ellipsis_bg.png étant une image de la même couleur que votre arrière-plan, qui ferait environ 100px de large et aurait la même hauteur que votre hauteur de ligne.

Ce n'est pas très joli, car votre texte peut être coupé au milieu d'une lettre, mais cela peut être utile dans certains cas.

Référence: http://www.css-101.org/articles/line-clamp/line-clamp_for_non_webkit-based_browsers.php

Jules Colle
la source
C'est bien, mais vous devez être sûr que votre texte est suffisamment long, car ce CSS ajoutera "..." même si le texte est suffisamment court pour tenir dans l'espace disponible. BTW: La même réponse a été fournie par Apopii il y a environ un mois;)
BlaM
@BlaM À peu près la même chose. Mais je pense que l'astuce du dégradé est soignée et que ce code est en CSS au lieu de SASS, donc je pense qu'il vaut la peine d'être une réponse distincte.
Jules Colle
3

Ellipsis multi-lignes CSS pur pour le contenu texte:

.container{
    position: relative;  /* Essential */
    background-color: #bbb;  /* Essential */
    padding: 20px; /* Arbritrary */
}
.text {
    overflow: hidden;  /* Essential */
    /*text-overflow: ellipsis; Not needed */
    line-height: 16px;  /* Essential */
    max-height: 48px; /* Multiples of line-height */
}
.ellipsis {
    position: absolute;/* Relies on relative container */
    bottom: 20px; /* Matches container padding */
    right: 20px; /* Matches container padding */
    height: 16px; /* Matches line height */
    width: 30px; /* Arbritrary */
    background-color: inherit; /* Essential...or specify a color */
    padding-left: 8px; /* Arbritrary */
}
<div class="container">
    <div class="text">
        Lorem ipsum dolor sit amet, consectetur eu in adipiscing elit. Aliquam consectetur venenatis blandit. Praesent vehicula, libero non pretium vulputate, lacus arcu facilisis lectus, sed feugiat tellus nulla eu dolor. Nulla porta bibendum lectus quis euismod. Aliquam volutpat ultricies porttitor. Cras risus nisi, accumsan vel cursus ut, sollicitudin vitae dolor. Fusce scelerisque eleifend lectus in bibendum. Suspendisse lacinia egestas felis a volutpat. Aliquam volutpat ultricies porttitor. Cras risus nisi, accumsan vel cursus ut, sollicitudin vitae dolor. Fusce scelerisque eleifend lectus in bibendum. Suspendisse lacinia egestas felis a volutpat.
    </div>
    <div class="ellipsis">...</div>
</div>

Veuillez consulter l'extrait pour un exemple en direct.

Jason Williams
la source
2

Ceci est similaire à celui d'Alex mais le fait en temps journal au lieu de linéaire, et prend un paramètre maxHeight.

jQuery.fn.ellipsis = function(text, maxHeight) {
  var element = $(this);
  var characters = text.length;
  var step = text.length / 2;
  var newText = text;
  while (step > 0) {
    element.html(newText);
    if (element.outerHeight() <= maxHeight) {
      if (text.length == newText.length) {
        step = 0;
      } else {
        characters += step;
        newText = text.substring(0, characters);
      }
    } else {
      characters -= step;
      newText = newText.substring(0, characters);
    }
    step = parseInt(step / 2);
  }
  if (text.length > newText.length) {
    element.html(newText + "...");
    while (element.outerHeight() > maxHeight && newText.length >= 1) {
      newText = newText.substring(0, newText.length - 1);
      element.html(newText + "...");
    }
  }
};
Dave Aaron Smith
la source
2

Il existe une solution jQuery simple de Devon Govett :

https://gist.github.com/digulla/5796047

Pour l'utiliser, appelez simplement ellipsis () sur un objet jQuery. Par exemple:

$ ("span"). ellipsis ();

BlaM
la source
J'étais sur le point de publier le même lien. :)
Gumbo
Le lien dans ce post est mort.
Justin Tanner
J'ai ajouté un lien de secours
BlaM
1

J'ai réécrit la fonction d'Alex pour l'utiliser dans la bibliothèque MooTools. Je l'ai changé un peu en saut de mots plutôt que d'ajouter les points de suspension au milieu d'un mot.

Element.implement({
ellipsis: function() {
    if(this.getStyle("overflow") == "hidden") {
        var text = this.get('html');
        var multiline = this.hasClass('multiline');
        var t = this.clone()
            .setStyle('display', 'none')
            .setStyle('position', 'absolute')
            .setStyle('overflow', 'visible')
            .setStyle('width', multiline ? this.getSize().x : 'auto')
            .setStyle('height', multiline ? 'auto' : this.getSize().y)
            .inject(this, 'after');

        function height() { return t.measure(t.getSize).y > this.getSize().y; };
        function width() { return t.measure(t.getSize().x > this.getSize().x; };

        var func = multiline ? height.bind(this) : width.bind(this);

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

        this.set('html', t.get('html'));
        t.dispose();
    }
}
});
j'aime l'Italie
la source
1

Je n'ai pas trouvé de script qui fonctionnait exactement comme je le voulais, tout comme le mien pour jQuery - pas mal d'options à définir avec plus sur leur chemin :)

https://github.com/rmorse/AutoEllipsis

rmorse
la source
1

J'ai été un peu surpris par le comportement du css.

var cssEllipsis = 
{   "width": "100%","display": "inline-block", 
"vertical-align": "middle", "white-space": "nowrap", 
"overflow": "hidden", "text-overflow": "ellipsis" 
};

Sauf si j'ai fourni la largeur du contrôle auquel j'avais besoin de lier les points de suspension, cela ne soutenait pas ma cause. La largeur est-elle une propriété incontournable à ajouter ??? Veuillez mettre vos pensées.

Premanshu
la source
1

FAITES L'ELLIPSIS EN UTILISANT UNIQUEMENT CSS

<html>
<head>
<style type="text/css">
#ellipsisdiv {
    width:200px;
    white-space: nowrap;  
    overflow: hidden;  
    text-overflow: ellipsis;  
}  
</style>
</head>
<body>
<div id="ellipsisdiv">
This content is more than 200px and see how the the ellipsis comes at the end when the content width exceeds the div width.
</div>
</body>
</html>

* Ce code fonctionne sur la plupart des navigateurs actuels. Si vous rencontrez un problème avec Opera et IE (ce que vous ne serez probablement pas), ajoutez-les dans le style:

-o-text-overflow: ellipsis;  
-ms-text-overflow: ellipsis;

* Cette fonctionnalité fait partie de CSS3. Sa syntaxe complète est:

text-overflow: clip|ellipsis|string;
Robin Rizvi
la source
1

Voici une belle bibliothèque de widgets / plugins qui a des points de suspension intégrés: http://www.codeitbetter.co.uk/widgets/ellipsis/ Tout ce dont vous avez besoin pour faire référence à la bibliothèque et appeler ce qui suit:

<script type="text/javascript"> 
   $(document).ready(function () { 
      $(".ellipsis_10").Ellipsis({ 
         numberOfCharacters: 10, 
         showLessText: "less", 
         showMoreText: "more" 
      }); 
   }); 
</script> 
<div class="ellipsis_10"> 
   Some text here that's longer than 10 characters. 
</div>
Tim
la source
1

vous pouvez faire cela beaucoup plus facilement avec css uniquement, par exemple: mode sass

.truncatedText {
   font-size: 0.875em;
   line-height: 1.2em;
   height: 2.4em; // 2 lines * line-height
   &:after {
      content: " ...";
   }
}

et vous avez des points de suspension;)

Apopii Dumitru
la source
0

Tout comme @acSlater, je n'ai pas trouvé quelque chose pour ce dont j'avais besoin, alors j'ai roulé le mien. Partage au cas où quelqu'un d'autre pourrait utiliser:

Méthode:
ellipsisIfNecessary(mystring,maxlength);
Usage:
trimmedString = ellipsisIfNecessary(mystring,50);
Code et lien de démonstration: https://gist.github.com/cemerson/10368014
Christopher D. Emerson
la source
Deux annotations: a) Ce code ne vérifie pas la taille réelle d'un élément HTML. Vous devez spécifier une longueur donnée - ce qui peut être la fonctionnalité requise, mais qui est en fait simple à faire. b) Vous ajoutez simplement "..." à la fin de la chaîne. Il y a un signe de points de suspension "…" que vous pourriez / devriez utiliser.
BlaM
Hey @BlaM - le code vérifie en fait la longueur par rapport au paramètre maxlength. Cela fonctionne au moins pour moi. Cela dit - ce n'est que mon humble cas particulier pour ma situation particulière. N'hésitez pas à utiliser l'une des solutions ci-dessus si celle-ci ne convient pas à votre situation.
Christopher
Oui, cela fonctionne avec une "longueur", mais pas avec une "largeur" ​​(taille de pixel).
BlaM
Idée intéressante - n'hésitez pas à créer une version mise à jour avec support pour cela. Je n'en ai pas besoin maintenant mais cela pourrait être utile à l'avenir.
Christopher
0
<html>
<head>
    <!-- By Warren E. Downs, copyright 2016.  Based loosely on a single/multiline JQuery using example by Alex,
    but optimized to avoid JQuery, to use binary search, to use CSS text-overflow: ellipsis for end,
    and adding marquee option as well.
    Credit: Marquee: http://jsfiddle.net/jonathansampson/xxuxd/
            JQuery version: http://stackoverflow.com/questions/536814/insert-ellipsis-into-html-tag-if-content-too-wide
            (by Alex, http://stackoverflow.com/users/71953/alex)
            (Improved with Binary Search as suggested by StanleyH, http://stackoverflow.com/users/475848/stanleyh)
    -->
    <meta content="text/html;charset=utf-8" http-equiv="Content-Type">
    <meta content="utf-8" http-equiv="encoding">
    <style>

        .single {
            overflow:hidden;
            white-space: nowrap;
            width: 10em;
            padding: 10px;
            margin: 0 auto;
            border: solid 1px blue;
        }

        .multiline {
            overflow: hidden;
            white-space: wrap;
            width: 10em;
            height: 4.5em;
            padding: 10px;
            margin: 0 auto;
            border: solid 1px blue;
        }

        .marquee {
            overflow: hidden;
            width: 40em;
            padding: 10px;
            margin: 0 auto;
            border: solid 1px blue;
        }

</style>
    <script>
        var _marqueeNumber=0;
        // mode=start,end,middle
        function clipText(text, len, mode) {
            if(!mode) { mode="end"; }
            else { mode=mode.toLowerCase(); }
            if(mode == "start") { return "&hellip;"+clipText(text,len,"_start"); }
            if(mode == "_start") { return text.substr(text.length - len); }
            if(mode == "middle") { 
                return clipText(text, len/2, "end") + clipText(text, len/2, "_start");
            }
            return text.substr(0, len) + "&hellip;";
        }

        function generateKeyframes(clsName, start, end) {
            var sec=5;
            var totalLen=parseFloat(start)-parseFloat(end);
            if(start.indexOf('em') > -1)      { sec=Math.round(totalLen/3); }
            else if(start.indexOf('px') > -1) { sec=Math.round(totalLen/42); }

            var style = document.createElement('style');
            style.type = 'text/css';
            style.innerHTML = 'body {}';
            document.getElementsByTagName('head')[0].appendChild(style);
            this.stylesheet = document.styleSheets[document.styleSheets.length-1];
            try {
                this.stylesheet.insertRule('.'+clsName+' {\n'+
                    '    animation: '+clsName+' '+sec+'s linear infinite;\n'+
                    '}\n', this.stylesheet.rules.length);
                this.stylesheet.insertRule('.'+clsName+':hover {\n'+
                    '    animation-play-state: paused\n'+
                    '}\n', this.stylesheet.rules.length);
                this.stylesheet.insertRule('@keyframes '+clsName+' {\n'+
                    '    0%   { text-indent: '+start+' }\n'+
                    '    100% { text-indent: '+end+' }\n'+
                    '}', this.stylesheet.rules.length);
            } catch (e) {
                console.log(e.message);
            }
        }

        function addClone(el, multiline, estyle) {
            if(!estyle) { 
                try { estyle=window.getComputedStyle(el); }
                catch(e) { return null; }
            }
            var t = el.cloneNode(true);
            var s=t.style;
            //s.display='none';
            s.visibility='hidden'; // WARNING: Infinite loop if this is not hidden (e.g. while testing)
            s.display='inline-block';
            s.background='black';
            s.color='white';
            s.position='absolute';
            s.left=0;
            s.top=0;
            s.overflow='visible';
            s.width=(multiline ? parseFloat(estyle.width) : 'auto');
            s.height=(multiline ? 'auto' : parseFloat(estyle.height));

            el.parentNode.insertBefore(t, el.nextSibling);

            return t;
        }
        function getTextWidth(el, multiline) {
            var t=addClone(el, multiline);
            if(!t) { return null; }
            var ts=window.getComputedStyle(t);
            var w=ts.width;
            if(multiline) {
                var es=window.getComputedStyle(el);
                var lines=Math.round(parseInt(ts.height)/parseInt(es.height))*2+0.5;
                w=w+'';
                var unit=''; // Extract unit
                for(var xa=0; xa<w.length; xa++) {
                    var c=w[xa];
                    if(c <= '0' || c >= '9') { unit=w.substr(xa-1); }
                }
                w=parseFloat(w);
                w*=lines; // Multiply by lines
                w+=unit; // Append unit again
            }
            t.parentNode.removeChild(t);
            return w;
        }

        // cls=class of element to ellipsize
        // mode=start,end,middle,marq (scrolling marquee instead of clip)
        function ellipsis(cls, mode) {
            mode=mode.toLowerCase();
            var elems=document.getElementsByClassName(cls);
            for(xa in elems) {
                var el=elems[xa];
                var multiline = el.className ? el.className.indexOf('multiline') > -1 : true;
                if(mode == "marq") {       
                    var w=getTextWidth(el, multiline);
                    if(!w) { continue; }
                    var mCls="dsmarquee"+(_marqueeNumber++);
                    var es=window.getComputedStyle(el);
                    generateKeyframes(mCls,es.width, '-'+w);
                    el.className+=" "+mCls; 
                    continue; 
                }
                if(mode == "end" && !multiline) { el.style.textOverflow="ellipsis"; continue; }
                var estyle=null;
                try { estyle=window.getComputedStyle(el); }
                catch(e) { continue; }
                if(estyle.overflow == "hidden") {
                    var text = el.innerHTML;
                    var t=addClone(el, multiline, estyle);

                    function height() {
                        var ts=window.getComputedStyle(t);
                        var es=window.getComputedStyle(el);
                        return parseFloat(ts.height) - parseFloat(es.height); 
                    }
                    function width() { 
                        var ts=window.getComputedStyle(t);
                        var es=window.getComputedStyle(el);
                        return parseFloat(ts.width) - parseFloat(es.width); 
                    }

                    var tooLong = multiline ? height : width;

                    var len=text.length;
                    var diff=1;
                    var olen=0;
                    var jump=len/2;
                    while (len > 0) {
                        var diff=tooLong();
                        if(diff > 0) { len-=jump; jump/=2; }
                        else if(diff < 0) { len+=jump; }
                        len=Math.round(len);
                        //alert('len='+len+';olen='+olen+';diff='+diff+';jump='+jump+';t='+JSON.stringify(t.innerHTML));
                        t.innerHTML=clipText(text, len, mode);
                        if(olen == len) { break; }
                        olen=len;
                    }
                    el.innerHTML=t.innerHTML;
                    t.parentNode.removeChild(t);
                }           
                //break;
                t.style.visibility='hidden';
            }
        }

        function testHarness() {
            ellipsis('ellipsis1', 'start'); 
            ellipsis('ellipsis2', 'end'); 
            ellipsis('ellipsis3', 'middle'); 
            ellipsis('marquee', 'marq')
        }
    </script>
    </head>
    <body onload="testHarness()">
    <div class="single ellipsis1" style="float:left">some long text that should be clipped left</div>
    <div class="single ellipsis2" style="float:right">right clip long text that should be clipped</div>
    <div class="single ellipsis3" style="float:center">some long text that should be clipped in the middle</div>

    <br />

    <p class="single marquee">Windows 8 and Windows RT are focused on your lifeyour friends and family, your apps, and your stuff. With new things like the <a href="http://windows.microsoft.com/en-US/windows-8/start-screen">Start screen</a>, <a href="http://windows.microsoft.com/en-US/windows-8/charms">charms</a>, and a <a href="http://windows.microsoft.com/en-US/windows-8/microsoft-account">Microsoft account</a>, you can spend less time searching and more time doing.</p>
    &nbsp;

    <br />

    <div class="multiline ellipsis1" style="float:left">Test test test test test test, some more long text, such as asdasdasdasdasd, that should be multiline clipped left(*)</div>

    <div class="multiline ellipsis2" style="float:right">right clip multiline long text, such as Test test test test test test, and some more long text that should be multiline clipped right.</div>

    <div class="multiline ellipsis3" style="float:center">Test test test test test test, some more long text, such as asdasdasdasdasd, that should be multiline clipped in the middle(*)</div>

    <br />

    <p class="multiline marquee">Multiline Marquee: Windows 8 and Windows RT are focused on your lifeyour friends and family, your apps, and your stuff. With new things like the <a href="http://windows.microsoft.com/en-US/windows-8/start-screen">Start screen</a>, <a href="http://windows.microsoft.com/en-US/windows-8/charms">charms</a>, and a <a href="http://windows.microsoft.com/en-US/windows-8/microsoft-account">Microsoft account</a>, you can spend less time searching and more time doing.</p>
    &nbsp;

    </body>
</html>
Warren Downs
la source