LoginSignup
1
1

More than 5 years have passed since last update.

jQuery UI position で、表示方向に応じたクラスを付加する

Last updated at Posted at 2017-10-16

いつ使うものか

  1. jQuery UI position で吹き出し型のツールチップを表示したい
  2. collision: 'flip' での位置調整は便利だけど、上下・左右逆になったときの ▽ 部分の処理どうしよう
    ss.png← こういう感じの切り替え処理

  3. 吹き出し型をやめれば気にする必要ないし、それでいいか...と妥協する

これの2対策。
Google の検索結果を見ると今一つ影の薄い jQuery UI position の、さらに場面限定ネタ。
ただ、やっている事はクラス付加なので他の使い道もあるかもしれない。

完成品

▽ の切り替えは「現在どの方向に吹き出しが表示されているか」が分かれば対応可能なので、position 適用時に基準要素からの相対位置に応じてクラス disp-top disp-btm disp-left disp-right を付加し、それを使って CSS 側で調整を行う。

HTML
<div class="box-tooltip">
<span class="cont-elm">sample text
<span class="cont-tooltip"><span class="inner">Tooltip text</span></span>
</span>
</div>
CSS(標準が上辺中央表示、フリップ時に下辺表示に切り替わる場合)
.cont-tooltip {
position: fixed;
display: none;
z-index: 100;
}

.cont-tooltip .inner {
position: relative;
display: block;
padding: 0.5em;
background: #fee;
border: solid 2px #e33;
text-align: center;
}

/* 吹き出し ▽ 部分の基本指定 */
.cont-tooltip:after {
position: absolute;
content: "";
width: 10px;
height: 10px;
bottom: -5px;
left: 50%;
margin-left: -5px;
background: #fee;
border-bottom: solid 2px #e33;
border-right: solid 2px #e33;
-webkit-transform: rotate(45deg);
-moz-transform: rotate(45deg);
-ms-transform: rotate(45deg);
-o-transform: rotate(45deg);
transform: rotate(45deg);
}

/* 吹き出しを下側に出す際の ▽ の指定 */
.cont-tooltip.disp-btm:after {
top: -5px;
border: none;
border-top: solid 2px #e33;
border-left: solid 2px #e33;
}

javascript(標準が上辺中央表示、フリップ時に下辺表示に切り替わる場合)
$(function() {
    $('.box-tooltip .cont-elm').hover(function(){
        $('.cont-tooltip',this).position({
            of: $(this),
            my: 'center bottom-10',
            at: 'center top',
            collision: 'flip',
            using: function(pos,info) {
                $(this).css(pos);
                var posV = (info.vertical == 'top'? 'btm' : 'top');
                var posH = (info.horizontal == 'left'? 'right' : 'left');
                $(this).removeClass('disp-top disp-btm disp-left disp-right');
                $(this).addClass('disp-' + posV + ' disp-' + posH);
            }
        }).show();
    },function(){
        $('.cont-tooltip',this).css({top:'0',left:'0'}).hide();
    });
});

position の flip 動作で表示するが切り替わる(▽ の切り替えが必要になる)のは「標準時とその反対側の辺」のペアだけで、上下左右には切り替わらない。
例えば、標準時「上辺の左側」表示で水平垂直両方に flip を設定した場合は「上辺の左側」「上辺の右側」「下辺の左側」「下辺の右側」の4種類の配置となり左辺と右辺は使用されない。上下左右に切り替わらないのは、おそらく flip の目的を考えると、ごく一部の特殊な状況を除いてこの動作で十分だからだと思う。
そのため、上記では汎用性を考え上下・左右の両方を出力しているが、切り替えで使用するのはどちらか一方だけの情報となる。
このあたりは、jsdo.it でサンプルを作成したので、実際の動作を見たほうが分かりやすいかもしれない。

解説:クラス付加は using で行う

表示位置に応じてクラスを付加するには using オプションを使う。
といっても、あらかじめパラメータとして相対位置情報が出力される仕様になっているので、それを取り出すだけで良い。

...
            using: function(pos,info) {
                $(this).css(pos);
                var posV = (info.vertical == 'top'? 'btm' : 'top');
                var posH = (info.horizontal == 'left'? 'right' : 'left');
                $(this).removeClass('disp-top disp-btm disp-left disp-right');
                $(this).addClass('disp-' + posV + ' disp-' + posH);
            }
...

まず下準備として、 using を使用した場合、top と left の位置情報は using の関数内で改めて適用する必要があるため、$(this).css(pos); で適用する。
さらりと書いているが、この「関数内で改めて適用する必要がある」事に気づかずハマりまくった。 using は、あくまで +α のための追加オプションで、function の中身は通常処理後に実行されると思っていたのだ。改めてリファレンスを読むと当然きちんと説明されており、一通り読んでも理解できなかったマヌケさが恨めしい。

その後は、2つ目のパラメータに含まれる相対位置情報を取り出して addClass すれば良い。
なお、このパラメータにおける相対表現は「position で操作する要素から見て、基準となる要素はどこにあるか」となっているため、感覚的に分かりやすい「基準要素のどちら側に表示しているか」になるよう反転させている。
また、相対位置の値は center をとる場合もあるが、flip 動作には関係が無いため「上か否か」「左か否か」のみを判定し、上/下・左/右だけを出力している。( center になるのは最初に指定した時のみで、またその場合は常に center なので判別する必要が無い。今回の例で言えば、左右方向は常に disp-left クラスが付加される)

解説:using 内の this について

using 内では position の操作対象が新たに this と定義されるため CSS で調整する際のクラス位置に注意。
今回の例で $(this).addClass によってクラスが付加されるのは、大元の this(= hover の対象である $('.box-tooltip .cont-elm') )ではなく、position の操作対象 $('.cont-tooltip',this) となる。
また、上記の理由により関数化して呼び出す場合も、using 内の this はそのままで良い。

javascript(関数化して呼び出す例)
$(function() {
    $('.box-tooltip .cont-elm').hover(function(){
        var event = $(this)
        posSet(event);
    },function(){
        $('.cont-tooltip',this).css({top:'0',left:'0'}).hide();
    });

    function posSet(event) {
        $('.cont-tooltip',event).position({
            of: $(event),
            my: 'center bottom-10',
            at: 'center top',
            collision: 'flip',
            using: function(pos,info) {
                $(this).css(pos);
                var posV = (info.vertical == 'top'? 'btm' : 'top');
                var posH = (info.horizontal == 'left'? 'right' : 'left');
                $(this).removeClass('disp-top disp-btm disp-left disp-right');
                $(this).addClass('disp-' + posV + ' disp-' + posH);
            }
        }).show();
    }
});
1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1