Passing multiple checkbox values in AJAX call - javascript

I use a ternary operator to check which checkboxes in a form have been selected. If a value has been selected, I affix the name-value pair to a query string which is then passed in an AJAX call. If not, I attach a name with an empty string value.
It works fine, I'm just wondering if there's a more compact/elegant way to do this as it seems somewhat verbose. I'm wondering if it's possible to use a for loop. The reason I'm not sure if this would work is it would involve dynamically assigning variable names within the loop based on the index.
var fields = $('input[name="apn"]').serializeArray();
var apn1 = fields[0] ? fields[0]["value"] : ''
query += '&apn1=' + apn1;
var apn2 = fields[1] ? fields[1]["value"] : ''
query += '&apn2=' + apn2;
var apn3 = fields[2] ? fields[2]["value"] : ''
query += '&apn3=' + apn3;
var apn4 = fields[3] ? fields[3]["value"] : ''
query += '&apn4=' + apn4;
var apn5 = fields[4] ? fields[4]["value"] : ''
query += '&apn5=' + apn5;
...

Map the values and indices to an array of objects, and just pass that directly to $.ajax, jQuery will use $.param on it for you :
var fields = $.map($('input[name="apn"]'), function(el, i) {
var o = {};
o['apn' + i] = el.value;
return o;
});

If its just checkboxes:
$('input[name="apn"]').each(function (i, el) {
if($(el).is(':checked')) {
query += '&apn'+i+'=' + el.value;
}
});

You can simply serialize the form:
var query = $("#FormId").serialize();

Related

How can I remove certain elements of a query string?

I'm working on a script, where you pass it a url like /search?filter1=question-1&filter2=question2, and when either question-1 or question-2 is changed, it will take the url, and replace the question-x with the question value.
One thing I want to build in, is if the value is empty, I want it to remove the query string part. So for example, if question-1 has a value of something, but 2 doesn't have a value yet, the url will be /search?filter1=something.
What I thought would work would be something like this
$url.match('/([^?&]*)' + name.toSearch + '/g') // toSearch is a value like question-1
But that returns null. Can anybody help me figure out what I need to change to get the output I'm after?
Given the url /search?filter=question-1, I need to see if the element with the name question[1] has a value, if it does, replace question-1 with the value, and if it doesn't have one, remove the total filter=question-1 string.
Knowing your requirements better from the comments, I completely rewrote my answer using parts of my original answer and some of your code:
// Given url
var url = '/search?filter1=question-1&filter2=question-2';
// Specify the filters so no extra query string noise enters the final url
var filters = ["filter1", "filter2", "filter3"];
// Split the query string parts
var urlParts = url.split(/([&?])/);
var reassembled = [];
// Break the url parts into key:value pairs
var qs = (function(a) {
if (a === "") return {};
var b = {};
for (var i = 0; i < a.length; ++i)
{
var p=a[i].split('=', 2);
if (p.length == 1)
b[p[0]] = "";
else
b[p[0]] = decodeURIComponent(p[1].replace(/\+/g, " "));
}
return b;
})(urlParts);
// This include a param:value in the reassembled array
function includeQSParam(param, value) {
if(qs[param]) {
reassembled.push(param + "=" + value);
}
}
// Run through the filters
for(var ind in filters) {
var filter = filters[ind];
// Check that the filter exists and the supplied value is of type question-
if(qs[filter] && qs[filter].indexOf("question-") >= 0) {
// Turns question-number into question[number] so it's a valid selector.
var inputSelector = "question["+(qs[filter]).replace(/\D/g, "")+"]";
// Get the input, and the value (author-supplied code)
var $input = $('[name="' + inputSelector + '"]');
// TODO: confirm this is how you get the value
var value = $input.closest('.question').val();
if($input.length > 0 && (value !== '' && value !== undefined)) {
// Replace the parameter's original value with the question value
includeQSParam(filter, value);
} else {
// Nothing to do. This filter will be removed automatically
}
}
}
// Reassemble the URL
var fixedUrl = urlParts[0] + (reassembled.length > 0 ? "?"+reassembled.join("&") : "");
Again, this was reworked from my original answer so there will be some bloat, but I didn't want to abandon the question on you.
Whilst Drakes answer is a good one, it didn't quite fit into my needs. I've ended up with this, which works well so far, but I'm still testing it.
var $url = '/search?filter1=question-1&filter2=question-2';
// Break the url into parts.
var $split = $url.split(/([&?])/);
$.each($split, function(indexToRemove, part){
// If the part is a question.
if(typeof part == 'string' && part.indexOf('question-') > -1){
var $number = part.split('=');
// Turns question-number into question[number] so it's a valid selector.
$inputSelector = String($number[1]).replace('-', '[') + ']';
// Get the input, and the value.
var $input = $('[name="' + $inputSelector + '"]');
var $value = getValue($input.closest('.question'));
// If there is an element, and there is a value.
if($input.length > 0 && ($value != '' && $value != undefined)){
$split[indexToRemove] = part.replace($number[1], $value);
} else {
$split.splice(indexToRemove, 1);
}
}
});
$url = $split.join('');
// If for example question-1 has a value of 'Test', and question-2 has no value, $url will now be '/search?filter1=Test'.

