Wstaw wielokropek (…) do znacznika HTML, jeśli zawartość jest zbyt szeroka

148

Mam stronę internetową z elastycznym układem, który zmienia swoją szerokość, jeśli rozmiar okna przeglądarki zostanie zmieniony.

W tym układzie są nagłówki (h2 ), które będą miały zmienną długość (w rzeczywistości są to nagłówki z postów na blogu, nad którymi nie mam kontroli). Obecnie - jeśli są szersze od okna - są podzielone na dwie linie.

Czy istnieje eleganckie, przetestowane (na różnych przeglądarkach) rozwiązanie - na przykład z jQuery - które skraca wewnętrzny kod HTML tego tagu nagłówka i dodaje „...”, jeśli tekst byłby zbyt szeroki, aby zmieścić się w jednym wierszu na bieżącym ekranie / szerokość pojemnika?

BlaM
źródło
1
Zaktualizowana odpowiedź z 2014 roku: stackoverflow.com/a/22811590/759452
Adrien Be
Stworzyłem wtyczkę opartą na tym wątku, która używa białych znaków CSS i zawijania słów do formatowania tekstu. github.com/nothrem/jQuerySmartEllipsis
Radek Pech

Odpowiedzi:

119

Mam rozwiązanie działające w FF3, Safari i IE6 + z tekstem jedno- i wielowierszowym

.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
źródło
22
Fajnie, szukałem, jak poradzić sobie z przepełnieniem wielu linii. Jedno ulepszenie: zamiast dodawać trzy kropki, dodaj wielokropek, „…”.
Simon Lieschke
4
To działa bardzo dobrze. Powinieneś to opublikować w witrynie jQuery.
Edgar,
1
Chociaż w IE, jeśli funkcja wielokropka zostanie zastosowana do elementu div, który ma tylko łącze, po wielokropku łącze znika. Jakieś wskazówki na ten temat?
Chantz,
6
Jeśli chcesz zobaczyć to w akcji, możesz zobaczyć to tutaj (przepraszam za złe formatowanie w kodzie wtyczki) jsfiddle.net/danesparza/TF6Rb/1
Dan Esparza
22
Aby poprawić wydajność, wykonaj wyszukiwanie binarne zamiast usuwać po jednym znaku w pętli „while”. Jeśli 100% tekstu nie pasuje, wypróbuj 50% tekstu; wtedy 75% tekstu, jeśli 50% pasuje, lub 25%, jeśli 50% nie pasuje, itp.
StanleyH,
182

Poniższe rozwiązanie CSS do obcinania tekstu w jednym wierszu działa ze wszystkimi przeglądarkami wymienionymi na stronie http://www.caniuse.com w momencie pisania, z wyjątkiem przeglądarki Firefox 6.0. Zauważ, że JavaScript jest całkowicie niepotrzebny, chyba że potrzebujesz obsługi zawijania tekstu wielowierszowego lub wcześniejszych wersji przeglądarki Firefox.

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

Jeśli potrzebujesz wsparcia dla wcześniejszych wersji Firefoksa, sprawdź moją odpowiedź na to drugie pytanie .

Simon Lieschke
źródło
2
Jest to o rząd wielkości szybsze niż podejście z jQuery. Działa dobrze w IE7 + i Chrome.
JDB nadal pamięta Monikę z
3
Działa to również dobrze w starożytnych przeglądarkach. Z powodzeniem używaliśmy go w Google w ~ 2004 roku, gdzie musieliśmy wspierać lub z wdziękiem degradować niektóre naprawdę narożne przeglądarki.
ElBel,
2
JS Fiddle dla tych, którzy chcą go wypróbować
Deepak Bala
@DilipRajkumar, musisz podać więcej szczegółów, np. Przykład JSFiddle pokazujący, że nie działa w IE 8.
Simon Lieschke
1
@SharpCoder nie. To, gdzie tekst się ucina, jest podyktowane szerokością elementu, który go zawiera, tj. Obcina się, gdy przekracza szerokość elementu.
Simon Lieschke
40

