indexing form elements with jquery - javascript

I've been searching around and all the answers I've seen will use something along the lines of $('form :input')$ to get all of the inputs. But I already have a reference to the form using $("form").submit() and I just need to grab a specific input field from the fieldname. I'm unsure of how to use $(this) with additional selectors to get the forms specific elements
So, how would I go about doing that.
Example of the bit of code I need to workout.
$('form').submit(function(){
var form = $(this)
var form_errors = array_of_errors
for(var fieldname in form_errors){
var errors = form_errors[fieldname]
var field = \\how to get this
\\ Something like $(form, 'input[name='+fieldname+']') maybe?
}
});

$(selector, context)
jQuery selectors can have a second argument, used to define their context.
$(`input[name=${fieldname}]`, form);
will do the trick.
This means that your selector will look only inside the element you have passed as context.
Documentation:
http://api.jquery.com/jquery/#jQuery-selector-context
$(context).find(selector)
An alternative could be to use find() in conjunction with the context:
$(form).find(`input[name=${fieldname}]`);

$('form').submit(function(){
var $form = $(this), // good naming practice to use $ to signify jQuery object
form_errors = validateForm(this); // semi-colon
var fields = Object.keys( form_errors );
for ( var i=0,n=fields.length; i<n; i++ ){
var field = fields[i],
errors = form_errors[field],
$field = $form.find('input[name=' + field + ']');
$field.applyErrorMarkup(errors); // whatever you plan to do with the field
}
});
// Pseudocode of one possible way to validate your form
function validateForm(frm){
var errors = {};
// BEGIN LOOP: <insert code to iterate over fields and validity checks>
var field = 'fieldname'; // placeholder
if( true /* error found */ ){
var err = errors[field];
var msg = 'new error message'; // should be the dynamic validity check error message (e.g., 'only numbers permitted')
errors[field] = err && [msg].concat( err ) || msg;
}
// END LOOP
return errors;
}

Related

Select Part of a Attribute - JQuery

