注:答えずに1年以上後に、この質問はalso posted at Stack Overflow in Portugueseだった - まだ決定的な解決策なしながら - 一部のユーザーと私はreplicate the stacking mechanism in JavaScriptすることができた(...車輪の再発明が、それでも)
CSS2 specification(強調鉱山)にてスタッキングコンテクストアルゴリズムを引用:
ルート要素は、ルートスタックコンテキストを形成します。他の積み重ね文脈は、要素(相対配置要素を含む)によって生成され、 'auto'以外の 'z-index'の計算値を有するによって生成される。スタッキングコンテキストは必ずしもブロックを含むものとは関係ありません。CSSの将来のレベルでは、他のプロパティは、その記述から、例えばコンテキスト、を積み重ねる「不透明度」
を導入することが、ここで返す関数です:要素のa)のz-index
、それは新しいスタックを作成する場合contex;またはb)undefined
それがない場合はありません>
function zIndex(ctx) {
if (!ctx || ctx === document.body) return;
var positioned = css(ctx, 'position') !== 'static';
var hasComputedZIndex = css(ctx, 'z-index') !== 'auto';
var notOpaque = +css(ctx, 'opacity') < 1;
if(positioned && hasComputedZIndex) // Ignoring CSS3 for now
return +css(ctx, 'z-index');
}
function css(el, prop) {
return window.getComputedStyle(el).getPropertyValue(prop);
}
これは、異なるスタッキングコンテキストを形成する要素を離れて設定することができるはずです。残りの要素のために(と等しいz-index
を持つ要素のための)Appendix Eは、彼らが「木の順序」を尊重すべきであると言うための:(視覚的ではない)論理的な順序でレンダリングツリーの
予約限定の深さ優先探索、ボックスを移動するプロパティを考慮した上で、双方向のコンテンツを作成できます。それらの「周りにボックスを移動する性質」を除き
トラバーサル実装し、この関数は正しくshoud:
:定義されたこれらの二つの機能を持つ
/* a and b are the two elements we want to compare.
* ctxA and ctxB are the first noncommon ancestor they have (if any)
*/
function relativePosition(ctxA, ctxB, a, b) {
// If one is descendant from the other, the parent is behind (preorder)
if ($.inArray(b, $(a).parents()) >= 0)
return a;
if ($.inArray(a, $(b).parents()) >= 0)
return b;
// If two contexts are siblings, the one declared first - and all its
// descendants (depth first) - is behind
return ($(ctxA).index() - $(ctxB).index() > 0 ? a : b);
}
を、我々は最終的に私たちの要素の比較関数を作成することができます
function inFront(a, b) {
// Skip all common ancestors, since no matter its stacking context,
// it affects a and b likewise
var pa = $(a).parents(), ia = pa.length;
var pb = $(b).parents(), ib = pb.length;
while (ia >= 0 && ib >= 0 && pa[--ia] == pb[--ib]) { }
// Here we have the first noncommon ancestor of a and b
var ctxA = (ia >= 0 ? pa[ia] : a), za = zIndex(ctxA);
var ctxB = (ib >= 0 ? pb[ib] : b), zb = zIndex(ctxB);
// Finds the relative position between them
// (this value will only be used if neither has an explicit
// and different z-index)
var relative = relativePosition(ctxA, ctxB, a, b);
// Finds the first ancestor with defined z-index, if any
// The "shallowest" one is what matters, since it defined the most general
// stacking context (affects all the descendants)
while (ctxA && za === undefined) {
ctxA = ia < 0 ? null : --ia < 0 ? a : pa[ia];
za = zIndex(ctxA);
}
while (ctxB && zb === undefined) {
ctxB = ib < 0 ? null : --ib < 0 ? b : pb[ib];
zb = zIndex(ctxB);
}
// Compare the z-indices, if applicable; otherwise use the relative method
if (za !== undefined) {
if (zb !== undefined)
return za > zb ? a : za < zb ? b : relative;
return za > 0 ? a : za < 0 ? b : relative;
}
else if (zb !== undefined)
return zb < 0 ? a : zb > 0 ? b : relative;
else
return relative;
}
実際にこの方法を示す3つの例があります:Example 1、Example 2、Example 3(申し訳ありませんが、 nglish ...これはまったく同じコードですが、関数と変数の名前はまったく異なります)。
このソリューションは不完全な可能性が高く、エッジケースでは失敗するはずです(自分では見つけられませんでしたが)。改善の提案があれば、本当に感謝しています。
私は時間があるときにあなたのコードをより慎重にテストしますが、一見一見うまく見えます。私はあなたが今までに持っている最も完全なものなので、あなたの答えを受け入れています。 – mgibsonbr