New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

html5 required attribute support? #515

Open
pushinginertia opened this Issue Mar 4, 2012 · 73 comments

Comments

Projects
None yet
@pushinginertia
Copy link

pushinginertia commented Mar 4, 2012

When chosen is initialized on a select input, it adds [style="display:none"] to the select tag and creates the various div tags it needs, as follows.

<select name="country" id="country" style="display: none; " class="chzn-done">
    <option selected="selected" value=""></option>
    ...
</select>

This is fine, but we have a problem if I add the html5 'required' attribute to my select tag, which produces the following markup after chosen initializes:

<select name="country" id="country" required="required" style="display: none; " class="chzn-done">
<option selected="selected" value=""></option>
...
</select>

The problem occurs when the user submits the form without selecting a value. To the user, the browser seems to do nothing. In fact, it's displaying an error message to the user to select a value, but because the CSS instructs the browser not to show the select element, the error message also doesn't appear.

This is happening in Chrome, I'm not sure about the behaviour of other browsers.

I haven't dug deep enough to suggest a solution, but this is an issue as we start to include html5 attributes in our forms.

@natedsaint

This comment has been minimized.

Copy link

natedsaint commented Mar 6, 2012

I've also just recently noticed this issue.
Required is not supported in all browsers, so I've created a fallback to loop through the elements of a form on submit and verify that there is some value there when "required" is present.
The problem still exists in chrome because the hidden select has no value and is not alerting the user as per the webkit docs:
http://trac.webkit.org/wiki/Styling%20Form%20Controls

"A validation message consists of four div elements with pseudo classes and some nodes for message text. You can customize the appearance by changing the style of these pseudo classes."

I'm thinking the best way to deal with this is to have chosen generate the additional markup to their rendered select with similar classes so that they will be styled by default in the browser, or potentially append pseudo elements to elements that have failed validation by using the appropriate failed conditions in CSS like :invalid.

For now, it looks like your only option is to have a DOM-level fallback like my javascript solution. I can provide it here if that would be helpful but it's really a fallback to chosen, not a way to fix the chosen framework.

@krtek4

This comment has been minimized.

Copy link

krtek4 commented Aug 16, 2012

What's the status on this issue ? I have the exact same problem with the last version of Firefox ( 14.0.1 )

Since HTML5 attributes are more and more used in websites, this should be adressed a way or the other.

@julienduthoit

This comment has been minimized.

Copy link

julienduthoit commented Sep 19, 2012

I have the same issue too. I would be curious to know your fallback solution.

Thanks

@CaptainN

This comment has been minimized.

Copy link

CaptainN commented Nov 13, 2012

It looks like there is only 1 major problem, and a secondary problem that would be great to fix.

  • If the form element is invalid (nothing is selected) browsers will kick up a little flag that shows the position of the error, with a message saying to fill this field out. With chosen, in Firefox, that message flag is in the bottom left of the browser window.
  • There is no style defined for invalid form fields. By default in Firefox (it varies between browsers, but they all do something similar) you get a red glow affect around each invalid form field. Chosen select boxes get nothing.

The first item is the more problematic one. Could this be fixed by utilizing a different select element hiding method? Replacing "display:none" on the hidden select element with "position: absolute;visibility: hidden;" gets pretty close - though that'll be more dependent on surrounding CSS...

@CaptainN

This comment has been minimized.

Copy link

CaptainN commented Nov 13, 2012

It doesn't work for Webkit though. It seems the error flag inherits the styles of the select box in webkit (Chrome), so if you set opacity: .5, the flag will also be opacity .5 (as one example). bummer.

@CaptainN

This comment has been minimized.

Copy link

CaptainN commented Nov 13, 2012

One more - Opera works correctly as is, but if I change it to the above position based CSS, then it doesn't work right. What a pain.

@CaptainN

This comment has been minimized.

Copy link

CaptainN commented Nov 13, 2012

Sorry for spamming this up. I think I got it though! If you wrap the select element in a span, and use this CSS on the wrapper (and remove the display:none on the select element):

width: 0px;
height: 0px;
overflow: hidden;
display: inline-block;
position: absolute;

You will get the error message and no break the page flow at the same time. The only problem is you have to leave the box visible in order to see the error message because Firefox and WebKit will hide the message if you don't. This causes the select box to receive tabs through the form.

The way around that might be to toggle display from none to inline-block on submit (or the 'invalid' event), then toggle it back on certain input events (like mouse down or keypress).

There is also a small positioning issue, resolvable by forcing the position to be directly under the chosen box.

@craue

This comment has been minimized.

Copy link
Contributor

craue commented Nov 27, 2012

Would be nice to see some kind of built-in support for this, if possible at all.

