Skip to content

Commit

Permalink
Merge pull request #22 from bboyle/google-earth
Browse files Browse the repository at this point in the history
fix #20: handling of required radio button bug
  • Loading branch information
bboyle committed Feb 9, 2015
2 parents cac6929 + 994ad6f commit 2dc8434
Show file tree
Hide file tree
Showing 6 changed files with 136 additions and 28 deletions.
2 changes: 1 addition & 1 deletion bower.json
@@ -1,7 +1,7 @@
{
"name": "html5.constraintValidationAPI",
"title": "HTML5 constraintValidationAPI",
"version": "1.0.4",
"version": "1.0.5",
"homepage": "https://github.com/bboyle/html5-constraint-validation-API",
"authors": [
"Ben Boyle <benjamins.boyle@gmail.com>"
Expand Down
61 changes: 49 additions & 12 deletions dist/html5.constraintValidationAPI.js
@@ -1,4 +1,4 @@
/*! HTML5 constraintValidationAPI - v1.0.4 - 2015-02-02
/*! HTML5 constraintValidationAPI - v1.0.5 - 2015-02-09
* https://github.com/bboyle/html5-constraint-validation-API
* Copyright (c) 2015 Ben Boyle; Licensed MIT */
/*exported initConstraintValidationAPI*/
Expand All @@ -16,6 +16,9 @@ if ( jQuery !== 'undefined' ) {

// for feature detection
input = $( '<input>' ).get( 0 ),
// radio button bug (google earth internal browser)
radioButtonBug = $( '<input type="radio" required checked>' ).get( 0 ).validity.valueMissing,
validateBuggyRadioButtons,

// polyfill test
polyfill = typeof input.validity !== 'object',
Expand Down Expand Up @@ -151,17 +154,11 @@ if ( jQuery !== 'undefined' ) {
});
}

// NOTE the code below runs in all browsers to polyfill implementation bugs

// google earth treats all required radio buttons as invalid
// if the only thing stopping submission is a required radio button group...
invalid = form.find( candidateForValidation ).filter( isInvalid );
if ( invalid.length === invalid.filter( ':radio' ).length && invalid.length === invalid.filter(function() {
// radio button has been checked, but is flagged as value missing
return this.validity.valueMissing && $( this.form.elements[ this.name ]).filter( ':checked' ).length > 0;
}).length ) {
// let submission continue
invalid.removeAttr( 'required' );
// NOTE all the code below runs in all browsers to polyfill implementation bugs

// required radio button check
if ( radioButtonBug ) {
validateBuggyRadioButtons( this );
}

// Opera 11 on OSX fires submit event even when fields are invalid
Expand Down Expand Up @@ -246,6 +243,46 @@ if ( jQuery !== 'undefined' ) {
});
}

// check for required radio button bug (google earth internal browser)
if ( radioButtonBug ) {
validateBuggyRadioButtons = function( form ) {
var seen = {};
var radio, valueMissing;

// check every required radio button
$( 'input', form ).filter( ':radio' ).filter( '[required],[aria-required="true"]' ).each(function() {
if ( typeof seen[ this.name ] === 'undefined' ) {
seen[ this.name ] = true;

radio = $( this.form.elements[ this.name ] );
valueMissing = radio.filter( ':checked' ).length === 0;

if ( valueMissing ) {
// make sure @required is set to use validation API
radio.attr( 'required', 'required' );
} else {
// using @aria-required=true so we can track this control
// removing @required here to bypass validation bug
radio.attr( 'aria-required', true ).removeAttr( 'required' );
}
}
});
};

// initial validity
$( 'form' ).each( validateBuggyRadioButtons );

// watch changes
if ( ! polyfill ) {
candidates.filter( ':radio' )
.unbind( 'change.constraintValidationAPI' )
.bind( 'change.constraintValidationAPI', function() {
validateBuggyRadioButtons( this.form );
})
;
}
}