Zbudowałem ten kod, używając wielu innych postów, z następującymi ulepszeniami:

  1. Używa wyszukiwania binarnego, aby znaleźć odpowiednią długość tekstu.
  2. Obsługuje przypadki, w których element (y) wielokropka są początkowo ukryte przez ustawienie jednorazowego zdarzenia pokazu, które ponownie uruchamia kod wielokropka, gdy element jest wyświetlany po raz pierwszy. Jest to przydatne w przypadku widoków głównych szczegółów lub widoków drzew, w których niektóre elementy nie są początkowo wyświetlane.
  3. Opcjonalnie dodaje atrybut tytułu do oryginalnego tekstu, aby uzyskać efekt najechania kursorem.
  4. Dodano display: blockdo stylu, dzięki czemu działa
  5. Używa znaku wielokropka zamiast 3 kropek.
  6. Automatycznie uruchamia skrypt dla czegokolwiek z klasą .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
źródło
2
Piękny. Brawo za wdrożenie mojej sugestii wyszukiwania binarnego.
StanleyH,
2
Krótka uwaga ... warto dodać .css ('max-width', 'none') do tempElement var ... W ten sposób możesz użyć deklaracji max-width w swoim css, dzięki czemu wtyczka będzie znacznie bardziej elastyczna (przynajmniej dla większości przypadków użycia, które mam). W każdym razie niezła robota. :)
gordyr
3
Jest to znacznie szybsza realizacja niż powyższa zaakceptowana odpowiedź. Jeśli masz wiele elementów .ellipsis i robisz z nimi coś dynamicznego, ten działa znacznie lepiej.
mjvotaw
Czy możesz podać przykład? Moje pytanie jest tutaj: stackoverflow.com/questions/26344520/…
SearchForKnowledge
Wyszukiwanie binarne jest lepsze, ale nie w przypadku bardzo małych zbiorów danych iw tym przypadku ogranicza wydajność w porównaniu z prostym wyszukiwaniem liniowym, takim jak indexOf () ... najwyraźniej
user1360809
20

Moja odpowiedź obsługuje tylko tekst jednowierszowy. Sprawdź komentarz gfullam poniżej na temat widelca wieloliniowego, wygląda całkiem obiecująco.

Kilka razy przepisałem kod z pierwszej odpowiedzi i myślę, że to powinno być najszybsze.

Najpierw znajduje „Szacowaną” długość tekstu, a następnie dodaje lub usuwa znak, aż szerokość będzie poprawna.

Logika, której używa, jest pokazana poniżej:

wprowadź opis obrazu tutaj

Po znalezieniu „szacunkowej” długości tekstu znaki są dodawane lub usuwane, aż do osiągnięcia żądanej szerokości.

Jestem pewien, że wymaga pewnych poprawek, ale oto kod:

(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.
źródło
3
Twoje rozwiązanie może nie być najlepsze, ale jest bardzo dobrze wyjaśnione. Podoba mi się taka logika aproksymacji. +1 :)
Flater
2
Rozwidliłem to, aby dodać obsługę obszarów tekstowych i wielowierszowego (pionowego) obcinania wielokropka: jsfiddle.net/gfullam/j29z7381 (lubię logikę przybliżenia BTW)
gfullam
19

Na wszelki wypadek, gdybyście wylądowali tutaj w 2013 roku - oto podejście do czystego CSS, które znalazłem tutaj: http://css-tricks.com/snippets/css/truncate-string-with-ellipsis/

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

To dobrze działa.

Joseph Juhnke
źródło
1
FWIW, text-overflownie działa z textareaelementami (stan na 2015). Jeśli potrzebujesz wsparcia textarea, możesz to osiągnąć, modyfikując zaakceptowaną odpowiedź lub korzystając z tego rozwidlenia .
gfullam
18

Zrobiłem naprawdę fajną wtyczkę jQuery do obsługi wszystkich odmian wielokropka o nazwie ThreeDots @ http://tpgblog.com/threedots

Jest znacznie bardziej elastyczny niż podejścia CSS i obsługuje znacznie bardziej zaawansowane, konfigurowalne zachowania i interakcje.

Cieszyć się.

Jeremy Horn
źródło
8

Bardziej elastyczna wtyczka jQuery umożliwiająca zachowanie elementu po elipsie (na przykład przycisk „czytaj więcej”) i aktualizację onWindowResize. Działa również w przypadku tekstu ze znacznikami:

http://dotdotdot.frebsite.nl

Matt
źródło
Właśnie przetestowałem tę wtyczkę, ale nie mogłem jej uruchomić. Trunk8 był dla mnie lepszym wyborem.
Guilherme Garnier
8

