HTML - bagaimana saya bisa menunjukkan tooltip SAJA ketika elipsis diaktifkan

205

Saya mendapatkan rentang dengan data dinamis di halaman saya, dengan ellipsisgaya.

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

Saya ingin menambahkan tooltip elemen ini dengan konten yang sama, tapi saya ingin itu muncul hanya ketika kontennya panjang dan elipsis muncul di layar.

Apakah ada cara untuk melakukannya?
Apakah browser membuat acara saat ellipsisdiaktifkan?

* Browser: Internet Explorer

Manusia laba-laba
sumber
1
Ingatlah bahwa text-overflow:ellipsis;itu tidak berfungsi sama sekali di Firefox - lihat pertanyaan ini untuk lebih lanjut: stackoverflow.com/questions/4927257/…
Spudley
2
Saya hanya harus melakukan hal serupa. Memeriksa apakah element.offsetWidth < element.scrollWidthsesuai jawaban ini tampaknya berhasil sejauh ini.
Martin Smith
deteksi ellipsis: stackoverflow.com/questions/7738117/…
Adrien Be
7
Catatan untuk anak cucu: text-overflow:ellipsis;sekarang berfungsi di Firefox; itu ditambahkan di Firefox 7 (dirilis September 2011).
sleske

Jawaban:

161

Inilah cara yang melakukannya menggunakan pengaturan elipsis bawaan, dan menambahkan titleatribut berdasarkan permintaan (dengan jQuery) berdasarkan komentar Martin Smith:

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

    if(this.offsetWidth < this.scrollWidth && !$this.attr('title')){
        $this.attr('title', $this.text());
    }
});
Jason Kleban
sumber
4
Terima kasih, bekerja seperti pesona! Namun jika Anda ingin membuatnya lebih efisien, Anda dapat mempertimbangkan untuk mengganti bind () dengan on () seperti: $ (dokumen) .on ('mouseenter', '.mightOverflow', function () {...});
Ziad
17
Jika Anda ingin tooltip dihapus secara otomatis jika teks tidak lagi meluap, ubah menjadi: $ (dokumen) .on ('mouseenter', '.mightOverflow', function () {var $ t = $ (this); var title = $ t.attr ('title'); if (! title) {if (this.offsetWidth <this.scrollWidth) $ t.attr ('title', $ t.text ())} else {if (this.offsetWidth> = this.scrollWidth && title == $ t.text ()) $ t.removeAttr ('title')}});
Chris Janssen
1
mouseenter adalah acara yang kita ikat atau dengarkan. Kami tidak benar-benar harus menambahkan tooltip ke elemen sampai seseorang benar-benar memikirkannya. Jadi kami menunda penambahan sampai titik mouseenter pada salah satu elemen DOM dengan kelas "mightoverflow". Just-In-Time-Tooltips
Jason Kleban
2
"As of jQuery 1.7, the .on() method is the preferred method for attaching event handlers to a document"untuk info lebih lanjut lihat api.jquery.com/bind dan api.jquery.com/on
Adrien Be
2
Itu tidak bekerja pada IE10 - offsetWidth identik dengan scrollWidth, keduanya memberi saya lebar terpotong.
SsjCosty
59

Inilah solusi CSS murni. Tidak perlu jQuery. Itu tidak akan menunjukkan tooltip, melainkan hanya akan memperluas konten secara penuh pada mouseover.

Bekerja dengan baik jika Anda memiliki konten yang diganti. Maka Anda tidak harus menjalankan fungsi jQuery setiap saat.

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

.might-overflow:hover {
    text-overflow: clip;
    white-space: normal;
    word-break: break-all;
}
Snæbjørn
sumber
18
Ini tidak sebagus tooltip, karena dapat merusak tata letak.
Alexander
2
Masalah dengan tooltips adalah mereka tidak berfungsi di ponsel, setidaknya untuk saat ini. Jawaban ini dapat (baca: mungkin akan) merusak tata letak, tetapi dapat disesuaikan dengan, misalnya, memiliki warna latar belakang yang berbeda untuk elemen yang melayang. Ini masih tidak berfungsi di ponsel, tetapi ini merupakan pilihan lain untuk desktop.
trysis
1
Terima kasih atas jawaban hebat ini yang dengan sempurna memenuhi kebutuhan saya. Menggunakan beberapa JavaScript, kita bisa membayangkan membuat blok benar-benar diposisikan sehingga tidak merusak tata letak.
Niavlys
2
Ini jawaban yang bagus, lebih baik daripada membengkak javascript pada masalah css. Jelas elipsis HARUS memiliki opsi judul otomatis, cara itu diterapkan pada saat ini kurang masuk akal. Sayang sekali css tidak mengizinkan: melayang-layang jika karakter terakhir adalah '...'
John
32

