HTML-省略記号がアクティブな場合にのみツールチップを表示するにはどうすればよいですか


205

私のページには、ellipsisスタイル付きの動的データのスパンがあります。

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

この要素のツールチップに同じコンテンツを追加したいのですが、コンテンツが長く、省略記号が画面に表示されている場合にのみ表示されます。

それを行う方法はありますか?がアクティブ
になるellipsisと、ブラウザはイベントをスローしますか?

*ブラウザ:Internet Explorer


1
念頭に置いてベアtext-overflow:ellipsis;Firefoxですべての仕事をしませんが-より多くのためにこの質問を参照してください。stackoverflow.com/questions/4927257/...
Spudley

2
私は似たようなことをしなければなりませんでした。この回答element.offsetWidth < element.scrollWidthに従ってこれまでのところ機能するように見えるかどうかを確認します。
マーティン・スミス


7
後世への注意:text-overflow:ellipsis;Firefoxで動作するようになりました。Firefox 7(2011年9月リリース)で追加されました。
sleske

回答:


161

組み込みの省略記号設定を使用してそれを行い、titleMartin Smithのコメントにオンデマンドの属性(jQueryを使用)を追加する方法を次に示します。

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

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

4
ありがとう、魅力のように機能します!ただし、より効率的にしたい場合は、次のようにbind()をon()に置き換えることを検討してください。$(document).on( 'mouseenter'、 '.mightOverflow'、function(){...});
Ziad、2013年

17
テキストがオーバーフローしなくなったときにツールチップを自動的に削除する場合は、次のように変更します:$(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())} else {if(this.offsetWidth> = this.scrollWidth && title == $ t.text())$ t.removeAttr( 'title')}});
Chris Janssen

1
mouseenterは、バインドまたはリッスンするイベントです。誰かが実際に要素の上にマウスを置くまで、要素にツールチップを実際に追加する必要はありません。したがって、クラス「mightoverflow」を持つDOM要素のいずれかでmouseenterのそのポイントまで追加を延期します。Just-In-Time-Tooltips
Jason Kleban 2013

2
"As of jQuery 1.7, the .on() method is the preferred method for attaching event handlers to a document"詳細については、api.jquery.com / bindおよびapi.jquery.com/onを
Adrien Be

2
IE10では機能しません。offsetWidthはscrollWidthと同じで、どちらも切り捨てられた幅を示します。
SsjCosty 2017年

59

これが純粋なCSSソリューションです。jQueryは必要ありません。ツールチップは表示されませんが、マウスオーバー時にコンテンツが完全な長さに拡大されます。

置き換えられるコンテンツがある場合は、うまく機能します。その後、毎回jQuery関数を実行する必要はありません。

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

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

18
レイアウトが壊れる可能性があるため、ツールチップほど良くありません。
Alexander

2
ツールチップの問題は、少なくとも今のところ、モバイルでは機能しないことです。この回答はレイアウトを壊す可能性があります(読む:おそらく崩れます)が、たとえばホバーされた要素の背景色が異なるように適応させることができます。これはまだモバイルでは機能しませんが、デスクトップの別のオプションです。
トリシス

1
私のニーズを完全にカバーするこの素晴らしい答えをありがとう。いくつかのJavaScriptを使用して、レイアウトを壊さないようにブロックを絶対配置することを想像できます。
Niavlys 2017年

2
CSSの問題でjavascriptを膨らませるよりも良い答えです。明らかに、省略記号は自動化されたタイトルオプションを持つべきであり、現時点での実装方法には意味がありません。cssが悪すぎると、最後の文字が「...」の場合、:hoverのみを許可できません
John

32

uosɐſの答えは基本的に正しいですが、おそらくmouseenterイベントでそれを実行したくないでしょう。これにより、要素の上にマウスを置くたびに、必要かどうかを判断する計算が行われます。要素のサイズが変化しない限り、それを行う理由はありません。

要素がDOMに追加された直後にこのコードを呼び出す方が良いでしょう。

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

または、いつ追加されるか正確にわからない場合は、ページの読み込みが完了した後でそのコードを呼び出します。

これを行う必要がある要素が複数ある場合は、それらにすべて同じクラス(「mightOverflow」など)を指定し、このコードを使用してすべてを更新できます。

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

