2017-01-08 26 views
1

我試圖重新創建jQuery的本機event處理程序,.click("body", "element, element", function(...));。如果用戶點擊除了這兩個元素之外的任何地方,它就會執行某些操作。javascript - 除了某些元素之外的任何東西; e.target不工作...有時

我已經成功完成此操作,但是,有時腳本將無法​​工作。過了一段時間,如果用戶點擊body,則實際下拉按鈕觸發,它不會爲下拉菜單切換class。我不確定爲什麼發生這種情況,因爲它是現在,然後每一個工作...


這是我的JavaScript

var uButton = document.getElementById("user_content"), // the trigger 
    uDropdown = document.getElementById("user__dropdown-menu"); // the menu 

document.onclick = function(e){ 
    if(e.target == uButton){ // if button has been clicked 
     toggleClass(uDropdown, "active"); // (custom function) toggle the class "active" 
    } else if(e.target != uButton && e.target != uDropdown){ // if anything BUT the dropdown and button are clicked 
     if(hasClass(uDropdown, "active")){ // (custom function) if the dropdown is active 
      uDropdown.className = "user__procedural-outer-dropdown"; // reset the classes to default 
     } 
    } 
} 

和相應的HTML

<div class="navigation__user-content" id="user_content"> <!-- the button !--> 
    <span id="nav_username">Sign In</span> 
    <div class="user__procedural-outer"></div> 
</div> 
<div class="user__procedural-outer-dropdown" id="user__dropdown-menu"></div> <!-- dropdown !--> 

我已經包括了JsFiddle以便您可以嘗試並重新創建我的問題。

非常感謝所有幫助,
謝謝。

+2

添加一個簡單的'的console.log(e.target)',可以看到的是,目標是有時'<跨度ID = 「nav_username」>登錄' – Claies

+0

@Claies我如何確保它在點擊按鈕或內容時有效?我已經嘗試過'uButton = document.querySelector(「#user_content,#user_content *);'但是,它仍然只是有效的 –

+0

我相信問題是嵌套HTML元素的事實,目標應該是最內層的嵌套元素。我相信解決方案將是一個做...while循環與條件'(elem = elem.parentNode)'。 –

回答

1

我修改你的代碼儘可能少。我希望這是你正在尋找的。

function hasClass(element, cls) { 
 
    return (' ' + element.className + ' ').indexOf(' ' + cls + ' ') > -1; 
 
} 
 
function toggleClass(element, cls){ 
 
\t element.classList.toggle(cls); 
 
} 
 

 
var uButton = document.getElementById("user_content"), // the trigger 
 
    uDropdown = document.getElementById("user__dropdown-menu"); // the menu 
 
var elems = [uButton, uDropdown]; 
 

 
document.onclick = function(e){ 
 
    var elem = e.target; // innermost target 
 
    do { // performs this block of code in a loop 
 
    if(elems.indexOf(elem) !== -1) 
 
     break; // breaks out of the loop if elem exists within elems 
 
    } 
 
    while(elem = elem.parentNode); // assigns the parent of elem to elem. 
 
    // if elem is null (a falsy value) the conditional will cause the loop to stop 
 
    // and the following code will be executed (otherwise the loop continues). 
 
    // * the following was an edit (for the use of switch): 
 
    switch(elem) { // switch is useful for relating code blocks to values 
 
    case uButton: 
 
     toggleClass(uDropdown, "active"); 
 
     break; // a break is required here or it will keep executing 
 
    case uDropdown: 
 
     void(0); // js for "do nothing" 
 
     break; 
 
    default: // executes if none of the above match 
 
     if(hasClass(uDropdown, "active")) 
 
     uDropdown.className = "user__procedural-outer-dropdown"; 
 
    } 
 
}
.navigation__user-content{ 
 
\t width: 70px; 
 
\t height: 15px; 
 
\t margin-top: 6px; 
 
\t padding: 8px; 
 
\t float: right; 
 
\t background: #730aa2; 
 
\t border-radius: 2px; 
 
\t cursor: pointer; 
 
} 
 
.navigation__user-content:hover{ 
 
\t box-shadow: inset 2px 2px 0px #5a0d91; 
 
} 
 
.navigation__user-content:hover #nav_username{ 
 
\t text-shadow: 2px 2px 0px #5a0d91; 
 
} 
 
.navigation__user-content > #nav_username{ 
 
\t display: inline-block; 
 
\t position: relative; 
 
\t top: -2px; 
 
\t left: 3px; 
 
\t font-size: 13px; 
 
\t font-weight: bold; 
 
\t color: #e6e6e6; 
 
} 
 
.user__procedural-outer{ 
 
\t float: right; 
 
\t position: relative; 
 
\t top: -2px; 
 
\t width: 17px; 
 
\t height: 17px; 
 
\t border-radius: 16px; 
 
\t background: url("noimagefound.png") no-repeat center; 
 
\t background-size: cover; 
 
} 
 
