2017-03-05 10 views
3

私のWebページでJSを使用してドロップダウンメニューを実装しようとしています。私はこれがCSSで可能であることを知っていますが、私はまだこれを達成するためにJSを使いたいと思います。window.setTimeout(someFunc、0)がsomeFuncを直接呼び出すのと同じではないのはなぜですか?

だから私はGoogleで周りに検索し、このコードを見つけました:

var timeout   = 500; 
var closetimer  = 0; 
var ddmenuitem  = 0; 

// open hidden layer 
function mopen(id) 
{ 
    // cancel close timer 
    mcancelclosetime(); 

    // close old layer 
    if(ddmenuitem) ddmenuitem.style.visibility = 'hidden'; 

    // get new layer and show it 
    ddmenuitem = document.getElementById(id); 
    ddmenuitem.style.visibility = 'visible'; 

} 
// close showed layer 
function mclose() 
{ 
    if(ddmenuitem) ddmenuitem.style.visibility = 'hidden'; 
} 

function mclosetime() 
{ 
    closetimer = window.setTimeout(mclose, timeout); 
} 

// cancel close timer 
function mcancelclosetime() 
{ 
    if(closetimer) 
    { 
     window.clearTimeout(closetimer); 
     closetimer = null; 
    } 
} 

// close layer when click-out 
document.onclick = mclose; 
#sddm 
{ margin: 0; 
    padding: 0; 
    z-index: 30} 

#sddm li 
{ margin: 0; 
    padding: 0; 
    list-style: none; 
    float: left; 
    font: bold 11px arial} 

#sddm li a 
{ display: block; 
    margin: 0 1px 0 0; 
    padding: 4px 10px; 
    width: 60px; 
    background: #5970B2; 
    color: #FFF; 
    text-align: center; 
    text-decoration: none} 