Wtyczka trunk8 jQuery obsługuje wiele wierszy i może używać dowolnego kodu HTML, a nie tylko znaków wielokropka, dla przyrostka obcięcia: https://github.com/rviscomi/trunk8

Demo tutaj: http://jrvis.com/trunk8/

Eliot Sykes
źródło
tak, ale to jest teraz starożytne. wygląda na to, że nie jest obsługiwany?
user2513846
1
Wygląda na to, że jest aktywnie wspierany - w momencie pisania (marzec 2016 r.) Numery i PR pokazują ostatnią aktywność twórcy projektu.
Eliot Sykes,
5

W CSS można to zrobić w dość prosty sposób wykorzystując fakt, że IE rozszerza to o niestandardowe standardy i obsługę FF:after

Możesz to również zrobić w JS, jeśli chcesz, sprawdzając scrollWidth celu i porównując go z szerokością jego rodziców, ale imho jest to mniej niezawodne.

Edycja: najwyraźniej jest bardziej rozwinięta niż myślałem. Wkrótce może pojawić się obsługa CSS3, a niektóre niedoskonałe rozszerzenia są dostępne do wypróbowania.

Ta ostatnia to dobra lektura.

annakata
źródło
Właściwie wolę rozwiązanie JS - ponieważ dodaje „...” tylko wtedy, gdy tekst jest szerszy niż dostępna przestrzeń.
BlaM
3

Ostatnio zrobiłem coś podobnego dla klienta. Oto wersja tego, co dla nich zrobiłem (przykład przetestowany we wszystkich najnowszych wersjach przeglądarek w systemie Win Vista). Nie jest idealny na całej planszy, ale można go dość łatwo dostosować.

Demo: http://enobrev.info/ellipsis/

Kod:

<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
źródło
3

Cóż, jednym prostym rozwiązaniem, które nie do końca dodaje „...”, ale zapobiega podziałowi <h2> na dwie linie, byłoby dodanie tego fragmentu 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 */
}

Przemyślałem to trochę dłużej i wymyśliłem takie rozwiązanie, musisz owinąć zawartość tekstową swojego tagu h2 innym tagiem (np. Span) (lub alternatywnie zawinąć h2s czymś, co ma podaną wysokość), a następnie możesz użyć tego rodzaju javascript, aby odfiltrować niepotrzebne słowa:

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
źródło
Właściwie myślałem o tym, aby wykorzystać to jako podstawę do ewentualnego rozwiązania, ale nie mam pojęcia, czy - na tej podstawie - dałoby się dowiedzieć, czy cały tekst jest teraz wyświetlany, czy też muszę go skrócić i dodać. " … ”. Samo odcięcie wyglądałoby dziwnie.
BlaM
3

Oto kolejne rozwiązanie JavaScript. Działa bardzo dobrze i bardzo szybko.

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

Przetestowano w Chrome, FF, IE w systemach Windows i Mac.

Adam Łukaszczyk
źródło
Chociaż jest to mniej automatyczne, stwierdziłem, że jest to dokładniejsze rozwiązanie niż odpowiedź Adama Tegena . Ten skrypt wymaga podania maksymalnej liczby wierszy tekstu zamiast zgadywania.
pączek
3

Istnieje rozwiązanie dla tekstu wielowierszowego z czystym CSS. Nazywa się line-clamp, ale działa tylko w przeglądarkach webkit. Jest jednak sposób, aby to naśladować we wszystkich nowoczesnych przeglądarkach (wszystkie nowsze niż IE8). Ponadto będzie działać tylko na jednolitym tle, ponieważ potrzebujesz obrazu tła, aby ukryć ostatnie słowa ostatniego wiersza. Oto jak to działa:

Biorąc pod uwagę ten 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>

Oto 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 to obraz tego samego koloru tła, który miałby około 100 pikseli szerokości i taką samą wysokość, jak wysokość linii.

Nie jest zbyt ładny, ponieważ tekst może być wycięty w środku litery, ale może być przydatny w niektórych przypadkach.

Źródła: http://www.css-101.org/articles/line-clamp/line-clamp_for_non_webkit-based_browsers.php