.user__procedural-outer-dropdown{ 
 
\t position: absolute; 
 
\t top: 43px; 
 
\t right: 0; 
 
\t width: 320px; 
 
\t height: 200px; 
 
\t overflow: hidden; 
 
} 
 
.user__procedural-outer-dropdown.active{ 
 
    background: red; 
 
}
<div class="navigation__user-content" id="user_content"> 
 
\t \t <span id="nav_username">Sign In</span> 
 
\t \t <div class="user__procedural-outer"></div> 
 
</div> 
 
<div class="user__procedural-outer-dropdown" id="user__dropdown-menu"></div>

+0

我知道這可能是一個很大的問題,但是通過評論解釋它是如何工作的?我還是JS的新手,如果可以的話,會很感激! :) –

+0

@Celan。讓我知道如果這足夠好 –

+1

工作!謝謝你:-) –

1

看來這裏有幾個問題。我將類名更名爲更簡單的單詞並測試代碼。我發現,根據你的CSS和你設置的位置:relative和position:absolute,下拉菜單div必須在用戶_...- outer div內!

我修改了以下代碼並進行測試。它的工作原理沒有問題:

var uButton = document.getElementById("user_content"), 
 
    uDropdown = document.getElementById("user-dropdown"); 
 

 
document.onclick = function (e) { 
 

 
    if (e.target == uButton || e.target.parentNode == uButton) { 
 
    toggleClass(uDropdown, "active"); 
 
    } else if (e.target != uButton && e.target != uDropdown) { 
 
    if (hasClass(uDropdown, "active")) { 
 
     uDropdown.className = "user-dropdown"; 
 
    } 
 
    } 
 
} 
 

 

 
function hasClass(element, cls) { 
 
    return (' ' + element.className + ' ').indexOf(' ' + cls + ' ') > -1; 
 
} 
 
function toggleClass(element, cls) { 
 
    element.classList.toggle(cls); 
 
}
.user-content{ 
 
\t width: 70px; 
 
\t height: 15px; 
 
\t margin-top: 6px; 
 
\t padding: 8px; 
 
\t float: right; 
 
\t background: #730aa2; 
 
\t border-radius: 2px; 
 
\t cursor: pointer; 
 
} 
 
.user-content:hover{ 
 
\t box-shadow: inset 2px 2px 0 #200050; 
 
} 
 
.user-content > #signin{ 
 
\t display: inline-block; 
 
\t position: relative; 
 
\t top: -2px; 
 
\t left: 3px; 
 
\t font-size: 13px; 
 
\t font-weight: bold; 
 
\t color: #e6e6e6; 
 
} 
 
.user-content:hover > #signin{ 
 
\t text-shadow: 1px 1px 3px #caca30; 
 
} 
 
.user-outer{ 
 
\t float: right; 
 
\t position: relative; 
 
\t top: -2px; 
 
\t width: 17px; 
 
\t height: 17px; 
 
\t border-radius: 16px; 
 
\t background: yellow no-repeat center; 
 
\t background-size: cover; 
 
} 
 
.user-dropdown{ 
 
\t position: absolute; 
 
\t top: 43px; 
 
\t right: 0; 
 
\t width: 320px; 
 
\t height: 200px; 
 
    /*background:#f8f8f8;*/ /* to see its position*/ 
 
    visibility: hidden; /* hide when not active */ 
 
\t overflow: hidden; 
 
} 
 
.user-dropdown.active{ 
 
    background: red; 
 
    visibility:visible; 
 
}
<p>This is a test page!</p> 
 

 
<div id="user_content" class="user-content"> 
 
    <span id="signin">Sign In</span> 
 
    <div id="user-outer" class="user-outer"> 
 
    <div id="user-dropdown" class="user-dropdown"></div> 
 
    </div> 
 
</div>

編輯: 使用if (e.target == uButton || e.target.parentNode == uButton)在點擊事件,包括按鈕,裏面的所有元素,以顯示下拉列表。

+0

不幸的是,我不能控制什麼類被稱爲,所以我有點卡住了他們哈哈 –

+0

我會檢查一下是否有效,謝謝:) –

1

,因爲你的nav_username不在user__procedural-outer,你需要的目標,也當document.onclick = function(e)發生

function hasClass(element, cls) { 
    return (' ' + element.className + ' ').indexOf(' ' + cls + ' ') > -1; 
} 
function toggleClass(element, cls){ 
    element.classList.toggle(cls); 
} 

var uButton = document.getElementById("user_content"), 
    uButtonSpan = document.getElementById("nav_username"), 
    /*since your "nav_username" is not in the "user__procedural-outer", you need to target it also when "document.onclick = function(e)" happens */ 
    uDropdown = document.getElementById("user__dropdown-menu"); 

document.onclick = function(e){ 
    if((e.target == uButton) || (e.target == uButtonSpan)){ 
     toggleClass(uDropdown, "active"); 
    } else if((e.target != uDropdown) && (e.target != uButtonSpan) && (hasClass(uDropdown, "active"))){ 
      uDropdown.className = "user__procedural-outer-dropdown"; 
    } 
} 
相關問題