Skip to content

Instantly share code, notes, and snippets.

@woshidan
Created June 14, 2015 17:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save woshidan/24aba7e583fed7b3c7c6 to your computer and use it in GitHub Desktop.
Save woshidan/24aba7e583fed7b3c7c6 to your computer and use it in GitHub Desktop.
wip-icon-tip
div.icon-tip.area {
background-color: #CCC;
margin-top: 100px;
margin-left: 50px;
padding: 30px;
}
div.icon-tip.tooltip {
opacity: 0;
text-align: center;
position: relative;
z-index: 100;
top: 0px;
left: 0px;
}
span.icon-tip.tooltip.container {
color: #FFF;
background-color: #F00;
font-size: 11px;
padding: 10px;
border-radius: 4px;
}
img.icon-tip.image {
margin-right: 3px;
width: 14px;
height: 14px;
}
span.icon-tip.caption {
font-size: 12px;
line-height: 14px;
}
span.icon-tip.tooltip.after {
width: 0;
height: 0;
bottom: -15px;
position: absolute;
left: 38%; /* うまく調整したいが...! */
display: inline;
border-top: 6px solid #F00;
border-left: 8px solid transparent;
border-right: 8px solid transparent;
}
"use strict";
$(function(){
var default_settings = {
opacity: 0.5,
iconSrc: null,
caption: "",
gravity: "bottom",
iconGravity: "left",
tipId: function() { return Math.round(Math.random() * 10000); },
html: function(tipID) {
return '\
<div class="icon-tip tooltip" data-tip-id="' + tipID + '">\
<span class="icon-tip tooltip container">\
<img class="icon-tip image left"/><span class="icon-tip caption"></span><img class="icon-tip image right"/>\
</span>\
</div>'},
};
// todo:
// もっと別の名前とか色々あった気がする。とりあえず、これだと名前空間が衝突しそうなので、
// せめてBackboneみたいに親玉の要素もちたい感あった。
var tip_settings = {};
// var parent_width = $("div.icon-tip.area").
// $(a.icon-tip)...的な記述に対して
// ええと、これだと1個分しかイベント起きねえな。
// それぞれに対してfetchしないと駄目? 感。
// 複数要素をfetchして一括で指定したい、みたいな場合には、
//
$("div.icon-tip.area").on('click', 'a.icon-tip', function(e) {
// todo: なぜ後で再度取得しようとすると { top: 0, left: 0 } になっているのだろう
// DOMイベントの伝搬とか関係あるのかな...
var position = $(this).position();
// tipIdが設定されていない場合、適当に乱数を割り振る。
// 一回表示したらtipIdをセットしてく。
// todo: 乱数がきちんと重複していないか調べる
if ($(this).data('tip-id') == null) {
// キャッシュ対策のため、ネイティブ関数で書き込んでいる
this.setAttribute("data-tip-id", default_settings.tipId());
}
var $target = $(e.target);
// todo: うまくどこかのパラメタに保存させて飛ばしたいものだけど...。
var settings = {};
settings["opacity"] = $target.data('opacity') ? $target.data('opacity') : default_settings.opacity;
settings["caption"] = $target.data('caption') ? $target.data('caption') : default_settings.caption;
settings["iconSrc"] = $target.data('icon-src') ? $target.data('icon-src') : default_settings.iconSrc;
settings["tipId"] = $target.data('tip-id') ? $target.data('tip-id') : default_settings.tipId();
var $tooltip = $('div[data-tip-id~=' + settings["tipId"] + '].icon-tip.tooltip');
tip_settings[settings["tipId"]] = tip_settings[settings["tipId"]] || {};
console.log(tip_settings);
if ( $tooltip.length > 0 && $tooltip.css('opacity') > 0) {
// 既に表示されている状態だったら表示処理を飛ばす
// ここ、もう少しうまくできない... Undefinedになるときがー。
remove_tip();
return false;
}
if ($tooltip.length == 0) {
console.log("DOM作成");
// 既に対応するtip-idの要素が作成されていたら飛ばす
// 透明な状態でツールチップの要素を div.icon-tip.area の末尾に追加
// $('.icon-tip.area').html($('.icon-tip.area').html() + default_settings.html(settings["tipId"]));
$('body').append(default_settings.html(settings["tipId"]));
$tooltip = $('div[data-tip-id~=' + settings["tipId"] + '].icon-tip.tooltip');
// ここも関数に切り出してok
// アイコンの設定が無ければ<img>要素は削除(アイコンに関する設定はimg要素に持たせる)
if (settings["iconSrc"] === null) {
$tooltip.find('img.icon-tip.image').remove();
} else {
$tooltip.find('img.icon-tip.image.right').remove();
$tooltip.find('img.icon-tip.image').attr('src', settings["iconSrc"]);
}
// 文字列の挿入
$tooltip.find('span.icon-tip.caption').html(settings["caption"]);
}
// 幅、高さ、親要素からの相対位置を取得・設定する
// 末尾に表示中の要素が増える事で相対位置がずれることがあるので、
// 複数表示する場合は、上手く言った時の元の親要素からの位置を記憶するようにする
// 現在の方針だと、表示領域は膨らんでしまうので、そこまで複数表示頑張る必要はあるのか...?
// => 複数表示を頑張るの止めたぞ!
// todo: この辺、親要素の位置決定、みたいな感じで関数に括り出したい感じ
if (tip_settings[settings["tipId"]]['width'] == null) {
$tooltip.css('width', $tooltip.find('span.icon-tip.tooltip.container').outerWidth() );
tip_settings[settings["tipId"]]['width'] = $tooltip.css('width');
} else {
$tooltip.css('width', tip_settings[settings["tipId"]]['width'] );
}
if (tip_settings[settings["tipId"]]['height'] == null) {
$tooltip.css('height', $tooltip.find('span.icon-tip.tooltip.container').outerHeight() - 6);
tip_settings[settings["tipId"]]['height'] = $tooltip.css('height');
} else {
$tooltip.css('height', tip_settings[settings["tipId"]]['height'] );
}
if (tip_settings[settings["tipId"]]['left'] == null) {
// todo: 14 はLineheightあたりと連動させて変える
// todo: 6px は吹き出しの△のサイズと連動させて変える
$tooltip.css('left', position.left + $tooltip.find('span.icon-tip.tooltip.container').outerWidth() / 2 - $tooltip.find('img.icon-tip.image').outerWidth() );
tip_settings[settings["tipId"]]['left'] = $tooltip.css('left');
} else {
$tooltip.css('left', tip_settings[settings["tipId"]]['left'] );
}
if (tip_settings[settings["tipId"]]['top'] == null) {
// 複数表示しようとした時、ここがなんかばぐる。
// 複数表示に切り替えた時は、$('div.icon-tip.area')でなくて、その外側のbodyの末尾に突っ込んでたから、
// この辺のサイズは変わらないはずなんだけどなー。
// まさか、こういうことだったとは...!
var $icon_tip_area = $($('div.icon-tip.area')[0]);
$tooltip.css('top', - $icon_tip_area.position().top - $icon_tip_area.innerHeight() - parseInt($icon_tip_area.css('margin-top')) + position.top - (14 * 2.5) - 6 );
// - $($('div.icon-tip.area')[0]).height() - (14 * 3.0) - 6 );
tip_settings[settings["tipId"]]['top'] = $tooltip.css('top');
} else {
$tooltip.css('top', tip_settings[settings["tipId"]]['top'] );
}
var $tooltip_after = $("span[data-tip-id~=" + settings["tipId"] + "].icon-tip.tooltip.after");
if ($tooltip_after.length == 0) {
$tooltip.append('<span class="icon-tip tooltip after" data-tip-id=' + settings["tipId"] + '></span>');
$tooltip_after = $("span[data-tip-id~=" + settings["tipId"] + "].icon-tip.tooltip.after");
}
// 透明度の設定
$tooltip.css('opacity', settings["opacity"]);
$tooltip_after.css('opacity', 1);
$tooltip.css('display', 'inline');
// 要素の消去
// 複数表示設定をやめたので、ここをオブジェクトにしまっているのは意味があるのか感あった。
tip_settings[settings["tipId"]]["click_flg"] = true;
var remove_tip = function(e) {
if (tip_settings[settings["tipId"]]["click_flg"]) {
tip_settings[settings["tipId"]]["click_flg"] = false;
return false;
}
// いい感じにアニメーションさせたい。
if ($tooltip.css('opacity') != 0) {
// $tooltip.css('width', 0); // ここはbody挿入止める前の名残だけど、bodyの末尾も伸びないなら伸びない方が良いので、
$tooltip.css('top', 0); // 表示してないときは、0に縮めておく...
$tooltip.css('left', 0); // というより、display:none <=> block とかだと、うまく相対位置表示できないの何故だ
// $tooltip.css('height', 0);
$tooltip.css('opacity', 0);
$tooltip_after.css('opacity', 0);
$tooltip.css('display', 'none');
$(document).off('click', remove_tip);
}
tip_settings[settings["tipId"]]["click_flg"] = true;
}
$(document).on('click', remove_tip);
});
});
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script type="text/javascript" src="http://code.jquery.com/jquery-1.11.3.js"></script>
<link rel="stylesheet" type="text/css" href="stylesheets/icon-tip.css"></script>
<script type="text/javascript" src="javascripts/icon-tip.js"></script>
</head>
<body>
<div class="icon-tip area">
<a class="icon-tip" data-caption="test1" data-tip-id="1" data-icon-src="images/bag44.png">
テストテキスト1
</a>
<a class="icon-tip" data-caption="test2" data-tip-id="2" data-icon-src="images/dress13.png">
テストテキスト2
</a>
<a class="icon-tip" data-caption="test3" data-icon-src="images/basket31.png">
テストテキスト3
</a>
<br>
<br>
<br>
<a class="icon-tip" data-caption="test4">
テストテキスト4
</a>
</div>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment