Undesired "flashing" in Jquery dropdown menu? - javascript

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 inside 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.

Related

Trying to add functionality to select option

In my program the user first enters some data to filter and the result goes to one dropdown select menu lets call this functionality function_1 . If there is only one result the it goes to make another query, lets call this function_2.
My problem here is when i have 2 or more results i should be able to:
1) check out the different options i get by clicking on the select to display all the options with a scrollbar if needed
2) After he saw the options there he clicks on one of them to activate function_2
The usual answers use the "change" event but, wont work if the user picks first default value because there is no change, he would have to pick an undesired result and go back to the first.
Using the click event on the select makes also unnecessary work because it triggers twice (one when i open the dropdown, other when option is selected)
Main problem here i think is the jquery selector, but im not sure if it can be done just with that.
This is an example of what im trying:
// function_1 in ajax
.done(result){
$.each(result.data,function (){
$('#select_ex').append("<option value...... ></option>");
if (result.count()===1){
$('#select_ex').trigger('change');
}
});
}
$('#select_ex option').change(function(){// tried with change, click or focus
function_2();
}
The html contains
<select name="select_ex" id="select_ex" size="0" ></select>
EDIT:
Not related to the duplicate question mentioned, since i already know why it doesnt select the option, besides it doesnt apply either since it only talks about connectors with ID, which is not even the point here (I could do my thing without IDs). Im asking for funcionality similar to ":selected" but with option->click.
Another workaround i thought of is filling the select with an empty/hidden field and set the selected property it, filtering afterwards and using the regular change event... but then the first item would be blank and doesn't seem very logic to me.
So I came to seek for any fresh ideas.
EDIT2
I added a white option for the multiple result and erased it afterwards by adding this line of code to imvain2 solution (where needed)
$("#select_ex option[value='0']").each(function() {$(this).remove();});
Although fixing your change function so that is is called for the select and not the option is important, your problem is the default selected option itself. As you mentioned, if they want the first option, they have to select something else to trigger the change function.
I would recommend adding a "blank" option as the first option and setting it as selected.
var $select_ex = $("#select_ex");
.done(result){
$select_ex.empty().append("<option value='0'>Select Your Ex Below!</option>");
$.each(result.data,function (){
$select_ex.append("<option value...... ></option>");
});
$select_ex.val("0");
}
$select_ex.change(function_2);

How can I show a hidden DIV for a selection included with others?

I have a javascript file that when called, checks to see if a particular option is selected on a form. The form allows for multiple selections before being submitted. When a particular item is selected within the given choices it shows a hidden menu. In this case with "audits" I am able to show the hidden menu fine when just "audits" is selected from the list. However, I'm having much difficulty in figuring out how to get the menu to show when "audits" would be selected/highlighted with others. Eg: I had audits, services, someotheroption
Below you can see the code I'm currently using and that's working only when the single item is selected. Any guidance would be much appreciated.
function toggleFields(){
function toggleFields(){
if ($("#installations").val() == "audits"){
$("#dbcredentialsfield").show();
}
else
$("#dbcredentialsfield").hide();
}
Using the code you have so far, I assume you probably want something like this:
$('#installations').on('change', function(){
$("#dbcredentialsfield").toggle($(this).val() == 'audits');
});
This says; when the select element (assuming your dropdown has the id of installations) changes, toggle the visibility of the element with id dbcredentialsfield depending on if the value of the select is audits or not.

When tableDnD is disabled it leaves residual css and I can't clear the css

tableDnD (table Drag and Drop) is a jQuery plugin I'm using to be able to re-order rows in my html table. It's a pretty cool library, but the fact that you can click, drag, and drop rows -- disables the ability to select that row by clicking -- it thinks you might be starting a drag and drop, or doing a 0-distance drag.
So you can view my example here, and see what I'm talking about -- http://jsfiddle.net/du31ufts/5/
It starts off as disabled, so enable the row re-ordering and see the library. Then, try to select just one row in the middle. The only way the blue highlighting indicating selection shows up is if you click outside the bounds of the table, and thus you would only be able to select starting from the bottom or top, and not be able to select one row at a time. I need to select these rows to be able to copy-paste these rows into excel.
I've tried looking into the library itself and detaching $('__dragtable_disable_text_selection__'), I've tried jquerys removeAttr for unselectable, I've tried
$('.dragtable-sortable').attr('-moz-user-select', 'none');
Nothing is re-enabling my ability to be able to click and select single rows. I'd like to do this without modifying tableDnD functions.
Which CSS properties could be affecting my ability to select table rows?
Create a textarea somewhere with ID #spot.
Use this code to extract data on click from a row and select it. Its delimited by tab so it should be pastable into excel easily.
$('tr').click(function(){
var copyContent = "";
$(this).children('td').each(function(){
copyContent = copyContent+$(this).text()+"\t";
});
$('#spot').val(copyContent);
$('#spot').select();
});
I asked about this on github and got an answer: It did require modification of the library. Specifically, replacing the if block starting at line 207 of the fiddle in this question with this
if (!$(this).hasClass("nodrag")) {
if (e.target.tagName == "TD") {
$.tableDnD.initialiseDrag(this, table, this, e, config);
return false;
}
}
modified fiddle. Thank you tschqr

Updating z-index multiple times in order that menu item appears correctly

There is a predictive search which creates a drop down menu of items the user can select from. Behind the dropdown there is a menu button which contains a z-index of 9999. Because of this the menu button appears in front of the dropdown menu. To fix this here is my solution :
Using jQuery listeners :
Once the user clicks into the search box update the z-index of the button :
$( ".myIcon").css("z-index" , 1);
and once the user clicks off the search box using the 'blur' listener re-update the z-index :
$( ".myIcon").css("z-index" , 9999);
This works but it does not seem very clean. I do not have access to the code that is used to generate the drop down menu so cannot update the z-index of this item.
Is there another solution I am not aware of ?
Give the parent of the search the same z-index
Though it's hard to know what the html looks like since you didn't include an example. If you want it to appear on the same level then you can give it the same z-index from the gate. If the block the search part is in is after the nav, then they will naturally be on top of each other with the same z-index.
#nav,#search{position:absolute;z-index:9999}
for example, would put #search above #nav given that #search is after #nav in the html; like:
<parent><nav/><search/></parent>
If it is located before it, and possibly with a different parent, then you can use something like:
#nav{z-index:9998} #search{z-index:9999}
which would be if the html is more like:
<search/><parent><nav/></parent>
Though, if you need it to turn on/off the z-index, and it can't be fixed at all on #search, then you're already heading the right direction.
Something like this would be fairly easy:
$('#search input').on('focusin', function(){//on focus
$(this).siblings('.myIcon').css({zIndex: '9999'});
}).on('focusout', function(){//on un-focus
$(this).siblings('.myIcon').css({zIndex: '1'});
});
Though if you were able to control the css then you could just make a class for .myIcon with z-index:9999 and instead use something like this:
.on{z-index:9999}/*added css*/
$('#search input').on('focusin focusout', function(){//on focus change
$(this).siblings('.myIcon').toggleClass('on');
});
made a fiddle: http://jsfiddle.net/filever10/pxdz5/
Are you able to request that the menu icon be changed to something a bit more reasonable?
There's no need to have it that high, simply 1 value above the next element is sufficient.
I'm sorry but I can't see any other way of solving this problem than the one you have suggested.
You can use this:
$( ".myIcon").css("visibility" , "hidden");
$( ".myIcon").css("visibility" , "visible");

How can I prevent the dropdown from opening in a DropDownList?

I have a custom table which I'd like to use as the DropDown portion as a DropDownList.
Ideally, when users click on a DropDownList, it should show the custom table instead of the usual drop down. I thought it'd be easy to prevent the dropdown from opening without disabling the DropDownList control, however that doesn't appear to be the case.
Is there an easy way to prevent a DropDownList from opening without disabling it?
Edit: This has to work for an embedded IE 7 web browser, and e.preventDefault() does not work in that browser version
You can do something like this:
Basically, I have positioned an invisible div over the dropdown to block it, and you can handle the click with the onclick of the masking div.
EDIT: I have updated this http://jsfiddle.net/EdM7B/1/
<div id='mask' onclick='alert("clicked");' style='width:200px; height:20px; position:absolute; background:white;filter:alpha(opacity=0);'></div>
<select id='selectList' show=1 style='width:200px; height:20px;'>
<option>Test</option>
</select>
I had to use a sort of hack because IE doesn't seem to render divs properly that have no background colour set, so it wasn't working correctly. This works in my IE7.
If you want it to work in all browsers you'll need to add chrome/firefox opacity CSS or have some IE only CSS to apply background colour.
I think due to the way it's positioned above, the opacity is actually not working properly because the element is positioned absolutely, either way it seems to work. I originally had it as opacity 1, but that sounds wrong to me as we want it invisible, so I changed it to 0.
It's possible to stop the dropdownlist from showing by using jQuery's event.preventDefault in the mousedown event (demo: http://jsfiddle.net/RCCKj).
Also see this related question: stop chrome to show dropdown list when click a select
Put it inside a div like this:
<div id="dllDiv" style="width:200px;height:200px;">
< asp:DropDownList ID="DropDownList1" runat="server" style="z-index:-1000px;pointer-events:none;">
< /asp:DropDownList>
</div>
You should set the css property pointer-events to none, then you can show your table hidden in a div or loaded it by using ajax, something like this:
(document).ready(function() {
$("#dllDiv").click(function() {
alert('adasd');
});
});
Have you thought about using a mega menu for this, you can put anything you want in the dropped down portion - for example your table

Categories