Undesired "flashing" in Jquery dropdown menu?
I've got the following piece of Jquery:
$("#collapse-menu > li > a").click(function() {
$(this).toggleClass("expanded").toggleClass("collapsed").find("+ ul").slideToggle("medium");
});
What it basically does is expands or collapses a menu of nested "lists" which contain dropdowns (simplified example):
<ul id="collapse-menu">
<li><a class="expanded">Basic Details</a>
<ul>
<li>
<select> .... </select>
</li>
<li>
<select> .... </select>
</li>
The code works absolutely fine EXCEPT when a large value is selected in any of the dropdowns. At that point, when clicked, the menu will still expand/collapse correctly but "flash" quickly while doing so, as if the entire element was being reset somehow. The data itself is fine but it's the flashing that's unwanted.
The strange thing is that if a small value is selected in a dropdown, there's no flashing. When a large value is selected (say, above 30 in an age dropdown of 18-99), the flashing starts happening.
Can anyone tell me why this is happening? Or whether there's something not right about the Jquery that's causing this.
Thanks.
UPDATE:
Adding a bounty to this. Have tried a few similar plugins/solutions out there on the net but they all seem to suffer from this "flashing" problem when large dropdown values are selected by default.
If it helps, here's a typical similar solution: http://www.i-marco.nl/weblog/jquery-accordion-menu/index_collapsed.html# ... but it suffers from the same problem when dropdowns are added insid开发者_如何转开发e the accordion.
I hope someone has a clean solution, instead of needing to hack this somehow.
From my observation: The issue seems Operating System dependent. The selects are painted by system, as they're system controls. On my Linux machine I experience no problems with blinking animation in the http://jsbin.com/ixake example. I expect You tested it on Windows (r)
It looks like the select is "scrolled" to the proper value everytime it's repainted. And that happens a lot while animating.
The easiest solution would be to substitute system selects with html-based selects to remove system dependency. There are unobtrusive jquery plugins that will do it for You.
Try this or pick any from here if that first one wasn't too good.
After that Your animation should depend only on JS and styling.
I think the problem is that every time the element is resized the dropdown scrolls to the selected element, which causes the flashing.
The answer would be to save each selection in javascript (on change say), then when the animation starts to deselect the value and then restore it when the animation stops. This will give you the same performance as you get when you have a small value selected, while preserving the user's selection.
You might also want to ensure that the form cannot be submitted while it is in a transitional stage, otherwise you'll get bad values coming back.
I personally think autocomplete may really be the way to go. However, I had the idea that hiding the long select by substituting a fake short one would make the slide smoother. Seems to work better on the one browser I tested (Firefox 3.0.18). The code could probably be cleaned up and there is the bug that sometimes the selects won't match sizes by default due to the internal scrollbars but that shouldn't be too difficult to fake.
$("#collapse-menu > li > a").click(function() {
var was_expanded = $(this).hasClass('expanded');
var uls = $(this).toggleClass("expanded").toggleClass("collapsed").find('+ ul');
if (was_expanded) {
$(this).parent().find('select').each(function() {
var fake = $('<select class="fake"><option>' + $(this).val() + '</option></select>');
$(this).parent().append(fake);
$(this).hide();
})
uls.slideUp('medium', function() { });
} else {
$('.fake').remove();
$('select').show();
uls.slideDown('medium', function() { });
}
});
What you can do is disable the select lists before animating the ul.
$("#collapse-menu > li > a").click(function() {
$(this)
.toggleClass("expanded").toggleClass("collapsed")
.find("+ ul").find("select").attr("disabled","disabled").end()
.slideToggle("medium",function(){
$(this).find("select").each(function(){this.disabled=false;});
});
});
give that a try and report back.
You will probably want to style (CSS) the disabled select lists to look identical to non-disabled ones.
NOTES
The above has a side effect of not submitting the selected values when a form is submitted. If this is a problem for you then I suggest you either remove all options from the select list except for the selected option before animating and then add them all back in once animation is complete. And if that won't work for you naugtur's suggestion to use HTML-styled select lists is probably the best option.
p.s. don't bother trying to use the readonly attribute on the select list...it doesn't exist.
精彩评论