I need to get the number only from an attribute (The number is dynamic). The button/anchor looks like this:
Delete Dish
The part I need to dissect is this bit 'bc_inventorybundle_menu_product_0' I only want the number, for use in another function (Delete a LI with an ID of menuitem0_dish)
The code I use for selecting ID's elsewhere is:
function getNum(element, attrPrefix) {
//set prefix, get number
var prefix = attrPrefix;
var num = element.attr("id").substring((prefix.length));
return num;
}
It works great on ID's but I cant seem to get it to work for Attributes instead of ID's
So User clicks delete button bc_inventorybundle_menu_product_0 then jQuery removes the < li id="menuitem0_dish">
I can't add an ID to the button so I have to use the attribute of the button. As I'm sure you can tell I'm a complete noob when it comes to JS/JQuery.
EDIT
Having read all the answers I feel I may need to elaborate a little.
I think the biggest issue is registering when the Button/Anchor is clicked.
What I currently have is this, which I know must be wrong:
$(document).on('click', 'data("field")', function(event) {
deleteDish(this);
});
function getbutNum(element, attrPrefix) {
//set prefix, get number
var prefix = attrPrefix;
var butnum = element.data("field").substring(prefix.length); //Changed as per suggestions
return butnum;
}
function deleteDish(field) {
var numbut = getbutNum();
//Delete the UL/LI
console.log("Num But" + numbut);
}
Asides from all else this gives me an error of 'unrecognized expression: data("field")'
Have you tried selecting your actual data attribute:
var num = element.attr("data-field").substring(prefix.length);
Or:
var num = element.data("field").substring(prefix.length);
EDIT
First add a class to your anchor element (I'm going under the assumption that you have more than one of these):
Delete Dish
Then:
$(".delete-dish").on("click", function (e) {
e.preventDefault();
var fieldData = $(this).data("field"),
num = fieldData.substring(fieldData.lastIndexOf("_") + 1);
console.log("Num But" + num);
});
Here is a fiddle to demonstrate
Using the attribute name that contains your input should work:
function getNum(element, attrPrefix) {
//set prefix, get number
var prefix = attrPrefix;
var num = element.attr("data-field").substring((prefix.length));
return num;
}
http://jsfiddle.net/zf3hmo4q/
Considering you want to parse attributes with "data-*" name:
function getNum(element, dataName, dataPrefix) {
var num = element.data(dataName).replace(dataPrefix, "");
return num;
}
console.log(getNum($(".btn"), "field", "bc_inventorybundle_menu_product_"));
Maybe something like this?
var getNumberFromAttribute = function(id, field) {
var field = $(id).data(field);
var parts = field.split("_");
return parts[parts.length - 1]
}
Here's a jsfiddle http://jsfiddle.net/o6go79cL/
UPDATE
You could just pass in the element. The only purpose of the id was to select the object. So you could also just do:
var getNumberFromAttribute = function(elm, field) {
var field = $(elm).data(field);
var parts = field.split("_");
return parts[parts.length - 1]
}
number = getNumberFromAttribute(anchorTag, "field");

JavaScript: Why isn't my closure working?

The following code is only assigning the value of the last .enter_form input to the last MYAPP.list[0].responses[MYAPP.score.round].form[key] (where key is the only thing that varies). I think it's because only the last value of the key is being passed to addEntry(), but I can't figure out how to get around that.
$('.enter_form input').each(function() {
var key = $(this).attr('id');
var val = $(this).val();
userDict[key] = val;
MYAPP.list[0].responses[MYAPP.score.round].form = [];
function addEntry() {
return function(k) {
MYAPP.list[0].responses[MYAPP.score.round].form[k] = {'entry': userDict[k]};
}(key);
}
addEntry();
}
Your addEntry function is redundant since each iteration is already run inside it´s own scope so key and val are preserved properly (hope that explanation makes sense). Also the array you where inserting into was overwritten each iteration as well, so at the end of the .each() you end up with an array with only 1 value. It should also be an object rather then an array, even if the id's are numerical.
// you where overwriting this each iteration
MYAPP.list[0].responses[MYAPP.score.round].form = {};
$('.enter_form input').each(function() {
var el= $(this); // cache instead of creating a new jQuery object each time
var key = el.attr('id');
var val = el.val();
userDict[key] = val;
MYAPP.list[0].responses[MYAPP.score.round].form[key] = {'entry': userDict[key]};
}); // ); was also missing
Should work.
It's a bit hard to work out what it's meant to do, but I think this is probably it:
MYAPP.list[0].responses[MYAPP.score.round].form = [];
$('.enter_form input').each(function() {
var $this = $(this),
key = this.id,
val = $this.val();
userDict[key] = val;
MYAPP.list[0].responses[MYAPP.score.round].form[key] = {
'entry': val
};
});
That's based on your saying that "...key is the only thing that varies" (presumably $(this).val() also varies, but I took your point). It will add entries to MYAPP.list[0].responses[MYAPP.score.round].form for each of the form's input ids, as well as adding them to the userDict map.
As a side note, if the id values on the input elements aren't purely numeric, then I suspect you want to start with a blank object:
MYAPP.list[0].responses[MYAPP.score.round].form = {};
// ^^-- change is here
...rather than an empty array:
MYAPP.list[0].responses[MYAPP.score.round].form = [];
...although since arrays are objects, it works even if you're adding non-numeric properties.
Off-topic: No need for $(this).attr('id'). Just use this.id.

Get all Radio Button and Text Field values

I have a form on my page that is located in a class .class-lesson. The form itself only contains text field and radio buttons. I do not know how many of each are in the form since it is dynamically generated by PHP. Each new input in the form is named q1, q2, ... qn.
I am trying to get all the values, whether answered or not, and stored into a javascript array. This is my code so far:
// get the value of each input field
var numQuestions = $(".class-lesson label").not(".csubmit").length;
// store each answer
for (var i = 0; i < numQuestions; i++) {
// store our variables
var tempAnswer = undefined;
var tempReference = $(":input[name=q"+(i+1)+"]");
// loop through each item
if ( tempReference.attr('type') == 'radio' ) tempAnswer = $(":input[name=q"+(i+1)+"]:checked").val();
else tempAnswer = tempReference.val();
// output / store the item
alert( tempAnswer );
}
I am sure there has to be an easier way to do this but I don't know. This is why I am asking. If I don't have the :checked then it will just grab the first value of the radio group.
So, how can I make this more efficient?
To get an entire <form> (or any set of inputs) in serialized form, as it would be if submitted to the server normally (without any JavaScript involved), use .serialize(), like this:
var formData = $(".class-lesson :input").serialize();
//or...
var formData = $("#formID").serialize();
If you're submitting via AJAX for example this makes your code incredibly simple, for example:
$.post("test.php", $("#formID").serialize(), function(data) {
alert("Response was: " + data);
});

a better way to check if a checkbox is defined?

currently i am using
var email, fax, sms = false;
if($('#uemail:checked').val() != undefined)
email = true;
if($('#ufax:checked').val() != undefined)
fax = true;
if($('#usms:checked').val() != undefined)
sms = true;
but its such a long way to write it.
is there a better way to write this?
Try this:
if($('#uemail').is(':checked'))
email = true;
Or even shorter:
email = $('#uemail').is(':checked');
You're passing the :checked selector into jQuery's .is() method which returns a boolean value;
http://api.jquery.com/is/
You can use .length, like this:
var email = $('#uemail:checked').length,
fax = $('#ufax:checked').length,
sms = $('#usms:checked').length;
.length is the length of the array of matched elements...if it's not checked, it's 0. And since .length == 0 serves for .length == false in JavaScript you can do the short version above. If you need a true/false, then just do .length != 0 instead :)
Or, another alternative that produces booleans, just use the DOM .checked property:
var email = $('#uemail')[0].checked,
fax = $('#ufax')[0].checked,
sms = $('#usms')[0].checked;
Or, no jQuery at all just use getElementById():
var email = document.getElementById('uemail').checked,
fax = document.getElementById('ufax').checked,
sms = document.getElementById('usms').checked;
An alternative may be to use an associative array and then loop through the keys. It would certainly be more DRY.
// Initialise all the checkbox values as unknown
var items = {
"email" : none,
"fax" : none,
"sms" : none
};
// Loop through each checkbox index
for (var index in items) {
// Get the id of the checkbox
var id = '#u' + index;
// Find out if the checkbox is checked
items[index] = $(id).is(':checked');
}

JavaScript form input loop help

I have a form that currently only parses the first input variable in the POST.
I have had to add multiple variables, so I would like the function to loop through and grab all the input parameters and add to the POST
Here's the working code for grabbing the first name and value.... How can I get it to check the form and grab all custom name's and variables.
example here
// dynamically add key/value pair to POST body
function read_custom_param(){
var nameEl = document.getElementById("custom_name");
var valueEl = document.getElementById("custom_value");
// save custom param name and value
var cust_param_name = nameEl.value;
var cust_param_value = valueEl.value;
// remove old custom param form elements
if (valueEl.parentNode && valueEl.parentNode.removeChild){
valueEl.parentNode.removeChild(valueEl);
}
if (nameEl.parentNode && nameEl.parentNode.removeChild){
nameEl.parentNode.removeChild(nameEl);
}
// add new custom param form elements
var el=document.createElement("input");
el.type="text";
el.name=cust_param_name;
el.value=cust_param_value;
document.getElementById("dcapiform").appendChild(el);
}
Kind Regards,
Chris
for whatever purpose ur trying to send ambiguous field names to the server, here is what ur looking for (u should consider a smarter way, may br processing on the server side instead)
var elems = document.getElementsByTagName("input");
var arr = [];
for (var i = 0; i<elems.length; i++){
if (elems[i].type != "text") continue;
if (elems[i].name.indexOf("custom_name") < 0) continue;
var index = parseInt(elems[i].name.substring(11)); // you should rename custom_name to custom_name1, and so for custom_value
arr[arr.length] = elems[i].value+"=" + elems["custom_value"+index].value;
}
document.forms[0]["passedITems"] = arr.join(",");
docmentt.forms[0].submit();
on your server side, read "passedItems", and split by ",", you get an array of "name=value", split again on "=" you get a sub array of name, and value

Categories

Resources