@CaptainN

This comment has been minimized.

Copy link

CaptainN commented Nov 27, 2012

I wrote a patch here: https://github.com/adcSTUDIO/chosen

It may not be robust enough for inclusion, but feel free to test it out.

@caderade

This comment has been minimized.

Copy link

caderade commented Nov 27, 2012

Thanks @CaptainN! I'll check it out!

@caderade

This comment has been minimized.

Copy link

caderade commented Nov 27, 2012

@CaptainN, I got it working - thanks for making those changes. However, do you know how to allow the width of the error popups to exceed the width of the select boxes themselves? On some of my smaller select elements, the error message is really thin which doesn't exactly look very good, and can even be hard to read on some.

If not, that's ok, you've already helped a ton with this. Thanks again!

@CaptainN

This comment has been minimized.

Copy link

CaptainN commented Nov 28, 2012

@caderade I'm not sure how to fix that problem. I tried overflow:visible and a couple of other things, and it still shows up short I'll try a few more things, but this looks like a problem with Firefox that may not have a workaround (these flags are generally pretty hard to deal with, along with that glow, which I haven't yet found a way to style completely).

@craue

This comment has been minimized.

Copy link
Contributor

craue commented Nov 29, 2012

@CaptainN: Very nice.

It works pretty well for me in Firefox 17 and Chrome 23.

In IE 8+9 (which don't support HTML5 form validation at all), when changing the value of the field, I get a JavaScript error because of the unknown :valid selector being used. Thus the script is aborted and the form doesn't get uglified in any way, which I expected in IE. 😏 Not raising an error would be nicer, though. Any idea?

@CaptainN

This comment has been minimized.

Copy link

CaptainN commented Nov 29, 2012

Oh bother. I actually figure jQuery would protect me more! I'll have to add an IE check or something...

Kevin N.

@caderade

This comment has been minimized.

Copy link

caderade commented Nov 29, 2012

@CaptainN It has the issue for me in Chrome as well. Wasn't sure if you thought it was a Firefox issue only or not. But dude, thanks a ton again man. Awesome work! Let us know if you are ever able to address the width thing though.

@CaptainN

This comment has been minimized.

Copy link

CaptainN commented Nov 29, 2012

It looks like jQuery has some built in pseudo selector support, and a hooks system so plugins can add their own, and if it doesn't find any, it passes it on to the underlying implementation - so :required and :valid throw an error in IE (and probably some versions of Safari) if they haven't been polyfilled. I'll see if I can throw an alternative kind of check in there, instead of using the pseudo selectors. It looks like I can just check attr("required") to replace :required - I'll probably have to do some kind of feature detect for :valid though - maybe a check for a .oninvalid property?

@CaptainN

This comment has been minimized.

Copy link

CaptainN commented Nov 29, 2012

Ok, I got a new patch up that fixes the IE error (and should fix it in any other browsers too). This patch changes a few things (nothing you should notice). Here are my notes:

  • matched the coding style of event handlers present in jquery version (bind instead of on, etc.)
  • I can't get the prototype version to hide the select element when validated - it looks like the form element's change event is being suppressed somehow (it works otherwise) - I think this is a bug, but not one I introduced. Need to investigate further.
  • There are some minor quirks about the positioning of the invalid element that may sometimes need manual intervention by the user through CSS (only a problem if required feature is used).
  • short widthed select boxes end up with smooshed required flags in the browser (also a problem with vanilla select elelements if you set the width through css). I can't find a workaround (let me know if you do!) Maybe take it up with Mozilla, since it'll happen with vanilla boxes too. Also, maybe check out their css extensions? https://developer.mozilla.org/en-US/docs/CSS/CSS_Reference/Mozilla_Extensions?redirectlocale=en-US&redirectslug=CSS_Reference%2FMozilla_Extensions (I couldn't find anything at a glance)
  • I can't get uglifyjs to work on Windows (so the .min.js builds aren't updated in my repo) - I'll try a build from OSX tomorrow.
@stof

This comment has been minimized.

Copy link
Collaborator

stof commented Nov 29, 2012

@CaptainN For your issue with UglifyJS, make sure you install the version 1 as the version 2 is not BC. #915 is updating the packages.json

@CaptainN

This comment has been minimized.

Copy link

CaptainN commented Nov 29, 2012

How do I switch the version using npm?

@stof

This comment has been minimized.

Copy link
Collaborator

stof commented Nov 29, 2012

@CaptainN npm install uglify-js@1 to force the version 1 IIRC (but I'm not a node expert). The other solution is to checkout my branch and running npm install with the updated packages.json file.

@CaptainN

This comment has been minimized.

Copy link

CaptainN commented Nov 29, 2012

I was able to build the uglified versions on my work mac (maybe it has an older version of uglify-js?). They are now up to date in my repo.

@craue

This comment has been minimized.

Copy link
Contributor

craue commented Dec 6, 2012

I'm only using the jQuery flavor currently. No script error in IE8/9 anymore. 👍 for seeing this feature in upstream soon.

@Tobion

This comment has been minimized.

Copy link

Tobion commented Jan 24, 2013

We are also facing this issue. Is there a workaround except disabling HTML5 validation?
@CaptainN fixed it from what I read. So I tried his chosen.jquery.js file in master branch. But it gives js error of msie undefined.

@CaptainN

This comment has been minimized.

Copy link

CaptainN commented Jan 24, 2013

I thought I fixed that. That fork was a while ago, and may need to be updated. I'll see if I can get to that this week, and look into the IE bug.

@CaptainN

This comment has been minimized.

Copy link

CaptainN commented Feb 8, 2013

I synced this upstream, and I didn't see any undefined error notices in IE. Try my repo again, and let me know if you still see this problem. (sorry it took so long)

Thanks!

@holic

This comment has been minimized.

Copy link

holic commented May 17, 2013

👍

@ursbraem

This comment has been minimized.

Copy link

ursbraem commented Jul 29, 2013

Could someone sum this up for me? Is there a fork or a patch around that is ready for production?

@andreialecu

This comment has been minimized.

Copy link
Contributor

andreialecu commented May 22, 2015

There was one other addition needed by the way. On iPhone, or other unsupported devices, the fiddle wouldn't work properly. Chosen disables itself on iPhone and leaves the <select> unchanged, and the code in the fiddle above would hide it, leaving no way to interact with the select.

This fiddle fixes it (by adding a display: none check):
http://jsfiddle.net/hq7b426j/1/

@cortopy

This comment has been minimized.

Copy link

cortopy commented May 22, 2015

Ah that's even better!! Thanks! I'm still testing too, but I'll post if anything else comes up

@RVP04

This comment has been minimized.

Copy link

RVP04 commented May 27, 2015

@CaptainN please brief i have same issue. wr i need to put that code. i am using inspina theme from wrapbootstrap.

@CaptainN

This comment has been minimized.

Copy link

CaptainN commented May 27, 2015

@vidhyaprakash85 I'm not sure what you mean. I had forked a long while ago, and wrote a pull request (#900) but the repos are out of sync now, and my fork is very out of date. You can findit here if it helps: https://github.com/adcSTUDIO/chosen

@RVP04

This comment has been minimized.

Copy link

RVP04 commented May 27, 2015

i am already using https://github.com/harvesthq/chosen how to do that :(

@TeLiXj

This comment has been minimized.

Copy link

TeLiXj commented Jun 17, 2015

@andreialecu your code works fine! thanks!!!

@DannyFeliz

This comment has been minimized.

Copy link

DannyFeliz commented Aug 26, 2015

Thanks @christhomas your code worked great 💃

@weiserma

This comment has been minimized.

Copy link

weiserma commented Nov 27, 2015

Neither @christhomas or @ghiculescu worked for me using a multi-grouped select. leaving it to server validation for now.

When I tried I the @ghiculescu patch, it worked except a scroll was displayed all the time, below the select box.
When I tried the @christhomas patch the popup appeared without the search box opening.

@doganmeh

This comment has been minimized.

Copy link

doganmeh commented Nov 28, 2016

I had to modify @ghiculescu 's script so I could call chosen twice as such:

target.find('select')
        .chosen('destroy')
        .chosen({disable_search_threshold: 10})

Otherwise, 2nd trip removed the style that was added in the first:

$.fn.oldChosen = $.fn.chosen
$.fn.chosen = function(options) {
  var select = $(this)
    , is_creating_chosen = !!options

    var style = 'display:visible; position:absolute; clip:rect(0,0,0,0);'

        if (is_creating_chosen && select.css('position') === 'absolute' && select.attr('style') != style) {
            // if we are creating a chosen and the select already has the appropriate styles added
            // we remove those (so that the select hasn't got a crazy width), then create the chosen
            // then we re-add them later
            select.removeAttr('style')
        }

        var ret = select.oldChosen(options)

        // only act if the select has display: none, otherwise chosen is unsupported (iPhone, etc)
        if (is_creating_chosen && select.css('display') === 'none') {
            // https://github.com/harvesthq/chosen/issues/515#issuecomment-33214050
            // only do this if we are initializing chosen (no params, or object params) not calling a method
            select.attr('style', style);
            select.attr('tabindex', -1);
        }
        return ret
}

I just added this extra condition to the 1st if: && select.attr('style') != style

@PhocaCz

This comment has been minimized.

Copy link

PhocaCz commented Apr 21, 2017

@doganmeh Works great in Chrome and mobile (with Chrome) but tested in Firefox 53.0 where it does not work

@PhocaCz

This comment has been minimized.

Copy link

PhocaCz commented Apr 21, 2017

Even this http://jsfiddle.net/hq7b426j/1/ does not work in Firefox 53.0

@PhocaCz

This comment has been minimized.

Copy link

PhocaCz commented Apr 21, 2017

Hmmm, but this seems more like a Firefox problem because if you click on the button more times, you will see that Firefox tries to display the message (but such is never rendered completely)

@fedifazzy

This comment has been minimized.

Copy link

fedifazzy commented Jun 1, 2017

I've used this solution. It is very simple and works perfect:

<style>
    select.submitted:invalid + .chosen-container{
        border-color: red !important;
    }
</style>
$('#yourSelector').chosen({
                no_results_text: "yourText",
                disable_search_threshold: 9,
                search_contains: true
                //your parameters
    }).on('invalid', function(){
        $(this).addClass('submitted');
    });
@jeromax2

This comment has been minimized.

Copy link

jeromax2 commented Sep 14, 2017

it seems that this doesn't work if you have chosen with multiple selections :
http://jsfiddle.net/jeromax/o5a8aogh/

@jeromax2

This comment has been minimized.

Copy link

jeromax2 commented Sep 14, 2017

I fixed it.

`
$.fn.oldChosen = $.fn.chosen
$.fn.chosen = function (options) {
var select = $(this),
is_creating_chosen = !!options;

if (is_creating_chosen && select.css('position') === 'absolute') {
// if we are creating a chosen and the select already has the appropriate styles added
// we remove those (so that the select hasn't got a crazy width), then create the chosen
// then we re-add them later
select.removeAttr('style');
}

var ret = select.oldChosen(options)

// only act if the select has display: none, otherwise chosen is unsupported (iPhone, etc)
if (is_creating_chosen && select.css('display') === 'none') {
// #515 (comment)
// only do this if we are initializing chosen (no params, or object params) not calling a method

  $(this).each(function(index){
	  if($(this)[0].multiple==true){
		  $(this).attr('style','display:visible; width:0px; height:0px; margin-top:25px; position:absolute; clip:rect(0,0,0,0)');
	  }else{
		  $(this).attr("style","display:visible; position:absolute; clip:rect(0,0,0,0)");
	  }
  })

select.attr('tabindex', -2);

}
return ret
}
`

@eriktelepovsky

This comment has been minimized.

Copy link

eriktelepovsky commented Oct 19, 2017

+1

Can somebody commit a fix for this? It's pretty old issue and very important functionality nowadays. Thank you.

@a-mawlawi

This comment has been minimized.

Copy link

a-mawlawi commented Dec 19, 2017

Not working on latest version.

@ghost

This comment has been minimized.

Copy link

ghost commented Jan 22, 2018

This seems to be breaking angular.js form validation when using angular-chosen too.

@xcrap

This comment has been minimized.

Copy link

xcrap commented Mar 15, 2018

It's 2018 and we're still having the same issue. It's a hell how HTML standards cannot work properly and integrated with external plugins. Crazy times :)

@MPParsley

This comment has been minimized.

Copy link

MPParsley commented Jul 5, 2018

This is breaking Drupal's chosen plugin as well. See https://www.drupal.org/project/chosen/issues/2705891

@valentinoli

This comment has been minimized.

Copy link

valentinoli commented Jul 10, 2018

Couldn't find any proper solution to this other than a workaround:

<div class="form__select">
  <select class="chosen">
    <!-- options -->
  </select>
</div>
.form__select {
    position: relative;
}

.form__select .chosen {
    display: block !important;
    height: 0;

    position: absolute;
    left: 35px;
    bottom: 0;

    outline: none;
    border-color: white;

    pointer-events: none;
}
@tripflex

This comment has been minimized.

Copy link

tripflex commented Oct 24, 2018

If you're using Chosen for all select elements, you can use this CSS to change make it visible (to DOM), but no opacity, no height, absolute position.

These CSS selectors target invalid select elements, with one of them targeting multiple adding a 15px margin-top to center it on the multiselect elements.

select:invalid {
    height: 0px !important;
    opacity: 0 !important;
    position: absolute !important;
    display: flex !important;
}
    
select:invalid[multiple] {
   margin-top: 15px !important;
}

Demo: http://jsfiddle.net/tripflex/2zdeu9oc/

BUT REALLY ... this should already be handled by the Chosen.JS lib

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment