Open ethaniel opened 13 years ago
This is the same as issue #59
Isn't this unavoidable since the container element, is well, "overflow :hidden" that's just how CSS works. The only way around this is to render the drop down outside of the container and then use absolute positioning.
Yeah, I agree with dfischer. Doesn't seem like a Chosen issue. By definition, the overflow property specifies what happens if content overflows an element's boundaries. If you don't want it the overflow to be hidden, then change that property.
While true, I think this is a common use case with dialog boxes. (Especially jquery dialog)
It is a common use case, however based on this ticket, like I previously mentioned... the entire structure and implementation has to change if you want to accomplish this.
You are required to render outside of the container for this to happen and then use jQuery/JS magic to figure out the positioning relative to the trigger.
jQuery Dialog's case doesn't depend upon a container element so it just uses positioning based on center dimensions and width of the dialog.
This is more of a CSS issue, not a Chosen issue. Don't put overflow: hidden on the container. You're going to have to use another technique to clear the floats below it if that's what you're doing.
I just wrote some code which I think does what you're looking for:
$.fn.extend({ chosen: function (data, options) { if ($(this).parent().css("overflow") == "hidden") { //get the offsets between parent and child to calculate the diff //when we push to absolute var y = $(this).offset().top - $(this).parent().offset().top, x = $(this).offset().left - $(this).parent().offset().left, $t1 = $("<div/>", { css: { "position": "relative", "height": $(this).parent().height, "width": $(this).parent().width } }), $t2 = $("<div/>", { css: { "position": "absolute", "top": y, "left": x } }); $t1.insertBefore($(this).parent()); $(this).parent().appendTo($t1); $t2.appendTo($t1); $(this).appendTo($t2); } return $(this).each(function (input_field) { if (!($(this)).hasClass("chzn-done")) { return new Chosen(this, data, options); } }); } });
(btw I'm new to github as of today so if there is a different place where I should be posting code let me know)
That code effectively does the following:
Interesting idea Matthew, but I think that's not going to work in a jQuery-UI dialog is it?
It's more likely that the dropdown element (.chzn-drop) needs to be pulled out of the .chzn-container and up to the document body...
Just add a style to the page and your answer is yes:
.ui-dialog{ overflow:visible; }
Doesn't work for me, since I create my pages using div's as columns (as opposed to td's and tables). I use "overflow:hidden" to stop runaway content from ruining neighbour divs.
I suppose many of you use the same structure.
That won't work, as the dialogs are set to overflow:auto so they can have scrollbars if necessary.
On Fri, Jul 29, 2011 at 11:47 PM, ethaniel reply@reply.github.com wrote:
Doesn't work for me, since I create my pages using div's as columns (as opposed to td's and tables). I use "overflow:hidden" to stop runaway content from ruining neighbour divs.
I suppose many of you use the same structure.
Reply to this email directly or view it on GitHub: https://github.com/harvesthq/chosen/issues/86#issuecomment-1681303
Before we get any further into this conversation, what I've done is a theoretical fix. It can't be applied to all scenarios because all it takes is one element having a counter-attribute to screw it up. The above solution with the overflow visible will only work with dialog option resizable:false. Why would you need to have a select overflow outside of a dialog?
Ok, here are a bunch of screenshots which hopefully clarify the issue.
http://i.imgur.com/9ZY9O.png http://i.imgur.com/c2PLo.png http://i.imgur.com/1oqZ7.png http://i.imgur.com/ZBrQj.png
Screenshots 1 & 2 show how it behaves, there isn't enough space for the dropdown "inside" the dialog, so it scrolls and is hidden as a result. This is very clunky to use and ugly and not how the built in select controls work (they show over the top of the content, no matter how deep inside it they are or what it's overflow style is.)
Screenshots 3 & 4 show my current work-around, which is to put a whole heap of space below the dropdown. This is also ugly and makes the form harder to use.
So, to summarise, the real point is that native select controls aren't restricted to their parent container and if it's possible, the chosen enhanced select control shouldn't be either, since it's designed to be a drop-in replacement for the native control.
This theoretically can be done but it would require a completely different construction/positioning system by the chosen plugin. This change would be extensive and require about a 30% rewrite of the current plugin. I consider this a feature request and not a bug. All browsers have a default render for select elements.Chosen replicates it using divs but is not treated like a select element.
Like I said, the only way to do this is absolute positioning OUTSIDE of the triggered element. There's no other way. Correct on @medelbrock
While it would be very nice to have chosen behave like a browser widget, I agree this should be considered a feature not a bug. Can we currently set a max height?
@veloper: I gave that a go (as best I could) and it didn't seem to help. I can't see how it would work either, as the div.chzn-drop
is still contained in the dialog, so will be clipped regardless of whether it is absolutely positioned or not.
The only way to stop that is going to be to pull the div.chzn-drop
out of the dialog and make it a child of <body>
, but as everyone is pointing out, that is a bigger change than anyone is willing to get their hands dirty trying.
Unfortunately using overflow:visible
isn't an option, the dialog needs to be scrollable if necessary.
I think I've solved the issue by setting the drop down position to absolute and whenever showing the drop down setting it's position. e.g. Changing (editing the javascript)
this.dropdown.css({
"top": dd_top + "px",
"left": 0
});
to
var parent = this.dropdown.parent();
var offset = parent.offset();
dd_top = offset.top + parent.outerHeight();
dd_width = parent.width();
this.dropdown.css({
"top": dd_top + "px",
"left": offset.left,
"width": dd_width + "px"
});
I'm running into this problem myself while trying to make Chosen work inside a Wijmo / jQuery UI Dialog. I may be way out of my league here, but isn't there a fairly simple fix of making the "dropdown" portion have "display: none" while hidden, and then "display: block" when shown? You'd still incur the scroll bars when the dropdown is open, but that's probably better than having the scroll bars always present.
The fix (tested in Chrome 13, Firefox 7 and IE 9) :
In chosen.css:
.chzn-container .chzn-drop { position: fixed; }
and in Chosen.prototype.results_show
var offset = this.container.offset(); this.dropdown.css({ "top": (offset.top+dd_top) + "px", "left": offset.left + "px", "display": "block" });
That's the stuff, good thinking @levushka. Resolved now in my branch: https://github.com/tompaton/chosen/commit/fda07051161f3fffe6049362b6c9b66ffbe857d1
Ok, it's a little more complicated than that. The above fix didn't work if the page was scrolled.
I've updated my repo with a changeset that sort of fixes it, the dropdown is positioned correctly now, but if the page is scrolled while the dropdown is visible it doesn't move as expected. That's annoying, but not a show stopper.
iOS 5 might solve this, but iOS currently doesn't support position: fixed in the same way that desktop browsers do. Chosen works terrifically on the desktop, but this might limit its uses on poorly designed mobile browsers...
I'm not just picking on Apple here, older version of Android also lack support for position: fixed.
As of jQuery 1.7 (not yet released, but in release candidate) they have a built-in test for CSS Position Fixed support: http://bugs.jquery.com/ticket/6809
Might be worth detecting jQuery 1.7 and using their result, or copying their code and getting a separate result otherwise.
+1 for position at the end of body element.
check the jquery widget "autocomplete". pretty good solution for that problem:
http://jqueryui.com/demos/autocomplete/
great plugin by the way.
I had this issue mostly in webkit browsers. IE just goes mental with chosen, so i disabled it if ie. Using jquery, i check if the browser is a webkit one, and adjust the overflow of the div containing my chosens like so:
if($.browser.webkit) $(this).css("overflow",($(this).is(":visible"))?"visible":"hidden");
where this is the div containing the chosens.
+1 @levushka and @tompaton Not perfect, but good enough-ish. Barely :)
@levushka solution is great, but it is global ... so at window.top when you scroll down and click to chosen, it roll down in wrong position. So here is solutuion for normal pages and popup windows
in Chosen.prototype.results_show
replace:
this.dropdown.css({
"top": dd_top + "px",
"left": 0
});
with:
if($('.popup').length!=0) {
var offset = this.container.offset();
this.dropdown.css({
"top": (offset.top+dd_top) + "px",
"left": offset.left + "px",
"display": "block"
});
} else {
this.dropdown.css({
"top": dd_top + "px",
"left": 0
});
}
CSS:
.popup .chzn-container .chzn-drop { position:fixed; }
If you are using jQuery UI or something else, you can have problems with z-index, so set chosen z-index to higher values (jQuery UI is it 1010+)
Now it is wokring in FF and for Chrome you need:
.popup { overflow-x:visible; overflow-y:visible; }
lover elements can have overlow:hidden with no problems.
Why not render the dropdown in the body and use Jquery UI's position function to position the box? http://jqueryui.com/demos/position/. This is the standard method used for many jquery ui widgets.
$( ".czn-drop" ).position({ of: $( "#container" ), my: "left top", at: "left bottom", });
Forgive me for barging in, I had the same problem with displaying chosen drop down in a jQueryUI dialog. I tried the usual stuff with overflow but this was messing my other dialogs.
What I did instead, was to set my dialog to a fixed height and set the chosen drop down to a fixed height as well. It would be nice to have an option to do this from chosen's options instead of css.
.chzn-drop { overflow: auto; max-height: 75px; }
Maybe this helps someone else.
Excuse-moi for a quite n00bish/RTFM question, but how can I render the dropdown outside the container (say, on body
)? Right now, the only thing that comes to my mind is to fork the plugin and shove that piece of code into it. There must be a more elegant way of achieving this.
Is there an event the choosen fires when the drop down is open/closed. If so, I can just change the overflow setting of the parents divs to visible and then back. I tried that with:
$(".chzn-drop").show(0, function () {
$(this).parents("div").css("overflow", "visible");
});
And, yea, it worked. But, then when I added:
$(".chzn-drop").hide(0, function () {
$(this).parents("div").css("overflow", "");
});
It no longer worked. I assume because I have several choosen controls on the form. If I could add this code inside an open/close event then I think it would get me where I want to go.
You can listen to the liszt:showing_dropdown
and liszt:hiding_dropdown
dispatched on the original select element
Excellent... so this solved my issue:
$(".chzn-select").on("liszt:showing_dropdown", function () { $(this).parents("div").css("overflow", "visible"); }); $(".chzn-select").on("liszt:hiding_dropdown", function () { $(this).parents("div").css("overflow", ""); });
Of course, it may not work with all layouts.
Thanks... BOb
I've forked the code to make the dropdown child of <body/>
. I didn't test it enough yet, but it's working here perfectly -> https://github.com/gil/chosen
Can you see if it solves your problem, @tompaton? I think I just have to detect scrolling now, to fix the position manually.
The fork fixed the display issue for me, and worked well at the bottom of the page where it limited the height it displayed to something reasonable. However, the fork stopped the multi-select functionality from working.
@geoffweatherall Really? Nice! :D About the problem with multi-selection, what stopped working? Could you please try the example.jquery.html
file and tell me if it's not working? For me it seems to be okay.
Yes, examples work fine (FF 12).
The single select example is in a fairly plain html page with "panels" that use overflow hidden. However, the multi select example is in a "dialog" created using colorbox (http://www.jacklmoore.com/colorbox) - don't ask me why, the project was like that when I arrived. I guess it might have something to do with that, I will look into it.
The fork fixes the cut-off issue in a number of locations in our application, including multi-selects that are not nested within colorboxes (http://www.jacklmoore.com/colorbox). I believe the issue with colorbox is no fault of chosen. Great fork :-)
Actually I found an issue with the fork that shows in the sample page (example.jquery.html). For the multi select control, if you click in the control to open the list of options, and then use the up arrow and down arrow keys to navigate the list, the list of options makes a surprise move to the top of the page. This issue does not occur for single selects. Tested in FF12, Chrome 18 and IE8.
@geoffweatherall Maybe the problem with the colorbox is that it's being rendered over the Chosen dropdown. Try something like this to see if it helps:
.chzn-drop {
z-index: 999999 !important;
}
Or try setting the colorbox opacity to 0.1 to check if you can see the dropdown bellow the colorbox.
The other problem, with the keys, I'll try to find some solution. I didn't use the multi-selection in the project I'm working now, so I almost didn't test it. Focused more on the single-selection option.
Ok, I tried this and I did get the drop downs visible, however the position is wrong. They are dropping down below the text box by quite a bit. Here is a jing showing the behavior. http://screencast.com/t/c4PCIHC176RX
Hi Gil,
I've tried your version and it's working! Thank you so much! There's only one small thing that stopped working.. It's the disable_search_threshold option. The search field won't dissapear.
Have you got any idea?
Thanks!
Nevermind! I managed to fix it myself, however.. maybe you should change that in the code aswell:
Change:
if (this.form_field.options.length <= this.disable_search_threshold) {
this.container.addClass("chzn-container-single-nosearch");
} else {
this.container.removeClass("chzn-container-single-nosearch");
}
To
if (this.form_field.options.length <= this.disable_search_threshold) {
this.dropdown.addClass("chzn-container-single-nosearch");
} else {
this.dropdown.removeClass("chzn-container-single-nosearch");
}
What's the status of this fork? Has it be merged into master? Or is it still in testing?
One other issue.. the fork seems to work will for me, but in firefox I see the dropdown div at the bottom of the page. It seems that the negative left position doesn't move it out of the display area. Perhaps it is due to some other styles I have... thought. Any idea? Why isn't it's display being set to none?
I made a pull request a long time ago for my original fix but it was never accepted (no idea why).
There have been a lot of additional tweaks suggested in this thread since then, I haven't played with any of them yet, and haven't checked to see if someone has a fork which incorporates them (if there isn't one, someone should create one, and if there is, that would be a good answer to your question.)
On Thu, Jun 7, 2012 at 6:44 AM, Bob Archer reply@reply.github.com wrote:
One other issue.. the fork seems to work will for me, but in firefox I see the dropdown div at the bottom of the page. It seems that the negative left position doesn't move it out of the display area. Perhaps it is due to some other styles I have... thought. Any idea? Why isn't it's display being set to none?
Reply to this email directly or view it on GitHub: https://github.com/harvesthq/chosen/issues/86#issuecomment-6162299
I tried them all, and none of them worked for me, because I have multiple fieldsets that are hidden and a long form that scrolls. So, my solution was to make the dropdown static and hidden initially, and shown when opened, which stretches the parent container. This works in all of my forms, even if it's at the very bottom of the screen.
in Chosen.prototype.results_show:
this.dropdown.css({
"top": dd_top + "px",
"left": 0,
"display": "block"
});
In Chosen.prototype.results_hide:
this.dropdown.css({
"left": "-9000px",
"display": "none"
});
in chosen.css:
.chzn-container .chzn-drop {
position: static;
display: none;
}
@gil, I just want to say thank you for your fork, I was about to give up on using Chosen for my project because of this bug.
I'm honestly quite surprised that the harvest guys don't see the flaw inherent in binding a floating popup to a constrained container. Even regardless of overflow rules, that's just not a good idea for a public library that has no idea what people may be doing around the widget.
I have a div with a form. The div has "overflow:hidden" option in the css. When Chosen gets created, and it goes below the bottom line of the div, it gets cut.
Here is a screenshot: