ももらぼっ!にっき


2005年01月06日 [長年日記]

_ [JavaScript] 中身が全て見れなかったときにtooltipを表示する。

例えばテーブルを使って一覧表を作成した場合、表に収まらなかった内容は折り返して表示されるのが基本。 でも、レイアウトの関係で折り返さないで欲しい、なんて思うときがある。 そんなときに、代替案として使えるっぽいのが、これ。

とりあえず、サンプルを見てほしい。

セルの中身が全て表示されて無いところにマウスをポイントするとよく見るツールチップが表示されると思う。 これは、IEの5.5くらい?から導入されたpopupオブジェクトというものを使用して実現している。

ソースはこんな感じだ。

/**
 * ツールチップを表示する。
 * @param field ツールチップを表示する対象
 * @param className ツールチップに適用されるクラス名(省略時は"Tooltip"となる)
 */
function showTooltip(field, className) {
  if (className == undefined) {
    className = "Tooltip";
  }

  //ポップアップ定義
  if (!field.popup) {
    function toInt(pixel) {
      var result = parseInt(pixel.slice(0, -2));
      if (isNaN(result)) {
        result = 0;
      }
      return result;
    }

    field.popup = window.createPopup();
    with (field.popup) {
      //スタイルシートをコピー
      var cssText;
      for (var i = 0; i < window.document.styleSheets.length; i++) {
        cssText = window.document.styleSheets(i).cssText;
        if (cssText != "") {
          document.createStyleSheet().cssText = cssText;
        }
      }

      //表示用DIV作成
      var div = document.createElement("div");
      document.body.appendChild(div);
      div.id = "TooltipDiv";
      div.me = field.popup;
      div.innerHTML = field.innerHTML;
      div.className = className;
      div.onmouseout = function() {
        this.me.hide();
      }
    }

    //表示関数作成
    field.showTooltip = function () {
      if (this.offsetWidth > this.parentElement.offsetWidth ||
        this.offsetHeight > this.parentElement.offsetHeight) {
        var p_left, p_top, p_right, p_bottom;
        with (this.popup.document.getElementById("TooltipDiv").currentStyle) {
          p_left = toInt(borderLeftWidth) + toInt(paddingLeft);
          p_top = toInt(borderTopWidth) + toInt(paddingTop);
          p_right = toInt(borderRightWidth) + toInt(paddingRight);
          p_bottom = toInt(borderBottomWidth) + toInt(paddingBottom);
        }
        var width = this.offsetWidth + p_left + p_right;
        var height = this.offsetHeight + p_top + p_bottom;
        this.popup.show(-p_left, -p_top, width, height, this);
      }
    }
  }

  //ポップアップ表示
  field.showTooltip();
}

この関数を、ツールチップを表示させたい内容に対してこんな風に指定してあげればよい。

<td><span class="PopupTooltip" onmouseover="showTooltip(this)">ほげもげ</span></td>

ちなみに、PopupTooltipの中身はこんな感じ。

.PopupTooltip {
  word-break: keep-all;
  white-space: nowrap;
}

勝手に改行されないようにCSSを定義している。

ポイントは、このpopupオブジェクトはdocumentオブジェクトを持っているのだが、 このdocumentオブジェクトは大元(呼び出し元)のdocumentとは全く関係ないようで、 スタイルシートやスクリプトの使い回しができないため、 適宜コピーしてやら無いといけないところ。 この辺でちょっと苦労した。

あとは、popupオブジェクトの生成ロジックを毎回実行しないように、 作成したオブジェクトを呼び出し元要素(この場合span)のプロパティとして定義するようにしているところ。 まぁ、正直効果があるかどうかは疑問なのだが(メモリ食ってるだろうしね)。

短いスクリプトではあるが、結構面白いコードができたと思っているんだけどどうだろう。

本日のツッコミ(全1件) [ツッコミを入れる]
_ Orator (2005年01月12日 22:38)

すごく良いなぁコレ。text-overflow:ellipsis; で処理しているセルでも使えますね。利用させてもらいます。