I want to loop over the elements of an HTML form, and store the values of the <input> fields in an object. The following code doesn't work, though:
function config() {
$("#frmMain").children().map(function() {
var child = $("this");
if (child.is(":checkbox"))
this[child.attr("name")] = child.attr("checked");
if (child.is(":radio, checked"))
this[child.attr("name")] = child.val();
if (child.is(":text"))
this[child.attr("name")] = child.val();
return null;
});
Neither does the following (inspired by jobscry's answer):
function config() {
$("#frmMain").children().each(function() {
var child = $("this");
alert(child.length);
if (child.is(":checkbox")) {
this[child.attr("name")] = child.attr("checked");
}
if (child.is(":radio, checked"))
this[child.attr("name")] = child.val();
if (child.is(":text"))
this[child.attr("name")] = child.val();
});
}
The alert always shows that child.length == 0. Manually selecting the elements works:
>>> $("#frmMain").children()
Object length=42
>>> $("#frmMain").children().filter(":checkbox")
Object length=3
Any hints on how to do the loop correctly?
don't think you need quotations on this:
var child = $("this");
try:
var child = $(this);
jQuery has an excellent function for looping through a set of elements: .each()
$('#formId').children().each(
function(){
//access to form element via $(this)
}
);
Depending on what you need each child for (if you're looking to post it somewhere via AJAX) you can just do...
$("#formID").serialize()
It creates a string for you with all of the values automatically.
As for looping through objects, you can also do this.
$.each($("input, select, textarea"), function(i,v) {
var theTag = v.tagName;
var theElement = $(v);
var theValue = theElement.val();
});
I have used the following before:
var my_form = $('#form-id');
var data = {};
$('input:not([type=checkbox]), input[type=checkbox]:selected, select, textarea', my_form).each(
function() {
var name = $(this).attr('name');
var val = $(this).val();
if (!data.hasOwnProperty(name)) {
data[name] = new Array;
}
data[name].push(val);
}
);
This is just written from memory, so might contain mistakes, but this should make an object called data that contains the values for all your inputs.
Note that you have to deal with checkboxes in a special way, to avoid getting the values of unchecked checkboxes. The same is probably true of radio inputs.
Also note using arrays for storing the values, as for one input name, you might have values from several inputs (checkboxes in particular).
if you want to use the each function, it should look like this:
$('#formId').children().each(
function(){
//access to form element via $(this)
}
);
Just switch out the closing curly bracket for a close paren. Thanks for pointing it out, jobscry, you saved me some time.
for me all these didn't work. What worked for me was something really simple:
$("#formID input[type=text]").each(function() {
alert($(this).val());
});
This is the simplest way to loop through a form accessing only the form elements. Inside the each function you can check and build whatever you want. When building objects note that you will want to declare it outside of the each function.
EDIT
JSFIDDLE
The below will work
$('form[name=formName]').find('input, textarea, select').each(function() {
alert($(this).attr('name'));
});
Related
I'm trying to create an array in Javascript with a size that is equivalent to the number of times a certain class is found in the DOM, and then iterate through it to grab the text from an input field present in that class. I can easily do this like so:
var count = 0;
$('.className').each(function() {
count++;
});
var classes = new Array(count);
count = 0;
$('.className input[type=text]').each(function() {
classes[count++] = $(this).val();
});
This looks like a lot of code for what seems to be a relatively simple task. Is there a more efficient or less lengthy way of doing this?
Thanks
It looks like you want this :
var classes = $('.className input[type=text]').map(function(){
return this.value
}).get();
But it's a guess : it's not clear why you start by counting all elements of the class and then iterate on the inputs.
You can construct an array of elements directly from your selector via the makeArray function, then transform the result using a map.
var classes = $.makeArray($('.className input[type=text]')).map(function() {
return $(this).val();
});
Use jQuery's map function, then get if you need a pure array:
var values = $('.className input[type=text]').map(function() {
return $(this).val();
}).get();
each passes the index, so you don't need to do it yourself:
var classes = [];
$('.className input[type=text]').each(function(index, value) {
classes[index] = $(this).val();
});
Arrays are dynamic and therefore don't need to be initialized. Create a new array, loop through the inputs and push the values to the new array:
var classes = [];
$('.className input[type=text]').each(function(idx, elem) {
classes.push($(elem).val());
});
I have some ajax onclick stuff that updates this line when the value is selected from the menu:
<li id="li_273" data-pricefield="special" data-pricevalue="0" >
The intention is to take the that value (data-pricevalue) and then multiple it by the amount that is entered from another input box. Here's my function to try to make that happen:
$('#main_body').delegate('#element_240','keyup', function(e){
var temp = $(this).attr("id").split('_');
var element_id = temp[1];
var price = $('#li_273').data("pricevalue");
var ordered = $(this).val();
var price_value = price * ordered;
price_value = parseFloat(price_value);
if(isNaN(price_value)){
price_value = 0;
}
$("#li_273").data("pricevalue",price_value);
calculate_total_payment();
});
Except I get the following error:
Uncaught TypeError: Cannot call method 'data' of null
It appears as tho my attempt to get the price value out of getElementById isn't correct. Any suggestions?
UPDATE: The code above has been edited from your suggestions and thanks to all. It appears to be working just fine now.
This part is wrong:
var price = document.getElementById('#li_273').data("pricevalue").val();
Instead, you should use jQuery all the way here:
var price = $('#li_273').data("pricevalue");
Btw, you shouldn't use .val() because .data() already returns a string. .val() is used exclusively for input elements such as <input> and <select> to name a few.
Update
Also, the rest of your code should be something like this:
var price_value = parseFloat(price);
if(isNaN(price_value)){
price_value = 0;
}
getElementById doesn't return a jQuery object it returns just a normal DOM object.
You can wrap any DOM object in a jQuery call to get it as a jQuery object:
$(document.getElementById("li_273")).data("pricevalue").val();
Or better yet just use jQuery
$("#li_273").data("pricevalue").val()
Your call should be document.getElementById('li_273') it's a normal method and doesn't require the hash as jQuery does.
EDIT As #kennypu points out you're then using jQuery on a non jQuery object. #Craig has the best solution.
document.getElementById('#li_273').data("pricevalue").val(); should be jQuery('#li_273').data("pricevalue").val();
Again the variable price_value is not present, I think you mean price.
Ex:
$('#main_body').delegate('#element_240','keyup mouseout change', function(e){
var temp = $(this).attr("id").split('_');
var element_id = temp[1];
var price = $('#li_273').data("pricevalue").val();
var ordered = $(this).val();
var price_value = parseFloat(price);
if(isNaN(price_value)){
price_value = 0;
}
$("#li_273").data("pricevalue",price_value);
calculate_total_payment();
});
The document.getElementById('#li_273') is the problem. The method won't recognize the hash. If you want to get the element ID using that method try document.getElementById('li_273') and it will work.
Otherwise use all jQuery.
Since you're using jQuery, why are you using document.getElementById instead of $(...)? It should be:
$('#li_273').data("pricevalue")
Note also that the data() method is only defined on jQuery objects, not DOM elements. And you don't need to call val() after it -- that's for getting the value of form elements.
Your getElementById is wrong with javascript you do not need the #, if your using jQuery do it like this instead (Also I removed the .val() because its not needed):
$('#main_body').delegate('#element_240','keyup mouseout change', function(e){
var temp = $(this).attr("id").split('_');
var element_id = temp[1];
var price = $('#li_273').data("pricevalue");
var ordered = $(this).val();
price_value = parseFloat(price_value);
if(isNaN(price_value)){
price_value = 0;
}
$("#li_273").data("pricevalue",price_value);
calculate_total_payment();
});
I have some list elements with dynamically id changing. Next i give this id's to other element, as a class one by one. So, this is my code:
$('#rounded_items li').one({click: function(){
$('#back_button').addClass(this.id);
}});
and #back_button receives classes 1, 2, 3, 4 from #rounded_items li. How can i grab the last class from back_button and give it to #rounded_items by click.
Is there any possible to give back the last class from element who receives this class?
maybe you can store it as data
$('#rounded_items li').one('click', function(){
var classes = $('#back_button').attr('class').split(/\s+/);
var last = classes[classes.length-1];
$.data($('#back_button')[0],'lastclass',last);
$('#back_button').addClass(this.id);
});
$('#back_button').click(function(){
var lastclass = $.data($('#back_button')[0],'lastclass');
$('#rounded_items').addClass(lastclass);
var classes = $('#back_button').attr('class').split(/\s+/);
$.data($('#back_button')[0],'lastclass',classes[classes.length-3]);
$('#back_button').removeClass(classes[classes.length-1]);
});
you can also try this:
$('#back_button').click(function(){
var classes = $('#back_button').attr('class').split(/\s+/);
$('#rounded_items').addClass(classes[classes.length-2]);
$('#back_button').removeClass(classes[classes.length-1]);
});
Use an array to store the ids, not a class attribute!
var stack = [];
$('#rounded_items li').one('click',function(){
stack.push(this.id);
});
$('#back_button').click(function(){
$('#rounded_items').setClass(stack.pop());
});
I'm assuming that your classes aren't really being used to style anything, as they're not legal CSS identifiers. If the intent is just to store some state, use .data:
var $back = $('#back_button');
$back.data('state', []); // empty array to store state
$('#rounded_items li').one({click: function() {
$back.data('state').push(this); // store clicked element
});
$back.on('click', function() {
var elem = $back.date('state').pop(); // retrieve last clicked element
if (elem) {
// do something with elem...
}
});
If the code is all in the same lexical scope you can just use a local array to store the state without using .data().
I have many jquery click function, they are very similar, how to combine them for shorter code. (use regex or use array foreach?)
$(".menu").live('click', function() {
var value = $(this).html();
$('#menu').html(value);
});
$(".nav").live('click', function() {
var value = $(this).html();
$('#nav').html(value);
});
$(".list").live('click', function() {
var value = $(this).html();
$('#list').html(value);
});
This should do:
var elems = ["menu", "nav", "list"];
$.each(elems, function(i, elem){
$("."+elem).live('click',function(){
var value = $(this).html();
$('#'+elem).html(value);
});
});
Create a list of elements.
Loop through it using $.each
The second argument of the function equals the element in the list (menu, nav, ..)
Rob's answer is definitely vote-up-worthy, but I just wanted to say that sometimes you want to limit the arbitrary connections between two elements. Why should element X have a class that MUST be the same name as element Y's ID? It's pretty arbitrary and can be a hassle for people to later figure out.
You can instead approach it like this to make it more robust:
alice
bob
sue
Now your JS becomes super straight-forward and easy:
$(".foo").live('click',function(){
var value = $(this).html();
var yourDataAttr= $(this).data('yourDataAttr');
$('#' + yourDataAttr).html(value);
});
I am using jQuery Serialize to serialize my form elements and would like to deserialize them back. Unfortunately can't find any working jQuery deserializer, any suggestions?
I wrote a version of jQuery.deserialize that supports serialized data generated from the serialize, serializeArray and serializeObject functions. It also supports all form element types, including checkboxes and radio buttons.
Try this:
function deparam(query) {
var pairs, i, keyValuePair, key, value, map = {};
// remove leading question mark if its there
if (query.slice(0, 1) === '?') {
query = query.slice(1);
}
if (query !== '') {
pairs = query.split('&');
for (i = 0; i < pairs.length; i += 1) {
keyValuePair = pairs[i].split('=');
key = decodeURIComponent(keyValuePair[0]);
value = (keyValuePair.length > 1) ? decodeURIComponent(keyValuePair[1]) : undefined;
map[key] = value;
}
}
return map;
}
I was very interested in trying JQuery.deserialize, but it didn't seem to handle checkboxes at all, so it didn't serve my purposes. So I wrote my own. It turned out to be easier than I thought, because the jQuery val() function does most of the work:
jQuery.fn.deserialize = function (data) {
var f = this,
map = {},
find = function (selector) { return f.is("form") ? f.find(selector) : f.filter(selector); };
//Get map of values
jQuery.each(data.split("&"), function () {
var nv = this.split("="),
n = decodeURIComponent(nv[0]),
v = nv.length > 1 ? decodeURIComponent(nv[1]) : null;
if (!(n in map)) {
map[n] = [];
}
map[n].push(v);
})
//Set values for all form elements in the data
jQuery.each(map, function (n, v) {
find("[name='" + n + "']").val(v);
})
//Clear all form elements not in form data
find("input:text,select,textarea").each(function () {
if (!(jQuery(this).attr("name") in map)) {
jQuery(this).val("");
}
})
find("input:checkbox:checked,input:radio:checked").each(function () {
if (!(jQuery(this).attr("name") in map)) {
this.checked = false;
}
})
return this;
};
You should be able to use this like this:
$("#myform").deserialize(data);
Where data is a parameter list such as what $("#myform").serialize() would produce.
It affects all fields in the form, and it will clear the values of fields that are not contained in the data. But you can also pass any selector to affect only specific fields, as you can with the serialize function. E.g.:
$("select").deserialize(data);
Half of jQuery Serialize is param(), so half of something that deserializes a query string is going to be a deparam. Unfortunately I haven't been able to find a good standalone deparam. For now I recommend getting the jQuery BBQ library and using that. If you don't need the other stuff you can remove them. I read somewhere that Ben Alman (cowboy) planned to extract deparam into its own module.
For the rest of deserializing, you'll just need to loop through the object that deparam returns and for each key and value pair in the object, select the form element based on the key, and set the form elements value to the value.
Bit late on this one, but somebody might find this useful.
function fetchInput(identifier) {
var form_data = identifier.serialize().split('&');
var input = {};
$.each(form_data, function(key, value) {
var data = value.split('=');
input[data[0]] = decodeURIComponent(data[1]);
});
return input;
}
I'm not now answering your question but my guess is that you want to serialize it and send back to server and then use the serialized data which is why you have to deserialize it?
If that's the case you should consider using .serializeArray(). You can send it as POST data in ajax, and then access later as well because you will have object.
May be a bit late, but perhaps you are looking for something like JQuery.deserialize. Problems: no support for checkboxes or radio buttons.
Using Jack Allan's deparam function with jQuery, you can change this line:
map[key] = value;
to
$('input[name=' + key + ']').val(value);
Which will load the data back into your form fields.
this code returns an array when same key is spotted multiple times in the serialized string
chaine="single=Single1&multiple=Multiple&multiple=Multiple1&multiple=Multiple2&multiple=Multiple3&check=check2&radio=radio1"
function deserialize(txt){
myjson={}
tabparams=chaine.split('&')
var i=-1;
while (tabparams[++i]){
tabitems=tabparams[i].split('=')
if( myjson[decodeURIComponent(tabitems[0])] !== undefined ){
if( myjson[decodeURIComponent(tabitems[0])] instanceof Array ){
myjson[decodeURIComponent(tabitems[0])].push(decodeURIComponent(tabitems[1]))
}
else{
myjson[decodeURIComponent(tabitems[0])]= [myjson[decodeURIComponent(tabitems[0])],decodeURIComponent(tabitems[1])]
}
}
else{
myjson[decodeURIComponent(tabitems[0])]=decodeURIComponent(tabitems[1]);
}
}
return myjson;
}
Needed all in a single string, which can be stored in maybe COOKIE, and later read and fill the same form with input values.
Input elements seperator: ~ (use any seperator)
Input attributes seperator: | (use any seperator)
input type | input name | input value ~ input2 type | input2 name | input2 value
var formData = '';
$('#form_id').find('input, textarea, select').each(function(i, field) {
formData += field.type+'|'+field.name+'|'+field.value+'~';
});
Example:
hidden|vote_id|10~radio|option_id|~radio|option_id|427~radio|option_id|428~
If what you want is to remove the standard URL-encoded notation, you can use JavaScript's decodeURIComponent(), which will give you a regular string, just like this:
var decodedString = decodeURIComponent("Http%3A%2F%2FHello%3AWorld");
alert(decodedString);
In this case, decodedString will look like Http://Hello:World, here's a working fiddle.
Got all of this searching for this same issue, and found the answer here: How can I decode a URL with jQuery?
I know this is an old question, but doing some searches for jQuery deserialize got me here, so I might as well try to give a different approach on the issue for people with the same problem.