So i have multiple buttons that is showing when it's clicked.
But i'm having a hard time hiding the content if another button is clicked.
The Javascript code looks like this
function portFunction() {
var e = document.getElementById("test2").style;
if(!e.display | e.display == "none"){
e.display = "block";
}
else{
e.display = "none";
}
}
And the html
<nav>
<ul>
<li onclick="portFunction();">Portfolio</li>
<li onclick="blogFunction();">Blog</li>
</ul>
</nav>
How can i make it so if another button is clicked, it hides the content for the last button that was open and display the new button content?
EDIT
Snippet code, ok so if you click on Portfolio some text will be displayed. But if you click on Blog some other text will be displayed, but the text from Portfolio will still be displayed. What i want is, if you click the Portfolio button and then the Blog button, the text from portfolio should go away. And i want this for every button.
function blogFunction() {
var e = document.getElementById("test").style;
if(!e.display | e.display == "none"){
e.display = "block";
}
else{
e.display = "none";
}
}
function portFunction() {
var e = document.getElementById("test2").style;
if(!e.display | e.display == "none"){
e.display = "block";
}
else{
e.display = "none";
}
}
#import url(http://fonts.googleapis.com/css?family=Open+Sans);
.center{
font: 100% open sans, sans-serif;
margin:0;
padding:0;
}
#test{
display:none;
height:20%;
width:20%;
z-index:11;
position:absolute;
left:50%;
right: 50%;
}
.testText{
color:red;
z-index:11;
}
#test2{
display:none;
height:20%;
width:20%;
z-index:11;
position:absolute;
left:50%;
}
<nav>
<ul>
<li class="current">Home</li>
<li onclick="portFunction();">Portfolio</li>
<li onclick="blogFunction();">Blog</li>
<li>About</li>
<li>Contact</li>
<li>Preview</li>
</ul>
</nav>
<div class="center">
<div id="test">
<h1 class="testText">
Test
</h1>
</div>
<div id="test2">
<h1 class="testText">
Test2
</h1>
</div>
</div>
A simpler way to do this would be to use classes and jQuery's eq() something like this:
$('.section-link').click(function() {
var cur = $('.section-link').index($(this)); // get the index of the clicked link
$('.section-display').removeClass('active'); // hide all of the sections
$('.section-display').eq(cur).addClass('active'); // show the section at the same index of the clicked link
});
.section-display:not(.active) {
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<nav>
<ul>
<li class="section-link">Portfolio
</li>
<li class="section-link">Blog
</li>
</ul>
</nav>
<br>
<br>
<div class="section-display active">Section One</div>
<div class="section-display">Section Two</div>
In response to your comment, Let's take the code line by line:
First, the CSS rule .section-display:not(.active) { display: none; } hides every element that has the class section-display, unless it also has the class active. This makes all of the divs hidden but allows you to add the classactive if you want a particular section to be shown by default.
In the jQuery, $('.section-link').click(function() { }); is a click handler. Basically, it says when someone clicks on an element that has the class section-link, run the code in this block
Inside the handler, the variable $(this) refers to a jQuery object that represents the element that was clicked (in your case a link).
The first line, var cur = $('.section-link').index($(this)); says, gather all of the elements that have the class section-link (all of you links) into an array and give me the index of the one that was clicked. So now we know that the user clicked the 2nd link for example.
The next line $('.section-display').removeClass('active'); removes the class active from all of the divs that have the class section-display which hides all the divs because of the css rule
On the next line $('.section-display').eq(cur).addClass('active');, $('.section-display') gathers all of the divs that have the class section-display into an array (these are the divs with the content). After that .eq(cur) selects the div from the array that is at the same index as the link that was clicked. And finally .addClass('active') adds the class active to the element which displays the4 element because of the css rule.
So now, clicking on the first section-link element will show the first section-display div and hide all others. Clicking on the second section-link element will show the second section-display div and hide all others. And so on...
I added a callLastFunc() function, it saves and calls previous function, to hide the content added by previous function call.
var lastCalled = null;
function callLastFunc(arg) {
if (arg[0])
return;
if (lastCalled)
lastCalled("byCallPrev");
lastCalled = arg.callee;
}
function blogFunction() {
var e = document.getElementById("test").style;
if(!e.display | e.display == "none"){
e.display = "block";
}
else{
e.display = "none";
}
callLastFunc(arguments);
}
function portFunction() {
var e = document.getElementById("test2").style;
if(!e.display | e.display == "none"){
e.display = "block";
}
else{
e.display = "none";
}
callLastFunc(arguments);
}
#import url(http://fonts.googleapis.com/css?family=Open+Sans);
.center{
font: 100% open sans, sans-serif;
margin:0;
padding:0;
}
#test{
display:none;
height:20%;
width:20%;
z-index:11;
position:absolute;
left:50%;
right: 50%;
}
.testText{
color:red;
z-index:11;
}
#test2{
display:none;
height:20%;
width:20%;
z-index:11;
position:absolute;
left:50%;
}
<nav>
<ul>
<li class="current">Home</li>
<li onclick="portFunction();">Portfolio</li>
<li onclick="blogFunction();">Blog</li>
<li>About</li>
<li>Contact</li>
<li>Preview</li>
</ul>
</nav>
<div class="center">
<div id="test">
<h1 class="testText">
Test
</h1>
</div>
<div id="test2">
<h1 class="testText">
Test2
</h1>
</div>
</div>
Hmm, you would be better to use a framework, but this is what you want right?
This example make use of vanillaJS Framework, which is very powerful out of the box ;)
// lib.js
sitesContent = {};
// blog.js
sitesContent['blog'] = "Blog content"; // You can use templates like handlebars
// portfolio.js
sitesContent['portfolio'] = "Portfolio content"; // Better to use templates
// app.js
function navAction(site) {
document.getElementById('content').innerHTML = sitesContent[site];
}
navAction('portfolio'); // Means load portfolio when loaded first time
<nav>
<ul>
<li><a onclick="navAction('portfolio')" href="#">Portfolio</a></li>
<li><a onclick="navAction('blog')" href="#">Blog</a></li>
</ul>
</nav>
<div id="content"></div>
Related
I'm relatively new to JavaScript, so I'm not sure if I'm doing things conventionally here, of if there's a better way of doing what I'm trying to do.
I have a JavaScript function that takes about 3,600 sentences from a JSON document and inserts them automatically into my HTML code. A unique id is generated for each once in the HTML.
I want to create an onclick event for each sentence so that when it's clicked more information appears underneath about the sentence. This means I have to declare thousands of variables, one for each sentence and one for each information div associated with that sentence:
var sent1 = document.getElementById('s1');
var sent1info = document.getElementById('s1info');
var sent2 = document.getElementById('s2');
var sent2info = document.getElementById('s2info');
var sent3 = document.getElementById('s3');
var sent3info = document.getElementById('s3info');
...
This is way too much to do manually. Is there a way to automate the process of declaring these variables, or is there a better way to do what I'm doing?
For context, my intention with each variable is to feed it into this function:
sent1.onclick = function(){
if(sent1info.className == 'open'){
sent1info.className = 'close';
} else{
sent1info.className = 'close';
}
};
From here the CSS will reduce the info box to a hight of 0 when the className is 'close' and expand it when the className is 'open'. But, again, this will require me writing out this function thousands of times.
Is there a way to do this automatically also? Or am I going about this all wrong?
Edit to show HTML:
<!DOCTYPE html>
<html>
<head>...</head>
<body>
<div id="everything">
<header id="theheader" class="clearfix">...</header>
<div id="thebody" class="box clearfix">
<aside id="page" class="side">...</aside>
<div class="items">
<article id="content" class="article">
<img id="sentpic" src="sentpic.jpg">
<h1>Sentences</h1>
<div id="sentences">
*** This is where the JS inserts sentences and information ***
<ul id='sent1' class='sentcontent'><li class='number'>1.</li><li class='thesent'>...</li></ul>
<div id='sent1info' class='infobox'>
<ul class='sentinfo'><li class='information'>Info:</li><li class='infotext'><em>...</em></li></ul>
<ul class='sentinfo'><li class='information'>Line:</li><li class='line'>...</li></ul>
</div>
<ul id='sent2' class='sentcontent'><li class='number'>2.</li><li class='thesent'>...</li></ul>"
<div id='sent2info' class='infobox'>
<ul class='sentinfo'><li class='information'>Info:</li><li class='infotext'><em>...</em></li></ul>
<ul class='sentinfo'><li class='information'>Line:</li><li class='line'>...</li></ul>
</div>
*** it goes on like this for each sent inserted ***
</div>
</article>
</div>
</div>
<div class="associates clearfix">...</div>
<footer class="foot">...</footer>
</div>
<script type="text/javascript" src="index.js"></script>
</body>
</html>
Using HTML <details> element:
const json = [
{thesent:"Lol", info:"This is some info 1", line:"Whatever 1..."},
{thesent:"Lorem", info:"Some info 2", line:"Something here 2..."},
];
const template_sentence = (ob, i) => `
<details class="sentence">
<summary>${i+1} ${ob.thesent}</summary>
<h3>${ob.info}</h3>
<div>${ob.line}</div>
</details>`;
document.querySelector("#sentences").innerHTML = json.map(template_sentence).join('');
<div id="sentences"></div>
Otherwise, by using your current non-semantic markup:
Targeting by ID (in your specific case) is not needed. There's other methods like the + Next Adjacent sibling selector in CSS.
And here's a JS example - should be self-explanatory, but feel free to ask.
Use JS to toggle a class (.active in this example) to the clickable UL element
Use CSS and the Next adjacent sibling selector + to make the info DIV display: block
/* Just a sample... you'll know how to modify this with the right properties I hope */
const json = [
{thesent:"Lol", info:"This is some info 1", line:"Whatever 1..."},
{thesent:"Lorem", info:"Some info 2", line:"Something here 2..."},
];
// The toggle function:
const toggleInfobox = ev => ev.currentTarget.classList.toggle("active");
// A single sentcontent template
const template_sentence = (ob, i) =>
`<ul class='sentcontent'>
<li class='number'>${i+1}</li>
<li class='thesent'>${ob.thesent}</li>
</ul>
<div class='infobox'>
<ul class='sentinfo'>
<li class='information'>Info:</li>
<li class='infotext'><em>${ob.info}</em></li>
</ul>
<ul class='sentinfo'>
<li class='information'>Line:</li>
<li class='line'>${ob.line}</li>
</ul>
</div>`;
// Get target element
const el_sentences = document.querySelector("#sentences");
// Loop JSON data and create HTML
el_sentences.innerHTML = json.map(template_sentence).join('');
// Assign listeners
const el_sentcontent = el_sentences.querySelectorAll(".sentcontent");
el_sentcontent.forEach(el => el.addEventListener('click', toggleInfobox));
/* BTW, why do you use <ul> ? That's not a semantic list! */
.sentcontent { padding: 0; cursor: pointer;}
.sentcontent li { display: inline-block; }
/* Arrows are cool, right? */
.sentcontent:before { content: "\25BC"; }
.sentcontent.active:before { content: "\25B2"; }
/* Hide adjacent .infobox initially,
/* and show adjacent .infobox on JS click */
.sentcontent + .infobox { display: none; }
.sentcontent.active + .infobox { display: block; }
<div id="sentences"></div>
In this Stack overflow answer you can find out more about toggling an element on some button click.
This question is more of an architectural issue than a need for creating dynamic variables. Consider this example:
ids are removed (existing class names used)
This pattern scales for n sentence instances
In handleClick, we toggle the open class on the clicked element, which lets us leverage the adjacent sibling selector via CSS
No need for a close class, since the absence of the open class represents the closed state.
let outerUL = document.querySelectorAll('.sentcontent')
function handleClick() {
this.classList.toggle('open');
}
outerUL.forEach(ul => {
ul.addEventListener('click', handleClick);
})
.sentcontent {
cursor: pointer;
}
.sentcontent.open + .infobox {
display: block;
}
.infobox {
background-color: #eee;
display: none;
padding: .25em .5em;
}
<ul class='sentcontent'>
<li class='number'>1.</li>
<li class='thesent'>Sent</li>
</ul>
<div class='infobox'>
<ul class='sentinfo'>
<li class='information'>Info</li>
<li class='infotext'><em>Info text</em></li>
</ul>
<ul class='sentinfo'>
<li class='information'>Line info</li>
<li class='line'>Line</li>
</ul>
</div>
<ul class='sentcontent'>
<li class='number'>2.</li>
<li class='thesent'>Sent</li>
</ul>
<div class='infobox'>
<ul class='sentinfo'>
<li class='information'>Info</li>
<li class='infotext'><em>Info text</em></li>
</ul>
<ul class='sentinfo'>
<li class='information'>Line info</li>
<li class='line'>Line</li>
</ul>
</div>
https://jsfiddle.net/d91va7tq/2/
When you have a very large json data then its good idee to keep in mind too not render the whole data at once, it will effect the webbrowser performance. Instead render when needed. And that is when the user click for more information.
I did some example below, make sure too read the comment
const json = [
{thesent:"Lol", info:"This is some info 1", line:"Whatever 1..."},
{thesent:"Lorem", info:"Some info 2", line:"Something here 2..."},
];
const container = document.querySelector(".container");
json.forEach((item)=> {
let x= item;
let el = document.createElement("li");
el.innerHTML = x.thesent;
container.appendChild(el);
el.addEventListener("click",()=> {
var infoContainer= el.querySelector(".info");
// dont create all html element at once, instead create them
//when the user click on it. this is better when you have a very large data.
if (!infoContainer){ // not created, then create
infoContainer = document.createElement("div");
infoContainer.className="info";
var info = document.createElement("div");
var line = document.createElement("div");
info.innerHTML = x.info;
line.innerHTML = x.line;
infoContainer.appendChild(info);
infoContainer.appendChild(line);
el.appendChild(infoContainer);
} else if (infoContainer.style.display == "none") // created and hidden, then display it
infoContainer.style.display = "block";
else infoContainer.style.display= "none"; // already displayed then hide it
});
})
.container li >div.info >div:first-child{
font-size: 12px;
}
.container li >div.info >div:last-child{
font-size: 10px;
}
<ul class="container">
</ul>
Following is my code. I am trying for a simple drop down when clicking on to li and slideup when clicking li back again. But it's not working. I don't know whats wrong. Can anyone comment on this? On top, I am trying to click on the body to get the menu slide back up again. But not when clicking inside the actual menu box (in green).
$(document).ready(function(){
let list = $('ul li');
let mega = $('.megamenu');
list.click(function(e){
e.preventDefault();
mega.slideDown(400);
if((e.target) == list){
mega.slideUp(400);
}
})
});
li{
list-style:none;
display:inline-block;
padding-right: 5rem;
}
.megamenu{
background:green;
padding:5rem;
color:white;
display:none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<ul>
<li>Page 1
<div class ='megamenu'><h1>Mega menu</h1></div>
</li>
<li>Page 2
<div class ='megamenu'><h1>Mega menu</h1></div>
</li>
</ul>
</div>
Could you change like this for click to li to dropdown and click li slideup again
$(document).ready(function(){
let list = $('.menu');
let mega = $('.submenu');
list.click(function(e){
e.preventDefault();
var menuDisplay = mega.css('display');
if(menuDisplay == 'block') {
mega.slideUp(400);
} else {
mega.slideDown(400);
}
})
});
HTML
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<ul>
<li class='menu'>Page 1
<div class ='submenu'><h1>Mega menu</h1></div>
</li>
<li class='menu'>Page 2
<div class ='submenu'><h1>Mega menu</h1></div>
</li>
</ul>
</div>
CSS
.menu{
list-style:none;
display:inline-block;
padding-right: 5rem;
}
.submenu{
background:green;
padding:5rem;
color:white;
display:none;
}
And click Page1 or Page2 to see slideUp and slideDown
I have trouble in writing a script to change the appearance of the clicked tab in a webpage navigation list. In other words, I want to make the clicked tab appear as the selected (in code). I tried to do that by changing its id to selected_link and restoring the id of the previously selected tab.
EDIT: Following jamespaned's suggestion, I replaced element IDs with classes.
My tabs appear like in this picture:
So, when I click to "bio", I want it to appear as "home" and "home" to appear as the other tabs.
As I'm a newbie in JavaScript coding, I didn't managed to accomplish that. Here is what I've done:
The HTML code for the (inline) navigation list:
<nav>
<ul id="navlist">
<li class="selected"> home </li>
<li class=""> bio </li>
<li class=""> publications </li>
<li class=""> software </li>
<li class=""> contact </li>
</ul>
</nav>
its respective CSS:
nav ul {
list-style:none;
padding:0;
margin:0;
}
nav li {
background-color:black;
display:inline;
border:solid;
border-width:1px 1px 0 1px;
margin:0 5px 0 0;
}
nav li a {
color:white;
padding:0 10px;
}
.selected {
background-color:white;
padding-bottom: 1px;
}
.selected_link{
color:blue;
}
and the JavaScript which I've designed to accomplish this task, but it didn't worked:
function changeSelected(clickedId)
{
var ulist = document.getElementById("navlist");
var elems = ulist.getElementsByTagName("class");
for (var i = 0; i < elems.length - 1; i++)
{
var sel = elems[i].getAttribute("class");
if (sel == selected)
{
var selli = elems[i];
break;
}
}
selli.setAttribute("class", "");
selli.lastElementChild.setAttribute("class", "");
var clicked = document.getElementById(clickedId);
clicked.setAttribute("class", "selected_link");
clicked.parentNode.setAttribute("class", "selected");
}
How could I do that using only plain JavaScript?
This Javascript will do what you want:
function changeSelected(clickedId)
{
var selli = document.getElementById("selected");
var sela = document.getElementById("selected_link");
sela.setAttribute("id", "");
selli.setAttribute("id", "");
var clicked = document.getElementById(clickedId);
clicked.setAttribute("id", "selected_link");
clicked.parentNode.setAttribute("id", "selected");
}
That said, here are some ideas that might help your Javascript education:
You are using Javascript to set your IDs, but the Javascript won't work on the next page after you've clicked on one of the links. You'll probably need to do some backend (PHP/Ruby, etc) coding to get your styles to change.
IDs are normally used to refer to a unique element on the page that doesn't change, such as a #header or #sidebar_banner. You might want to use a class instead, such as ".selected_link".
You don't need both #selected_link and #selected. You could do ".selected" and ".selected a" to change the CSS so you only need to change one element.
Hope that helps!
I have 4 <li> and I like them to become the trigger of linked images. I use javascript here and this project does not allow jQuery. Please refer to the code snippet.
var children = document.querySelectorAll('#resistorContent > section[id]');
function showDetailContent(target) {
// Simply loop over our children and ensure they are hidden:
for (var i = 0, child; child = children[i]; i++) {
child.style.display = 'none';
}
// Now, show our child we want to show
document.getElementById(target).style.display = 'block';
}
/* Start Hidden, show first */
#resistorContent > section[id] {
width: 940px;
height: 400px;
overflow: hidden;
display:none;
}
#resistorContent > section[id]:first-child {
display: block;
}
<div id="resistorContent">
<section id="resistorDetail1"><img src="http://d3d71ba2asa5oz.cloudfront.net/40000483/images/pic1.jpg" alt=""></section>
<section id="resistorDetail2"><img src="http://d3d71ba2asa5oz.cloudfront.net/40000483/images/pic2.jpg" alt=""></section>
<section id="resistorDetail3"><img src="http://d3d71ba2asa5oz.cloudfront.net/40000483/images/pic3.jpg" alt=""></section>
<section id="resistorDetail4"><img src="http://d3d71ba2asa5oz.cloudfront.net/40000483/images/pic4.jpg" alt=""></section>
<ul>
<li onmouseover="showDetailContent('resistorDetail1')">Hover 1!</li>
<li onmouseover="showDetailContent('resistorDetail2')">Hover 2!</li>
<li onmouseover="showDetailContent('resistorDetail3')">Hover 3!</li>
<li onmouseover="showDetailContent('resistorDetail4')">Hover 4!</li>
</ul>
</div>
</section>
It works quite fine in jsfiddle and here in the code snippet. But if you paste them to your text editor and preview it in the browser, it renders different result. It creates a pile of all 4 images and it is not hiding the image as javascript intended. What did I do wrong here?
Thanks in advance.
I'm fairly certain the issue is that you are loading your script in the <head> element in your document. This causes an issue because your script tries to loop over the DOM and make changes, but if your script is in the <head> tag, it's executing before the DOM that contains the images is ready. That would be why the images are not being hidden and just stacking. Try running the script just before the closing </body> tag. Your file should look similar to this (but generally it's better to use external stylesheets and link to your javascript files):
<!DOCTYPE html>
<html>
<head>
<title>Testing DOM loading and script placement</title>
<style type="text/css">
/* Start Hidden, show first */
#resistorContent > section[id] {
width: 940px;
height: 400px;
overflow: hidden;
display:none;
}
#resistorContent > section[id]:first-child {
display: block;
}
</style>
</head>
<body>
<div id="resistorContent">
<section id="resistorDetail1"><img src="//placehold.it/940x450/5B696A/fff/&text=PIC+1" alt=""></section>
<section id="resistorDetail2"><img src="//placehold.it/940x450/4D686B/fff/&text=PIC+2" alt=""></section>
<section id="resistorDetail3"><img src="//placehold.it/940x450/415558/fff/&text=PIC+3" alt=""></section>
<section id="resistorDetail4"><img src="//placehold.it/940x450/345658/fff/&text=PIC+4" alt=""></section>
<ul>
<li onmouseover="showDetailContent('resistorDetail1')">Hover 1!</li>
<li onmouseover="showDetailContent('resistorDetail2')">Hover 2!</li>
<li onmouseover="showDetailContent('resistorDetail3')">Hover 3!</li>
<li onmouseover="showDetailContent('resistorDetail4')">Hover 4!</li>
</ul>
</section>
</div>
<script>
var children = document.querySelectorAll('#resistorContent > section[id]');
function showDetailContent(target) {
// Simply loop over our children and ensure they are hidden:
for (var i = 0, child; child = children[i]; i++) {
child.style.display = 'none';
}
// Now, show our child we want to show
document.getElementById(target).style.display = 'block';
}
</script>
</body>
</html>
Here's a demo that doesn't rely on the platform inserting the javascript in the right spot: http://jsbin.com/qulajeroru/2/edit?html,output (click "Run with JS")
I'm in the process of learning Javascript and I'm trying to create a simple dropdown menu.
An example of my desired functionality can be seen on the google homepage in the top menu with the "more" and "settings" dropdown.
I have a ul that is set to display:inline using the onclick() JS event handler. How do I make the ul go back to display:none when I click any where else on the page other than the now visible ul?
I've Googled about blur and setting the focus to another element but I don't know how to actually do it.
I want to do this in straight Javascript, not jQuery.
Here is the html I use:
<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>A1</li>
<li>A2 This is Long</li>
<li>A3</li>
</ul>
<ul id="id2" class="submenu">
<li>B1</li>
<li>B2</li>
<li>B3</li>
</ul>
</div>
When the user clicks on one of the linked <a> tags, the <ul> which is hidden and directly below the <a> tag becomes visible. I want the <ul> element to dissapear when the user clicks anywhere but the <ul>.
Edit:
Here is my javascript:
function menu(id) {
var myLayer = document.getElementById(id);
if (myLayer.style.display == "none" || myLayer.style.display == "") {
myLayer.style.display = "block";
} else {
myLayer.style.display = "none";
}
}
Edit 2:
Complete CodE:
<!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 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>
<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>A1</li>
<li>A2 This is Long</li>
<li>A3</li>
</ul>
<ul id="id2" class="submenu">
<li>B1</li>
<li>B2</li>
<li>B3</li>
</ul>
</div>
</body>
</html>
This is quite simple actually.
Once you have a reference to the DOM element that you want to bind the blur event listener to, assign it like this:
myLayer.onblur = function() {
myLayer.style.display = 'none';
};
jQuery creates a blur event you can bind a function to, is there a strong reason not to use jQuery? Using a JavaScript library even if it is just for event handling, helps insulate you from browser differences. I've only ever used focus/blur events for text input or textarea elements in a form. It sounds like you want a list to float on top of the other elements. I'd position the list relatively and give it a z-index that is higher than the background. I'd bind a click event to the area outside the list, to dismiss the list pop-up. Is toggling a pop-up/modal window what you want? I'd have a look at jQuery SimpleModal for modal window examples, or look at how one is implemented if you want to roll your own.
If you are looking for a way to stop "onclick" event if it happens inside your menu then "event.stopPropagation();" may be what you need
<body onclick="menu('id1'); menu('id2');">
<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" onclick="alert('click menu'); event.stopPropagation();">
<li>A1</li>
<li>A2 This is Long</li>
<li>A3</li>
</ul>
<ul id="id2" class="submenu" onclick="alert('click menu'); event.stopPropagation();">
<li>B1</li>
<li>B2</li>
<li>B3</li>
</ul>
</div>
</body>