How do I extract JSON string using a JavaScript variable?

I am currently trying to retrieve the corresponding dial_code by using the name which I am obtaining as a variable.
The application uses a map of the world. When the user hovers over a particular country, that country is obtained using 'getRegionName'. This is then used to alter the variable name. How can I use the variable name to retrieve the dial_code that it relates to?
JSON
var dialCodes = [
{"name":"China","dial_code":"+86","code":"CN"},
{"name":"Afghanistan","dial_code":"+93","code":"AF"}
];
The following code runs on mouse hover of a country
var countryName = map.getRegionName(code);
label.html(name + ' (' + code.toString() + ')<br>' + dialCodes[0][countryName].dial_code);
This code doesn't work correctly. The dialCodes[0][countryName].dial_code is the part that is causing the error, but I'm not sure how to correctly refer to the corresponding key/value pair
If you have to support old browsers:
Loop over the entries in the array and compare to the given name:
var dialCode;
for(var i = 0; i < dialCodes.length; i++) {
if(dialCodes[i].name === countryName) {
dialCode = dialCodes[i].dial_code;
break;
}
}
label.html(countryName + ' (' + dialCode + ')');
If you browser support Array.prototype.filter:
dialCodes.filter(function(e) { return e.name === 'China' })[0].dial_code
If you have control over it, I recommend making your object more like a dictionary, for example if you are always looking up by the code (CN or AF) you could avoid looping if you did this:
var dialCodes = {
CN: { "name":"China","dial_code":"+86","code":"CN" },
AF: {"name":"Afghanistan","dial_code":"+93","code":"AF"}
};
var code = dialCodes.CN.dial_code;
Or
var myCode = 'CN'; // for example
var code = dialCodes[myCode].dial_code;
Since it's an array you can use filter to extract the data you need.
function getData(type, val) {
return dialCodes.filter(function (el) {
return el[type] === val;
})[0];
}
getData('code', 'CN').dial_code; // +86

jQuery .each: Do not add comma in last field

