web-dev-qa-db-ja.com

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

ページにEllipsisを含む動的データのスパンがあります。意味:

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

そして、同じコンテンツ(title = '$ {myData}')でこの要素のツールチップを追加したいのですが、コンテンツが長く、省略記号が画面に表示される場合にのみ表示したいです。
それを行う方法はありますか?

1つの方向-ブラウザ(私の場合はIE)が省略記号を描画すると、それに関するイベントがスローされますか?

171
Spiderman

組み込みのEllipsis設定を使用してこれを実行し、Martin Smithのコメントに基づいて(jQueryを使用して)title属性をオンデマンドで追加する方法を次に示します。

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

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

これが純粋な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;
}
44
Snæbjørn

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());
});
32
Elezar

これが私の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

16
Tony Brix

省略記号が実際に適用されているかどうかを検出し、ツールチップを表示して全文を表示する必要があります。要素がコンテンツをほぼ保持している場合に「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/

11
Feng Dihai

ブラウザのビルドインツールチップの代わりにブートストラップのツールチップを使用する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");
      }
    }
  });
};
10
Steven

以下に、他の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>
4
Hannes

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

Ellipsis 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());
});
3
fanfavorite

Javascriptのみを使用してこれを実行する場合は、次のようにします。スパンにid属性を与え(DOMから簡単に取得できるように)、「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を使用する場合は、これよりもエレガントなソリューションがあります。

2
Mark Costello

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

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

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

    $(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');
      }
  });
0
FarukT

スパンを別のスパンで囲み、元のスパンまたは内側のスパンの幅が新しいスパンまたは外側のスパンの幅よりも大きいかどうかを単純にテストできます。私がおそらく言うことに注意してください-それはおおよそ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());
            }
        }
    });
}
0
George Jempty

上記の解決策はどれもうまくいきませんでしたが、すばらしい解決策を見つけました。人々が犯す最大の間違いは、ページロード時に要素で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
Brian Gabriel

次に、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>
0
wuarmin