diff --git a/src/core.js b/src/core.js index 74d195e42..93fe25568 100644 --- a/src/core.js +++ b/src/core.js @@ -375,7 +375,8 @@ $.extend( $.validator, { this.invalid = {}; this.reset(); - var groups = ( this.groups = {} ), + var currentForm = this.currentForm, + groups = ( this.groups = {} ), rules; $.each( this.settings.groups, function( key, value ) { if ( typeof value === "string" ) { @@ -398,6 +399,12 @@ $.extend( $.validator, { this.name = $( this ).attr( "name" ); } + // Ignore the element if it belongs to another form. This will happen mainly + // when setting the `form` attribute of an input to the id of another form. + if ( currentForm !== this.form ) { + return; + } + var validator = $.data( this.form, "validator" ), eventType = "on" + event.type.replace( /^validate/, "" ), settings = validator.settings; @@ -631,6 +638,11 @@ $.extend( $.validator, { this.name = name; } + // Ignore elements that belong to other/nested forms + if ( this.form !== validator.currentForm ) { + return false; + } + // Select only the first element for each name, and only those with rules specified if ( name in rulesCache || !validator.objectLength( $( this ).rules() ) ) { return false; diff --git a/test/index.html b/test/index.html index 3235689da..0079aa7d9 100644 --- a/test/index.html +++ b/test/index.html @@ -113,7 +113,7 @@

- +
@@ -449,6 +449,9 @@


+
+ +
diff --git a/test/test.js b/test/test.js index 79bf0cf1b..dbe901556 100644 --- a/test/test.js +++ b/test/test.js @@ -187,6 +187,173 @@ QUnit.test( "valid(), ignores ignored elements", function( assert ) { assert.ok( $( "#firstnamec" ).valid() ); } ); +QUnit.test( "valid() should ignore elements that belong to other/nested forms", function( assert ) { + var form = $( "#testForm28" ); + + form.validate(); + + // 1. Test with nested form + form.append( + "
" + + " " + + "
" + ); + + try { + form.valid(); + assert.ok( true, "It should ignore the input of nested form" ); + } catch ( err ) { + assert.ok( false, "Shouldn't throw an error" ); + } + + // Remove the validator atteched to testForm28 + form.removeData( "validator" ); + $( "#testForm28-nested" ).remove(); + + // 2. Test using another form outside of validated one + form.parent().append( + "
" + + " " + + " " + + "
" + ); + + $( "#testForm28-other" ).validate(); + + try { + $( "#testForm28-other" ).valid(); + assert.ok( true, "It should ignore the input of other form" ); + } catch ( err ) { + assert.ok( false, "Shouldn't throw an error" ); + } + + $( "#testForm28-other" ).remove(); +} ); + +QUnit.test( "form() should ignore elements that belong to other/nested forms", function( assert ) { + var form = $( "#testForm28" ); + var v = form.validate(); + + form.validate(); + + // 1. Test with nested form + form.append( + "
" + + " " + + "
" + ); + + try { + v.form(); + assert.ok( true, "It should ignore the input of nested form" ); + } catch ( err ) { + assert.ok( false, "Shouldn't throw an error" ); + } + + // Remove the validator atteched to testForm28 + form.removeData( "validator" ); + $( "#testForm28-nested" ).remove(); + + // 2. Test using another form outside of validated one + form.parent().append( + "
" + + " " + + " " + + "
" + ); + + v = $( "#testForm28-other" ).validate(); + + try { + v.form(); + assert.ok( true, "It should ignore the input of other form" ); + } catch ( err ) { + assert.ok( false, "Shouldn't throw an error" ); + } + + $( "#testForm28-other" ).remove(); +} ); + +QUnit.test( "elements() should ignore elements that belong to other/nested forms", function( assert ) { + var form = $( "#testForm28" ); + var v = form.validate(); + + // 1. Test with nested form + form.append( + "
" + + " " + + "
" + ); + + try { + assert.equal( v.elements().length, 1, "There should be only one element to validate" ); + } catch ( err ) { + assert.ok( false, "Shouldn't throw an error" ); + } + + // Remove the validator atteched to testForm28 + form.removeData( "validator" ); + $( "#testForm28-nested" ).remove(); + + // 2. Test using another form outside of validated one + form.parent().append( + "
" + + " " + + " " + + "
" + ); + + v = $( "#testForm28-other" ).validate(); + + try { + assert.equal( v.elements().length, 1, "There should be only one element to validate" ); + } catch ( err ) { + assert.ok( false, "Shouldn't throw an error" ); + } + + $( "#testForm28-other" ).remove(); +} ); + +QUnit.test( "Ignore elements that have form attribute set to other forms", function( assert ) { + + // Append a form that contains an input with form attribute set to "testForm28" + $( "#testForm28" ).parent().append( + "
" + + " " + + " " + + "
" + ); + + // Attach the plugin to the appended form + $( "#testForm28-other" ).validate(); + + // 1. Simulate typing + try { + $( "[name='f28input']", "#testForm28-other" ).trigger( "keyup" ); + assert.ok( true, "It should ignore the input of other form" ); + } catch ( err ) { + assert.ok( false, "Shouldn't throw an error while typing" ); + } + + // 2. Simulate forcussing in the input + try { + $( "[name='f28input']", "#testForm28-other" ).trigger( "focusin" ); + assert.ok( true, "It should ignore the input of other form" ); + } catch ( err ) { + assert.ok( false, "Shouldn't throw an error on focus" ); + } + + // 3. Simulate focussing out the input + try { + $( "[name='f28input']", "#testForm28-other" ).trigger( "focusout" ); + assert.ok( true, "It should ignore the input of other form" ); + } catch ( err ) { + assert.ok( false, "Shouldn't throw an error on blur" ); + } + + $( "#testForm28-other" ).remove(); +} ); + QUnit.test( "addMethod", function( assert ) { assert.expect( 3 ); $.validator.addMethod( "hi", function( value ) {