I want to get values of all fields in a variable separated by a comma. For example: 1,2,3
The following code will work fine, but it only adds the comma at end of the last value also. How can I remove that?
fields = $('.wrap').find('.text');
var data = '';
fields.each(function() {
var value = $(this).val();
if ( value != '' ) {
data += ' ' + value + ',';
}
});
alert(data);
JSFiddle:
http://jsfiddle.net/cn5Gt/
I always use arrays for these kind of things:
var fields = $('.wrap').find(".text[value!='']");
var data = [];
fields.each(function() {
data.push($(this).val());
});
alert(data.join(','));
You can push elements on array than just use join() method.
fields = $('.wrap').find('.text');
var data = [];
fields.each(function() {
var value = $(this).val();
if ( value != '' ) {
data.push(value);
}
});
alert(data.join());
Try the code below, using the i which is the loop index and test against the length of the jQuery object.
fields = $('.wrap').find('.text');
var length = fields.length;
var data = '';
fields.each(function(i) {
var value = $(this).val();
if ( value != '' ) {
if(i === length-1) { //The last one
data += ' ' + value;
} else {
data += ' ' + value + ',';
}
}
});
Updated fiddle
You could just remove the final character afterwards?
data = data.substr(0, data.length - 1);
http://jsfiddle.net/cn5Gt/3/
Simplest of all:just replace your last line with the below line
alert(data.slice(0,-1));//where data is string
http://jsfiddle.net/cn5Gt/7/
DOC MDN : slice
How about something like this:
var data = $('.wrap').find('.text')
.map(function(i,el){ return el.value || null; })
.get().join(", ");
Demo: http://jsfiddle.net/cn5Gt/11/
jQuery's .map() method will "Pass each element in the current matched set through a function, producing a new jQuery object containing the return values." You can still include your if ( value != '' ) { test in the callback function because if your function returns null or undefined then .map() will not use that particular value. (I've used || null above as a shortcut to an if/else structure.)
Call .get() (or .toArray()) on the result and you'll have an actual array, which means you can then use the Array .join() method to form a string with the values comma separated.
If you need to do other processing on each item besides just getting the value you could stick with the .each() loop and add the values to an array that you then join after the loop (like some of the other answers), or just use the string .slice() method to remove the trailing comma and space characters.
Try this:
Using the length function to determine the position of the each
var fields = $('.wrap').find('.text');
var len = fields.length;
var data = '';
fields.each(function(index, element) {
var value = $(this).val();
if ( value != '' ) {
data += ' ' + value;
if (index != len - 1) {
data += ',';
}
}
});
alert(data);

Return Multiple CheckBox Values if Checked in jQuery