Jawaban uosɐſ pada dasarnya benar, tetapi Anda mungkin tidak ingin melakukannya di acara mouseenter. Itu akan menyebabkannya melakukan perhitungan untuk menentukan apakah itu diperlukan, setiap kali Anda mengarahkan mouse ke elemen. Kecuali jika ukuran elemen berubah, tidak ada alasan untuk melakukan itu.

Akan lebih baik untuk langsung memanggil kode ini segera setelah elemen ditambahkan ke DOM:

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

Atau, jika Anda tidak tahu kapan tepatnya itu ditambahkan, panggil kode itu setelah halaman selesai dimuat.

jika Anda memiliki lebih dari satu elemen yang perlu Anda lakukan dengan ini, maka Anda dapat memberi mereka semua kelas yang sama (seperti "mightOverflow"), dan menggunakan kode ini untuk memperbarui semuanya:

$('.mightOverflow').each(function() {
    var $ele = $(this);
    if (this.offsetWidth < this.scrollWidth)
        $ele.attr('title', $ele.text());
});
Elezar
sumber
+1, melakukannya pada pemuatan halaman tampaknya lebih sederhana tetapi juga memberikan lebih banyak kemungkinan. yaitu. Anda mungkin ingin menata elemen ini yang memiliki tooltip dengan garis bawah bertitik untuk "memberi sinyal" tooltip. seperti$(".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
'setiap kali Anda mengarahkan mouse' salah (sekarang setidaknya - saya tidak tahu apakah jawabannya diperbarui) Tidak memeriksa apakah sebelumnya dihitung '&&! $ this.attr (' title ')'
Rune Jeppesen
Tidak, itu hanya membuatnya tidak menambahkan atribut title lagi. The perhitungan untuk menentukan apakah itu dibutuhkan masih dilakukan. this.offsetWidth < this.scrollWidthdan mungkin bahkan pemeriksaan !$this.attr('title')akan dilakukan setiap kali Anda mengarahkan mouse ke elemen.
Elezar
9
Masalah dengan metode ini adalah bahwa semua elemen diperiksa sekaligus (dampak kinerja potensial) dan itu hanya menghitung sekali, sehingga jika pengguna menyusutkan browser menyebabkan hal-hal menjadi terpotong atau meluas, menyebabkan mereka tidak lagi terpotong Anda tidak dapat memotong perbarui keberadaan tooltip. Melampirkan kode Anda ke ukuran jendela lagi akan memiliki masalah kinerja karena setiap item memeriksa ukurannya. Dengan menggunakan delegasi acara "$ (dokumen) .on ('mouseenter', '.mightOverflow', ..." dan menunda pemeriksaan hingga Anda beralih ke elemen, Anda dapat memperbarui dengan cepat dan hanya memeriksa 1 elemen @ waktu
Chris Janssen
Itu tidak bekerja pada IE10 - offsetWidth identik dengan scrollWidth, keduanya memberi saya lebar terpotong.
SsjCosty
18

Berikut adalah dua solusi CSS murni lainnya:

  1. Tampilkan teks terpotong di tempat:

.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. Tampilkan "tooltip" yang sewenang-wenang :

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

Hannes
sumber
Ini persis apa yang saya cari!
Praneet Nadkar
Solusi luar biasa, persis apa yang saya butuhkan. Terima kasih !
Agu V
17

Ini plugin jQuery saya:

(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);

Pemakaian:

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

Edit:

Saya telah membuat inti untuk plugin ini. https://gist.github.com/UziTech/d45102cdffb1039d4415

Tony Brix
sumber
1
Itu tidak bekerja pada IE10 - offsetWidth identik dengan scrollWidth, keduanya memberi saya lebar terpotong.
SsjCosty
@SsjCosty mengapa Anda menguji pada IE 10? Seharusnya tidak ada yang menggunakan IE 10 pada saat ini, karena siapa pun yang dapat menginstal IE 10 dapat menginstal IE 11.
Tony Brix
Ah, kami memiliki kebijakan perusahaan yang mendukung versi IE minimum kami adalah 10. Juga karena banyak klien kami (beberapa bank dan berbagai lembaga) masih menggunakan IE10. Baiklah.
SsjCosty
12

Kita perlu mendeteksi apakah ellipsis benar-benar diterapkan, kemudian menunjukkan tooltip untuk mengungkapkan teks lengkap. Tidak cukup hanya dengan membandingkan "this.offsetWidth < this.scrollWidth " ketika elemen hampir memegang kontennya tetapi hanya kurang satu atau dua piksel lebarnya, terutama untuk teks karakter Cina / Jepang / Korea lebar lebar.

Berikut ini sebuah contoh: http://jsfiddle.net/28r5D/5/

Saya menemukan cara untuk meningkatkan deteksi ellipsis:

  1. Membandingkan "this.offsetWidth < this.scrollWidth " dulu, lanjutkan langkah # 2 jika gagal.
  2. Alihkan gaya css sementara ke {'overflow': 'visible', 'white-space': 'normal', 'word-break': 'break-all'}.
  3. Biarkan peramban melakukan relayout. Jika pembungkus kata terjadi, elemen akan memperluas ketinggiannya yang juga berarti elipsis diperlukan.
  4. Kembalikan gaya css.

Ini peningkatan saya: http://jsfiddle.net/28r5D/6/

Feng Dihai
sumber
10

Saya membuat plugin jQuery yang menggunakan tooltip Bootstrap alih-alih tooltip bawaan browser. Harap dicatat bahwa ini belum diuji dengan browser yang lebih lama.

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");
      }
    }
  });
};
Steven
sumber
Sederhana dan cemerlang. Terima kasih!
GumZ
3