Jules Colle
źródło
To miłe, ale musisz mieć pewność, że twój tekst jest wystarczająco długi, ponieważ ten CSS doda "...", nawet jeśli tekst jest wystarczająco krótki, aby zmieścić się w dostępnej przestrzeni. BTW: Tej samej odpowiedzi udzielił Apopii około miesiąc temu;)
BlaM
@BlaM Rzeczywiście prawie to samo. Ale myślę, że sztuczka z gradientem jest zgrabna i ten kod w CSS zamiast SASS, więc myślę, że warto jest osobną odpowiedzią.
Jules Colle
3

Wielowierszowe wielokropki w czystym CSS dla zawartości tekstowej

.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>

Sprawdź fragment, aby zobaczyć przykład na żywo.

Jason Williams
źródło
2

Jest to podobne do Alexa, ale robi to w czasie logowania zamiast liniowo i przyjmuje parametr 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
źródło
2

Istnieje proste rozwiązanie jQuery autorstwa Devona Govetta :

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

Aby użyć, po prostu wywołaj ellipsis () na obiekcie jQuery. Na przykład:

$ ("span"). ellipsis ();

BlaM
źródło
Właśnie miałem zamieścić ten sam link. :)
Gumbo
Link w tym poście jest martwy.
Justin Tanner
Dodałem link
awaryjny
1

Przepisałem funkcję Alexa do biblioteki MooTools. Zmieniłem to trochę na skok słów, zamiast dodawać wielokropek w środku słowa.

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();
    }
}
});
kocham Włochy
źródło
1

Nie mogłem znaleźć skryptu, który działałby dokładnie tak, jak chciałem, więc zrobiłem mój własny dla jQuery - sporo opcji do ustawienia, a więcej na ich drodze :)

https://github.com/rmorse/AutoEllipsis

rmorse
źródło
1

Byłem jednak nieco zaskoczony zachowaniem css.

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

Chyba że podałem szerokość kontrolki, do której musiałem powiązać wielokropek, nie pomogło. Czy szerokość to właściwość, którą trzeba dodać ??? Proszę, przedstaw swoje myśli.

Premanshu
źródło
1

ZRÓB ELIPSY, UŻYWAJĄC TYLKO 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>

* Ten kod działa w większości obecnych przeglądarek. Jeśli napotkasz jakiś problem z Operą i IE (co prawdopodobnie nie będzie), dodaj je w stylu:

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

* Ta funkcja jest częścią CSS3. Jego pełna składnia to:

text-overflow: clip|ellipsis|string;
Robin Rizvi
źródło
1

Oto ładna biblioteka widżetów / wtyczek, która ma wbudowane wielokropki: http://www.codeitbetter.co.uk/widgets/ellipsis/ Wszystko, czego potrzebujesz, aby to zrobić, odwołaj się do biblioteki i wywołaj:

<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
źródło
1

możesz to zrobić dużo łatwiej tylko z css, na przykład: tryb sass

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

i masz wielokropek;)

Apopii Dumitru
źródło
0

Podobnie jak @acSlater nie mogłem znaleźć czegoś do tego, czego potrzebowałem, więc stworzyłem własne. Udostępnianie na wypadek, gdyby ktoś inny mógł użyć:

Metoda:
ellipsisIfNecessary(mystring,maxlength);
Stosowanie:
trimmedString = ellipsisIfNecessary(mystring,50);
Kod i link demonstracyjny: https://gist.github.com/cemerson/10368014
Christopher D. Emerson
źródło
Dwie adnotacje: a) Ten kod nie sprawdza rzeczywistego rozmiaru elementu HTML. Musisz określić daną długość - która może być wymaganą funkcjonalnością, ale w rzeczywistości jest trywialna. b) Po prostu dodajesz „...” na końcu ciągu. Jest tam znak wielokropka „…”, którego możesz / powinieneś użyć.
BlaM
Hej @BlaM - kod faktycznie porównuje długość z parametrem maxlength. Przynajmniej na mnie to działa. To powiedziawszy - to tylko moja skromna jednorazowa okazja do mojej szczególnej sytuacji. Możesz skorzystać z dowolnego z powyższych rozwiązań, jeśli to nie działa dobrze w Twojej sytuacji.
Christopher D. Emerson
Tak, działa z „długością”, ale nie z „szerokością” (rozmiarem w pikselach).
BlaM
Ciekawy pomysł - nie wahaj się stworzyć zaktualizowanej wersji z obsługą tego. Nie potrzebuję tego teraz, ale może mi się przydać w przyszłości.
Christopher D. Emerson
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
źródło