$(document).ready(function(){
$("a").each(function () {
if ( $(this).siblings().size() > 0)
{
$(this).append("<span class='has-child'>has child</span>");
$(this).toggle(
function (){
$("ul").removeClass("showme");
$(this).siblings(".selected").addClass("showme");
//$(this).next().css({display: "block"});
},
function (){
$(this).siblings(".selected").removeClass("showme");
//$(this).next().css({display: "none"});
});
}
});
$('ul > li > ul > li:last-child > a').css('background','yellow');
});
the css,
ul > li > ul {
display:none;
}
ul > li:hover ul{
display: block;
}
.showme {
display: block;
}
first of all, it seems fine - I can toggle the targeted sibling, but why after the first toggle at any parent, I have to click twice sometime to hide other siblings when I click/ toggle at the current parent?
$(document).ready(function(){
// Change the first <ul> of the HTML to <ul id="tree"> in order for the next line to work
// I changed it because it's bit overkill to walk ALL <a>'s on the page when you're just interested in
// the <a>'s in the tree
$("#tree a").each(function () {
// add .selected in .siblings() to be more specific
if ($(this).siblings('.selected').size() > 0) {
// Please, no single quotes for HTML attributes...
$(this).append("<span class=\\"has-child\\">has child</span>");
// The toggle here was causing the problem of needing to click twice.
// .toggle() does not take into account if an element is currently visible, but merely
// lets you assign two onclick functions where the first function is fired every even click
// and the second one if fired every odd click
// Because a click of an element in your case can cause *another* element to show/hide, the
// normal principle of .show()/.hide() doesn't work here anymore
$(this).click( function (){
// check if the next element (the "drop down") is currently visible
if ($(this).siblings('.selected').is(':visible')) {
$('.selected').removeClass('showme'); // hide all drop downs
$(this).siblings('.selected').addClass('showme'); // and show the drop down connected to this link
}
});
}
});
$('ul > li > ul > li:last-child > a').css('background','yellow');
});
Hi, thanks so much for explaining about toggle(). I have tried your suggestion, however, the current parent does not toggle anymore, it only toggle when I click on other parents… have a look here,
$(this).click( function (){
// check if the next element (the "drop down") is currently visible
if ($(this).siblings('.selected').is(':visible')) {
$('.selected').removeClass('showme'); // hide all drop downs
$(this).siblings('.selected').addClass('showme'); // and show the drop down connected to this link
}
});
}
with
$(this).click( function (){
// check if the next element (the "drop down") is currently visible
var sibling = $(this).siblings('.selected');
$('.selected').not( sibling ).removeClass('showme'); // hide all visible drop downs, but not the sibling of the clicked <a>
if (!sibling.hasClass('showme')) {
sibling.addClass('showme'); // show the drop down connected to this <a>
} else {
sibling.removeClass('showme'); // hide the drop down connected to this <a>
}
});
hi thanks again! I have modified the code a little, so that I can toggle the parent in the way I want to achieve,
$(this).click( function (){
// check if the next element (the "drop down") is currently visible
var sibling = $(this).siblings('.selected');
$('.selected').not( sibling ).removeClass('showme'); // hide all visible drop downs, but not the sibling of the clicked <a>
if (!sibling.hasClass('showme')) {
sibling.css({display: 'block'});
sibling.addClass('showme'); // show the drop down connected to this <a>
} else {
sibling.css({display: 'none'});
sibling.removeClass('showme'); // hide the drop down connected to this <a>
}
return false;
});
but then, the problem is the css hover is not working anymore!
is there any way I can have both toggle and hover at the same time, or I only can have one of them??
Why did you use sibling.css()? Isn’t that what you created the “showme” CSS class for? Does sibling.css() add anything to the script it didn’t do before (besides breaking the :hover CSS) ?
PS. Instead of node.css({display: "block";}); you can use node.show(); and instead of node.css({display: "none";}); you can use node.hide();. Shorter and better readable
I can do the hover with usual css’s tricks, and I want the next sibling/ children to stay open when I click on the parent, the problem is that when I close/ hide the next sibling/ children, I cannot open/ show the the next sibling/ children again by hovering. so i thought addClass could help me on this… guess I was wrong.
this is the initial idea…
$(document).ready(function(){
$("a").each(function () {
if ( $(this).siblings().size() > 0)
{
$(this).append("<span class='has-child'>has child</span>");
$(this).toggle(
function (){
$(this).next().css({display: "block"});
//$(this).parent().css({background: "#000"});
},
function (){
$(this).next().css({display: "none"});
});
}
});
$('ul > li > ul > li:last-child > a').css('background','yellow');
});
it seems that there’s no way to re-open/ show the sibling/ children again after hiding them with toggle() - doesn’t it?
The css :hover doesn’t work because .show() and .hide() – and their .css nephews as well – set an inline style on the elements, which by definition take precedence over styles defined in the CSS.
Hence, if you drop the .hide() and .show() and use .addClass() and .removeClass() --as I’ve already provided for you-- it will work, because ul > li:hover ul takes precedence over .show.
Am I missing something or are you seeing a problem where there is none?
nope, you are not missing anything! it is just that I am rubbish in explaining this, without demonstrating the problem on screen for u. will get back to this thread when I can explain it better or when i get the solution
you can hover the parent, and you can stop the hover when you click on the parent.
you can toggle the parent without hovering away from the parent.
when you close/ hide the sibling/ children, you can start hovering the parent again.
but the flaw of this solution is, the more I click on the same parent without hovering away from it, the script seems to run oddly and getting ‘tired’…
No offense, but if you need 41 lines of jQuery (not counting black lines and comment-only lines) to achieve the three relative simple points you outlined above you’re doing something wrong
My advise is to delete all jQuery code you have so far and go back to the drawing board. The code you have now is way over-complicated.
Furthermore, I’m not a usability expert, but the workings of your menu are utterly confusing me.
Am I correct to assume you want to toggle the menu items with jQuery but want to offer an alternative to users who don’t have javascript enabled through the use of CSS hover?
If so, there’s a better solution for that.
In your master stylesheet, leave ul > li:hover > ul { display: block; }
Create an external stylesheet with the rule ul > li:hover > ul { display: block; }
That way, if a user doesn’t have javascript enabled the functionality will be available using CSS hover, but if they do have javascript enabled, javascript cancels the CSS behavior through the loading of the external stylesheet and replaces it with javascript functionality.
nope, no offence at all! :goof: thanks for pointing out the mistake I am doing indeed
actually is the other way round - I would like to offer the use of CSS hover as the first choice, but also to offer Javascript’s toggling as an alternative.
the reason doing is that sometime the CSS hover doesn’t work properly on Apple’s machine and IE browser (whether on PC or Apple). so, I thought Javascript’s toggling can provide this solution when the browser and machine fail the CSS
this is an interesting idea. I will think about it. again, thanks so much
In that case get rid of the child-selectors in your CSS (which are not properly supported in all major browsers), ie change ul > li:hover > ul to ul li:hover ul (which is supported in all major browser) and use Whatever:hover to enable :hover for all elements in IE < 7
The website of Whatever:hover suggests
body {
behavior: url("csshover3.htc");
}
but I find that a bit over-kill and suggest you only apply it for elements and classes where you actually need it. In your case that would be
ul li {
behavior: url("csshover3.htc");
}
In addition, if you store that rule in a stylesheet called ie6.css and serve it using conditional comments by putting the following in the <head> of your HTML
only IE versions lower than 7 will download and apply it while other browsers don’t bother
PS. Come to think of it, you could also rewrite ul > li:hover > ul to li:hover ul because the first ul is superfluous and li:hover ul is a better (faster) rule than ul li:hover ul