+1、ページの読み込み時にそれを行うことはより簡単に見えますが、より多くの可能性を提供します。すなわち。ツールチップに「シグナル」を送るために、点線の下線が付いたツールチップを持つこの要素をスタイルすることができます。のような$(".mightOverflow").each(function() { if( $(this).offsetWidth < $(this).scrollWidth && !$(this).attr('title')){ $(this).attr('title', $(this).text()); $(this).css('border-bottom', '1px dotted #A8A8A8'); } });
エイドリアン・ビー14

「マウスオーバーするたびに」が間違っている(現在、少なくとも-回答が更新されたかどうかはわかりません)以前に計算されたかどうかをチェックします '&&!$ this.attr(' title ')'
Rune Jeppesen

いいえ、それは単にtitle属性を再び追加しないようにするだけです。計算は、まだ行われている必要なのかどうかを判断します。this.offsetWidth < this.scrollWidthおそらく!$this.attr('title')、要素の上にマウスを置くたびにチェックが実行されます。
Elezar 2014年

9
この方法の問題は、すべての要素が一度にチェックされ(潜在的なパフォーマンスへの影響)、1回しか計算されないため、ユーザーがブラウザーを縮小して切り詰められたり展開されたりして切り捨てられなくなった場合、ツールチップの存在を更新します。コードをウィンドウのサイズ変更に再度アタッチすると、すべてのアイテムがサイズをチェックするため、パフォーマンスの問題が発生します。イベント委任「$(document).on( 'mouseenter'、 '.mightOverflow'、...」を使用し、要素の上にマウスを置くまでチェックを遅らせることで、その場で更新でき、一度に1つの要素のみをチェックできます
クリスヤンセン

IE10では機能しません。offsetWidthはscrollWidthと同じで、どちらも切り捨てられた幅を示します。
SsjCosty 2017年

18

次に、他の2つの純粋なCSSソリューションを示します。

  1. 切り捨てられたテキストを所定の位置に表示します。

.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. 任意の「ツールチップ」を表示

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


これがまさに私が探していたものです!
Praneet Nadkar

まさに私が必要とする優れたソリューション。ありがとうございました !
Agu V

17

ここに私のjQueryプラグインがあります:

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

使用法:

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

編集:

このプラグインの要点を作りました。 https://gist.github.com/UziTech/d45102cdffb1039d4415


1
IE10では機能しません。offsetWidthはscrollWidthと同じで、どちらも切り捨てられた幅を示します。
SsjCosty

@SsjCosty IE 10でテストするのはなぜですか?IE 10をインストールすることができ、誰もがIE 11をインストールすることができるので、この時点でIE 10を使用して、誰があってはならない
トニー・ブリックス

ええと、サポートされている最低限のIEバージョンは10であるという会社のポリシーがあります。また、多くのクライアント(一部の銀行やさまざまな機関)がまだIE10を使用しているためです。しかたがない。
SsjCosty

12

省略記号が実際に適用されているかどうかを検出し、ツールチップを表示して全文を表示する必要があります。this.offsetWidth < this.scrollWidth要素がコンテンツをほぼ保持しているが、幅が1ピクセルまたは2ピクセルしかない場合、特に全角の中国語/日本語/韓国語のテキストの場合、「」を比較するだけでは十分ではありません。

次に例を示します。http//jsfiddle.net/28r5D/5/

省略記号の検出を改善する方法を見つけました:

  1. this.offsetWidth < this.scrollWidth最初に「」を比較し、失敗した場合は手順2を続行します。
  2. CSSスタイルを一時的に{'overflow': 'visible'、 'white-space': 'normal'、 'word-break': 'break-all'}に切り替えます。
  3. ブラウザに再レイアウトを実行させます。ワードラップが発生すると、要素はその高さを拡張します。これは、省略記号も必要であることを意味します。
  4. CSSスタイルを復元します。

これが私の改善です:http : //jsfiddle.net/28r5D/6/


10

ブラウザの組み込みツールチップの代わりにBootstrapのツールチップを使用するjQueryプラグインを作成しました。これは古いブラウザでテストされていないことに注意してください。

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

シンプルで素晴らしい。ありがとうございました!
GumZ

3

これは私がやったことです。ほとんどのツールチップスクリプトでは、ツールチップを保存する関数を実行する必要があります。これは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();
});

