Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
dist
node_modules
package-lock.json
37 changes: 32 additions & 5 deletions src/core.js
Original file line number Diff line number Diff line change
Expand Up @@ -700,14 +700,28 @@ $.extend( $.validator, {
elements: function() {
var validator = this,
rulesCache = {},
selectors = [ "input", "select", "textarea", "[contenteditable]" ];
selectors = [ "input", "select", "textarea", "[contenteditable]" ],
formId = this.currentForm.id,
elements;

// Select all valid inputs inside the form (no submit or reset buttons)
return $( this.currentForm )
elements = $( this.currentForm )
.find( selectors.concat( this.settings.customElements ).join( ", " ) )
.not( ":submit, :reset, :image, :disabled" )
.not( this.settings.ignore )
.filter( function() {
.not( this.settings.ignore );

// If the form has an ID, also include elements outside the form that have
// a form attribute pointing to this form
if ( formId ) {
elements = elements.add(
$( selectors.concat( this.settings.customElements ).join( ", " ) )
.filter( "[form='" + validator.escapeCssMeta( formId ) + "']" )
.not( ":submit, :reset, :image, :disabled" )
.not( this.settings.ignore )
);
}

return elements.filter( function() {
var name = this.name || $( this ).attr( "name" ); // For contenteditable
var isContentEditable = typeof $( this ).attr( "contenteditable" ) !== "undefined" && $( this ).attr( "contenteditable" ) !== "false";

Expand Down Expand Up @@ -1133,7 +1147,20 @@ $.extend( $.validator, {
},

findByName: function( name ) {
return $( this.currentForm ).find( "[name='" + this.escapeCssMeta( name ) + "']" );
var formId = this.currentForm.id,
selector = "[name='" + this.escapeCssMeta( name ) + "']",
elements = $( this.currentForm ).find( selector );

// If the form has an ID, also include elements outside the form that have
// a form attribute pointing to this form
if ( formId ) {
elements = elements.add(
$( selector )
.filter( "[form='" + this.escapeCssMeta( formId ) + "']" )
);
}

return elements;
},

getLength: function( value, element ) {
Expand Down
10 changes: 9 additions & 1 deletion test/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -504,7 +504,15 @@ <h3></h3>
</form>
<form id="customElementsForm">
<custom-text name="customTextElement" id="customTextElement" />
</form>
</form>
<form id="testForm29">
<input type="text" name="f29input1" required>
</form>
<input type="text" name="f29input2" form="testForm29" required>
<form id="testForm30">
<input type="checkbox" name="f30checkbox1" value="1" required>
</form>
<input type="checkbox" name="f30checkbox2" value="1" form="testForm30" required>
</div>
</body>
</html>
34 changes: 34 additions & 0 deletions test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,40 @@ QUnit.test( "Ignore elements that have form attribute set to other forms", funct
$( "#testForm28-other" ).remove();
} );

QUnit.test( "Validate elements outside form with form attribute", function( assert ) {
assert.expect( 4 );

var form = $( "#testForm29" );
assert.ok( form.length === 1, "Form should be found in the DOM" );

var v = form.validate();

// The form has one input inside and one input outside with form attribute
assert.equal( v.elements().length, 2, "Both elements should be included" );

// Validate the form - both fields are required and empty
var result = v.form();
assert.ok( !result, "Form validation should fail when both inputs are empty" );
assert.equal( v.numberOfInvalids(), 2, "Should have 2 invalid elements" );
} );

QUnit.test( "Validate checkboxes outside form with form attribute", function( assert ) {
assert.expect( 4 );

var form = $( "#testForm30" );
assert.ok( form.length === 1, "Form should be found in the DOM" );

var v = form.validate();

// The form has one checkbox inside and one checkbox outside with form attribute
assert.equal( v.elements().length, 2, "Both checkboxes should be included" );

// Validate the form - both checkboxes are required and unchecked
var result = v.form();
assert.ok( !result, "Form validation should fail when both checkboxes are unchecked" );
assert.equal( v.numberOfInvalids(), 2, "Should have 2 invalid elements" );
} );

QUnit.test( "addMethod", function( assert ) {
assert.expect( 3 );
$.validator.addMethod( "hi", function( value ) {
Expand Down
Loading