2010-08-19 8 views
10

자바 스크립트를 배우는 중이고 간단한 드롭 다운 메뉴를 만들려고합니다. 원하는 기능의 예는 톱 메뉴의 Google 홈페이지에서 'more (추가)'및 'settings (설정)'드롭 다운으로 볼 수 있습니다. 특히 메뉴를 클릭하면 메뉴가 사라집니다.Javascript body OnClick

자바 스크립트의 hideMenus 함수에 어떤 코드를 삽입해야 화면상의 어느 곳에서나 클릭이 발생할 때 보이는 코드를 숨길 수 있습니까?

<!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"> 

<head> 
<meta content="text/html; charset=utf-8" http-equiv="Content-Type" /> 
<title>Untitled 1</title> 

<style type="text/css"> 
a 
{ 
    color:blue; 
} 

.info ul.submenu 
{ 
    border: solid 1px #e0e0e0; 
    background-color: #fff; 
    position: absolute; 
    padding: 0; 
    z-index: 2; 
    display: none; 
} 

.info ul.submenu li 
{ 
    display: block; 
    border-top: solid 1px #e0e0e0; 
    margin: 0px 10px 0 10px; 
} 

.info ul.submenu li a 
{ 
    display: block; 
    padding: 7px 0px 6px 0; 
    color: #1177ee; 
    cursor:pointer; 
} 

</style> 

<script type="text/javascript"> 

function hideMenus() 
{ 
//TODO 
} 

function menu(id) {  
    var myLayer = document.getElementById(id);  

    myLayer.onblur = function() {  
     myLayer.style.display = 'none'; 
    }; 

    if (myLayer.style.display == "none" || myLayer.style.display == "") {  
     myLayer.style.display = "block";  
    } else {  
     myLayer.style.display = "none";  
    }  
} 

</script> 
</head> 

<body onclick="hideMenus();"> 
<div class="info">  
    Some Text Boom A <a onclick="menu('id1');">Link</a> | More text  
    <a onclick="menu('id2');">Another Link</a> | more text  
    <ul id="id1" class="submenu">  
     <li><a href="dfhdfh">A1</a></li>  
     <li><a href="aetjetjsd">A2 This is Long</a></li>  
     <li><a href="etetueb">A3</a></li>  
    </ul>  
    <ul id="id2" class="submenu">  
     <li><a href="dfhdfh">B1</a></li>  
     <li><a href="aetjetjsd">B2</a></li>  
     <li><a href="etetueb">B3</a></li>  
    </ul>  
    </div>  
</body> 
</html> 

저는 jQuery를 사용하고 싶지 않습니다.

+6

당신은 매개 변수'e'와'stop_event'을 정의하고 있지만, 이벤트 매개 변수를 호출하지 않는 –

답변

1

