いつ使うものか
-
jQuery UI position で吹き出し型のツールチップを表示したい
-
collision: 'flip'
での位置調整は便利だけど、上下・左右逆になったときの ▽ 部分の処理どうしよう
← こういう感じの切り替え処理
-
吹き出し型をやめれば気にする必要ないし、それでいいか...と妥協する
これの2対策。
Google の検索結果を見ると今一つ影の薄い jQuery UI position の、さらに場面限定ネタ。
ただ、やっている事はクラス付加なので他の使い道もあるかもしれない。
完成品
▽ の切り替えは「現在どの方向に吹き出しが表示されているか」が分かれば対応可能なので、position 適用時に基準要素からの相対位置に応じてクラス disp-top
disp-btm
disp-left
disp-right
を付加し、それを使って CSS 側で調整を行う。
<div class="box-tooltip">
<span class="cont-elm">sample text
<span class="cont-tooltip"><span class="inner">Tooltip text</span></span>
</span>
</div>
.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;
}
$(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 はそのままで良い。
$(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();
}
});