I have a form which allows the user to input their own custom values for a simple online ‘thermostat’ (Minimum Temperature, Maximum Temperature and PowerSaver Maximum Temperature).
I am trying to write some jquery such that when the user submits the form with the custom values, it sets the custom values, and also changes the text to show the user which changes they made (e.g. “You've changed your minimum temperature to 5”)
Currently, only the first form field ‘minimum temperature’ is working, and setting the correct value. The other two aren’t working as expected.
In addition, I’d like the user to be able to set all the custom values at once (one form submission), and for the following statements to appear on screen simultaneously e.g.:
You've changed your minimum temperature to 5
You've changed your maximum temperature to 50
You've changed your power saver maximum temperature to 30
The above statements should only show if the user has entered a value on that field. i.e. if the user has only entered a value for the maximum temperature, it should only show the following statement:
You've changed your maximum temperature to 50
Any help or pointers in the right direction would be really appreciated. Thanks very much in advance!
Code for the form:
<form id="custom-values">
<input type="text" id="mintemperature" placeholder="Minimum temperature">
<input type="text" id="maxtemperature" placeholder="Maximum temperature">
<input type="text" id="maxtemperatureps" placeholder="Max. PowerSaver temperature">
<input type="submit" class="submit-button" value="Set!">
</form>
Jquery code:
$('#custom-values').on('submit', function(event) {
event.preventDefault();
if ($('#mintemperature').val() !== "") {
$('#message').text("You've changed your minimum temperature to " + $('#mintemperature').val())
thermostat.minTemperature = parseInt($('#mintemperature').val())
}
if ($('#maxtemperature').val() !== "") {
$('#message').text("You've changed your maximum temperature to " + $('#maxtemperature').val())
thermostat.minTemperature = parseInt($('#mintemperature').val())
}
if ($('#maxtemperatureps').val() !== "") {
$('#message').text("You've changed your power saver maximum temperature to " + $('#maxtemperatureps').val())
thermostat.minTemperature = parseInt($('#mintemperature').val())
}
});
One approach is:
$('#custom-values').on('submit', function(event) {
event.preventDefault();
// creating an object to define what setting is associated
// with each element (identified by its id as the key):
var messages = {
'mintemperature' : 'minimum',
'maxtemperature' : 'maximum',
'maxtemperatureps' : 'maximum power-saving'
},
// creating an array, using map and get, of the nodes that have
// had their values changed from the default, and whose value can
// be parsed as a number (in base 10):
changes = $(this).find('input[type="text"]').map(function () {
if ( this.value !== this.defaultValue && parseInt(this.value, 10)) {
return this;
}
}).get(),
// creating an '<li>' element as a jQuery object:
li = $('<li />'),
// creating a variable to hold a clone within the (later) forEach:
clone;
// empty out existing messages:
$('#messages').empty();
// iterate over the array of changed nodes:
changes.forEach(function (changed) {
// cloning the created jQuery <li> object:
clone = li.clone();
// setting its html to the following concatenated string:
clone.html('You have changed the ' + messages[changed.id] + ' temperature setting, to: ' + changed.value + '°C')
// appending the <li> to the '#messages' element:
.appendTo('#messages');
});
});
#messages {
border: 1px solid #000;
margin: 0.5em;
}
/* hiding the #messages element if it has
no content (including white-space): */
#messages:empty {
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form id="custom-values">
<input type="text" id="mintemperature" placeholder="Minimum temperature">
<input type="text" id="maxtemperature" placeholder="Maximum temperature">
<input type="text" id="maxtemperatureps" placeholder="Max. PowerSaver temperature">
<input type="submit" class="submit-button" value="Set!">
</form>
<ul id="messages"></ul>
References:
appentTo().
clone().
empty().
eq().
get().
html().
on().
Related
I’m looking for a way to automate a form.
Here are the details:
Extract a certain number (displayed in its html)
Do some calculations on the extracted number (percentage of that number)
Then automatically fill the remaining input fields with the result instead of typing it out.
This is a common occurrence in forms. The solution depends on what framework / libraries you're using. Assuming you're using none, here is how you might go about it:
https://jsfiddle.net/f52h1smj/1/
rough HTML:
<form>
<label for="number">Number: </label>
<input id="number" type="number" />
<br /> <br />
<label for="calculatedNumber">Calculated Number (50%): </label>
<input id="calculatedNumber" type="number" disabled="true" />
</form>
JS:
(() => {
//get the form element nodes
const $number = document.getElementById("number");
const $calculatedNumber = document.getElementById("calculatedNumber");
//add an event listen to the value you're going to use to pre calculate the other fields
$number.addEventListener("keyup", (e) => {
//it's value is available like so
const value = e.target.value;
//do some validation so that you're calculations don't throw exceptions
if (Number(value) !== 0 && !Number.isNaN(value)) {
//set the value of the other inputs to whatever you like by setting the 'value' property of the node.
$calculatedNumber.value = value / 2;
} else {
$calculatedNumber.value = null;
}
});
})();
These things become a lot simpler in frameworks like React and Angular.
I'm trying to write a function with jQuery that will create a series of new inputs next to a series of unique inputs that already exist. The function should add event listeners to each of the new inputs so that whenever its value changes (something is typed into it, for example), the value of the original input next to it has the same value.
Eventually I will simply hide the original form so that the end user only sees the new form. I'm doing this for the sake of being able to control which parts of the form the user can see/modify and also to have more control over the way the form looks. The reason I have to do all this is because I have to do all this is because I'm modifying a Microsoft Sharepoint item creation form, and the only way to modify it is to add javascript to the page. If there's a better way of doing this I'm all ears. I'm relatively new to coding and very new to coding in Sharepoint.
Anyways, here's what I have:
var inputIdArr = [
'OrigInput1',
'OrigInput2',
'OrigInput3',
'OrigInput4',
'OrigInput5',
'OrigInput6',
'OrigInput7'
];
function newInputs(arr) {
for (str in arr) {
var elem = $( "[id='" + inputIdArr[str] + "']" );
var parent = elem.parent();
var newInputId = `newInput${str}`
var newInput = `<input type='text' id=${newInputId} />`;
parent.append(newInput);
$( `[id=${newInputId}]` ).change(function() {
console.log(newInputId + " changed");
elem.val($( `[id=${newInputId}]` ).value);
});
}
}
$(document).ready(function(){
newInputs(inputIdArr);
});
Currently, the console always logs "newInput7 changed". I'm not sure how to fix it so it logs that the correct new input has changed. I could also use guidance on where to go once that's done.
Programmatically keeping track of the generated ids of dynamically created elements is an anti-pattern that leads to needlessly verbose code and a maintenance headache.
Instead you can make the logic much more succinct and extensible by simply using classes and DOM traversal to group and relate elements to each other, something like this:
$('input.orig').after('<input type="text" class="appended" />');
$('#container').on('input', 'input.appended', function() {
$(this).prev('.orig').val(this.value);
})
.appended {
border: 1px solid #C00;
}
input {
display: block;
margin: 2px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="container">
<input type="text" class="orig" />
<input type="text" class="orig" />
<input type="text" class="orig" />
</div>
Also note that using attribute selectors to find elements by id is redundant when the # id selector is available and much faster - even though it's not needed for this to work.
This should give you rought start,, I've created 7 original fields, and your function does new fields successfully. I've added event or binding on new fields outside of your loop because there was some issue I think.
// fields selection
var inputIdArr = [
'OrigInput1',
'OrigInput2',
'OrigInput3',
'OrigInput4',
'OrigInput5',
'OrigInput6',
'OrigInput7'
];
// function for creating new fields
function newInputs(arr) {
for (str in arr) {
var elem = $("[id='" + inputIdArr[str] + "']");
var parent = elem.parent();
var newInputId = `newInput${str}`
var newInput = `<input type='text' id=${newInputId} />`;
parent.append(newInput);
}
}
// create new inputs on dom ready
$(document).ready(function() {
newInputs(inputIdArr);
});
// bind new inputs and send value to org inputs
$(document).on('input', '[id^="newInput"]', function(el){
$(this).prev().val( $(this).val() );
});
input:nth-child(1){ border:1px solid red; }
input:nth-child(2){ border:1px solid blue; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div><input type="text" id="OrigInput1"></div>
<div><input type="text" id="OrigInput2"></div>
<div><input type="text" id="OrigInput3"></div>
<div><input type="text" id="OrigInput4"></div>
<div><input type="text" id="OrigInput5"></div>
<div><input type="text" id="OrigInput6"></div>
<div><input type="text" id="OrigInput7"></div>
I have some input field dynamically generated inside form. I am trying to read the value of hidden input and append to to the end of text area
.<input type="hidden" id="formtype_loans_0_comment" name="formtype[loans][0][comment]" disabled="disabled" value="VAlue 1 value 123" />
<textarea id="formtype_loans_0_description" name="formtype[loans][0][description]">Text Area 1 or 1 </textarea>
<input type="hidden" id="formtype_loans_1_comment" name="formtype[loans][1][comment]" disabled="disabled" value="VAlue value 123" />
<textarea id="formtype_loans_1_description" name="formtype[loans][1][description]">test desc</textarea>
and Here is the js code, but it's not working,
var values = [];
$("input[name='formtype[loans][][description]']").each(function() {
values.push($(this).val());
});
alert(values);
Your selector "input[name='formtype[loans][][description]']" won't match any elements, because the [] in the middle will not match to the [0] or [1] (etc.) in the middle of the actual element name attributes.
For the HTML shown you could use the attribute starts with selector [name^=value]:
$('input[name^="formtype[loans]"]').each(function() {
If each textarea will always immediately follow its associated hidden input then within the .each() loop that iterates over the inputs you can say $(this).next() to get the textarea.
If the textareas might be elsewhere in the DOM then you could find them by selecting by the name attribute based on the name of the current input:
$('textarea[name="' + this.name.replace("comment", "description") + '"')
Demonstrated in context:
$('input[name^="formtype[loans]"]').each(function() {
var val = this.value
// add input's value to end of associated textarea's existing value:
$('textarea[name="' + this.name.replace("comment", "description") + '"')
.val(function(i, v) { return v + ' ' + val })
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<input type="hidden" id="formtype_loans_0_comment" name="formtype[loans][0][comment]" disabled="disabled" value="Hidden value 0" />
<textarea id="formtype_loans_0_description" name="formtype[loans][0][description]">Text Area A</textarea>
<input type="hidden" id="formtype_loans_1_comment" name="formtype[loans][1][comment]" disabled="disabled" value="Hidden value 1" />
<textarea id="formtype_loans_1_description" name="formtype[loans][1][description]">Text Area B</textarea>
If you want to simply replace the textarea's current value rather than adding to the end of it then you can simplify the above to:
$('input[name^="formtype[loans]"]').each(function() {
$('textarea[name="' + this.name.replace("comment", "description") + '"')
.val(this.value)
})
var values = [],
inputs = $('input[type="hidden"]'),
textareas = $('textarea');
if (inputs.length === textareas.length) {
$.each(inputs, function(i, input) {
var val = ($(input).val()) ? $(input).val(): undefined;
if (val) {
$(textareas).eq(i).empty().val(val);
}
});
}
alert(values);
The working code above assumes a couple of things:
There will always be one textarea per hidden input.
The associated textarea will always be the next sibling after the hidden input.
Even if that is not the case, there are still various ways to resolve this challenge. But I'll break down the different parts of the code:
First, instantiate your variables. Most importantly, cache your selected HTML elements into vars: touching the DOM is expensive and negatively impacts performance (e.g. querying the DOM each time in a loop).
Next, we put a conditional test to ensure there is one textarea for each input. No need to waste time iterating through a loop looking for elements that aren't there.
Finally, iterate through each of the selected inputs confirming each of them have a value. Again, no need manipulating textarea if there is no value to insert. If there is a value in the input, insert it into the textarea that occupies the same position as the input in each of your arrays of elements.
anyone could help me out on how i could achieve this with either javascript or jquery maybe to get the following as mentioned below
say i have this field1
<input type="text" name="field1" value="">
and then i have this field2
<input type="hidden" name="field2" value="">
what i mean to say the field2 should be hidden but if someone enters some value in field1 then field2 shows but if no value on field1 then it disappears?
thanks in advance and appreciate your time and help
You'd get the first field, check if it has a value, and toggle the second field based on that, but you should not be using a hidden input, but instead hide it with CSS
$('[name="field1"]').on('input', function() {
var el = $('[name="field2"]').toggle( this.value !== "" );
if (this.value === "") el.val("");
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" name="field1" value="" placeholder="type something">
<br><br>
<input type="text" name="field2" value="" style="display:none">
As you've also tagged your question with JavaScript it seems worth offering the following:
// retrieving the first - if any - element with its
// 'name' attribute equal to the value of 'field1':
var input = document.querySelector('[name=field1]');
// adding an event-listener to that element, listening
// for the 'input' event (keyup, paste, copy...) and
// assigning the method's anonymous function as the
// event-handler:
input.addEventListener('input', function(e) {
// 'e': here unused, is a reference to the event
// which triggered the function to be called; using
// e.type will give the specific event, if required
// (and other properties are, of course, available).
// retrieving the first - if any - element with has
// its 'name' attribute equal to 'field2':
var conditionalInput = document.querySelector('[name=field2]');
// if the value of the <input> element that received
// the event has a value that, when leading and trailing
// white-space is removed, results in a truthy
// evaluation (the string length is non-zero):
if (this.value.trim().length) {
// we set the display style of the conditionally-
// shown <input> to 'block', you could instead use
// 'inline-block' if you prefer:
conditionalInput.style.display = 'block';
// otherwise, if the length of the trimmed-value is
// zero (falsey):
} else {
// we set the display style of the conditionally-
// shown <input> to 'none':
conditionalInput.style.display = 'none';
// and also remove its entered value:
conditionalInput.value = '';
}
});
var input = document.querySelector('[name=field1]');
input.addEventListener('input', function(e) {
var conditionalInput = document.querySelector('[name=field2]');
if (this.value.trim().length) {
conditionalInput.style.display = 'block';
} else {
conditionalInput.style.display = 'none';
conditionalInput.value = '';
}
});
<input type="text" name="field1" value="" />
<input type="text" name="field2" value="" />
In your HTML please note that I've adjusted the <input> element's type, from 'hidden' to 'text', this is because some browsers – I believe mostly Internet Explorer – has, or had, issues when changing the type of an <input> element dynamically.
If your use-case doesn't depend on cross-browser compatibility then you can, of course, change the type (conditionalInput.type = 'text'/conditionalInput.type = 'hidden') rather than the display.
var textEntered = function() {
var input = document.userNameForm.userInput.value;
if(input) {
document.getElementById("resultText").innerHTML += input + "<br>";
}
}
This is what I have so far and this obviously just prints out the user inputs onto the screen in a list. But I want to somehow store all these user inputs from the form I have in my HTML, (maybe in an array?) and maybe assign each to a number and use Math.floor(Math.random()) to print out a random result. (I'm just making a little/random site where you put in the names of your friends and it returns and prints a random name from the names that you give it, if that makes sense).
I'm a beginner just so you know
function textEntered() {
var inputs = [];
$('form input').each((i,e)=>inputs.push(e.value));
if (inputs) {
document.getElementById("resultText").innerHTML += inputs[Math.floor(Math.random()*inputs.length)] + "<br>";
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form>
<input value="Hello">
<input value="World">
<input value="from Stardust">
<button onclick="textEntered()">Submit Now!</button>
</form>
<div id="resultText">Submit it!
<br><br>
</div>
Is this essentially what you are looking for?