2015-12-19 48 views
1

我只是在學習Javascript(非常開始),並且在將焦點應用於元素時嘗試使隱藏的「子導航」菜單出現時出現問題。我保持它非常基本(我認爲)。將焦點事件添加到使用javascript的元素時遇到問題

這個想法與懸停時顯示隱藏的「子導航」菜單相同。當應用用戶標籤到元素和焦點時,菜單顯示並且菜單中的鏈接變得可以聚焦。當用戶退出菜單時,菜單會再次隱藏。我希望這種情況發生在任何數量的導航元素上。

的HTML:

<nav role="navigation"> 
    <ul> 
     <li><a href="#">Link 1</a></li> 
     <li><a href="#" class="has-dropdown">Link 2</a> 
     <ul class="dropdown"> 
      <li><a href="#">Link 2a</a></li> 
      <li><a href="#">Link 2b longer</a></li> 
      <li><a href="#">Link 2c longest text</a></li> 
     </ul> 
     </li> 
     <li><a href="#">Link 3</a></li> 
     <li><a href="#">Link 4</a></li> 
    </ul> 
</nav> 

不知道你需要它,但這裏是CSS:

nav[role=navigation] { 
    width: 100%; 
    background: #505050; 
    font-family: Oswald,sans-serif; 
    font-weight: 200; 
} 

nav[role=navigation] ul { 
    margin: 0; 
    padding: 0; 
    list-style: none; 
    display: -webkit-flex; 
    display: -ms-flexbox; 
    display: flex; 
    -webkit-flex-wrap: wrap; 
    -ms-flex-wrap: wrap; 
    flex-wrap: wrap; 
    -webkit-justify-content: flex-start; 
    -ms-flex-pack: start; 
    justify-content: flex-start; 
} 

nav[role=navigation] ul li { 
    -webkit-flex: 0 1 auto; 
    -ms-flex: 0 1 auto; 
    flex: 0 1 auto; 
    text-align: center; 
    padding: .8333rem; 
    border-right: 1px solid #252525; 
    position: relative; 
} 

nav[role=navigation] ul li:last-of-type { 
    border-right: none; 
} 

nav[role=navigation] ul li:hover a + ul { 
    display: block; 
} 

nav[role=navigation] ul ul { 
    list-style: none; 
    position: absolute; 
    top: 100%; 
    left: 0; 
    background: #252525; 
    padding: 0; 
    width: 200%; 
    text-align: left; 
    display: none; 
} 

nav[role=navigation] ul ul.active { 
    display: block; 
} 

nav[role=navigation] ul a { 
    padding: 0 1rem; 
    color: #fff; 
    text-decoration: none; 
} 

nav[role=navigation] ul a:focus, 
nav[role=navigation] ul a:hover { 
    text-decoration: underline; 
    color: #ccc; 
} 

的JavaScript:

var topLevel = document.getElementsByClassName("has-dropdown"); 

for (var i = 0; i < topLevel.length; i++) { 
    topLevel[i].onfocus = function() { 
     console.log("you have activated the dropdown"); 
     topLevel.nextElementSibling.className = "active"; 
    } 
} 

當我標籤的鏈接觸發這樣,我就可以在任何有子菜單但子菜單不顯示的鏈接上正確地獲取日誌消息。當我從控制檯運行時,出現錯誤「無法設置屬性」className「未定義。」

我相信這與變量是一個數組有關,因爲如果我設置topLevel的索引,如topLevel [0]它可以很好地工作。

我想用香草JS。沒有JQuery。

我已經搜索了類似的問題,但無法找到任何答案在我頭上或只給JQuery解決方案。

我看:

CSS3 drop down menu
For-each over an array in JavaScript? - >這一次讓我的大腦出血。
Target items in an array on click?
How to split an array with retrieved values from DOM

答案可能藏身在上述職位之一,但如果是,我無法找到它。感謝您幫助初學者。

+0

我tryed代碼上的jsfiddle和它的工作如預期的樣子:HTTPS: //jsfiddle.net/chktsx8h/ – Rodrigo

+0

我看着你的小提琴,它不工作。當link2被給予焦點時,子菜單不會出現。 – djlotus

+0

我認爲這是瀏覽器,我很抱歉。我嘗試使用Chrome。 – Rodrigo

回答

0

在現代瀏覽器中,你應該添加一個偵聽:

var topLevel = document.getElementsByClassName("has-dropdown"); 

for (var i = 0; i < topLevel.length; i++) { 
    topLevel[i].addEventListener('focus',function(event) { 
     console.log("you have activated the dropdown"); 
    event.currentTarget.nextElementSibling.className = "active"; 
    },false); 
} 

參考:addEventListener not working in IE8

舊的瀏覽器

var topLevel = document.getElementsByClassName("has-dropdown"); 

for (var i = 0; i < topLevel.length; i++) { 
    if (topLevel[i].addEventListener) { 
      topLevel[i].addEventListener('focus',function(event) { 
      console.log("you have activated the dropdown"); 
      event.currentTarget.nextElementSibling.className = "active"; 
     },false); 
    } 
    else { 
     topLevel[i].attachEvent("focus", function(event) { 
     console.log("you have activated the dropdown"); 
     event.currentTarget.nextElementSibling.className = "active"; 
    }); 
} 
+0

刪除類取決於你(何時)做到這一點,但引用:'.classList.remove(「active」);' –

+0

我避免'addEventListener'的原因是因爲我需要支持IE8。吮,我知道,但必要的。如果爲悲傷的瀏覽器提供支持對於像我這樣的菜鳥來說工作太多,我會默認使用這種方法。 – djlotus

+0

嗯,那麼IE的東西是有道理的。您可以查看jQuery代碼,看看它們如何規範化這些事件(並且仍然不使用jQuery)......它在那裏經過了相當好的審查和測試 - 例如1.11.x版本。 –

0

我在我的項目進入了同樣的問題https://github.com/arthurdd/scales/blob/master/index.js#L60

基本上我所做的就是定義一個函數add_listeners_all(你可能不會需要這樣的功能,如果你只是做這一次)

這裏的代碼

function add_listeners_all(selector, fun) { 
    Array.prototype.slice.apply(document.querySelectorAll(selector)).forEach(el) { 
     el.addEventListener('click', fun); 
    }); 
}); 

我不記得我是如何得到它做到這一點的語義,但它完美,因爲你可以在現場演示http://backtick.town/~jay/scales(下發展看,不要指望它來工作還沒有)

正如你所看到的,你可以替換document.querySelectorAll(selector)toplevel陣列和fun您的功能。

同樣,這個記憶對我來說都很模糊,所以這可能不起作用。如果它不起作用,請隨時向我傾訴併發泄你的憤怒。

+0

不知道這是如何適用。你聲明「我不記得我是如何做到這一點的語義,但它完美的作品,你可以在現場演示http://backtick.town/~jay/scales中看到」但是然後聲明「(正在開發中,不要期望它能夠工作)「。我點擊了你的項目和你的鏈接,但沒有看到與我的問題有關的任何事情。也許我錯過了它。你能進一步解釋嗎?正如我所說,我剛剛開始學習,可能無法正確連接點。 – djlotus

+0

對不起。我處理元素事件偵聽器的方式是通過遍歷它們並設置事件偵聽器,就像你在這裏試圖做的那樣。通過使用forEach循環和'addEventListener',您可以輕鬆應用此技術。 – birdoftheday

+0

我會研究一下。 – djlotus

相關問題