Forum Moderators: open
var counter = 0;
function moreFields() {
counter++;
var newFields = document.getElementById('readroot').cloneNode(true);
newFields.id = '';
newFields.style.display = 'block';
var newField = newFields.childNodes;
for (var i=0;i<newField.length;i++) {
var theName = newField[i].name
if (theName)
newField[i].name = theName + counter;
}
var insertHere = document.getElementById('writeroot');
insertHere.parentNode.insertBefore(newFields,insertHere);
}
window.onload = moreFields;
I believe that this is due to the form elements being removed, and the spry validation associated with these fields were not removed, and as a result it is waiting for an input in something that doesn't exist, and as a result the form is not submitted...
after the spry validator has been run at least once in IE, the newly created elements appear with a state as required, and not blank as the first group of elements.
<input type="button" value="Remove Payment"
onclick="this.parentNode.parentNode.removeChild(this.parentNode);" />
<!DOCTYPE html>
<head>
<link rel="stylesheet" type="text/css" href="http://static.flowplayer.org/tools/demos/dateinput/css/skin1.css">
<link href="SpryValidationTextFields.css" rel="stylesheet" type="text/css" >
<title>Test</title>
</head>
<div id="standardform" style="display:none">
<input type="hidden" name="counter" value="marker" />
<select name="payment_type">
<option value="single" selected="selected">Single</option>
<option value="1">Monthly</option>
<option value="3">Quarterly</option>
<option value="6">Semi Anual</option>
<option value="12">Anual</option>
</select>
<span id="spryvalidatorNumber">
<input name="number" value="" />
<span class="textfieldRequiredMsg">A value is required.</span>
<span class="textfieldInvalidFormatMsg">Invalid format.</span>
</span>
<span id="spryvalidatorValue">
<input name="value" value="" />
</span>
<span id="spryvalidatorStartDate">
<input type="date" class="date" name="startdate" value="" />
</span>
<input type="button" value="Remove Payment"
onclick="lessFields(this.parentNode);" /><br />
</div>
<form method="post" action="formprocess.php">
<div id="writeroot"></div>
<input type="button" id="btnmoreFields" value="Add Payment!" onclick="moreFields();" />
<input type="submit" value="Send" />
</form>
<script src="dateinput.js"></script> <!--http://cdn.jquerytools.org/1.2.5/full/jquery.tools.js?foo"-->
<script src="SpryValidationTextField.js" type="text/javascript"></script>
<script type="text/javascript">
var counter = 0;
var spryValidators = {
textFields: []
};
/**
* Given a DOM node, iterate through the children and return the name of the
* first input found. If no inputs are found, return null.
* @param n The Node whose children will be iterated through
*/
function getFirstInputName(n) {
var children = n.childNodes,
i,
n;
for (i = 0, n = children.length; i < n; i++) {
// if a child node is an element (nodeType 1) and has tagName "input"
// then we can stop searching and return the name
if (children[i].nodeType == 1 && children[i].tagName.toLowerCase() == "input") {
return children[i].name;
}
}
// if no input elements were found, return null
return null;
}
/**
* @param el The element whose children we want to inspect
* @param uniqueValue A unique value that will be appended to the id of child
* elements.
* is needed to create the Spry.Widget.ValidationTextField.
*/
function updateChildren(el, uniqueValue) {
var i, // index to an array
n, // length of the array
newFields = el.childNodes, // The children of the current el
theName, // the name attribute of child inputs
uid; // a unique id of the validator span wrapper around an input
// iterate through each of the children of the element passed in
for (i = 0, n = newFields.length; i < n; i++) {
// ignore all children that are not HTMLElement nodes (nodeType 1)
if (newFields[i].nodeType == 1) {
// check to see if the current element is a span element. If so,
// we'll need to updated that elements children as well.
if (newFields[i].tagName.toLowerCase() == "span") {
var firstInputName = getFirstInputName(newFields[i]);
if (firstInputName) {
// give it a unique id based on it's current id, plus the
// unique value that was passed in, plus the index in the array
uid = newFields[i].id + "_" + uniqueValue + "_" + i;
newFields[i].id = uid;
// Record the id value in an array. When we're all done looping,
// we'll create a validator for each item in the array.
spryValidators.textFields.push({uid: uid, name: firstInputName});
// update the child nodes of the span
updateChildren(newFields[i], uid);
}
}
else {
// this is not a span element, so must be a form control
// Note, that is not a strict requirement... if the markup that
// we copied contained other elements than form controls and
// span element, then we should probably add additional checks
// here. However, given the HTML above, this should work.
// ...
// give this element a unique name based on the current name
// plus the global counter
theName = newFields[i].name;
if (theName) {
newFields[i].setAttribute("name", theName + counter);
newFields[i].name = theName + counter;
}
}
}
}
}
/**
* Add a duplicate of 'standardform' field items to the form.
*/
function moreFields() {
counter++;
// Get the block containing the nodes to be cloned
var newFields = document.getElementById('standardform').cloneNode(true);
newFields.id = '';
newFields.style.display = 'block';
//var newField = newFields.childNodes;
updateChildren(newFields, counter);
var insertHere = document.getElementById('writeroot');
insertHere.parentNode.insertBefore(newFields,insertHere);
// Setup date field
var d = $("input.date[name!=startdate]");
d.each(function (i, el) {
$(el).dateinput({
format: 'yyyy-mm-dd', // the format displayed for the user
selectors: true, // whether month/year dropdowns are shown
//min: -100, // min selectable day (100 days backwards)
//max: 1, // max selectable day (100 days onwards)
offset: [10, 20], // tweak the position of the calendar
speed: 'fast', // calendar reveal speed
firstDay: 0, // which day starts a week. 0 = sunday, 1 = monday etc..
yearRange: [-6, 7],
trigger: true
});
});
// Attach spry Validation
for (i = 0, n = spryValidators.textFields.length; i < n; i++) {
if (spryValidators.textFields[i]) {
// This is just for debugging
alert('creating validator: ' + spryValidators.textFields[i].uid + ", " +spryValidators.textFields[i].name);
switch (spryValidators.textFields[i].name) {
case "number":
new Spry.Widget.ValidationTextField(spryValidators.textFields[i].uid, "integer", {validateOn: ["change"]});
break;
case "value":
new Spry.Widget.ValidationTextField(spryValidators.textFields[i].uid, "real", {validateOn: ["change"]});
break;
case "startdate":
new Spry.Widget.ValidationTextField(spryValidators.textFields[i].uid, "date", {validateOn: ["change"], format:"yyyy-mm-dd"});
break;
}
// remove this field from the array so we dont attempt to create
// it again next time moreFields is called.
spryValidators.textFields[i] = null;
}
}
}
/**
* @param el The node to be removed
*/
function lessFields(el) {
var children = el.childNodes,
i,
n;
for (i = 0, n = children.length; i < n; i++) {
if (children[i].nodeType == 1) {
// check to see if the current element is a span element. If so,
// we'll need to updated that elements children as well.
if (children[i].tagName.toLowerCase() == "span") {
var firstInputName = getFirstInputName(children[i]);
if (firstInputName) {
Spry.Widget.Utils.destroyWidgets(children[i]);
}
}
}
}
el.parentNode.removeChild(el);
}
</script>
</body>
</html>
for the second problem, when i click on Add Payment on IE, and enter some data in the newly created fields, and the click again on Add Payment, the newly created fields appear in RED and next to each field a message states A Value is Required...
How can i make the newly created fields appear without the warning that a value is required in its initial state.
<span id="sprytextfield4">
<input name="textfield" value="" />
<span class="textfieldRequiredMsg">A value is required.</span><span class="textfieldInvalidFormatMsg">Invalid format.</span></span>
case "textfield":// Attach spry Validation
for (i = 0, n = spryValidators.textFields.length; i < n; i++) {
if (spryValidators.textFields[i]) {
// This is just for debugging
alert('creating validator: ' + spryValidators.textFields[i].uid + ", " +spryValidators.textFields[i].name);
switch (spryValidators.textFields[i].name) {
case "number":
new Spry.Widget.ValidationTextField(spryValidators.textFields[i].uid, "integer", {validateOn: ["change"]});
break;
case "value":
new Spry.Widget.ValidationTextField(spryValidators.textFields[i].uid, "real", {validateOn: ["change"]});
break;
case "startdate":
new Spry.Widget.ValidationTextField(spryValidators.textFields[i].uid, "date", {validateOn: ["change"], format:"yyyy-mm-dd"});
break;
new Spry.Widget.ValidationTextField(spyrValidators.textFields[i].uid, "none", {validateOn:["change"]});
break;
}
// remove this field from the array so we dont attempt to create
// it again next time moreFields is called.
spryValidators.textFields[i] = null;
}
but for some reason it doesn't validate if it is empty...
new Spry.Widget.ValidationTextField(spyrValidators.textFields[i].uid, "none", {validateOn:["change"]});
new Spry.Widget.ValidationTextField(spryValidators.textFields[i].uid, "none", {validateOn:["change"]});
<table>
<tr>
<td>
FORM LABELS
</td>
<td>
FORM ELEMENTS
</td>
</tr>......
</table
// Note, that is not a strict requirement... if the markup that
// we copied contained other elements than form controls and
// span element, then we should probably add additional checks
// here. However, given the HTML above, this should work.
<!DOCTYPE html>
<head>
<link rel="stylesheet" type="text/css" href="http://static.flowplayer.org/tools/demos/dateinput/css/skin1.css">
<link href="SpryValidationTextFields.css" rel="stylesheet" type="text/css" >
<title>Test</title>
</head>
<div id="standardform" style="display:none">
<input type="hidden" name="counter" value="marker" />
<table>
<tr>
<td>
FORM LABELS
</td>
<td>
<select name="payment_type">
<option value="single" selected="selected">Single</option>
<option value="1">Monthly</option>
<option value="3">Quarterly</option>
<option value="6">Semi Anual</option>
<option value="12">Anual</option>
</select>
<span id="spryvalidatorNumber">
<input name="number" value="" />
<span class="textfieldRequiredMsg">A value is required.</span>
<span class="textfieldInvalidFormatMsg">Invalid format.</span>
</span>
</td>
</tr>
</table>
<span id="spryvalidatorValue">
<input name="value" value="" />
</span>
<span id="spryvalidatorStartDate">
<input type="date" class="date" name="startdate" value="" />
</span>
<span id="sprytextfield4">
<input name="textfield" value="" />
<span class="textfieldRequiredMsg">A value is required.</span>
<span class="textfieldInvalidFormatMsg">Invalid format.</span>
</span>
<input type="button" value="Remove Payment"
onclick="lessFields(this.parentNode);" /><br />
</div>
<form method="post" action="formprocess.php">
<div id="writeroot"></div>
<input type="button" id="btnmoreFields" value="Add Payment!" onclick="moreFields();" />
<input type="submit" value="Send" />
</form>
<script src="dateinput.js"></script> <!--http://cdn.jquerytools.org/1.2.5/full/jquery.tools.js?foo"-->
<script src="SpryValidationTextField.js" type="text/javascript"></script>
<script type="text/javascript">
var counter = 0;
var spryValidators = {
textFields: []
};
/**
* Given a DOM node, iterate through the children and return the name of the
* first input found. If no inputs are found, return null.
* @param n The Node whose children will be iterated through
*/
function getFirstInputName(n) {
var children = n.childNodes,
i,
n;
for (i = 0, n = children.length; i < n; i++) {
// if a child node is an element (nodeType 1) and has tagName "input"
// then we can stop searching and return the name
if (children[i].nodeType == 1 && children[i].tagName.toLowerCase() == "input") {
return children[i].name;
}
}
// if no input elements were found, return null
return null;
}
/**
* @param el The element whose children we want to inspect
* @param uniqueValue A unique value that will be appended to the id of child
* elements.
* is needed to create the Spry.Widget.ValidationTextField.
*/
function updateChildren(el, uniqueValue) {
var i, // index to an array
n, // length of the array
newFields = el.childNodes, // The children of the current el
tagname, // the tag name of the child element
theName, // the name attribute of child inputs
uid; // a unique id of the validator span wrapper around an input
// iterate through each of the children of the element passed in
for (i = 0, n = newFields.length; i < n; i++) {
// ignore all children that are not HTMLElement nodes (nodeType 1)
if (newFields[i].nodeType == 1) {
tagname = newFields[i].tagName.toLowerCase();
switch (tagname) {
case "span":
// if the current element is a span element we'll need to
// update that elements children as well. We'll only do that
// if the span element contains an input element.
var firstInputName = getFirstInputName(newFields[i]);
if (firstInputName) {
// give it a unique id based on it's current id, plus the
// unique value that was passed in, plus the index in the array
uid = newFields[i].id + "_" + uniqueValue + "_" + i;
newFields[i].id = uid;
// Record the id value in an array. When we're all done looping,
// we'll create a validator for each item in the array.
spryValidators.textFields.push({uid: uid, name: firstInputName});
// update the child nodes of the span
updateChildren(newFields[i], uid);
}
break;
case "input":
case "select":
case "textarea":
// this is a form control
// give this element a unique name based on the current name
// plus the global counter
theName = newFields[i].name;
if (theName) {
newFields[i].setAttribute("name", theName + counter);
newFields[i].name = theName + counter;
}
break;
default:
// this is neither a form control or a span element so drill
// down to it's children
updateChildren(newFields[i], uniqueValue);
break;
}
}
}
}
/**
* Add a duplicate of 'standardform' field items to the form.
*/
function moreFields() {
counter++;
// Get the block containing the nodes to be cloned
var newFields = document.getElementById('standardform').cloneNode(true);
newFields.id = '';
newFields.style.display = 'block';
//var newField = newFields.childNodes;
updateChildren(newFields, counter);
var insertHere = document.getElementById('writeroot');
insertHere.parentNode.insertBefore(newFields,insertHere);
// Setup date field
var d = $("input.date[name!=startdate]");
d.each(function (i, el) {
$(el).dateinput({
format: 'yyyy-mm-dd', // the format displayed for the user
selectors: true, // whether month/year dropdowns are shown
//min: -100, // min selectable day (100 days backwards)
//max: 1, // max selectable day (100 days onwards)
offset: [10, 20], // tweak the position of the calendar
speed: 'fast', // calendar reveal speed
firstDay: 0, // which day starts a week. 0 = sunday, 1 = monday etc..
yearRange: [-6, 7],
trigger: true
});
});
// Attach spry Validation
for (i = 0, n = spryValidators.textFields.length; i < n; i++) {
if (spryValidators.textFields[i]) {
// This is just for debugging
//alert('creating validator: ' + spryValidators.textFields[i].uid + ", " +spryValidators.textFields[i].name);
switch (spryValidators.textFields[i].name) {
case "number":
new Spry.Widget.ValidationTextField(spryValidators.textFields[i].uid, "integer", {validateOn: ["change"]});
break;
case "value":
new Spry.Widget.ValidationTextField(spryValidators.textFields[i].uid, "real", {validateOn: ["change"]});
break;
case "startdate":
new Spry.Widget.ValidationTextField(spryValidators.textFields[i].uid, "date", {validateOn: ["change"], format:"yyyy-mm-dd"});
break;
case "textfield":
alert('attaching textfield validator to ' + spryValidators.textFields[i].uid);
new Spry.Widget.ValidationTextField(spryValidators.textFields[i].uid, "none", {validateOn:["change"]});
break;
}
// remove this field from the array so we dont attempt to create
// it again next time moreFields is called.
spryValidators.textFields[i] = null;
}
}
}
/**
* @param el The node to be removed
*/
function lessFields(el) {
var children = el.childNodes,
i,
n;
for (i = 0, n = children.length; i < n; i++) {
if (children[i].nodeType == 1) {
// check to see if the current element is a span element. If so,
// we'll need to updated that elements children as well.
if (children[i].tagName.toLowerCase() == "span") {
var firstInputName = getFirstInputName(children[i]);
if (firstInputName) {
Spry.Widget.Utils.destroyWidgets(children[i]);
}
}
}
}
el.parentNode.removeChild(el);
}
</script>
</body>
</html>
with theupdateChildren(newFields[i], uniqueValue);
newFields[i] information with the associated uniqueValue, and loop until it finds something.
Regards the styling and the use of tables, I wanted to use the tables so that the text would align to the right next to the input elements, and the input elements will have the same start point so that it will look more professional. Nothing more, nothing less. :P
Please tell me if what i understood is correct...