HTML - SADECE üç nokta etkinleştirildiğinde araç ipucunu nasıl gösterebilirim?


206

Sayfamda ellipsisstille birlikte dinamik veriler içeren bir açıklık var .

.my-class
{
  text-overflow: ellipsis;
  overflow: hidden;
  white-space: nowrap;  
  width: 71px;
}
<span id="myId" class="my-class"></span>
document.getElementById('myId').innerText = "...";

Bu öğeye aynı içeriğe sahip araç ipucuna eklemek istiyorum, ancak yalnızca içerik uzun olduğunda ve üç nokta ekranda belirdiğinde görünmesini istiyorum.

Bunu yapmanın bir yolu var mı?
Tarayıcı ellipsisetkinleştirildiğinde bir olay atar mı ?

* Tarayıcı: Internet Explorer


1
text-overflow:ellipsis;Firefox'ta hiç işe yaramadığını unutmayın - daha fazla bilgi için bu soruya bakın: stackoverflow.com/questions/4927257/…
Spudley

2
Sadece benzer bir şey yapmak zorunda kaldım. Olmadığını kontrol etme element.offsetWidth < element.scrollWidthgereği bu cevap Bugüne kadar yapılan çalışmalarla görünüyor.
Martin Smith


7
Posterity için not: text-overflow:ellipsis;artık Firefox'ta çalışıyor; Firefox 7'ye eklendi (Eylül 2011'de yayınlandı).
sleske

Yanıtlar:


161

Yerleşik üç nokta ayarını kullanarak bunu yapan ve titleMartin Smith'in yorumu üzerine isteğe bağlı özellik (jQuery ile) ekleyen bir yol var :

$('.mightOverflow').bind('mouseenter', function(){
    var $this = $(this);

    if(this.offsetWidth < this.scrollWidth && !$this.attr('title')){
        $this.attr('title', $this.text());
    }
});

4
Teşekkürler, bir cazibe gibi çalışır! Ancak daha verimli hale getirmek istiyorsanız bind () öğesini on () ile so: $ (document) .on ('mouseenter', '.mightOverflow', function () {...});
Ziad

17
Metin artık taşmıyorsa araç ipucunun otomatik olarak kaldırılmasını istiyorsanız: $ (document) .on ('mouseenter', '.mightOverflow', function () {var $ t = $ (this); var title = $ t.attr ('title'); if (! title) {if (this.offsetWidth <this.scrollWidth) $ t.attr ('title', $ t.text ())} başka {if (this.offsetWidth> = this.scrollWidth && title == $ t.text ()) $ t.removeAttr ('title')}});
Chris Janssen

1
mouseenter bağladığımız veya dinlediğimiz olaydır. Birisi gerçekten üzerlerine fareyi alana kadar araç ipucunu öğelere eklememiz gerekmez. Bu nedenle, ekleme işlemini "mightoverflow" sınıfına sahip DOM öğelerinden herhangi birinde mouseenter'in o noktasına kadar erteliyoruz. Tam Zamanında Araç İpuçları
Jason Kleban

2
"As of jQuery 1.7, the .on() method is the preferred method for attaching event handlers to a document"daha fazla bilgi için bkz. api.jquery.com/bind ve api.jquery.com/on
Adrien Be

2
IE10'da çalışmaz - offsetWidth, scrollWidth ile aynıdır ve her ikisi de kesilmiş genişliği verir.
SsjCosty

59

İşte saf bir CSS çözümü. JQuery'ye gerek yok. Bir araç ipucu göstermez, bunun yerine içeriği fareyle üzerine gelindiğinde tam olarak genişletir.

Değiştirilen içeriğiniz varsa harika çalışır. Sonra her seferinde bir jQuery işlevi çalıştırmak zorunda kalmazsınız.

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

.might-overflow:hover {
    text-overflow: clip;
    white-space: normal;
    word-break: break-all;
}

18
Araç ipucu kadar iyi değil, çünkü düzeni bozabilir.
Alexander

2
Araç ipuçlarıyla ilgili sorun, en azından şimdilik mobil cihazlarda çalışmaz. Bu cevap düzeni okuyabilir (muhtemelen: bozacaktır), ancak örneğin üzerine gelinen eleman için farklı bir arka plan rengine sahip olacak şekilde uyarlanabilir. Bu hala mobil cihazlarda çalışmaz, ancak masaüstü için başka bir seçenektir.
trysis

1
İhtiyaçlarımı mükemmel bir şekilde karşılayan bu harika cevap için teşekkürler. Bazı JavaScript kullanarak, bloğun düzeni bozmaması için kesinlikle konumlandırıldığını hayal edebiliriz.
Niavlys

2
Bu güzel bir cevap, bir css sorunu javascript şişkin daha iyi. Açıkça üç nokta otomatik bir başlık seçeneğine sahip OLMALIDIR, şu anda uygulanma şekli anlamsızdır. Çok kötü css sadece izin vermez: son karakterler '...' ise fareyle üzerine gelin
John

32

uosɐſ'un cevabı temel olarak doğrudur, ancak muhtemelen mouseenter etkinliğinde yapmak istemezsiniz. Bu, öğenin üzerine her fareye bastığınızda, gerekli olup olmadığını belirlemek için hesaplama yapmasına neden olur. Elemanın boyutu değişmedikçe, bunu yapmak için hiçbir neden yoktur.

Öğe DOM'ye eklendikten hemen sonra bu kodu çağırmanız daha iyi olur:

var $ele = $('#mightOverflow');
var ele = $ele.eq(0);
if (ele.offsetWidth < ele.scrollWidth)
    $ele.attr('title', $ele.text());

Veya tam olarak ne zaman eklendiğini bilmiyorsanız, sayfanın yüklenmesi tamamlandıktan sonra bu kodu arayın.

bunu yapmanız gereken tek bir öğeden daha fazlasına sahipseniz, onlara aynı sınıfı ("mightOverflow" gibi) verebilir ve hepsini güncellemek için bu kodu kullanabilirsiniz:

$('.mightOverflow').each(function() {
    var $ele = $(this);
    if (this.offsetWidth < this.scrollWidth)
        $ele.attr('title', $ele.text());
});

+1, sayfa yüklemesinde yapmak daha basit görünüyor, ancak daha fazla olasılık sunuyor. yani. araç ipucunu "işaretlemek" için bir araç ipucu olan bu öğeye noktalı alt çizgiyle stil uygulamak isteyebilirsiniz. gibi$(".mightOverflow").each(function() { if( $(this).offsetWidth < $(this).scrollWidth && !$(this).attr('title')){ $(this).attr('title', $(this).text()); $(this).css('border-bottom', '1px dotted #A8A8A8'); } });
Adrien Be

'her fareyle üzerine geldiğinizde' yanlış (şimdi en azından - cevabın güncellenip güncellenmediğini bilmiyorum) Daha önce hesaplanıp hesaplanmadığını kontrol eder '&&! $ this.attr (' title ')'
Rune Jeppesen

Hayır, bu sadece title niteliğini tekrar eklemesini engeller. Gerekli olup olmadığını belirlemek için hesaplama hala yapılır. this.offsetWidth < this.scrollWidthve muhtemelen kontrol !$this.attr('title')her öğeyi farenin üzerinde yaptığınızda gerçekleştirilecektir.
Elezar

9
Bu yöntemin sorunu, tüm öğelerin bir kerede kontrol edilmesidir (potansiyel performans etkisi) ve yalnızca bir kez hesaplar, böylece kullanıcı tarayıcıyı küçültür veya genişlemesine neden olursa, artık kesilmemesine neden olur araç ipucunun varlığını güncelleyin. Kodunuzu yeniden pencere boyutuna yeniden eklemek, her öğenin boyutunu kontrol ettiği için bir performans sorunu olacaktır. "$ (Document) .sistem ( 'mouseenter', '.mightOverflow' ..." Olay yetkisinin kullanılmasına ve eleman mouseover kadar çek geciktirerek, sen anında güncelleyebilirsiniz ve bir anda yalnızca @ 1 elemanını kontrol
Chris Janssen

IE10'da çalışmaz - offsetWidth, scrollWidth ile aynıdır ve her ikisi de kesilmiş genişliği verir.
SsjCosty

18

İşte diğer iki saf CSS çözümü:

  1. Kesilmiş metni yerinde göster:

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

.overflow:hover {
  overflow: visible;
}

.overflow:hover span {
  position: relative;
  background-color: white;

  box-shadow: 0 0 4px 0 black;
  border-radius: 1px;
}
<div>
  <span class="overflow" style="float: left; width: 50px">
    <span>Long text that might overflow.</span>
  </span>
  Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ad recusandae perspiciatis accusantium quas aut explicabo ab. Doloremque quam eos, alias dolore, iusto pariatur earum, ullam, quidem dolores deleniti perspiciatis omnis.
</div>

  1. Rasgele bir "ipucu" göster :

.wrap {
  position: relative;
}

.overflow {
  white-space: nowrap; 
  overflow: hidden;
  text-overflow: ellipsis;
  
  pointer-events:none;
}

.overflow:after {
  content:"";
  display: block;
  position: absolute;
  top: 0;
  right: 0;
  width: 20px;
  height: 15px;
  z-index: 1;
  border: 1px solid red; /* for visualization only */
  pointer-events:initial;

}

.overflow:hover:after{
  cursor: pointer;
}

.tooltip {
  /* visibility: hidden; */
  display: none;
  position: absolute;
  top: 10;
  left: 0;
  background-color: #fff;
  padding: 10px;
  -webkit-box-shadow: 0 0 50px 0 rgba(0,0,0,0.3);
  opacity: 0;
  transition: opacity 0.5s ease;
}


.overflow:hover + .tooltip {
  /*visibility: visible; */
  display: initial;
  transition: opacity 0.5s ease;
  opacity: 1;
}
<div>
  <span class="wrap">
    <span class="overflow" style="float: left; width: 50px">Long text that might overflow</span>
    <span class='tooltip'>Long text that might overflow.</span>
  </span>
  Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ad recusandae perspiciatis accusantium quas aut explicabo ab. Doloremque quam eos, alias dolore, iusto pariatur earum, ullam, quidem dolores deleniti perspiciatis omnis.
</div>


Tam da aradığım şey buydu!
Praneet Nadkar

Mükemmel çözüm, tam da ihtiyacım olan şey. Teşekkür ederim !
Agu V

17

İşte benim jQuery eklentisi:

(function($) {
    'use strict';
    $.fn.tooltipOnOverflow = function() {
        $(this).on("mouseenter", function() {
            if (this.offsetWidth < this.scrollWidth) {
                $(this).attr('title', $(this).text());
            } else {
                $(this).removeAttr("title");
            }
        });
    };
})(jQuery);

Kullanımı:

$("td, th").tooltipOnOverflow();

Düzenle:

Bu eklenti için bir özgeçmiş yaptım. https://gist.github.com/UziTech/d45102cdffb1039d4415


1
IE10'da çalışmaz - offsetWidth, scrollWidth ile aynıdır ve her ikisi de kesilmiş genişliği verir.
SsjCosty

@SsjCosty IE 10 üzerinde neden test yapıyorsunuz? IE 10'u yükleyebilen herkes IE 11'i yükleyebildiğinden, bu noktada IE 10'u kullanan kimse olmamalıdır.
Tony Brix

Ah, desteklenen minimum IE sürümümüzün 10 olduğu bir şirket politikamız var. Ayrıca birçok müşterimiz (bazı bankalar ve çeşitli kurumlar) hala IE10 kullanıyor. Oh iyi.
SsjCosty

12

Üç noktanın gerçekten uygulanıp uygulanmadığını tespit etmeliyiz, ardından tam metni göstermek için bir araç ipucu göstermeliyiz. this.offsetWidth < this.scrollWidthÖğe yalnızca içeriğini tuttuğunda değil, yalnızca tam genişlikli Çince / Japonca / Korece karakterlerin metni için yalnızca bir veya iki piksel daha geniş olmadığında " " karşılaştırılarak yeterli değildir .

İşte bir örnek: http://jsfiddle.net/28r5D/5/

Üç nokta algılamayı iyileştirmenin bir yolunu buldum:

  1. this.offsetWidth < this.scrollWidthÖnce " " ile karşılaştırın , başarısız olursa # 2 numaralı adıma devam edin.
  2. Css stilini geçici olarak {'overflow': 'visible', 'white-space': 'normal', 'word-break': 'break-all'} olarak değiştirin.
  3. Tarayıcının geçiş yapmasına izin verin. Sözcük kaydırma gerçekleşirse, öğe yüksekliğini genişletir ve bu da üç nokta gerektiği anlamına gelir.
  4. Css stilini geri yükle.

İşte gelişimim: http://jsfiddle.net/28r5D/6/


10

Tarayıcının yerleşik araç ipucu yerine Bootstrap araç ipucunu kullanan bir jQuery eklentisi oluşturdum. Bunun eski tarayıcıda test edilmediğini lütfen unutmayın.

JSFiddle: https://jsfiddle.net/0bhsoavy/4/

$.fn.tooltipOnOverflow = function(options) {
    $(this).on("mouseenter", function() {
    if (this.offsetWidth < this.scrollWidth) {
        options = options || { placement: "auto"}
        options.title = $(this).text();
      $(this).tooltip(options);
      $(this).tooltip("show");
    } else {
      if ($(this).data("bs.tooltip")) {
        $tooltip.tooltip("hide");
        $tooltip.removeData("bs.tooltip");
      }
    }
  });
};

Basit ve parlak. Teşekkür ederim!
GumZ

3

Ben de öyle yaptım. Çoğu araç ipucu komut dosyası, araç ipuçlarını depolayan bir işlevi yürütmenizi gerektirir. Bu bir jQuery örneğidir:

$.when($('*').filter(function() {
   return $(this).css('text-overflow') == 'ellipsis';
}).each(function() {
   if (this.offsetWidth < this.scrollWidth && !$(this).attr('title')) {
      $(this).attr('title', $(this).text());
   }
})).done(function(){ 
   setupTooltip();
});

Üç nokta css olup olmadığını kontrol etmek istemediyseniz, aşağıdaki gibi basitleştirebilirsiniz:

$.when($('*').filter(function() {
   return (this.offsetWidth < this.scrollWidth && !$(this).attr('title'));
}).each(function() {
   $(this).attr('title', $(this).text());
})).done(function(){ 
   setupTooltip();
});

Etrafında "when" var, böylece "setupTooltip" fonksiyonu tüm başlıklar güncellenene kadar yürütülmez. "SetupTooltip" i, araç ipucu işlevinizle ve * işaretini denetlemek istediğiniz öğelerle değiştirin. * eğer bırakırsanız hepsini geçecek.

Sadece başlık özelliklerini tarayıcı araç ipucuyla güncellemek istiyorsanız, aşağıdaki gibi basitleştirebilirsiniz:

$('*').filter(function() {
   return $(this).css('text-overflow') == 'ellipsis';
}).each(function() {
   if (this.offsetWidth < this.scrollWidth && !$(this).attr('title')) {
      $(this).attr('title', $(this).text());
   }
});

Veya üç nokta olup olmadığını kontrol etmeden:

$.when($('*').filter(function() {
   return (this.offsetWidth < this.scrollWidth && !$(this).attr('title'));
}).each(function() {
   $(this).attr('title', $(this).text());
});

Neden inişli çıkışlı? Lütfen bunu yapıyorsanız, insanların sorunun ne olduğunu bilmesi için yorum yapın. Teşekkürler.
fanfavorite

2

Bunu sadece javascript kullanarak yapmak istiyorsanız, aşağıdakileri yaparım. Yayılma alanına bir id özelliği verin (böylece DOM'dan kolayca alınabilir) ve tüm içeriği 'content' adlı bir özelliğe yerleştirin:

<span id='myDataId' style='text-overflow: ellipsis; overflow : hidden;
 white-space: nowrap; width: 71;' content='{$myData}'>${myData}</span>

Ardından, javascript'inizde, öğe DOM'a eklendikten sonra aşağıdakileri yapabilirsiniz.

var elemInnerText, elemContent;
elemInnerText = document.getElementById("myDataId").innerText;
elemContent = document.getElementById("myDataId").getAttribute('content')
if(elemInnerText.length <= elemContent.length)
{
   document.getElementById("myDataId").setAttribute('title', elemContent); 
}

Tabii ki, yayılma alanını DOM'a eklemek için javascript kullanıyorsanız, içeriği eklemeden önce bir değişkende tutabilirsiniz. Bu şekilde, yayılma alanı üzerinde bir içerik özelliğine ihtiyacınız olmaz.

JQuery kullanmak istiyorsanız bundan daha zarif çözümler var.


Güzel. Bu sayfanın diğer bölümünde JQuery kullanıyorum beri - JQuery zarif çözüm nedir ??
Örümcek Adam

$("#myDataId").attr("title", function() { var innerText = $(this).text(); var content = $(this).attr("content"); if (innerText.length <= content.length) { return content; } return null; });
Mark Costello

1
İlk önerinizi saf javascript ile denedim - işe yaramıyor. 'innerText' özelliği her zaman ekranda tam olarak gösterilmese bile metnin tam uzunluğunu kaydeder: elemInnerText.length == elemContent.length !!
Spiderman

Yayılma stiliniz genişlik 71'dir. Dizenin genişliğinin bundan daha uzun olup olmadığını neden kontrol etmiyorsunuz? Gerçekten korkak bir şey yapmak istiyorsanız, metin taşması olmadan gizli bir öğe ekleyebilirsiniz: üç nokta kümesi ve her ikisinin genişliklerini karşılaştırabilirsiniz. Gizli olan, gizli olmayandan daha genişse, görünür olana bir başlık özelliği ekleyin.
Mark Costello

2

Üç nokta nereye gideceğimi belirleyen CSS sınıfım var. Buna dayanarak, aşağıdakileri yapıyorum (eleman seti farklı olabilir, elipslerin kullanıldığı yerleri yazıyorum, elbette ayrı bir sınıf seçici olabilir):

$(document).on('mouseover', 'input, td, th', function() {
    if ($(this).css('text-overflow') && typeof $(this).attr('title') === 'undefined') {
        $(this).attr('title', $(this).val());
    }
});

1
benim durumum yerine kullanılan thisbir öyleydianchorthis.text()val()
Basheer AL-MOMANI

2

İşte bir Vanilla JavaScript çözümü:

(function init() {

  var cells = document.getElementsByClassName("cell");

  for(let index = 0; index < cells.length; ++index) {
    let cell = cells.item(index);
    cell.addEventListener('mouseenter', setTitleIfNecessary, false);
  }

  function setTitleIfNecessary() {
    if(this.offsetWidth < this.scrollWidth) {
      this.setAttribute('title', this.innerHTML);
    }
  }

})();
.cell {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  border: 1px;
  border-style: solid;
  width: 120px; 
}
<div class="cell">hello world!</div>
<div class="cell">hello mars! kind regards, world</div>


1

Bu benim çözümüm, bir cazibe olarak çalışıyor!

    $(document).on('mouseover', 'input, span', function() {
      var needEllipsis = $(this).css('text-overflow') && (this.offsetWidth < this.scrollWidth);
      var hasNotTitleAttr = typeof $(this).attr('title') === 'undefined';
      if (needEllipsis === true) {
          if(hasNotTitleAttr === true){
            $(this).attr('title', $(this).val());
          }
      }
      if(needEllipsis === false && hasNotTitleAttr == false){
        $(this).removeAttr('title');
      }
  });

Merhaba @ FarukT çözümünüz benim için iyi çalışıyor, çok teşekkür ederim. Ben giriş ve span varsayalım iki html etiketleri varsa sormak istiyorum ve ben bu offsetWidth kullanarak bazı Aritmetik hesaplamalar yapmak için aynı anda her iki bu etiketlerin offsetWidth hesaplamak istiyorum. Bunu nasıl yaparım?
Kunal Tyagi

Merhaba @KunalTyagi, 2 ayrı işlev ile bunu yapabilirsiniz, ben sadece bir girdi ve açıklık ile yazılmıştır ama bu işlevi 2 kez, sadece ilk örnek fonksiyonu ile sadece giriş ve sadece ikinci işlev yayılma. bunun gibi: $ (document) .on ('fareyle üzerine gelme', 'giriş', işlev () {...}); ve ikincisi $ (document) .on ('fareyle üzerine gelme', 'açıklık', işlev () {...});
FarukT

0

Yukarıdaki çözümlerin hiçbiri benim için işe yaramadı, ama harika bir çözüm buldum. İnsanların yaptığı en büyük hata, sayfa yüklendikten sonra öğe üzerinde belirtilen 3 CSS mülkünün tümüne sahip olmaktır. Bu stilleri + araç ipucunu dinamik olarak EĞER ve SADECE elips istediğiniz aralık ana öğesinden daha genişse eklemeniz gerekir.

    $('table').each(function(){
        var content = $(this).find('span').text();
        var span = $(this).find('span');
        var td = $(this).find('td');
        var styles = {
            'text-overflow':'ellipsis',
            'white-space':'nowrap',
            'overflow':'hidden',
            'display':'block',
            'width': 'auto'
        };
        if (span.width() > td.width()){
            span.css(styles)
                .tooltip({
                trigger: 'hover',
                html: true,
                title: content,
                placement: 'bottom'
            });
        }
    });

0

Açıklığı başka bir açıklıkla kuşatabilirsiniz, ardından orijinal / iç açıklığın genişliğinin yeni / dış açıklıktan daha büyük olup olmadığını test edin. Muhtemelen diyorum ki - kabaca bir spaniçimde olduğu durumuma dayanıyor, tdbu yüzden aslında bir spaniç ile çalışacaksa bilmiyorum span.

İşte kendime benzer bir konumda bulabilecek başkaları için benim kod burada; Açısal bağlamda olmasına rağmen değiştirmeden kopyalarım / yapıştırıyorum, okunabilirlik ve temel kavramdan uzaklaştığını düşünmüyorum. Bir servis yöntemi olarak kodladım çünkü birden fazla yere uygulamam gerekiyordu. İçinde bulunduğum seçici, birden fazla örneğe uyan bir sınıf seçici oldu.

CaseService.applyTooltip = function(selector) {
    angular.element(selector).on('mouseenter', function(){
        var td = $(this)
        var span = td.find('span');

        if (!span.attr('tooltip-computed')) {
            //compute just once
            span.attr('tooltip-computed','1');

            if (span.width() > td.width()){
                span.attr('data-toggle','tooltip');
                span.attr('data-placement','right');
                span.attr('title', span.html());
            }
        }
    });
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.