// check validity on submit
// this should be bound before all other submit handlers bound to the same form
// otherwise they will execute before this handler can cancel submit (oninvalid)
Expand Down
4 changes: 2 additions & 2 deletions dist/html5.constraintValidationAPI.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Expand Up @@ -2,7 +2,7 @@
"name": "html5.constraintValidationAPI",
"title": "HTML5 constraintValidationAPI",
"description": "A polyfill for the HTML5 constraintValidationAPI",
"version": "1.0.4",
"version": "1.0.5",
"homepage": "https://github.com/bboyle/html5-constraint-validation-API",
"author": {
"name": "Ben Boyle",
Expand Down
59 changes: 48 additions & 11 deletions src/html5.constraintValidationAPI.js
Expand Up @@ -20,6 +20,9 @@ if ( jQuery !== 'undefined' ) {

// for feature detection
input = $( '<input>' ).get( 0 ),
// radio button bug (google earth internal browser)
radioButtonBug = $( '<input type="radio" required checked>' ).get( 0 ).validity.valueMissing,
validateBuggyRadioButtons,

// polyfill test
polyfill = typeof input.validity !== 'object',
Expand Down Expand Up @@ -155,17 +158,11 @@ if ( jQuery !== 'undefined' ) {
});
}

// NOTE the code below runs in all browsers to polyfill implementation bugs

// google earth treats all required radio buttons as invalid
// if the only thing stopping submission is a required radio button group...
invalid = form.find( candidateForValidation ).filter( isInvalid );
if ( invalid.length === invalid.filter( ':radio' ).length && invalid.length === invalid.filter(function() {
// radio button has been checked, but is flagged as value missing
return this.validity.valueMissing && $( this.form.elements[ this.name ]).filter( ':checked' ).length > 0;
}).length ) {
// let submission continue
invalid.removeAttr( 'required' );
// NOTE all the code below runs in all browsers to polyfill implementation bugs

// required radio button check
if ( radioButtonBug ) {
validateBuggyRadioButtons( this );
}

// Opera 11 on OSX fires submit event even when fields are invalid
Expand Down Expand Up @@ -250,6 +247,46 @@ if ( jQuery !== 'undefined' ) {
});
}

// check for required radio button bug (google earth internal browser)
if ( radioButtonBug ) {
validateBuggyRadioButtons = function( form ) {
var seen = {};
var radio, valueMissing;

// check every required radio button
$( 'input', form ).filter( ':radio' ).filter( '[required],[aria-required="true"]' ).each(function() {
if ( typeof seen[ this.name ] === 'undefined' ) {
seen[ this.name ] = true;

radio = $( this.form.elements[ this.name ] );
valueMissing = radio.filter( ':checked' ).length === 0;

if ( valueMissing ) {
// make sure @required is set to use validation API
radio.attr( 'required', 'required' );
} else {
// using @aria-required=true so we can track this control
// removing @required here to bypass validation bug
radio.attr( 'aria-required', true ).removeAttr( 'required' );
}
}
});
};

// initial validity
$( 'form' ).each( validateBuggyRadioButtons );

// watch changes
if ( ! polyfill ) {
candidates.filter( ':radio' )
.unbind( 'change.constraintValidationAPI' )
.bind( 'change.constraintValidationAPI', function() {
validateBuggyRadioButtons( this.form );
})
;
}
}

// check validity on submit
// this should be bound before all other submit handlers bound to the same form
// otherwise they will execute before this handler can cancel submit (oninvalid)
Expand Down
36 changes: 35 additions & 1 deletion test/google-earth.html
Expand Up @@ -24,6 +24,16 @@
<p>This form is for testing validation in the google earth internal browser.
You should be able to submit this form (and be taken to this repo home page).</p>


<button>Uncheck all radio buttons</button>
<script>
$( 'button' ).click(function() {
$( ':radio' ).prop( 'checked', false );
});
</script>


<h2>Form A</h2>
<form action="https://github.com/bboyle/html5-constraint-validation-API" action>

<ol class="questions">
Expand Down Expand Up @@ -68,10 +78,34 @@
</li>
</ol>
</li>

</ol>
</form>


<h2>Form B</h2>

<form action="https://github.com/bboyle/html5-constraint-validation-API" method="get">
<ol class="questions">
<li class="select1">
<fieldset id="cc-type">
<legend>
<span class="label">Card type</span>
<abbr title="(required)">*</abbr>
</legend>
<ul class="choices compact">
<li><input type="radio" name="card_type" id="cc-type-visa" value="Visa" checked="checked" required="required" /><label for="cc-type-visa">Visa</label></li>
<li><input type="radio" name="card_type" id="cc-type-mastercard" value="MasterCard" /><label for="cc-type-mastercard">MasterCard</label></li>
</ul>
</fieldset>
</li>

<li class="footer">
<ol class="submit">
<li><strong><input type="submit" value="Submit" /></strong></li>
</ol>
</li>
</ol>
</form>

</body>
</html>

0 comments on commit 2dc8434

Please sign in to comment.