省略記号cssをチェックしたくない場合は、次のように簡略化できます。

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

私の周りには「いつ」があるので、すべてのタイトルが更新されるまで「setupTooltip」関数は実行されません。「setupTooltip」をツールチップ関数に置き換え、*をチェックする要素に置き換えます。*あなたがそれを残した場合、それらすべてを通過します。

ブラウザのツールチップを使用してタイトル属性を更新するだけの場合は、次のように単純化できます。

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

または省略記号のチェックなし:

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

なぜ反対票か。あなたがそうしているのであればコメントしてください、そうすれば人々は何が問題なのかを知っています。ありがとう。
ファンのお気に入り2016年

2

JavaScriptのみを使用してこれを実行する場合は、次のようにします。(DOMから簡単に取得できるように)スパンにid属性を指定し、すべてのコンテンツを 'content'という名前の属性に配置します。

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

次に、JavaScriptで、要素が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); 
}

もちろん、JavaScriptを使用してスパンをDOMに挿入する場合は、挿入する前にコンテンツを変数に保持するだけで済みます。この方法では、スパンにコンテンツ属性は必要ありません。

jQueryを使用する場合は、これよりも優れたソリューションがあります。


いいね。このページの他の部分でJQueryを使用しているため、JQueryのエレガントなソリューションとは何ですか?
スパイダーマン

$("#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
純粋なjavascriptを使用して最初の提案を試しましたが、機能しません。'innerText'プロパティは、画面に完全に表示されなくてもテキスト全体を保存するので、常にelemInnerText.length == elemContent.length !!
スパイダーマン2011年

スパンのスタイルは幅71です。文字列の幅がそれより長いかどうか確認してみませんか?本当にファンキーなことをしたい場合は、text-overflow:ellipsisを設定せずに非表示要素を追加して、両方の幅を比較できます。非表示の方が非非表示よりも幅が広い場合は、表示属性にタイトル属性を追加します。
Mark Costello

2

省略記号を配置する場所を決定するCSSクラスがあります。これに基づいて、私は次のことを行います(要素セットは異なる場合があります。省略記号が使用されている場合は、それらを記述します。もちろん、別個のクラスセレクターでもかまいません)。

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

1
私のケースthisは、代わりにanchor私が使用しthis.text()たものだったval()
Basheer AL-MOMANI 2017年

2

バニラ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>


1

これは私の解決策であり、魅力として機能します!

    $(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あなたの解決策は私にとってうまく機能しています。ありがとうございました。2つのhtmlタグがあるかどうかを確認したいと思います。入力とスパンを想定し、これらの両方のタグのoffsetWidthを同時に計算して、それらのoffsetWidthを使用していくつかの算術計算を実行します。どうすればいいですか?
Kunal Tyagi

こんにちは@ KunalTyagi、2つの分離された関数でそれを行うことができます。私は入力とスパンで1つだけ記述されましたが、この関数を2回複製できます。たとえば、最初の関数は入力のみで、2番目の関数はスパンのみです。このように:$(document).on( 'mouseover'、 'input'、function(){...}); 2番目の$(document).on( 'mouseover'、 'span'、function(){...});
FarukT

0

上記の解決策はどれもうまくいきませんでしたが、素晴らしい解決策を見つけました。人々が犯している最大の間違いは、ページ読み込み時に要素で3つのCSSプロパティがすべて宣言されていることです。これらのスタイルとツールチップを動的に追加する必要があるのは、楕円を配置するスパンがその親よりも広い場合に限ります。

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

スパンを別のスパンで囲み、元の/内側のスパンの幅が新しい/外側のスパンの幅より大きいかどうかを単にテストすることができます。注私はおそらく言うこと-それは大体私が持っていた私の状況に基づいているspanの内部td私は実際にそれがで動作するかどうか分からないので、span内部をspan

ここに、私のような立場にいる可能性のある他の人のための私のコードがあります。Angularのコンテキストであっても、変更せずにコピー/貼り付けしていますが、読みやすさと基本的な概念が損なわれるとは思いません。複数の場所に適用する必要があったため、サービスメソッドとしてコーディングしました。私が渡しているセレクターは、複数のインスタンスに一致するクラスセレクターです。

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());
            }
        }
    });
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.