I have an HTML form that adds parameters to an URL. I only want the extra parameter added if a certain option is selected in the same form. So let's say I want to add the parameter "addedParameter=1" to the URL if "Commercial" is selected, otherwise I don't want the parameter to appear at all (other wise I get no results for "House" and "Land") Please let me know what I can do.
<select id="pt" value="pt" name="pt" onChange="addParameter()">
<option value="" name="">Select</option>
<option value="1" name="1">House</option>
<option value="2" name="2">Commercial</option>
<option value="3" name="3">Land</option>
</select>
<input type="hidden" id="add" name="" value="1">
function addParameter(){
if(pt.selectedIndex == 1)
document.getElementById("add").name = "addedParameter";
}
I'd suggest that, rather than adding/removing the element based on a condition you should, instead, make use of the disabled attribute (only non-disabled elements are considered 'successful' and, therefore only non-disabled elements will have their names/values submitted):
function addParameter () {
var sel = document.getElementById('pt'),
input = document.getElementById('add');
input.disabled = sel.selectedIndex != 2;
}
document.getElementById('pt').onchange = addParameter;
JS Fiddle demo.
Note, in the demo I've removed the type="hidden" attribute-value, in order to visibly demonstrate the effect, but that's not required for this approach to work. Also, the conditional input has the disabled="disabled" attribute set by default (so if the form is submitted prior to this select being affected by the user it'll still not be accidentally submitted).
You could do it clearer by using jQuery. When html definitions are not enough, I prefer to create and delete the (input) nodes all by dynamic javascript. The two ways you are discussing (changing by select event or by adding a submit event handler) also works with that :
function addParameter() {
if ($('#pt').val() == "2") $('<input/>', { id: 'id_optionalParam', name: 'optionalParam', value: '1234', type: 'hidden' }).appendTo('#TheForm');
else $('#id_optionalParam').remove();
}
<input type="hidden" id="add" name="addedParameter" value="1">
function addParameter(){
if(pt.selectedIndex != 1)
input = document.getElementById("add")
parent = input.parentNode
parent.removeChild(input)
}
This will remove the input when the additionalParameter is not set, otherwise it won't get changed.
Edit: alternative solution:
function addParameter(){
if(pt.selectedIndex == 1) {
document.getElementById("add").name = "addedParameter";
} else {
document.getElementById("add").name = "";
}
}
Also see the docs for removeChild
I think that the best approach in this situation is to attach an event handler to the submit event of the form. Do what you need and then submit the form. Adding the input in the html and removing it after that is not so flexible.
<script>
window.onload = function() {
var form = document.getElementById("theform"),
select = document.getElementById("pt");
form.addEventListener("submit", function(event) {
event.preventDefault();
if(select.value == 2) {
var element = document.createElement("INPUT");
element.setAttribute("type", "hidden");
element.setAttribute("name", "addedParameter");
element.setAttribute("value", "1");
form.appendChild(element);
}
form.submit();
});
}
</script>
<form method="get" id="theform">
<select id="pt" value="pt" name="pt" onChange="addParameter()">
<option value="" name="">Select</option>
<option value="1" name="1">House</option>
<option value="2" name="2">Commercial</option>
<option value="3" name="3">Land</option>
</select>
<input type="submit" />
</form>
You can add extra parameter by adding an extra fidden field fo the form when needed option is selected, and remove it otherwise:
function addParameter(){
var addedParameterField = document.getElementById("addedParameter");
if (pt.selectedIndex != 1) {
if (addedParameterField) {
addedParameterField.parentNode.removeChild(addedParameterField);
}
} else {
if (!addedParameterField) {
var addedParameterField = document.createElement("input");
addedParameterField.type = "hidden";
addedParameterField.name = "addedParameter";
addedParameterField.value = "1";
container = document.getElementById('myform');
container.appendChild(addedParameterField);
}
}
}
Related
I have a form which has multiple parts of it which change based on user input. Some fields are required in certain cases but not in others and there is JS which hides and shows the appropriate fields.
I am aware of the checkValidity() function which can be called on a form object to check if the HTML5 validation passes (attributes like required, pattern, etc.).
But my form is too complex for that and checkValidity() for the form may indicate that my form is invalid but I have intentionally hidden that field from the user based on, e.g. an option chosen in a select box.
Is there something similar to checkValidity() for an individual field? Or is there another elegant solution to this problem?
EDIT: Here's a working example that demonstrates the issue https://jsfiddle.net/w5ycvtsm/
HTML:
<form id="mainform">
<select id="opts" name="opts">
<option value="A">A</option>
<option value="B">B</option>
<option value="C">C</option>
<option value="_other">Other</option>
</select>
<br/>
<input type="text" id="opt_other" name="opt_other" required>
<br/>
<input type="submit"/>
</form>
JS:
function fixOptsState() {
var v = document.getElementById('opts').value;
var otherEl = document.getElementById('opt_other');
if (v == "_other") {
otherEl.style.display = 'block';
} else {
otherEl.style.display = 'none';
}
}
document.getElementById('opts').addEventListener('change', fixOptsState);
fixOptsState();
document.getElementById('mainform').addEventListener('submit', function(e) {
e.preventDefault();
var mainform = document.getElementById('mainform');
console.log(mainform.checkValidity());
});
checkValidity() actually gives an error in Chrome, saying
An invalid form control with name='opt_other' is not focusable.
You can use checkValidity function to validate the html5 field as soon as it loose focus. so that it will not validate hidden input field.
$('input').blur(function(event) {
event.target.checkValidity();
}).bind('invalid', function(event) {
setTimeout(function() { $(event.target).focus();}, 50);
});
How about creating and destroying the input dynamically?
function fixOptsState() {
var v = document.getElementById('opts').value;
var otherEl = document.createElement('input');
otherEl.id="opt_other";
otherEl.setAttribute("required","");
if (v == "_other") {
document.getElementById('mainform').insertBefore(otherEl,document.querySelector('input[type=submit]'));
} else {
document.getElementById('opt_other')!=undefined?document.getElementById('mainform').removeChild(document.getElementById('opt_other')):void(0);
}
}
document.getElementById('opts').addEventListener('change', fixOptsState);
fixOptsState();
document.getElementById('mainform').addEventListener('submit', function(e) {
e.preventDefault();
var mainform = document.getElementById('mainform');
console.log(mainform.checkValidity());
});
<form id="mainform">
<select id="opts" name="opts">
<option value="A">A</option>
<option value="B">B</option>
<option value="C">C</option>
<option value="_other">Other</option>
</select>
<br/>
<input type="text" id="opt_other" name="opt_other" required>
<br/>
<input type="submit"/>
</form>
Javascript does enable you to read the input in a single textbox in the form. Just grab it by giving it a unique ID in HTML5 and validate on key update. Then make whatever many functions needed to test all textboxes individually with its own parameters and complexity.
This works great for me, it is an improvement on Sagar V's. In my case, you don't need to append the form to the body, much cleaner.
function checkInput(el) {
// Clone Input
const clone = el.cloneNode(true);
// Create Temp From
const tempForm = document.createElement('form');
tempForm.appendChild(clone);
// Check Form
console.log('Validity = ' + tempForm.checkValidity());
}
const requiredInputs = querySelectorAll('input[required]');
// or whatever selector applies to your case
requiredInputs.forEach(el => {
el.addEventListener('change', () => { checkInput(el) });
});
I think you can validate using the following method.
Refer to a link to find more Validity Properties
if (!$("#your_id")[0].validity.valid)
// display your message label
$('#InvalidPhoneNumber').text('Invalid phone number');
You can use the following function to validate single and form both.
Notes: you need to update according to your requirement.
function formValidation(
event,
form_id,
list_of_elements = []
) {
var form = $(`#${form_id}`);
if (event != undefined) {
event.preventDefault();
event.stopPropagation();
}
if (list_of_elements.length > 0) {
list_of_elements.forEach(id => {
var ele = $("#"+id)[0];
if (!ele.validity.valid) {
//display error messages
ele.next().text('error message');
}
});
return false;
}
if (form[0].checkValidity() == false) {
form.addClass('was-validated');
return false;
}
return true;
}
I have datalist like below -
<input id="name" list="allNames" />
<datalist id="allNames">
<option value="Adnan1"/>
<option value="Faizan2"/>
</datalist>
What I want is, when an item is typed in completely(for example say in input box when user completely type "Adnan1") or selected from list, then I want an event. I tried couple of approaches but both doesn't help me so far. Approaches are -
$("#name").change(function(){
console.log("change");
}
problem with this is, the event only gets triggered when input gets out of focus I.e. when I click somewhere in the screen.
I also tried
$("#name").bind('change', function () {
console.log('changed');
});
but the callback gets triggered each time when I type in. I actually need to make an AJAX call when item is completely selected. Either via type-in or by selecting from dropdown.
First approach is bad for user perspective because he has to make extra click and second has disadvantage as for every letter an event will be triggered.
All I want is an event when either user made a selection or typed complete sentence. is there a way to achieve this? any event that I missing and that can solve my problem.
On modern browsers, you can use input event, e.g:
$("#name").on('input', function () {
var val = this.value;
if($('#allNames option').filter(function(){
return this.value.toUpperCase() === val.toUpperCase();
}).length) {
//send ajax request
alert(this.value);
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<input id="name" list="allNames" />
<datalist id="allNames">
<option value="Adnan1" />
<option value="Faizan2" />
</datalist>
PS: as input event has better support than datalist element, there is indeed no reason to not use it if you are already using datalist element.
You can use input event for achieving such functionality, as below :
$(document).ready(function() {
$('#name').on('input', function() {
var userText = $(this).val();
$("#allNames").find("option").each(function() {
if ($(this).val() == userText) {
alert("Make Ajax call here.");
}
})
})
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id="name" list="allNames" />
<datalist id="allNames">
<option value="Adnan1" />
<option value="Faizan2" />
</datalist>
Simple solution
document.getElementById('name').addEventListener('input', function () {
console.log('changed');
});
Hacky as a sin, but works for me. (Note that if you are typing 'Rum-Cola' it doesn't stop on the 'Rum' option)
const opts = $("option").map(function(){return this.value;}).get();
$("#favourite-drink").on("keydown", function(e){
if(e.key){ // in case of mouse event e.key is 'undefined'
if (e.key === "Enter") { // looks like user wants to confirm the choice
if(opts.indexOf(this.value) >= 0){
this.blur();
console.log("Selected: " + this.value);
}
}
else {
this.setAttribute("data-keyboardinput", "true"); // remember that it's keyboard event
setTimeout(function(){ //and keep it in memory for 100ms
this.removeAttribute("data-keyboardinput")
}.bind(this), 100);
}
}
});
$("#favourite-drink").on("input", function(){
if(!this.dataset.keyboardinput && opts.indexOf(this.value) >= 0){ // if it's not a key press followed event
console.log("Selected: " + this.value);
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<p>Choose a drink:</p>
<input id="favourite-drink" list="drinks">
<datalist id="drinks">
<option value="Rum"></option>
<option value="Rum-Cola"></option>
<option value="Vodka"></option>
</datalist>
Check if this works for you :
var dataList=[];
$("#allNames").find("option").each(function(){dataList.push($(this).val())})
console.log(dataList);
$("#name").on("keyup focus blur change",function(){
if(dataList.indexOf($(this).val())!=-1)
console.log("change");
})
I pushed datalist options into array , and on change event keyup , blur or focus , i check if input value exists in my datalist array.
In addition to what was said above, we can also check the inputType of the input which must correspond to "insertReplacementText"
function textThatComesFromADatalist (event){
const inputType = event.inputType;
const isReplacingText = (typeof inputType === "undefined")
|| (inputType === "insertReplacementText");
return isReplacingText;
}
function onInput(event) {
if(textThatComesFromADatalist(event)){
alert('selected: '+event.target.value);
}
}
<input oninput="onInput(event)" list="ice-cream-flavors" id="ice-cream-choice" name="ice-cream-choice" />
<datalist id="ice-cream-flavors">
<option value="Chocolate">
<option value="Coconut">
<option value="Mint">
<option value="Strawberry">
<option value="Vanilla">
</datalist>
Simple solution is that check the input text value exist in datalist or not, and if it does, run an ajax request.
$("#input_form").on('input', function(event){
if ($("#input_datalist option[value='" + $('#input_form').val() + "']").val() != undefined) {
//send ajax request
}
});
If a user selects a certain option value in one select field, how do you then make a text field hidden, s it will not be needed. This must be done before the form is submitted?
For example in the following select field, a user select chooses value='a' then how would this text field become hidden:
<select name="form" id="aForm">
<option value="a">choice1</option>
<option value="b">choice2</option>
<option value="c">choice3</option>
</select>
<input type="text" style="width:285px" name="textField" id="textField"/>
$("#aForm").on("change", function() {
if ($(this).val() == "a")
$("#textField").hide();
else
$("#textField").show();
});
Here is also a jsfiddle
I assumed that you will show the textfield for any other value than a.
If you're using plain JavaScript and not jQuery
function hideTF() {
var s = document.getElementById("aForm");
document.getElementById("textField").style.display
= (s.selectedIndex > 0 && s.options[s.selectedIndex] == 'a'
? "none" : "block");
}
var s = document.getElementById("aForm");
if (s.attachEvent)
s.attachEvent("onchange", hideTF);
else
s.addEventListener("change", hideTF, false);
You can use a variation of this:
var selection = aForm.selectedIndex,
field = document.getElementById('textField');
if ( selection === x ) {
field.style.display = "block"; // or visibility = "hidden"
}
This should be enclosed in an .onchange event. aForm.selectedIndex is the index of the corresponding <option> element that is selected.
I want to create a dynamic alert from a specific input value within each form. I have many forms on a page. Each alert needs to be slighly different. I am using two of the forms input values to produce the custom message. <input type="hidden" name="on0" value="Size"> & <input type="hidden" name="on1" value="Color">. I have the alert working for the first form on the page, but after the second form, my alert does not match the selected input value of that form. How can I target a specific instance of these input values within the form a user interacts with?
Here is a simplified version of my code showing only two forms:
example on - jsfiddle
<form method="post" class="list1">
<input type="hidden" name="on0" value="Size">
<select name="os0">
<option value="">-- Choose a Size --</option>
<option value="Short">Short</option>
<option value=" Medium">Medium</option>
<option value=" Long">Long</option>
</select>
<input type="hidden" name="on1" value="Color">
<select name="os1">
<option value="">
-- Choose a Color --
</option>
<option value="ivory">ivory</option> <option value=" black"> black</option>
</select>
<input type="button" value="Add to Cart" class="catalog">
</form>
<!-- seconed form start -->
<hr />
<form method="post" class="list2">
<input type="hidden" name="on0" value="Option">
<select name="os0">
<option value="">-- Choose a Option --</option>
<option value="Option 1">Option 1</option>
<option value="Option 2">Option 2</option>
<option value="Option 3">Option 3</option>
</select>
<input type="hidden" name="on1" value="Accent Color">
<select name="os1">
<option value="">
-- Choose a Choose a Accent Color --
</option>
<option value="red">Red</option>
<option value="yellow">yellow</option>
<option value="orange">orange</option>
</select>
<input type="button" value="Add to Cart" class="catalog">
</form>
And my js
$(document).ready(function(){
var size_x = $("input[name='on0']").val();
var color_x = $("input[name='on1']").val();
function popWarning() {
if ($("select[name='os0']").val() === "") {
alert('Please choose a ' + size_x);
return false;
}
if ($("select[name='os1']").val() === "") {
alert('Please choose a ' + color_x);
return false;
}
}
$("input.catalog").click(function() {
popWarning();
});
});
Reference the form and use that as context.
function popWarning(form) {
var size_x = form.find("input[name='on0']").val();
var color_x = form.find("input[name='on1']").val();
var size = form.find("input[name='os0']").val();
var color = form.find("input[name='os1']").val();
if (size === "") {
alert('Please choose a ' + size_x);
return false;
}
if (color === "") {
alert('Please choose a ' + color_x);
return false;
}
}
$("input.catalog").click(function() {
popWarning( $(this.form) );
});
Let us pass in the reference to the button since that seems to be the breaking point.
function popWarning(button) {
var form = button.get(0).form;
var size_x = form.find("input[name='on0']").val();
var color_x = form.find("input[name='on1']").val();
var size = form.find("input[name='os0']").val();
var color = form.find("input[name='os1']").val();
if (size === "") {
alert('Please choose a ' + size_x);
return false;
}
if (color === "") {
alert('Please choose a ' + color_x);
return false;
}
}
$("input.catalog").click(function() {
popWarning( $(this) );
});
How do you expect the script to know which form (and therefore elements with the same name attribute) you're talking about without specifying it? Try something like this:
$(document).ready(function(){
function popWarning(obj) {
var $form = $(obj).closest("form");
var size_x = $form.find("input[name='on0']").val();
var color_x = $form.find("input[name='on1']").val();
var sel_os0 = $form.find("select[name='os0']");
var sel_os1 = $form.find("select[name='os1']");
if (sel_os0.val() === "") {
alert('Please choose a ' + size_x);
return false;
}
if (sel_os1.val() === "") {
alert('Please choose a ' + color_x);
return false;
}
}
$("input.catalog").click(function() {
popWarning(this);
});
});
Working example:
http://jsfiddle.net/7YJ63/6/
This way, popWarning is able to grab the parent form from the input.catalog that triggered it by click, via obj (this passed in). Then, all elements/values are found with find because you know that the elements you're looking for are a descendent of the form.
You have two selects with the name os0 and two with the nameos1. That is the root of your problem.
The if statements do not pass once the first form is completed because the first DOM element with the name os0 has already been completed. Change the name to os2 or something similar and do unique if conditions.
I have the alert working for the first form on the page, but after the second form, my alert does not match the selected input value of that form.
That's not the problem, really. Try your JSFiddle, select a size, then click the color "add to cart" button. You'll see the correct message. The problem is that your click handler says "if size is empty, say size, otherwise if color is empty, say color".
I would rewrite your click event listener and scope it by its form, something like:
$('#sizeForm input.catalog').click(function(){
var form = $(this).parents('form');
...
});
...etc. That should make it easy to determine which form was clicked. Or possibly easier:
<input class="catalog size" ... />
$('input.catalog.size').click(function(){popWarning('size');});
...which could be more slick/dynamic so that you could handle all the forms in a single handler...but that's maybe overkill of an answer for the nature of your question.
Anyway. Good luck.
I think you can adhere more to DRY and elegance if you use the this keyword to iterate over the select lists with JQuery's each(). Something along these lines:
$("input.catalog").click(function() {
form = $(this).parent();
select = form.find("select");
message = '';
select.each(
function(){
if ($(this).val()=='') {
number = $(this).attr("name").substr(-1);
message+= $("input[name=on" + number + "]").val() + " ";
}
}
);
if (message!='') {
console.log("Please select the following: " + message);
return false;
}
});
I want to have a drop down menu where a user can select from several predefined options but i also want to give him the option of inserting a user specific value, i was thinking having one of the options as "user specific" which will in turn allow the user to insert a user specif entry in a text box that appears or is editable when user selects the "user specific" option. any one have any ideas how i can implement this is HTML and Javascript?
thank you
Attach an onchange event to the select and when he selects "Custom" or something like that, make some input visible below the select. This input should be initially hidden (css display:none). When the user selects "custom" make it display:inline.
Jukka wrote an article on how to create a combobox-like effect. I've only skimmed it, but it looks accessible and his content is usually of very high quality.
You can go about like:
<select id="myid" onchange="doIt(this);">
optons...
</select>
<script type="text/javascript">
function doIt(field) {
if (field.value === 'user specific')
{
var tbox = document.createElement('input');
tbox.setAttribute('type', 'text');
document.form_name.appendChild(tbox);
}
}
</script>
See here: http://jsfiddle.net/EscRV/
html
<select id="mySelect">
<option>value 1</option>
<option value="[new]">new</option>
</select>
js
// get a cross-browser function for adding events, place this in [global] or somewhere you can access it
var on = (function(){
if (window.addEventListener) {
return function(target, type, listener){
target.addEventListener(type, listener, false);
};
}
else {
return function(object, sEvent, fpNotify){
object.attachEvent("on" + sEvent, fpNotify);
};
}
}());
var mySelect = document.getElementById("mySelect");
on(mySelect, "change", function(){
if (this.value === "[new]") {
var newOptionName = prompt("input new option");
if (newOptionName){
mySelect.options[mySelect.options.length] = new Option(newOptionName);
this.value= newOptionName;
}
}
});
Following code will help to solve your problem.
<html>
<head></head>
<body>
<select id="sbox">
<option value="1" onclick="hideUserOption();">First option</option>
<option value="2" onclick="hideUserOption();">second option</option>
<option value="3" onclick="showUserOption();">User Specific</option>
</select>
<div id="userOptions" style="display:none">
<input type="text" />
<input type="submit" value="Save"/>
</div>
<script type="text/javascript">
function showUserOption() {
var userOptions = document.getElementById("userOptions");
userOptions.style.display = "block";
}
function hideUserOption() {
var userOptions = document.getElementById("userOptions");
userOptions.style.display = "none";
}
</script>
</body>
</html>