#sddm li a:hover 
{ background: #49A3FF} 

#sddm div 
{ position: absolute; 
    visibility: hidden; 
    margin: 0; 
    padding: 0; 
    background: #EAEBD8; 
    border: 1px solid #5970B2} 

    #sddm div a 
    { position: relative; 
     display: block; 
     margin: 0; 
     padding: 5px 10px; 
     width: auto; 
     white-space: nowrap; 
     text-align: left; 
     text-decoration: none; 
     background: #EAEBD8; 
     color: #2875DE; 
     font: 11px arial} 

    #sddm div a:hover 
    { background: #49A3FF; 
     color: #FFF} 
<ul id="sddm"> 
    <li><a href="#" onmouseover="mopen('m1')" onmouseout="mclosetime()">Home</a> 
     <div id="m1" onmouseover="mcancelclosetime()" onmouseout="mclosetime()"> 
     <a href="#">HTML DropDown</a> 
     <a href="#">DHTML DropDown menu</a> 
     <a href="#">JavaScript DropDown</a> 
     <a href="#">DropDown Menu</a> 
     <a href="#">CSS DropDown</a> 
     </div> 
    </li> 
    <li><a href="#" onmouseover="mopen('m2')" onmouseout="mclosetime()">Download</a> 
     <div id="m2" onmouseover="mcancelclosetime()" onmouseout="mclosetime()"> 
     <a href="#">ASP Dropdown</a> 
     <a href="#">Pulldown menu</a> 
     <a href="#">AJAX dropdown</a> 
     <a href="#">DIV dropdown</a> 
     </div> 
    </li> 
    <li><a href="#" onmouseover="mopen('m3')" onmouseout="mclosetime()">Order</a> 
     <div id="m3" onmouseover="mcancelclosetime()" onmouseout="mclosetime()"> 
     <a href="#">Visa Credit Card</a> 
     <a href="#">Paypal</a> 
     </div> 
    </li> 
    <li><a href="#" onmouseover="mopen('m4')" onmouseout="mclosetime()">Help</a> 
     <div id="m4" onmouseover="mcancelclosetime()" onmouseout="mclosetime()"> 
     <a href="#">Download Help File</a> 
     <a href="#">Read online</a> 
     </div> 
    </li> 
    <li><a href="#" onmouseover="mopen('m5')" onmouseout="mclosetime()">Contact</a> 
     <div id="m5" onmouseover="mcancelclosetime()" onmouseout="mclosetime()"> 
     <a href="#">E-mail</a> 
     <a href="#">Submit Request Form</a> 
     <a href="#">Call Center</a> 
     </div> 
    </li> 
</ul> 
<div style="clear:both"></div> 

<div style="clear:both"></div> 

私はドロップダウンがすぐに消えるしたいので、マウスポインタが出て移動した後、私はJSを少し編集しましたドロップダウンの

function mclosetime() 
{ 
    closetimer = window.setTimeout(mclose, 0); 
} 

timeout変数を削除:だから私はこれにそれを変更しました。すべてはまだ動作します。それで、mclosetimeは、基本的にmcloseを0の遅れで呼び出していることに気付きました。私はmclosetimeがあまり機能せず、取り除くことができると思っていました。だから私はそれを取り出して、直接mcloseを呼び出すためにliの要素を変更:

<li><a href="#" onmouseover="mopen('m1')" onmouseout="mclose()">Home</a> 
     <div id="m1" onmouseover="mcancelclosetime()" onmouseout="mclose()"> 
     <a href="#">HTML DropDown</a> 
     <a href="#">DHTML DropDown menu</a> 
     <a href="#">JavaScript DropDown</a> 
     <a href="#">DropDown Menu</a> 
     <a href="#">CSS DropDown</a> 
     </div> 
    </li> 

次にドロップダウンはもう動作しません!マウスポインタをドロップダウンメニューに移動するとすぐにドロップダウンが消えます。私はこれがclosetimerが0であることに起因していると思ったので、私はこれにmcloseを変更:

function mclose() 
{ 
    closetimer = 1; 
    if(ddmenuitem) ddmenuitem.style.visibility = 'hidden'; 
} 

それでも同じことが起こります。

私は本当に混乱しています。 window.setTimeoutは、タイムアウトが0の場合に関数を呼び出すだけではありませんか?それ以上のことがなければ、ここでmcloseと呼ぶとうまくいくはずです!

+0

は、技術的に、 'のsetTimeout(FUNC、遅延)が' 'ない_exactly delay'のミリ秒after_、delay'のミリ秒' than_ _no以下で 'func'を呼び出すことを意味します。 – Passerby

+0

@Passerbyなぜそれが違いになるのでしょうか?また、ドキュメントへのリンクを教えてください。私はW3Schoolsの 'setTimeout'に関するページを読んでいますが、これについては言及していません。 – Sweeper

+0

[このMDNドキュメント](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout)、特に「Notes」の部分をお読みください。 – Passerby

答えて

1

setTimeout(myFun, 0)myFunがすぐに呼び出されることを保証できません。

フックの下で、window.setTimeout(myFun, 0)を実行すると、ブラウザは単に機能myFunをブラウザのイベントキューに入れます。そして、ブラウザは、キューに他のものがない場合にのみ、すぐにそれを実行します。キューに何かが存在すると、それはあなたのmyFunより早く実行されます。

+0

私は今見ます! 'mclose'が少し遅れて呼び出されるのはこの遅延です。この遅延の間、私のマウスはドロップダウンメニューに移動し、タイムアウトはキャンセルされます。 – Sweeper

0

setTimoutは非同期に動作します。つまり、現在の呼び出しスタックの実行が終了すると、mcloseが実行されます。 mcloseを直接呼び出すと、それは現在の呼び出しスタックで(同期的に)順番に実行されますが、setTimoutはすぐに次の呼び出しスタックで実行されます。

0

setTimeout機能に問題はありません。問題はJavaScriptのmouse-outイベントにあり、ネストされた子要素にも適用されます。マウスを子DIVに移動するとすぐに、親のマウス出力イベントが発生します。 JQueryは、あなたが望むものを正確に実行するmouseleaveイベントを使用することで、この問題を簡単に解決できます。

https://api.jquery.com/mouseleave/

関連する問題