꽤 괜찮은 설정이있는 것처럼 보입니다. 어떤 이벤트 버블 링 문제가 발생할 가능성이 있습니다 (자세한 내용은 PPK's Event Order Article을 참조하십시오). 즉 현재 질문의 범위를 외부 것 같다, 그래서 난 그냥 당신이 무엇을 요구 당신을 줄 것이다 :

hideMenus() 
{ 
    var uls = document.getElementsByTagName('ul'), i; 
    for (i = 0; i < uls.length; i++) 
    { 
     if (uls[i].className === 'submenu' && uls[i].style.display !== 'none') 
     { 
      uls[i].style.display = 'none'; 
     } 
    } 
} 

첫째, 우리는 페이지에있는 모든 <UL> 년대를 얻을. 그런 다음 모든 항목을 반복하여 하위 메뉴인지 확인하고 현재 표시되어 있는지 확인합니다. 둘 다 사실이라면, 우리는 그것을 숨 깁니다.ULS에 두 개 이상의 클래스 (class="animal submenu")가있는 경우

  • , 그때는
  • 그것은 모든 <을 통해 모양 메뉴를 숨길하지 않습니다

    이 코드와 몇 가지 오류가 있습니다 ul > 님의 페이지입니다. 이것은 정확하게 효율적이지는 않지만 getElementsByClass에 대한 브라우저 간 지원 없이는 할 수있는 유일한 방법입니다.

이것은 거대한 결함이 아닙니다. 특히 자바 스크립트에 대해 배우고 코드를 면밀히 제어하면 (즉, 다른 개발자가 작업하지 않는 경우) 특히 그렇습니다. 대체로 좋은 디딤돌입니다.

미래에는 onclick="..."을 사용하지 않고 요소에 이벤트 처리기를 추가 할 수있는 매우 일반적인 기능인 addEvent을 사용하는 것이 좋습니다. 두 가지 다른 구현이 있지만, 거의 (모두) 모두 사용자의 관점에서 동일하게 작동합니다. 여기 Dean Edwards's VersionJohn Resig's Version

행운에 대한 링크가 있습니다! 여기

+1

'getElementsByTagName' – lincolnk

+0

죄송합니다! 좋은 캐치. 고정 및 +1 –

-1

신체에 클릭하면 어디서나 클릭을 캡처 할 수 있습니다. javascript 이벤트 전파 모델로 인해 요소의 아무 곳이나 클릭하고 이벤트 전파를 중단하지 않으면 본문에 도달하여 메뉴를 숨길 수 있습니다.

기본적으로 이것은 onclick 본문을 캡처하여 메뉴를 숨기도록 지정하므로 페이지의 아무 영역이나 클릭하면 메뉴가 닫힙니다.

그러나 이것은 원하지 않는 동작을 숨 깁니다. 메뉴를 표시하기 위해 버튼을 클릭하면 메뉴가 표시되고 그 숨기기가 끝나면 (이벤트가 본문에 도달했을 때) 빠르게 표시됩니다. 이를 방지하려면 메뉴를 표시하는 버튼을 클릭 할 때 이벤트가 전파되지 않도록해야합니다 (아래에 게시 한 코드에서 어떻게 작동하는지 확인할 수 있습니다). 이 코드는 제대로 작동하도록 터치해야하는 위치를 보여줍니다.

// this function stops event e or window.event if e is not present from 
// propagating to other elements. 
function stop_event(e) { 
    if(!e) { 
     e = window.event; 
    } 
    if (e.stopPropagation) e.stopPropagation(); 
    e.cancelBubble = true; 
    if (e.preventDefault) e.preventDefault(); 
    e.returnValue = false; 
    return false; 
} 

// now you just hide all the menus in your hideMenus 
function hideMenus() 
{ 
    //pseudocode! 
    for all visible menus - hide // or if you want you can hide all menus, 
           // the hidden will remain hidden 
} 

이제 중요한 부분입니다.

function menu(id) {  
    // your stuff here 
    stop_event(); // this will stop the event going down to the body 
        // and hiding it after showing it 
        // this means it will not flicker like: show-hide 
} 

그리고 마지막으로 전체 UL 요소에

:

//partly pesudocode 
ul.onclick = function() { stop_event(); } 

이가 무엇을 다시 설명하기 :

1 일. hideMenu 함수를 body.onclick에 연결합니다. 즉, 이벤트를 중지하지 않으면 항상 메뉴가 숨겨집니다.

둘째. 메뉴 버튼을 클릭하면 메뉴가 표시되고 이벤트가 본문으로 이동하지 않게됩니다. 이렇게하면 body.onclick이 실행되지 않으며 메뉴를 연 직후에 숨길 수 없습니다.

3rd. ul.onclick은 메뉴를 클릭 할 때 메뉴가 숨겨지지 않는다는 것을 의미합니다 (메뉴 자체를 클릭 할 때 메뉴를 숨기려면이 부분을 제거 할 수 있습니다).

+0

"내가 jQuery를 사용하고 싶지 않아요?" –

+0

E는 필요하지 않습니다. 당신이 코드를 자세히 보면 또한 경우에는 영업 이익이 원하는 그냥 뭐합니까 - 당신은 (그가 웹 페이지 자체가 아닌 OS 나 브라우저 프레임을 의미하는 경우) 화면의 아무 곳이나 클릭하면 그 몸에 hideMenu을 걸려 있기 때문에, 메뉴를 숨기기 딸깍 하는 소리. 마지막 부분은 ... 지금 편집 할 것이고, 한번 더 읽은 후에는 정말 어리석은 것처럼 보입니다. – bisko

+0

끔찍한 일로, onclick = "hideMenus();"가있는 부분을 간과했습니다. 'window.event'는 IE에서만 지원되기 때문에'e'가 필요합니다. //developer.mozilla (비 IE 브라우저에서) DOM 레벨 0 인라인 이벤트 핸들러를 이용하지만 상기 'event' 인터페이스 그래서'e'는 [액세스 (HTTPS이고, A * 래퍼 함수 * 매개 변수로 전달 된 .org/en/DOM/요소 # Event_Handlers). 시도하려면 [JSBin] (http://jsbin.com/imuwo3/2/edit)을 참조하십시오. 이렇게 이벤트 버블 링을 중지하는 것은 불가능합니다. 설명에 대하여 : 실제로 이것은 훨씬 명확 해졌습니다. –

0

우리가 드롭 다운 메뉴가 우리의 웹 응용 프로그램에서 사용하는 논리는 어느 정도되어 그것을 푼다 때

<html> 
<head> 
    <title></title> 
</head> 
<body> 
    <div style="position:relative;width:250px"> 
     <a id="link" href="javascript:" onclick="showDiv(this)">Show menu</a> 
     <ul id="entries" style="display:none;background:#DEF;padding:0;margin:0"> 
     <li>item 1</li> 
     <li>item 2</li> 
     </ul> 
     <input id="inp" style="position:absolute;left:-30px;width:0" /> 
    </div> 

    <script> 
     function showDiv(lnk){ 
      var entries = document.getElementById('entries'), 
       inp = document.getElementById('inp'), 
       nh = 'data-nohide'; 
      //show the entries 
      entries.style.display = 'block'; 
      entries.removeAttribute(nh); 
      inp.focus(); 
      //if mouse over, can't close it 
      entries.onmouseover = function(){ 
       this.setAttribute(nh, true); 
       inp.focus(); 
      }; 
      //if mouse out, can close it 
      entries.onmouseout = function(){ 
       this.removeAttribute(nh); 
      }; 
      entries.onclick = function(e){ 
       //code when the user clicks on the menu... 
       alert((e.target||e.sourceElement).innerHTML); 
       this.style.display = 'none'; 
      }; 
      //if the user press ESC 
      inp.onkeyup = function(e){ 
       if(e.keyCode === 27){ 
        this.style.display = 'none'; 
        this.removeAttribute(nh); 
       }else{ 
        //do something else with other keys(ie:down, up, enter)... 
        inp.focus(); 
       } 
      }; 
      //click somewhere else input onblur 
      inp.onblur = function(){ 
       if(!entries.getAttribute(nh)){ 
        entries.style.display = 'none'; 
        entries = inp = null; 
       } 
      }; 
     } 
    </script> 
</body> 
</html> 

onblur입니다 비결은 focus이있는 input 필드를 사용하고, 메뉴를 트리거하고 닫습니다.

mouseover, mouseout은 사용자가 메뉴에서 항목을 클릭 할 때 onblur이 발생하지 않도록합니다.

링크에 열기/닫기와 같은 전환 효과를 위해, 나는 서로가 필요 숨이 링크를 같아요. 대한 upvoted

관련 문제