Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.javascript > #20869 > unrolled thread
| Started by | Tuxedo <tuxedo@mailinator.com> |
|---|---|
| First post | 2013-08-05 19:35 +0200 |
| Last post | 2013-08-09 21:23 +0200 |
| Articles | 5 — 2 participants |
Back to article view | Back to comp.lang.javascript
Enhancing typical CSS drop menu with onclick event Tuxedo <tuxedo@mailinator.com> - 2013-08-05 19:35 +0200
Re: Enhancing typical CSS drop menu with onclick event JJ <duh@nah.meh> - 2013-08-06 15:59 +0700
Re: Enhancing typical CSS drop menu with onclick event Tuxedo <tuxedo@mailinator.com> - 2013-08-06 16:46 +0200
Re: Enhancing typical CSS drop menu with onclick event JJ <duh@nah.meh> - 2013-08-07 03:23 +0700
Re: Enhancing typical CSS drop menu with onclick event Tuxedo <tuxedo@mailinator.com> - 2013-08-09 21:23 +0200
| From | Tuxedo <tuxedo@mailinator.com> |
|---|---|
| Date | 2013-08-05 19:35 +0200 |
| Subject | Enhancing typical CSS drop menu with onclick event |
| Message-ID | <ktonod$ei8$1@news.albasani.net> |
Below is an old-fashioned dropdown method that can still be good for
devices that support :hover but which works poorly on touch screen devices
where :hover and onmouseover doesn't exist or isn't usable anymore. In this
example there are two independent 'navmenu' class span blocks, which may
appear in different places on a page, although more typically similar
things may be done as a nested group of <ul> dropdowns in a holding <ul> in
horizontal or vertical site navigation style (e.g. A List Apart, Son of
Suckerfish etc.).
However, using a same html class for separate menus, I would like a
javascript to apply 'left: auto' to the dropdown navmenu that is clicked on
(instead of using hover as below). Or perhaps it could equally be done by
'display' a previously 'hidden' html object.
Thereafter when either clicking the same node link a second time or another
node link on the same page, the previously visible dropdown should become
hidden again, so only one dropdown is visible at any one time.
How can this be done in Javascript? (I guess collecting the relevant
classes and applying changes in combination with 'this' keyword).
<!DOCTYPE html>
<style>
.navmenu .dropdown{
left: -999em;
position: absolute;
display: block;
}
.navmenu:hover .dropdown{
left: auto;
}
</style>
<span class="navmenu">
<a href="node1.html">Node 1</a>
<span class="dropdown">
<ul>
<li><a href="sub1.html">Sub 1</a></li>
<li><a href="sub2.html">Sub 2</a></li>
</ul>
</span>
</span>
<hr>
<span class="navmenu">
<a href="node2.html">Node 2</a>
<span class="dropdown">
<ul>
<li><a href="sub3.html">Sub 3</a></li>
<li><a href="sub4.html">Sub 4</a></li>
</ul>
</span>
</span>
For added usability an "x" could be included somewhere, maybe at the
bottom-right or top-right of each dropdown span block, which could remove
the current dropdown when clicked.
Any ideas, code bits or links to sites that have solved this already
(although not by popular code libraries) would be much appreciated!
Tuxedo
[toc] | [next] | [standalone]
| From | JJ <duh@nah.meh> |
|---|---|
| Date | 2013-08-06 15:59 +0700 |
| Message-ID | <19fdmc1ur4uoq$.11i5vm93mk195$.dlg@40tude.net> |
| In reply to | #20869 |
On Mon, 5 Aug 2013 19:35:08 +0200, Tuxedo wrote:
> Below is an old-fashioned dropdown method that can still be good for
> devices that support :hover but which works poorly on touch screen devices
> where :hover and onmouseover doesn't exist or isn't usable anymore. In this
> example there are two independent 'navmenu' class span blocks, which may
> appear in different places on a page, although more typically similar
> things may be done as a nested group of <ul> dropdowns in a holding <ul> in
> horizontal or vertical site navigation style (e.g. A List Apart, Son of
> Suckerfish etc.).
>
> However, using a same html class for separate menus, I would like a
> javascript to apply 'left: auto' to the dropdown navmenu that is clicked on
> (instead of using hover as below). Or perhaps it could equally be done by
> 'display' a previously 'hidden' html object.
>
> Thereafter when either clicking the same node link a second time or another
> node link on the same page, the previously visible dropdown should become
> hidden again, so only one dropdown is visible at any one time.
>
> How can this be done in Javascript? (I guess collecting the relevant
> classes and applying changes in combination with 'this' keyword).
Use this.
<script>
(function() {
function init() {
function navClick(ev) {
var ev = ev || event;
var node = ev.target || ev.srcElement;
var dropdown = node.parentNode.querySelector(".dropdown");
dropdown.style.left = dropdown.style.left === "" ? "auto" : "";
return false;
}
var navs = document.querySelectorAll(".navmenu");
for (var i = 0; i < navs.length; i++) {
var node = navs[i].querySelector("a");
node.onclick = navClick;
}
}
if (window.addEventListener) {
addEventListener("DOMContentLoaded", init, false);
} else {
attachEvent("onload", init);
}
})();
</script>
> <style>
> .navmenu .dropdown{
> left: -999em;
> position: absolute;
> display: block;
> }
>
> .navmenu:hover .dropdown{
> left: auto;
> }
> </style>
Remove the CSS for ".navmenu:hover .dropdown" since it's no longer used.
> <span class="navmenu">
> <a href="node1.html">Node 1</a>
>
> <span class="dropdown">
> <ul>
> <li><a href="sub1.html">Sub 1</a></li>
> <li><a href="sub2.html">Sub 2</a></li>
> </ul>
> </span>
>
> </span>
>
> <hr>
>
> <span class="navmenu">
> <a href="node2.html">Node 2</a>
>
> <span class="dropdown">
> <ul>
> <li><a href="sub3.html">Sub 3</a></li>
> <li><a href="sub4.html">Sub 4</a></li>
> </ul>
> </span>
>
> </span>
Consider adding this CSS rule to hide the list bullets.
.dropdown {
list-style: none;
}
[toc] | [prev] | [next] | [standalone]
| From | Tuxedo <tuxedo@mailinator.com> |
|---|---|
| Date | 2013-08-06 16:46 +0200 |
| Message-ID | <ktr27r$nsh$1@news.albasani.net> |
| In reply to | #20874 |
JJ wrote:
Thanks, it works. I tested on most current browsers as well as on IE8.
I added <a href="javascript:void(0);"> in the node links and removed the
hover CSS:
.navmenu:hover .dropdown{
left: auto;
}
Your solution is a nice and short procedure without need for special HTML
IDs for each drop down, etc. magically working on any number of independent
structures on a page:
<span class="navmenu"><a href="javascript:void(0);">Node ...</a>
<span class="dropdown">
<ul>
<li><a href="sub...html">Sub ...</a></li>
</ul>
</span>
</span>
It's particularly useful if showing more than one drop down at the time is
a good feature.
Alternatively, can your script easily be made to show only one dropdown at
any one time?
For example, if Node 1 is clicked and directly thereafter Node 2 is clicked
without first closing Node 1, can the dropdown for Node 1 close by the
action of clicking/opening Node 2 (or any other node)? I guess it could be
done somehow by closing the dropdown of any/all other open dropdowns, if
there are, just before opening the latest clicked node/dropdown?
Yes, the idea is to hide the bullets. The HTML/CSS example is a skeleton,
just to keep the code short in the original post.
Many thanks again for your script!
Tuxedo
> On Mon, 5 Aug 2013 19:35:08 +0200, Tuxedo wrote:
[...]
>
> Use this.
>
> <script>
> (function() {
> function init() {
> function navClick(ev) {
> var ev = ev || event;
> var node = ev.target || ev.srcElement;
> var dropdown = node.parentNode.querySelector(".dropdown");
> dropdown.style.left = dropdown.style.left === "" ? "auto" : "";
> return false;
> }
> var navs = document.querySelectorAll(".navmenu");
> for (var i = 0; i < navs.length; i++) {
> var node = navs[i].querySelector("a");
> node.onclick = navClick;
> }
> }
> if (window.addEventListener) {
> addEventListener("DOMContentLoaded", init, false);
> } else {
> attachEvent("onload", init);
> }
> })();
> </script>
>
> > <style>
> > .navmenu .dropdown{
> > left: -999em;
> > position: absolute;
> > display: block;
> > }
> >
> > .navmenu:hover .dropdown{
> > left: auto;
> > }
> > </style>
>
> Remove the CSS for ".navmenu:hover .dropdown" since it's no longer used.
>
> > <span class="navmenu">
> > <a href="node1.html">Node 1</a>
> >
> > <span class="dropdown">
> > <ul>
> > <li><a href="sub1.html">Sub 1</a></li>
> > <li><a href="sub2.html">Sub 2</a></li>
> > </ul>
> > </span>
> >
> > </span>
> >
> > <hr>
> >
> > <span class="navmenu">
> > <a href="node2.html">Node 2</a>
> >
> > <span class="dropdown">
> > <ul>
> > <li><a href="sub3.html">Sub 3</a></li>
> > <li><a href="sub4.html">Sub 4</a></li>
> > </ul>
> > </span>
> >
> > </span>
>
> Consider adding this CSS rule to hide the list bullets.
>
> .dropdown {
> list-style: none;
> }
[toc] | [prev] | [next] | [standalone]
| From | JJ <duh@nah.meh> |
|---|---|
| Date | 2013-08-07 03:23 +0700 |
| Message-ID | <169h2xu4o50sk.ejf3hto84v6q.dlg@40tude.net> |
| In reply to | #20875 |
On Tue, 6 Aug 2013 16:46:18 +0200, Tuxedo wrote:
> It's particularly useful if showing more than one drop down at the time is
> a good feature.
>
> Alternatively, can your script easily be made to show only one dropdown at
> any one time?
>
> For example, if Node 1 is clicked and directly thereafter Node 2 is clicked
> without first closing Node 1, can the dropdown for Node 1 close by the
> action of clicking/opening Node 2 (or any other node)? I guess it could be
> done somehow by closing the dropdown of any/all other open dropdowns, if
> there are, just before opening the latest clicked node/dropdown?
I forgot about that, sorry. This one's better.
(function() {
var last = null;
function closeLast(now) {
if (last) {
last.style.left = "";
}
last = now;
}
function clicked(ev) {
var ev = ev || event;
var node = ev.target || ev.srcElement;
if ((node.tagName==="A") && (node.parentNode.className==="navmenu")) {
var dropdown = node.parentNode.querySelector(".dropdown");
if (dropdown !== last) {
dropdown.style.left = "auto";
closeLast(dropdown);
} else {
closeLast(null);
}
if (ev.preventDefault) {
ev.preventDefault();
} else {
ev.returnValue = false;
}
} else {
closeLast(null);
}
}
if (document.addEventListener) {
document.addEventListener("click", clicked, false);
} else {
document.attachEvent("onclick", clicked);
}
})();
[toc] | [prev] | [next] | [standalone]
| From | Tuxedo <tuxedo@mailinator.com> |
|---|---|
| Date | 2013-08-09 21:23 +0200 |
| Message-ID | <ku3fjj$pso$1@news.albasani.net> |
| In reply to | #20878 |
JJ wrote:
> On Tue, 6 Aug 2013 16:46:18 +0200, Tuxedo wrote:
[...]
>
> I forgot about that, sorry. This one's better.
Many thanks for posting the below version. It works perfectly!
Tuxedo
>
> (function() {
> var last = null;
> function closeLast(now) {
> if (last) {
> last.style.left = "";
> }
> last = now;
> }
> function clicked(ev) {
> var ev = ev || event;
> var node = ev.target || ev.srcElement;
> if ((node.tagName==="A") && (node.parentNode.className==="navmenu")) {
> var dropdown = node.parentNode.querySelector(".dropdown");
> if (dropdown !== last) {
> dropdown.style.left = "auto";
> closeLast(dropdown);
> } else {
> closeLast(null);
> }
> if (ev.preventDefault) {
> ev.preventDefault();
> } else {
> ev.returnValue = false;
> }
> } else {
> closeLast(null);
> }
> }
> if (document.addEventListener) {
> document.addEventListener("click", clicked, false);
> } else {
> document.attachEvent("onclick", clicked);
> }
> })();
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.javascript
csiph-web