当初は、フローティング配置とマウス追跡を組み合わせたツールチップ効果を作成したいと考えていましたが、いくつかの重要な場所で配置とマウス追跡が依然として異なることが判明したため、個別に実行する必要があります。
このエフェクト自体はそれほど難しいものではなく、より使いやすく、より多くの場所で使用できるようにするために、プログラムの構造と拡張に主に力を入れています。
プログラムの特徴
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" " http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd ">
<html xmlns=" http://www.w3.org/1999/xhtml ">
<頭>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
<title>JavaScript のフローティング位置プロンプト効果</title>
<スクリプト>
var $$ = 関数 (id) {
return "string" == typeof id ? document.getElementById(id) : id;
};
var isIE = navigator.userAgent.indexOf('MSIE') != -1;
var isIE6 = isIE && ([/MSIE (d).0/i.exec(navigator.userAgent)][0][1] == "6");
var isChrome = navigator.userAgent.indexOf('Chrome') != -1;
var isSafari = navigator.userAgent.indexOf('AppleWebKit') != -1;
// Tino Zijdel、Matthias Miller、Diego Perini からの意見をもとに
// http://dean.edwards.name/weblog/2005/10/add-event/
function addEvent(要素, タイプ, ハンドラー) {
if (element.addEventListener) {
element.addEventListener(タイプ, ハンドラー, false);
} それ以外 {
if (!handler.$$guid) handler.$$guid = addEvent.guid++;
if (!element.events) element.events = {};
var handlers = element.events[タイプ];
if (!handlers) {
ハンドラー = 要素.イベント[タイプ] = {};
if (要素["on" + タイプ]) {
ハンドラー[0] = 要素["on" + タイプ];
}
}
handlers[handler.$$guid] = ハンドラー;
要素["on" + タイプ] = ハンドルイベント;
}
};
addEvent.guid = 1;
function RemoveEvent(要素, タイプ, ハンドラー) {
if (element.removeEventListener) {
element.removeEventListener(タイプ, ハンドラー, false);
} それ以外 {
if (要素.イベント && 要素.イベント[タイプ]) {
element.events[type][handler.$$guid] を削除します。
}
}
};
関数ハンドルイベント(イベント) {
var returnValue = true;
イベント = イベント || fixEvent(((this.ownerDocument || this.document || this).parentWindow || window).event);
var handlers = this.events[event.type];
for (ハンドラー内の変数 i) {
this.$$handleEvent = ハンドラー[i];
if (this.$$handleEvent(event) === false) {
戻り値 = false;
}
}
戻り値を返します。
};
関数 fixEvent(event) {
イベント.ターゲット = イベント.srcElement;
if(event.type == "マウスアウト") {
イベント.関連ターゲット = イベント.toElement;
}else if(event.type == "マウスオーバー") {
イベント.関連ターゲット = イベント.fromElement;
}
リターンイベント。
};
var Extend = 関数(宛先, ソース) {
for (ソース内の var プロパティ) {
宛先[プロパティ] = ソース[プロパティ];
}
返送先。
}
var に含まれるもの = function(a, b){
return a.contains ? a != b && a.contains(b) : !!(a.compareDocumentPosition(b) & 16);
}
var Bind = function(object, fun) {
var args = Array.prototype.slice.call(arguments, 2);
戻り関数() {
return fun.apply(object, args.concat(Array.prototype.slice.call(arguments)));
}
}
var BindAsEventListener = function(object, fun) {
var args = Array.prototype.slice.call(arguments, 2);
戻り関数(イベント) {
return fun.apply(object, [event].concat(args));
}
}
varFixedTips = function(tip, options){
this.Tip = $$(tip);//プロンプトボックス
this._trigger = null;//トリガーオブジェクト
this._timer = null;//タイマー
this._cssTip = this.Tip.style;// 簡略化されたコード
this._onshow = false;//現在の表示ステータスを記録します
this.SetOptions(オプション);
//チップオブジェクトの処理
this._cssTip.margin = 0;//位置の問題を回避する
this._cssTip.position = "絶対";
this._cssTip.visibility = "非表示";
this._cssTip.display = "ブロック";
this._cssTip.zIndex = 99;
this._cssTip.left = this._cssTip.top = "-9999px";// プレースホルダー内のスクロール バーを避ける
//オフセット補正パラメータ
var iLeft = iTop = 0、p = this.Tip;
while (p.offsetParent) {
p = p.offsetParent; iLeft += p.offsetLeft;
};
this._offsetleft = iLeft;
this._offsettop = iTop;
//Tip オブジェクトに移動しても表示し続ける
addEvent(this.Tip, "mouseover", BindAsEventListener(this, function(e){
//外部要素が入った場合、それは現在非表示遅延段階にあることを意味し、タイマーをクリアして非表示をキャンセルします。
this.Check(e.popularTarget) && clearTimeout(this._timer);
}));
//ie6 は選択をハンドルします
if (isIE6) {
this._iframe = document.createElement("<iframe style='position:absolute;filter:alpha(opacity=0);display:none;'>");
document.body.insertBefore(this._iframe, document.body.childNodes[0]);
};
//クリックして非表示にするために使用します
this._fCH = BindAsEventListener(this, function(e) {
if (this.Check(e.target) && this.CheckHide()) {
this.ReadyHide(this._trigger.ClickHideDelay);
};
});
//非表示にするメソッドをトリガーするために使用されます
this._fTH = BindAsEventListener(this, function(e) {
if (this.Check(e.popularTarget) && this.CheckHide()) {
this.ReadyHide(this._trigger.TouchHideDelay);
};
});
};
FixedTips.prototype = {
_doc: document.documentElement,//コードを簡略化します
// デフォルトのプロパティを設定します
SetOptions: 関数(オプション) {
this.options = {//デフォルト値
ClickShow: true,//クリックモードで表示するかどうか
ClickShowDelay: false,//クリック表示の遅延かどうか
ClickHide: true,//クリックモードを非表示にするかどうか
ClickHideDelay: false,//クリックして遅延を非表示にするかどうか
TouchShow: true,//トリガーモードを表示するかどうか
TouchShowDelay: true,//表示遅延をトリガーするかどうか
TouchHide: true,//トリガーモードが非表示かどうか
TouchHideDelay: true,//非表示遅延をトリガーするかどうか
ShowDelay: 300,//表示遅延時間
HideDelay: 300,//遅延時間を非表示にする
Align: "clientleft",//水平方向の配置
vAlign: "clienttop",//垂直配置
Custom: { left: 0, top: 0 },//カスタム位置
Percent: { left: 0, top: 0 },//カスタマイズされたパーセント位置
Adaptive: false,//適応型位置決めを行うかどうか
Reset: false,//適応位置決め中に再位置決めするかどうか
onShow: function(){},//表示時に実行
onHide: function(){}//非表示時に実行
};
Extend(this.options, options || {});
}、
//トリガー要素を確認する
チェック: function(elem) {
//外部要素(つまり、trigger要素とTipオブジェクト自体およびその内部要素以外の要素オブジェクト)であるかどうかを返します。
!this._trigger を返します ||
!(
this.Tip === 要素 || this._trigger.Elem === 要素 ||
を含む (this.Tip, elem) || を含む (this._trigger.Elem, elem)
);
}、
//表示準備完了
ReadyShow: 関数(遅延) {
clearTimeout(this._timer);
var トリガー = this._trigger;
//クリックして非表示にします
trigger.ClickHide && addEvent(document, "click", this._fCH);
//トリガーモードを非表示にする
trigger.TouchHide && addEvent(this._trigger.Elem, "mouseout", this._fTH);
// トリガーを遅らせるかどうか
if (遅延) {
this._timer = setTimeout(Bind(this, this.Show),trigger.ShowDelay);
} else { this.Show() };
}、
//見せる
表示: function() {
clearTimeout(this._timer);
this._trigger.onShow();//属性を簡単に変更できるように前に置きます
//プリセットの位置とカスタムの位置に基づいて左と上を計算します
var トリガー = this._trigger、rect = トリガー.Elem.getBoundingClientRect()、
スクロールドキュメント = isChrome || ドキュメント.ボディ: this._doc,
スクロール左 = スクロールドキュメント.スクロール左、スクロールトップ = スクロールドキュメント.スクロールトップ、
カスタム左 = トリガー.カスタム.左、カスタムトップ = トリガー.カスタム.トップ、
iLeft = this.GetLeft(rect,trigger.Align) +customLeft,
iTop = this.GetTop(rect,trigger.vAlign) + CustomTop;
//カスタムのパーセンテージの配置
if (trigger.Percent.left) { iLeft += .01 *trigger.Percent.left *trigger.Elem.offsetWidth };
if (trigger.Percent.top) { iTop += .01 *trigger.Percent.top *trigger.Elem.offsetHeight };
//適応的なウィンドウの位置決め
if (トリガー.アダプティブ) {
//位置決めパラメータを修正する
var maxLeft = this._doc.clientWidth - this.Tip.offsetWidth,
maxTop = this._doc.clientHeight - this.Tip.offsetHeight;
if (トリガー.リセット) {
//自動再配置
if (iLeft > maxLeft || iLeft < 0) {
iLeft = this.GetLeft(rect, 2 * iLeft > maxLeft ? "left" : "right") + CustomLeft;
};
if (iTop > maxTop || iTop < 0) {
iTop = this.GetTop(rect, 2 * iTop > maxTop ? "top" : "bottom") + customTop;
};
} それ以外 {
//適切な位置に修正
iLeft = Math.max(Math.min(iLeft, maxLeft), 0);
iTop = Math.max(Math.min(iTop, maxTop), 0);
};
};
//位置と表示を設定する
this._cssTip.left = iLeft +scrollLeft - this._offsetleft + "px";
this._cssTip.top = iTop +scrollTop - this._offsettop + "px";
this._cssTip.visibility = "可視";
//ie6 は選択をハンドルします
if (isIE6) {
this._iframe.style.left = iLeft +scrollLeft + "px";
this._iframe.style.top = iTop +scrollTop + "px";
this._iframe.style.width = this.Tip.offsetWidth + "px";
this._iframe.style.height = this.Tip.offsetHeight + "px";
this._iframe.style.display = "";
};
//トリガーモードを非表示にする
trigger.TouchHide && addEvent(this.Tip, "mouseout", this._fTH);
}、
//相対トリガー要素の左側を取得します
GetLeft: function(rect, align) {
スイッチ (align.toLowerCase()) {
ケース「左」:
戻り値rect.left - this.Tip.offsetWidth;
ケース「クライアント左」:
戻り値rect.left;
ケース「中央」:
return (rect.left + rect.right - this.Tip.offsetWidth)/2;
ケース「クライアント権」:
戻り値rect.right - this.Tip.offsetWidth;
「右」の場合:
デフォルト :
直角右を返します。
};
}、
//トリガー要素を基準にして先頭を取得します
GetTop: function(rect, valign) {
スイッチ (valign.toLowerCase()) {
ケース「トップ」:
戻り値rect.top - this.Tip.offsetHeight;
ケース「クライアントトップ」:
戻り値rect.top;
ケース「中央」:
return (rect.top + rect.bottom - this.Tip.offsetHeight)/2;
ケース「クライアントボトム」:
戻り値rect.bottom - this.Tip.offsetHeight;
ケース「底部」:
デフォルト :
戻り値rect.bottom;
};
}、
//非表示の準備をする
ReadyHide: 関数(遅延) {
clearTimeout(this._timer);
if (遅延) {
this._timer = setTimeout(Bind(this, this.Hide), this._trigger.HideDelay);
} else { this.Hide() };
}、
//隠れる
非表示: function() {
clearTimeout(this._timer);
//非表示に設定します
this._cssTip.visibility = "非表示";
this._cssTip.left = this._cssTip.top = "-9999px";
//ie6 は選択をハンドルします
if (isIE6) { this._iframe.style.display = "なし" };
// トリガーオブジェクトの処理
if (!!this._trigger) {
this._trigger.onHide();
RemoveEvent(this._trigger.Elem, "マウスアウト", this._fTH);
}
this._trigger = null;
//イベントを削除
RemoveEvent(this.Tip, "mouseout", this._fTH);
RemoveEvent(document, "クリック", this._fCH);
}、
//トリガーオブジェクトを追加
追加: function(elem, options) {
//トリガーオブジェクトを作成する
var elem = $$(elem)、トリガー = Extend(Extend({ Elem: elem }, this.options), options || {});
//クリックして表示
addEvent(elem, "クリック", BindAsEventListener(this, function(e){
if (trigger.ClickShow) {
if (this.CheckShow(トリガー)) {
this.ReadyShow(trigger.ClickShowDelay);
} それ以外 {
clearTimeout(this._timer);
};
};
}));
//トリガーモード表示
addEvent(elem, "マウスオーバー", BindAsEventListener(this, function(e){
if (トリガー.TouchShow) {
if (this.CheckShow(トリガー)) {
this.ReadyShow(trigger.TouchShowDelay);
else if (this.Check(e.popularTarget)) {
clearTimeout(this._timer);
};
};
}));
//トリガーオブジェクトを返す
リターントリガー;
}、
//チェックを表示
CheckShow: 関数(トリガー) {
if (トリガー !== this._trigger) {
//同じトリガー オブジェクトでない場合は、競合を避けるために最初に Hide を実行します。
this.Hide(); this._trigger = トリガーを返します。
} else { 戻り値 false };
}、
//非表示チェック
CheckHide: function() {
if (this._cssTip.visibility === "hidden") {
//元々は非表示状態なので、もうHideを実行する必要はありません
clearTimeout(this._timer);
RemoveEvent(this._trigger.Elem, "マウスアウト", this._fTH);
this._trigger = null;
RemoveEvent(document, "クリック", this._fCH);
false を返します。
} else { true を返します。
}
};
</script>
</head>
<本文>
<スタイル>
.trigger{ボーダー:1px 色:#003099; パディング:100px; 余白:150px;}
.tip{ボーダー:1px 色:#c00000; 行の高さ:20px;}
</スタイル>
<div style="padding:50px;">
<div id="idTip" class="tip"></div>
<div id="idTrigger1" class="トリガー">
<選択>
<オプション>テスト</オプション>
</選択>
</div>
<br>
水平位置:
<ラベル>
<input name="nAlign" type="radio" value="left" />
左 </label>
<ラベル>
<input name="nAlign" type="radio" value="clientleft" />
クライアント左 </label>
<ラベル>
<input name="nAlign" type="radio" value="center" />
中央 </label>
<ラベル>
<input name="nAlign" type="radio" value="clientright" />
クライアントの権利 </label>
<ラベル>
<input name="nAlign" type="radio" value="right" selected="チェック済み" />
右 </label>
<br>
垂直位置:
<ラベル>
<input name="nVAlign" type="radio" value="top" />
トップ </label>
<ラベル>
<input name="nVAlign" type="radio" value="clienttop" />
クライアントトップ</label>
<ラベル>
<input name="nVAlign" type="radio" value="center" />
中央</label>
<ラベル>
<input name="nVAlign" type="radio" value="clientbottom" />
クライアントボトム</label>
<ラベル>
<input name="nVAlign" type="radio" value="bottom" selected="チェック済み" />
一番下</lab>
<br>
<br>
カスタムターゲティング:
左:
<input id="idLeft" type="text" size="5" value="0" maxlength="3" />
トップ:
<input id="idTop" type="text" size="5" value="0" maxlength="3"/>
<br>
<br>
<input id="idClick" type="checkbox" selected="チェック済み" />
<label for="idClick">クリック方法</label>
<input id="idTouch" type="checkbox" selected="チェック済み" />
<label for="idTouch">トリガーメソッド</label>
<br>
<br>
遅延時間:
<input id="idDelayTime" type="text" size="5" value="0" maxlength="4"/>
<input id="idDelay" type="button" value="遅延をキャンセル" />
<br>
<br>
その他の応用例: <br>
<br>
<div id="idTest1"> タイトルの使用: <a href=" http://www.cnblogs.com/cloudgamer/archive/2008/11/17/1334778.html " title="ドラッグ アンド ドロップ効果">ドラッグエフェクト</a> <a href=" http://www.cnblogs.com/cloudgamer/archive/2008/12/03/1346386.html " title="ドラッグ アンド ズーム エフェクト">ドラッグ アンド ズームエフェクト</a > <a href=" http://www.cnblogs.com/cloudgamer/archive/2008/07/21/1247267.html " title="画像カット エフェクト">画像カット エフェクト</a > </div >
<br>
<br>
人気のアバター表示エフェクト: <br>
<br>
<div id="idTest2"> <a href=" http://www.cnblogs.com/cloudgamer/archive/2008/07/06/1236770.html " title="画像のスライド切り替え効果"> <img src= "/articleimg/2009/07/6852/r_mx1.jpg" border="0"/></a> http://www.cnblogs.com/cloudgamer/archive/2008/05/ 23/1205642.html " title="画像変形効果"><img src="/articleimg/2009/07/6852/r_mx2.jpg" border="0"/></a> <a href=" http://www.cnblogs.com/cloudgamer/archive/2008/05/13/1194272.html " title="画像スライド表示効果"><img src="/articleimg/2009/07/6852/r_mx3.jpg " border="0" /></a> </div>
<br>
<br>
[閉じる] ボタン: <a id="idTest3" href=" http://www.cnblogs.com/cloudgamer/archive/2009/05/18/TableFixed.html">テーブルの行の配置効果</a>
</div>
<スクリプト>
var forEach = function(array, callback, thisObject){
if(array.forEach){
array.forEach(callback, thisObject);
}それ以外{
for (var i = 0, len = array.length; i < len; i++) { callback.call(thisObject, array[i], i, array) }
}
}
////////////////////////////////////////
var ft = 新しいFixedTips("idTip");
////////////////////////////////////////
var トリガー 1 = ft.Add("idTrigger1", {
onShow: function(){
//位置決めテスト
var sAlign = this.Align、sVAlign = this.vAlign;
forEach(document.getElementsByName("nAlign"), function(o){ if(o.checked){ sAlign = o.value; } });
forEach(document.getElementsByName("nVAlign"), function(o){ if(o.checked){ sVAlign = o.value; } });
this.Align = sAlign;
this.vAlign = sVAlign;
this.Custom.left = $$("idLeft").value 0;
this.Custom.top = $$("idTop").value |
トリガー 1.ShowDelay = トリガー 1.HideDelay = $$("idDelayTime").value 0 || 300;
ft.Tip.innerHTML = sAlign + "<br>" + sVAlign + "<br>" + "left: " + this.Custom.left + "、top: " + this.Custom.top;
}
});
//遅延テスト
$$("idDelayTime").value = トリガー1.ShowDelay;
$$("idDelay").onclick = function(){
if(trigger1.TouchShowDelay){
トリガー1.ClickShowDelay = トリガー1.ClickHideDelay =
トリガー1.TouchShowDelay = トリガー1.TouchHideDelay = false;
$$("idDelayTime").disabled = true;
this.value = "遅延を設定";
}それ以外{
トリガー1.ClickShowDelay = トリガー1.ClickHideDelay =
トリガー1.TouchShowDelay = トリガー1.TouchHideDelay = true;
$$("idDelayTime").disabled = false;
this.value = "遅延をキャンセル";
}
}
//メソッドのテスト
$$("idClick").onclick = function(){
トリガー 1.ClickShow = トリガー 1.クリック非表示 = this.checked;
}
$$("idTouch").onclick = function(){
トリガー1.TouchShow = トリガー1.TouchHide = this.checked;
}
/////////////////////////////////////////
forEach($$("idTest1").getElementsByTagName("a"), function(o){
var title = o.title; o.title = "";
ft.Add(o, { vAlign: "bottom", Percent: { left: 50, top: 0 }, onShow: function(){ ft.Tip.innerHTML = title; } });
})
/////////////////////////////////////////
forEach($$("idTest2").getElementsByTagName("a"), function(o){
var img = o.getElementsByTagName("img")[0]、title = o.title;
o.title = "";
ft.Add(img, { カスタム: { 左: -6, 上: -6 },
onShow: function(){
var str = '<a href="' + o.href + '"><img src="' + img.src + '" border="0"/></ >';
str += '<br /><a href="' + o.href + '">' + タイトル + '</a>';
ft.Tip.innerHTML = str;
}
});
})
/////////////////////////////////////////
ft.Add("idTest3", { ClickHide: false、TouchHide: false、Align: "右"、
onShow: function(){
var str = ' <a href=" http://www.cnblogs.com/cloudgamer/archive/2009/03/11/1408333.html ">カラー グラデーションとグラデーション効果</a><br />';
str += ' <a href=" http://www.cnblogs.com/cloudgamer/archive/2008/10/20/1314766.html ">模倣 163 ネットワーク ディスク更新なしファイル アップロード システム</a><br / >';
str += '<input type="button" onclick="ft.Hide();" value="クリックして閉じる" />';
ft.Tip.innerHTML = str;
}
});
</script>
</body>
</html>
JavaScript、位置決め、フローティング、ヒント、ツールヒント、FixedTips、ヒント
プログラムの説明
ヒントオブジェクト:
Tip オブジェクトはプロンプト情報を表示するために使用されるコンテナであり、プログラムは Tip 属性によって表されます。これには要件はありません。プログラムの初期化時にいくつかの設定が行われます。
まず以下の設定を行います。
this._cssTip.margin = 0;
this._cssTip.position = "絶対";
this._cssTip.visibility = "非表示";
this._cssTip.display = "ブロック";
this._cssTip.zIndex = 99;
this._cssTip.left = this._cssTip.top = "-9999px";
プログラムは Tip の offsetWidth と offsetHeight を取得する必要があるため、位置決めの問題を避けるために Visibility を 0 に設定します。また、スクロール バーが表示されるのを避けるために left と top を設定する必要もあります。チップがスペースを占めています。
先端が他の配置要素の内側にある可能性があるため、2 つのオフセット補正パラメータを設定する必要があります。
var iLeft = iTop = 0、p = this.Tip.offsetParent;
while (!(p === document.body || p === document.documentElement)) {
iLeft += p.offsetLeft; iTop += p.offsetTop;
};
this._offsetleft = iLeft;
this._offsettop = iTop;
最後に、後ほど説明しますが、Tip のマウスオーバーにイベントを追加します。