Skip to content
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 · 80 comments
Open

html5 required attribute support? #515

pushinginertia opened this issue Mar 4, 2012 · 80 comments

Comments

@pushinginertia
Copy link

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
Copy link

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
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
Copy link

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

Thanks

@CaptainN
Copy link

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
Copy link

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
Copy link

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
Copy link

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
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
Copy link

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
Copy link

Thanks @CaptainN! I'll check it out!

@caderade
Copy link

@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
Copy link

@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
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
Copy link

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

Kevin N.

@caderade
Copy link

@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
Copy link

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
Copy link

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
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
Copy link

How do I switch the version using npm?

@stof
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
Copy link

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
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
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
Copy link

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
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
Copy link

holic commented May 17, 2013

👍

@ursbraem
Copy link

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

@doganmeh
Copy link

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
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
Copy link

PhocaCz commented Apr 21, 2017

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

@PhocaCz
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
Copy link

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
Copy link

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

@jeromax2
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
Copy link

+1

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

@a-mawlawi
Copy link

Not working on latest version.

@ghost
Copy link

ghost commented Jan 22, 2018

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

@xcrap
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
Copy link

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

@valentinoli
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
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

@jonathanbull
Copy link

jonathanbull commented Mar 19, 2019

Here's my workaround, if it's of any use:

// Initialise Chosen
$(function () {
    $('select').chosen();
});

// Place the original input behind the Chosen input, matching the height and width so that the warning appears in the correct position
$('select').on('chosen:ready', function () {
    const height = $(this).next('.chosen-container').height();
    const width = $(this).next('.chosen-container').width();

    $(this).css({
            'position': 'absolute',
            'height': height,
            'width': width,
            'opacity': 0
        })
        .show();
});

@AndrewSouthpaw
Copy link

@jonathanbull can you show it within context? I tried your solution and it didn't work.

@Reforced
Copy link

Reforced commented May 7, 2019

@AndrewSouthpaw This is my code, fixs works fine for me :)

$("#select").val([]); // disable default selection by browser
$('#select').on('chosen:ready', function(evt, params, chosen) {
	$(this).css({'position': 'absolute', 'height': 0, 'opacity': 0}).show();
});
$("#select").chosen();

@eloyesp
Copy link

eloyesp commented Oct 9, 2019

I'm using a slight different code (based on the code here):

$('.chosen-select').on("chosen:ready", function (evt, data) {
  $(this)
    .addClass('chosen_hidden')
    .attr('tabindex', '-1')
    .prependTo(data.chosen.container)
    .show()
  })
  .chosen({width: '100%'})
.chosen_hidden {
  position: absolute;
  top: 0;
  bottom: 0;
  max-height: 100%; // required for IE 10
  // **not required** opacity: 0;
}

It does not handle the 'destroy' action, but it does position the error message nicely and seems to work on Firefox and Chromiun. As the original selector is not hidden, the error highlight border is visible. Update: with max-height it also works on IE. Other update: add tabindex -1 to make sure it does not receive focus. (while still being focusable and receive error messages).

@jhedstrom
Copy link

There has been an open PR that resolves this, but I think it got lost since the other thread it targeted was closed. See #2594

@jonathanbull
Copy link

@jhedstrom would love to see that merged. Do you know if this library is still maintained?

@damsalem
Copy link

damsalem commented Oct 22, 2020

I used something similar to @eloyesp's solution above and shared that here:

#2594 (comment)

Thanks @jhedstrom for pointing me in the right direction!

carlobeltrame added a commit to hitobito/hitobito_sac_cas that referenced this issue May 24, 2023
The HTML5 required attribute does not work on chosen selects. This is a
known bug since 2012: harvesthq/chosen#515
The chosen project is dead, and all chosen selects will be replaced when
we upgrade bootstrap. For now, this fix works just as well in the self
registration form.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests