I'm looking for a really generic way to "fill out" a form based on a parameter string using javascript.
for example, if i have this form:
<form id="someform">
<select name="option1">
<option value="1">1</option>
<option value="2">2</option>
</select>
<select name="option2">
<option value="1">1</option>
<option value="2">2</option>
</select>
</form>
I'd like to be able to take a param string like this: option1=2&option2=1
And then have the correct things selected based on the options in the query string.
I have a sort of ugly solution where I go through children of the form and check if they match the various keys, then set the values, but I really don't like it.
I'd like a cleaner, generic way of doing it that would work for any form (assuming the param string had all the right keys).
I'm using the prototype javascript library, so I'd welcome suggestions that take advantage of it.
EDIT: this is what I've come up with so far (using prototype for Form.getElements(form))
function setFormOptions(formId, params) {
params = params.split('&');
params.each(function(pair) {
pair = pair.split('=');
var key = pair[0];
var val = pair[1];
Form.getElements(form).each(function(element) {
if(element.name == key) {
element.value = val;
}
});
});
}
I feel that it could still be faster/cleaner however.
If you're using Prototype, this is easy. First, you can use the toQueryParams method on the String object to get a Javascript object with name/value pairs for each parameter.
Second, you can use the Form.Elements.setValue method (doesn't seem to be documented) to translate each query string value to an actual form input state (e.g. check a checkbox when the query string value is "on"). Using the name.value=value technique only works for text and select (one, not many) inputs. Using the Prototype method adds support for checkbox and select (multiple) inputs.
As for a simple function to populate what you have, this works well and it isn't complicated.
function populateForm(queryString) {
var params = queryString.toQueryParams();
Object.keys(params).each(function(key) {
Form.Element.setValue($("someform")[key], params[key]);
});
}
This uses the Object.keys and the each methods to iterate over each query string parameter and set the matching form input (using the input name attribute) to the matching value in the query params object.
Edit: Note that you do not need to have id attributes on your form elements for this solution to work.
Try this:
Event.observe(window, 'load', function() {
var loc = window.location.search.substr(1).split('&');
loc.each(function(param) {
param = param.split('=');
key = param[0];
val = param[1];
$(key).value = val;
});
});
The above code assumes that you assign id values as well as names to each form element. It takes parameters in the form:
?key=value&key=value
or
?option1=1&option2=2
If you want to keep it at just names for the elements, then try instead of the above:
Event.observe(window, 'load', function() {
var loc = window.location.search.substr(1).split('&');
loc.each(function(param) {
param = param.split('=');
key = param[0].split('_');
type = key[0];
key = key[1];
val = param[1];
$$(type + '[name="' + key + '"]').each(function(ele) {
ele.value = val;
});
});
This code takes parameters in the form of:
?type_key=value&type_key=value
or
?select_option1=1&select_option2=2
You said you're already going through the elements and setting the values. However, maybe this is cleaner that what you have?
function setFormSelectValues(form, dataset) {
var sel = form.getElementsByTagName("select");
dataset.replace(/([^=&]+)=([^&]*)/g, function(match, name, value){
for (var i = 0; i < sel.length; ++i) {
if (sel[i].name == name) {
sel[i].value = value;
}
}
});
}
You could then adapt that to more than just select elements if needed.
Three lines of code in prototype.js:
$H(query.toQueryParams()).each(function(pair) {
$("form")[pair.key].setValue(pair.value);
});
You can get form data in JavaScript object using formManager .
Related
I have 2 select boxes, with the second showing a subset of all options based on the category in the first box. The second box contains ids and names, where the option value equals the id. I already filtered out the id's I am interested in and have them in an array. This will change each time and can be different sizes (filtering all users by groups). What I would like to do is take a clone of the complete options and then only show those whos id (or value) is present. So, compare the array of filtered values to the complete set. I did see a couple ways to remove options, but most were for only one value at a time or for fixed values, so it didn't exactly fit what I need and I can't figure out how to do this last step! Looks like the following:
<select id = 'doctor_select' >
<option value = '1' > John Doe </option>
<option value = '2' > Jane Doe </option>
.... etc
edit: solved for now by hiding all and doing a for each loop to enable the ones I need.
I wouldn't do it like this, but you could clone the original combo and simply remove the unnecessary options from the DOM. Something like:
var newDoctorSelect=$("#doctor_select").clone();
$(newDoctorSelect).children("option").each(function() {
if(some condition) $(this).remove();
});
$("#somewhere").append(newDoctorSelect);
But I'd recommend either using AJAX or storing the options in an object and populating the select when needed.
var optionsByCategory={
"1":{"1":"One","3":"Three"},
"2":{"2":"Two"}
};
$("#categorySelect").on("change",function() {
var options=optionsByCategory[$(this).val()];
//OR some AJAX call to retreive the options from the server instead
$("#doctor_select option").remove();
for(var k in options) $("#doctor_select").append($("<option>").val(k).text(options[k]));
});
You could do this:
var options = getElementsByTagName("option"),
elem,
length = options.length;
for (var i = 0; i<length; i++) {
if (!((elem = options[i]).value === IDYouWantToMatch)); elem.parentNode.removeChild(elem);
}
I think you want something like the following using filter()
var $sel = $('#doctor_select'),
$opts = $sel.children();
var $filteredOpts = $opts.clone().filter(function(){
return someArray.indexOf(this.value)>-1;
})
$sel.empty().append($filteredOpts);
The stored $opts can now be re-used for future changes
I would like to get the values of dynamically created hidden fields with a class reference.
Example of created hidden field
<input class="SelectedClaimants" id="CodesList_2__Claimant" name="CodesList[2].Claimant" type="hidden" value="Jason Statham">
This is something along the lines of what i have tried.
$('.listSelected').on('DOMSubtreeModified', function (event) {
$(".SelectedClaimants").find('input[type=hidden]').each(function () {
var testC += $(this).val();
});
});
I was aiming to have them create into an array object, but at the moment i am happy just to get the values out into a concatenated string.
Try this (the result is logged to the console). It's based onn Tushar's answer, but the selector was wrong.
$('input[type="hidden"].SelectedClaimants').map(function () {
return $(this).val();
}).get().join(',')
You can use .querySelectorAll(), spread element, for..of loop. Note, id, e.g., CodesList_2__Claimant should be unique in document.
var testC = [];
for (let el of [...document.querySelectorAll("input[type='hidden'].SelectedClaimants")]) {
testC.push(el.value)
}
So I've been trying this for a while but no luck so far. What I want to achieve is, after selecting a value from the drop down, that value should be compared with the json multi-dimensional array. If it matches, then there are certain html elements on the webpage whose content needs to be replaced with the corresponding json values.
Here is the what I've been working so far (link)
<select onchange="executeMe(this)" id="selectOpt">
<option value="445">Choose...</option>
<option value="445">Daisy</option>
<option value="446">Romeo</option>
</select>
<br/><br/><br/>
<label id="entity_id">replaceThis</label>
So in the fiddle, if the user chooses "Daisy" from the dropdown, (the first array has Daisy in it) the corresponding value set from the array should be displayed in each of the html element on the webpage.
I can use only javascript for this. Thanks in advance guys...
You've got problems. First, your string you get back from your map function is massive and certainly won't pass an equality check with your option value. Additionally, your anonymous function is going to return the first value and not iterate through your for loop properly. There's no correlation between your select option values/labels and the items in the array. Try this:
function executeMe(select) {
var myselect = document.getElementById("selectOpt");
var selectOption = myselect.options[myselect.selectedIndex].innerHTML;
var i = theArray.length, obj, index, val;
while (i--) {
obj = theArray[i];
for (index in obj) {
val = obj[index];
//following matches on both keys and values, if you only
//want values delete the second part of the check
if (val == selectOption || index == selectOption) {
var string = '', prop;
for (prop in obj) {
string += prop + ': ' + obj[prop].toString() + '<br>';
}
document.getElementById('entity_id').innerHTML = string;
}
}
}
}
If this isn't what you need let me know with a comment.
So I'm trying to populate a dropdown with the states, the value for the option should be the two characters value, and the text for the option should be the full state's name, using the code below is returning a value of 0,1,2,3... and returning all the options in the var as the text.
var states = ["Select State","","Alabama","AL","Alaska","AK","Arizona","AZ","Arkansas","AR",...];
$.each(states, function(val, text) {
$('#selector').append( $('<option> </option>').val(val).html(text) )
});
Try this, using an object for states instead of an array. Same results, but it's more clear what's what and you're less likely to have problems if you accidentally skip a name or abbreviation:
var states = {
"Select State":"",
"Alabama":"AL",
"Alaska":"AK",
"Arizona":"AZ",
"Arkansas":"AR"
};
var val, text;
for (text in states) {
val = states[text];
$('<option/>').val(val).text(text).appendTo($('#selector'));
};
http://jsfiddle.net/g59U4/
The problem is that the callback function provided to .each results in val containing the index of the current iteration (e.g. 0, 1, 2 etc.) and text containing the value of that index of the array.
To achieve what you are trying to, you would probably be better off with a normal for loop:
for(var i = 0; i < states.length; i+=2) {
$("#selector").append($('<option> </option>').val(states[i+1]).html(states[i]));
}
You would be even better off caching the jQuery object containing #selector outside of your loop, so it doesn't have to look it up every iteration.
Here's a working example of the above.
Another option would be to use an object instead of an array, using the state name or abbreviation as the keys, and the other as the values. Edit: just like #mblase75 has done
Well you have the jQuery.each function arguments confused. The first is the index of the value in the array, and the second in the value itself. What you need to do is something like:
$.each(states, function(index) {
if(index%2 > 0) {
//continue, basically skip every other one. Although there is probably a better way to do this
return true;
}
$('#selector').append( $('<option> </option>').val(states[index+1]).html(states[index]) )
});
That would be really straightforward if your array had two dimensions. Considering you really need to use the one-dimensional array you presented, you could do this:
var states = ["Select State","","Alabama","AL","Alaska","AK","Arizona","AZ","Arkansas","AR"];
for(var i=1; i<states.length; i+=2) {
$('#selector').append( $('<option value="' + states[i] + '">' + states[i-1] + '</option>').val(val).html(text) )
}
If you changed your array to be an array of objects, you could do something like this -
var states = [{"text":"Select State","val":""},{"text":"Alabama","val":"AL"}]; //etc
$.each(states, function(val, statedata) {
$('#selector').append( $('<option> </option>').val(statedata.val).html(statedata.text) )
});
This change passes a JavaScript object in to the callback each time. The object has text and val properties and is passed in to the callback as the statedata parameter. The val parameter holds the current index position of the array so it is not required to populate the select box.
Demo - http://jsfiddle.net/sR35r/
I have a similar situation populating a select list with a two-dimensional array as the result of an $.ajax callback ....
JSON ...
[["AL","Alabama"],["AK","Alaska"],["AS","American Samoa"],["AZ","Arizona"] ...
var stateOptions = $('#state');
var html ='';
for (var i =1; i<data.length; i++){
html+= '<option value="' +data[i][0]+ '">' +data[i][1]+ '</option>';
}
stateOptions.append(html);
<form name="form" id="form">
<select name="state" id="state">
<option value=''>State</option>
</select>
</form>
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Convert form data to JS object with jQuery
Here is my problem, I have a whole bunch of elements that look like this...
<input type="email" id="email" data-item="email" data-key="contact_details"/>
<input type="tel" id="mobileNo" data-item="mobileNo" data-key="contact_details"/>
<input type="text" id="sleeve_length" data-item="sleeve_length" data-key="measurements"/>
<input type="text" id="inseam" data-item="inseam" data-key="measurements"/>
Each element has a 'data-key' and 'data-item' which corresponds to the json form i'm trying to turn them into, which will look something like this...
{
"measurements" : {"sleeve_length" : value, "inseam" : value},
When each data-item is unique... and like this when it isn't...
"contact_details" : [
{"email" : value, "mobileNo" : value},
{"email" : value, "mobileNo" : value}
]
}
Now because my web app involves many forms, I need a way to dynamically transform the markup above into these json strings... but I can't seem to wrap my head around it!
Does anyone have any idea how I can approach this?
Something like so:
var json = {};
$('#path .to input').each(function(e) {
var key = $(this).attr('data-key');
var param = $(this).attr('data-item');
var obj = {};
obj[param] = $(this).val();
// If we already have a record...
if(key in json) {
// If it's not an array, make it an array
if(typeof(json[key].push) != 'function')
json[key] = [ json[key] ];
// Toss it on the pile
json[key].push(obj);
} else {
// There's only 1 thus far, keep it k/v
json[key] = obj;
}
});
etc. Fairly basic, the key points just being testing whether or not the key you're working with exists or not, and if so, converting it to an array.
Edit: this is untested, but it should work.
Edit 2: revised code so your hash key vars don't come across as strings.
You could let some JS MVC / MVVC library do this for you. For example, Knockout. I haven't used it myself yet, but from a glance it seems neat. You define mapping between your JSON object and HTML form fields, and the library would monitor form fields and update the JSON object (a "view model").
Something like:
var myJson = {};
// jQuery
$('input').each(function () {
myJson[$(this).attr('data-key')][$(this).attr('data-value')] = $(this).val();
});
// Native JS
var els = document.getElementsByTagName('input');
for (var i = 0, l = els.length; i < l; i += 1) {
myJson[els[i]['data-key']][els[i]['data-value']] = els[i].value;
}
Should do the trick. It loops through all of the input elements on the page and puts the data found in each element into an object with the key data-key and sets that equal to an object with the key data-value and the value the value of the input element.
Helpful?
Edit: Is that better? I don't know what I was thinking.