3

基本的に、openツールチップをトリガーした要素に対していくつかのチェックを実行するハンドラーを jQuery UI ツールチップにアタッチしています。私がこれまでに持っているもの:

$(document).tooltip({
  open: function(e, ui) {
    var el = e.toElement/* || e.relatedTarget*/;
    console.log(el.offsetWidth, el.scrollWidth);
    if (el.offsetWidth === el.scrollWidth) {
      ui.tooltip.hide();
    }
  }
});

上記のチェックは、流動的なレイアウトの一部である要素が水平にオーバーフローしていない限り、ツールチップが表示されないようにします。このjsBinでわかるように、Chrome でうまく動作します。

ただし、Firefoxevent.toElementではundefined. SO の周りのスレッドを読んevent.relatedTargetで、それが適切な代替物になると思いましたが、そうではありません。は現在ホバーされてevent.toElementいるアイテムを参照しますが、 はポインティング デバイスが終了した要素を参照します。これは、 W3C 仕様による正しい動作です(Chrome の に似ています)。event.relatedTargetmouseoverevent.fromTarget

event.targetと参照も試しましevent.currentTargetたが、これらはツールチップ イベント ハンドラーがバインドされているノードであるため、これらを指しています。Tooltip APIページを調べても役に立ちませんでした。thisdocument

非常に基本的なことを見落としているのか、それともそれほどオーソドックスではない方法を試す必要があるのか​​ どうかはわかりません。

openFirefox で動作するツールチップのハンドラー内からトリガーされた要素への参照を取得する方法はありますか? または、この目的の動作をより簡単/同様の方法で実現できる魔法のjQuery UIツールチップオプション/メソッドはありますか?

4

2 に答える 2

7

これはかなりハックな解決策ですが、ここに私が見つけた一時的な修正があります。編集:以下の最初のクロスブラウザソリューションを終了した後、それほどハックではありません. 以下にリストされている#1#4、および#2のソリューションを使用できるはずです。

jQuery Event オブジェクトには隠しoriginalEventプロパティがあり、質問の場合はネイティブmouseoverイベントを参照します。したがってevent.originalEvent.target、Chrome と Firefox の両方で使用できます。

open: function(e, ui) {
  var el = e.originalEvent.target;
  if (el.offsetWidth === el.scrollWidth) {
    ui.tooltip.hide();
  }
}

置き場

古い IE のサポートが関係している場合はevent.srcElement、 whenevent.targetが存在しない場合に使用する必要があります。

var el = e.originalEvent.target || e.originalEvent.srcElement;

置き場


#1 クロスブラウザ ソリューション

最後に、ツールチップをトリガーする要素内にネストされた要素がある場合、.closest()ツールチップの委譲セレクターと同じフィルターを渡すメソッドを使用してモンキーパッチを適用する必要があります (itemsオプション[title]:not([disabled])、 UI 1.10.2以降のデフォルト):

var el = $(e.originalEvent.target || e.originalEvent.srcElement).closest($(this).tooltip('option', 'items'))[0];

置き場

これは基本的に、ここに示すようにツールチップ ウィジェットが内部で行うことです。


#2 代替のクロスブラウザー ソリューション

単純な DOM クエリを使用して、それほど多くの回避策を必要としない代替ソリューション:

var el = $('[aria-describedby="'+ui.tooltip[0].id+'"]')[0];

置き場


#3 内部メソッドの悪用

これは使用しないでください。ただし、内部メソッドをオーバーライドすることで、パラメーターとして渡されたイベントのターゲット要素を含む jQuery オブジェクト_openにアクセスできます。問題は、 DOM に既に存在しているにもかかわらず、まだ「作成されていない」ため、ウィジェットtargetにアクセスできないことです。ID で DOM クエリを実行する内部メソッドを使用して回避できます。したがって、アニメーションが開始された直後に、そのライブ サイクルが影響を受けずに実行できます。アニメーションはそこにあり、通常どおりに削除されますが、このサイクル全体に沿っています。tooltip.tooltip('widget')_findhideshowmouseleavedisplay:none

var bk_open = $.ui.tooltip.prototype._open;
$.ui.tooltip.prototype._open = function(event, target, content) {
  bk_open.apply(this, arguments);
  if (target[0].offsetWidth === target[0].scrollWidth) {
    this._find(target).hide();
  }
};

$(document).tooltip();

置き場

その DOM クエリはかなり不要なので、要素を含む jQuery オブジェクトを返す_find内部メソッドを拡張して、オーバーライドされた実行前に JS のレキシカル スコープを使用してツールチップ要素への参照を保存することもできます。_tooltiptooltip_open

var tooltipproto = $.ui.tooltip.prototype,
    bk_open = tooltipproto._open,
    bk_tooltip = tooltipproto._tooltip,
    $tooltip;
tooltipproto._open = function(event, target, content) {
  bk_open.apply(this, arguments);
  if (target[0].offsetWidth === target[0].scrollWidth) {
    $tooltip.hide();
  }
};
tooltipproto._tooltip = function(element) {
  return ($tooltip = bk_tooltip.apply(this, arguments));
};
$(document).tooltip();

置き場

もちろん、_tooltip内部メソッドはtargetas パラメータを受け取り、 を返すためtooltip、このメソッドをオーバーライドするだけで操作全体を実行できますが、このメソッドが返された後にtooltipis shown が返されるためsetTimeout(fn, 0)、望ましくないちらつき効果が発生する可能性があります。

ただし、これは非常に単純なものに対して、過度にハックで、扱いにくく、冗長です。


#4 クリーンなソリューション

文書化されていないメソッド、属性、プロトタイプのオーバーライド、DOM クエリを使用しないなどの「クリーン」。最初のスニペットに戻ると、必要なのはツールヒントをトリガーした要素への参照だけでした。この要素は、ハンドラーの前に呼び出される関数のthis内部で参照されるため、レキシカル スコープを使用して、その参照を 1 つ上のレベルに格納できます。contentopen

var el;
$(document).tooltip({
  content: function() {
    el = this;
    return this.title;
  },
  open: function(e, ui) {
    if (el.offsetWidth === el.scrollWidth) {
      ui.tooltip.hide();
    }
  }
});

置き場

content上記のスニペットのカスタム関数は、jQuery のデフォルトの HTML タグの削除を削除することに注意してください(ツールチップ内で HTML を使用するのが好きなので)。元contentのハンドラーの機能を維持したい場合:

var el,
    bk_content = $.ui.tooltip.prototype.options.content;
$(document).tooltip({
  content: function() {
    el = this;
    return bk_content.apply(this, arguments);
  },
  open: function(e, ui) {
    if (el.offsetWidth === el.scrollWidth) {
      ui.tooltip.hide();
    }
  }
});

置き場


当面の間、この機能の実装をリクエストする jQuery UI バグトラッカーでチケットを開きます。これがそれです:

ツールチップ: オープン/クローズ ハンドラー内でツールチップをトリガーした要素を公開します

于 2013-04-22T04:04:16.053 に答える
2

完全を期すために、ウィジェットにはプロパティが含まれています。tooltipsこれは、開いているすべてのツールチップの ID をキーとして、関連するターゲット要素を値として含むオブジェクトです。

var widget = $(this).data("ui-tooltip");
var el = widget.tooltips[ui.tooltip[0].id][0];

要素への直接参照があるためクリーンですが、変更される可能性のある実装の詳細であるため、少しダーティでもあります。

そうは言っても、そのようなものui.targetは確かにいいでしょう。

于 2013-04-22T09:20:08.453 に答える