Inilah yang saya lakukan. Sebagian besar skrip tooltip mengharuskan Anda untuk menjalankan fungsi yang menyimpan tooltips. Ini adalah contoh jQuery:

$.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();
});

Jika Anda tidak ingin memeriksa elipsis css, Anda dapat menyederhanakannya seperti:

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

Saya memiliki "kapan" di sekitarnya, sehingga fungsi "setupTooltip" tidak dijalankan sampai semua judul telah diperbarui. Ganti "setupTooltip", dengan fungsi tooltip Anda dan * dengan elemen yang ingin Anda periksa. * Akan melalui mereka semua jika Anda meninggalkannya.

Jika Anda hanya ingin memperbarui atribut judul dengan tooltip browser, Anda dapat menyederhanakan seperti:

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

Atau tanpa memeriksa elipsis:

$.when($('*').filter(function() {
   return (this.offsetWidth < this.scrollWidth && !$(this).attr('title'));
}).each(function() {
   $(this).attr('title', $(this).text());
});
fanfavorite
sumber
Mengapa downvote? Silakan berkomentar jika Anda melakukan itu sehingga orang tahu apa masalahnya. Terima kasih.
fanfavorite
2

Jika Anda ingin melakukan ini hanya menggunakan javascript, saya akan melakukan hal berikut. Berikan rentang atribut id (sehingga dapat dengan mudah diambil dari DOM) dan tempatkan semua konten dalam atribut bernama 'konten':

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

Kemudian, dalam javascript Anda, Anda dapat melakukan hal berikut setelah elemen dimasukkan ke DOM.

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); 
}

Tentu saja, jika Anda menggunakan javascript untuk memasukkan rentang ke DOM, Anda bisa menyimpan konten dalam variabel sebelum memasukkannya. Dengan cara ini Anda tidak perlu atribut konten pada rentang tersebut.

Ada solusi yang lebih elegan dari ini jika Anda ingin menggunakan jQuery.