I have multiple checkbox in my page. i want to retrieve its values if checked.
Here is HTML Code..
<input name="ctl1189" type="checkbox" id="chkTicket_189310" class=" chkTicket" value="189310">
<input name="ctl1190" type="checkbox" id="chkTicket_189311" class=" chkTicket" value="189311">
And So on..
Javascript Code:
function updateTicketAction() {
var allUpdatedVendorTickets = $('.chkTicket').filter(function() { return this.value != $input.is(':unchecked'); });
var sFinalUpdateList = '';
allUpdatedVendorTickets.each(function() {
var ids = $(this).attr('id').split('_')[1];
sFinalUpdateList += ((sFinalUpdateList == '') ? '' : '|') + ids + ',' + $(this).val();
});
alert(sFinalUpdateList);
}
function updateTicketAction() {
var sFinalUpdateList = '';
$("input.chkTicket:checked").each(
function() {
var ids = $(this).attr('id').split('_');
var id = ids[1];
sFinalUpdateList += ((sFinalUpdateList == '') ? '' : '|') + id + ',' + $(this).val();
}
);
alert(sFinalUpdateList);
}
http://jquery-howto.blogspot.com/2008/12/how-to-check-if-checkbox-is-checked.html
I just created a fiddle. Look in the JavaScript console for the resulting object, which you can then further process.
Code:
var checkedCheckboxes = $('.chkTicket:checked'),
results = {};
checkedCheckboxes.each(function () {
var key = $(this).attr('id').split('_')[1];
results[key] = $(this).val();
});
function alertResults(results) {
var text = '', sep = '';
$.each(results, function (key, value) {
text += sep + key + '=' + value;
sep = '|';
});
alert(text);
}
alertResults(results);
console.log(results);
try this code
var collect='';
$('input:checked').each(function(i,e){
collect+=(collect===''? $(e).attr('name')+'='+$(e).val():','+$(e).attr('name')+'='+$(e).val());
alert(collect);
})
Here is a jsfiddle snippet that returns all checked inputs..
One question though, why do you split your id-attribute when you have your id stored in value-attribute? Anyways, hope this works for you!
function updateTicketAction() {
var allUpdatedVendorTickets = $('.chkTicket:checked');
var sFinalUpdateList = '';
allUpdatedVendorTickets.each(function () {
sFinalUpdateList += ((sFinalUpdateList == '') ? '' : '|') + $(this).val();
});
alert(sFinalUpdateList);
}
Or you can use map():
var el = $('input[type=checkbox]:checked').map(function(i,e){
var id = $(e).attr('id').replace('chkTicket_', '');
var val = $(e).val();
return {
'id' : id,
'value' : val
}
});
console.log(el[0].id);
Your filter function is wrong.
this.value != $input.is(':unchecked');
You're comparing a .value property (string) to the return value of the .is jQuery method (boolean). It's similar to:
'value' != !true //checked
'value' != !false //unchecked
Both will always return true - unless value is 0 or an empty string which evaluates to a falsy value and the right side of the expression evaluates to false, for which the != different operator will return false.
So, your filter's callback doesn't filter anything at all, except taking out checked boxes with value 0 or no value (which is unintentional).
You can avoid using a filter function by using the :checked selector:
var allUpdatedVendorTickets = $('.chkTicket:checked');
Now you'll have a jQuery object containing only the checked .chkTicket, much better.
Next thing, you're making bad use of strings.
"189310,189310|189311,189311"
That's what your function is generating. Every time you need to manipulate those results, you'll have to split the string at |, creating a new array. It's much better to store it as an array already.
var sFinalUpdateList = [];
Assuming your keys and values are always the same as in your example, you should store them only once as well.
allUpdatedVendorTickets.each(function() {
sFinalUpdateList.push(this.value);
});
This will generate a much more clean and maintainable array with only the checked boxes' values:
sFinalUpdateList =>
[0] -> "189310"
[1] -> "189311"
You can obtain their IDs by appending chkTicket_ to those values.
jsFiddle

Use "event's" output as a variable

I have a problem to manipulate checkbox values. The ‘change’ event on checkboxes returns an object, in my case:
{"val1":"member","val2":"book","val3":"journal","val4":"new_member","val5":"cds"}
The above object needed to be transformed in order the search engine to consume it like:
{ member,book,journal,new_member,cds}
I have done that with the below code block:
var formcheckbox = this.getFormcheckbox();
formcheckbox.on('change', function(checkbox, value){
var arr=[];
for (var i in value) {
arr.push(value[i])
};
var wrd = new Array(arr);
var joinwrd = wrd.join(",");
var filter = '{' + joinwrd + '}';
//console.log(filter);
//Ext.Msg.alert('Output', '{' + joinwrd + '}');
});
The problem is that I want to the “change” event’s output (“var filter” that is producing the: { member,book,journal,new_member,cds}) to use it elsewhere. I tried to make the whole event a variable (var output = “the change event”) but it doesn’t work.
Maybe it is a silly question but I am a newbie and I need a little help.
Thank you in advance,
Tom
Just pass filter to the function that will use it. You'd have to call it from inside the change handler anyway if you wanted something to happen:
formcheckbox.on('change', function(cb, value){
//...
var filter = "{" + arr.join(",") + "}";
useFilter(filter);
});
function useFilter(filter){
// use the `filter` var here
}
You could make filter a global variable and use it where ever you need it.
// global variable for the search filter
var filter = null;
var formcheckbox = this.getFormcheckbox();
formcheckbox.on('change', function(checkbox, value){
var arr = [],
i,
max;
// the order of the keys isn't guaranteed to be the same in a for(... in ...) loop
// if the order matters (as it looks like) better get them one by one by there names
for (i = 0, max = 5; i <= max; i++) {
arr.push(value["val" + i]);
}
// save the value in a global variable
filter = "{" + arr.join(",") + "}";
console.log(filter);
});

Categories