Mark Costello
sumber
Bagus. Karena saya menggunakan JQuery di bagian lain halaman ini - apa solusi elegan JQuery ??
Spiderman
$("#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
Saya mencoba saran pertama Anda dengan javascript murni - tidak berhasil. properti 'innerText' menyimpan panjang teks yang lengkap bahkan jika itu tidak muncul sepenuhnya di layar jadi selalu: elemInnerText.length == elemContent.length !!
Spiderman
Gaya rentang Anda adalah lebar 71. Mengapa tidak memeriksa apakah lebar tali lebih panjang dari itu? Jika Anda ingin melakukan sesuatu yang sangat funky, Anda bisa menambahkan elemen tersembunyi tanpa teks-overflow: ellipsis atur dan bandingkan lebar keduanya. Jika yang tersembunyi lebih lebar dari yang tidak tersembunyi, tambahkan atribut judul ke yang terlihat.
Mark Costello
2

Saya memiliki kelas CSS, yang menentukan di mana harus meletakkan ellipsis. Berdasarkan itu, saya melakukan hal berikut (set elemen bisa berbeda, saya menulis itu, di mana elipsis digunakan, tentu saja itu bisa menjadi pemilih kelas yang terpisah):

$(document).on('mouseover', 'input, td, th', function() {
    if ($(this).css('text-overflow') && typeof $(this).attr('title') === 'undefined') {
        $(this).attr('title', $(this).val());
    }
});
Alexander
sumber
1
i kasus saya thisadalah anchorjadi saya menggunakan this.text()bukannyaval()
Basheer AL-Momani
2

Inilah solusi Vanilla JavaScript:

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

Wuarmin
sumber
1

Ini solusi saya, berfungsi sebagai pesona!

    $(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');
      }
  });
FarukT
sumber
Hai @ FarukT solusi Anda berfungsi dengan baik untuk saya, terima kasih banyak. Saya ingin bertanya apakah saya memiliki dua tag html misalkan input & span dan saya ingin menghitung offsetWidth dari kedua tag ini sekaligus untuk melakukan beberapa perhitungan Aritmatika menggunakan offsetWidth tersebut. Bagaimana saya melakukannya?
Kunal Tyagi
Hai @KunalTyagi, Anda dapat melakukannya dengan 2 fungsi yang terpisah, saya hanya menulis satu dengan input dan span tetapi Anda dapat mereplikasi fungsi ini 2 kali, misalnya fungsi pertama dengan hanya input dan pada fungsi kedua hanya rentang. seperti ini: $ (dokumen) .on ('mouseover', 'input', function () {...}); dan yang kedua $ (dokumen) .on ('mouseover', 'span', function () {...});
FarukT
0

Tidak ada solusi di atas yang berfungsi untuk saya, tetapi saya menemukan solusi yang bagus. Kesalahan terbesar yang dilakukan orang adalah memiliki semua 3 properti CSS yang dideklarasikan pada elemen setelah pageload. Anda harus menambahkan gaya-gaya + tooltip secara dinamis JIKA dan HANYA JIKA rentang yang Anda inginkan elips lebih lebar daripada induknya.

    $('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'
            });
        }
    });
Brian Gabriel
sumber
0

Anda mungkin dapat mengelilingi rentang dengan rentang lain, kemudian cukup menguji apakah lebar rentang asli / dalam lebih besar dari rentang baru / rentang luar. Perhatikan bahwa saya katakan mungkin - ini didasarkan pada situasi saya di mana saya memiliki bagian spandalam tdjadi saya tidak benar-benar tahu bahwa jika itu akan bekerja dengan bagian spandalamspan .

Namun di sini adalah kode saya untuk orang lain yang mungkin menemukan diri mereka dalam posisi yang mirip dengan milik saya; Saya menyalin / menempelnya tanpa modifikasi walaupun itu dalam konteks Angular, saya tidak berpikir itu mengurangi keterbacaan dan konsep penting. Saya mengkodekannya sebagai metode layanan karena saya perlu menerapkannya di lebih dari satu tempat. Pemilih yang saya lewati telah menjadi pemilih kelas yang akan cocok dengan banyak instance.

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());
            }
        }
    });
}
Dexygen
sumber