Change value of <input> to include a superscript, using Javascript - javascript

The following code works correctly for me, in HTML.
<input type = "text" name = "var_1" id = "i_var_1" value = "x&sup8">
The following, using Javascript, also works:
<p id = "p1"><input type = "text" name = "var_1" id = "i_var_1" value = "0"></p>
<script....>
q1 = document.getElementById("p1");
q1.innerHTML = '<INPUT TYPE = "text" name = "var_1a" id = "i_var_1a" value = "x&sup8">';
</script>
However I need to add in the superscript when a button is pressed. So I have something like:
<p id = "p1"><input type = "text" name = "var_1" id = "i_var_1" value = "0"></p>
<input type = "button" id = "i_button" value = "Add the superscript" onclick="Add_Superscript()";>
<script.....>
function Add_Superscript()
{
q1 = document.getElementById("p1");
b1 = document.getElementById("i_var_1");
c1 = b1.value.toString() + "&sup8";
q1.innerHTML = '<INPUT TYPE = "text" name = "var_1a" id = "i_var_1a" value = c1.value>';
}
</script>
The above code does not reproduce the superscript properly.
Anyone any ideas? Thanks in advance for comments.

Not sure this is what you want, but it adds &sup8 to whatever is in the input box.
function Add_Superscript() {
q1 = document.getElementById("p1");
b1 = document.getElementById("i_var_1");
c1 = b1.value.toString() + "&sup8";
q1.innerHTML = '<INPUT TYPE = "text" name = "var_1a" id = "i_var_1a" value = "' + c1 + '">';
}
<p id="p1">
<input type="text" name="var_1" id="i_var_1" value="0">
</p>
<input type="button" id="i_button" value="Add the superscript" onclick="Add_Superscript()" ;>

I don't know what you're trying to do but maybe it's because of the c1.value ! Try:
q1.innerHTML = '<INPUT TYPE = "text" name = "var_1a" id = "i_var_1a" value =' + c1 + '>';

You have several typos in your code and a lot of unnecessary code as well. You just need to set up a click event handler on the button that populates the value of the pre-existing input. No need to create a new input.
A few notes:
When you were trying to create the new input element (which it turns out you don't need to do in the first place), you had the entire thing as a string. You need to inject the dynamic value into that string, by terminating the string, concatenating the new value in and then concatenating the closing of the string, like this:
q1.innerHTML = '<input type="text" name="var_1a" id="i_var_1a" value=' + c1.value + '>';
Next, it's best to use good naming conventions for elements and variables. Prefix an id and name with something that describes the "type" of thing the element is. Use btn (button), txt (textbox), chk (checkbox), rad (radio button), etc. And don't use _ (that's a very old convention). Instead use "camelCase". Further, with form elements, you need to give them a name for form submission purposes, but it is also a good idea to give them and id for CSS and JavaScript purposes. Use the same id that you used for name so that you don't have two different names for the same thing.
Lastly, don't configure your HTML elements to event handlers via HTML attributes (onclick, onmouseover, etc.). Doing this creates global anonymous functions that alter the this binding in the callback function, it creates "spaghetti code" that is hard to scale and debug and it doesn't follow the W3C DOM Event specification. Instead, do all the work in JavaScript and use .addEventListener() to connect functions to events.
// Get references to the relevant DOM elements
var btn = document.getElementById("btnGo");
var input = document.getElementById("txtInput");
// Set up a click event handling function
btn.addEventListener("click", add_Superscript);
function add_Superscript(){
// Create a new value that is the old value plus a "superscript" value
var newVal = input.value + "&sup8";
// Update the input with the new value:
input.value = newVal;
}
<p>
<input type="text" name="txtInput" id="txtInput" value="0">
</p>
<input type = "button" id="btnGo" value="Add the superscript">

Related

getElementByID.onchange not working after i update html with = innerHTML

My starting html looks like this:
<label> Names: </label><br>
<input type="text" class="form-control name" placeholder="name1" id="name1" name ="name1"><br>
and i have a variable that captures the html:
var html = "<label> Names: </label><br><input type=\"text\" class=\"form-control name\" placeholder=\"name1\" id=\"name1\" name =\"name1\"><br>"
Then I have an onchange operator that performs a couple functions when the first row has text in it. the .onchange is picked up fine the first time and the subsequent functions are run. I end up with an additional row:
for (n = 1; n < inputLength+1 ; ++n) {
var test2 = document.getElementById(dude+n);
test2.onchange = forFunction
}
function forFunction() {
for (m = 1; m < inputLength+1 ; ++m) {
var test = document.getElementById(dude+m)
if (test.value != "") {
var txt = "<input type=\"text\" class=\"form-control name\" placeholder="+dude+(m+1)+" id="+dude+(m+1)+" name="+dude+(m+1)+"><br>";
document.getElementById('group_names').innerHTML = updateHTML(txt);
//function updateHTML(txt)
}
}
}
var html = "<label> Names: </label><br><input type=\"text\" class=\"form-control name\" placeholder=\"name1\" id=\"name1\" name =\"name1\"><br>"
function updateHTML(txt) {
html = html + txt;
return html;
}
The issue is that after all that completes i end up with two input rows as desired: name1 and name2. However, when i enter text in those fields for a second time, the .onchange is not picked up. but the elements are there in the html when i inspect and view the html.
Also, when i
console.log(inputFormDiv.getElementsByTagName('input').length);
the length of the inputs increases from 1 to 2 after i first run functions (upon the first time i change the value in my input field) so that is getting recognized correctly, just not the .onchange.
thoughts?
The onchange will only work if added to the attribute on the html and the user clicks out of a textbox e.g:
<input onchange="forFunction()" type="text" class="form-control name" placeholder="name1" id="name1" name ="name1">
To add the onchange event in JavaScript code. Add the change event to the addEventListener e.g:
var test2 = document.getElementById(dude+n);
test2.addEventListener('change', forFunction, false)
However if you want the event to fire whilst the user is types a key then use the keypress event. e.g:
var test2 = document.getElementById(dude+n);
test2.addEventListener('keypress', forFunction, false
A basic example: https://jsfiddle.net/xrL6y012/1/
Instead of .innerHTML = html + text do .insertAdjacentHTML('beforeend', text), that way you keep the original html (and events binding).
Edit: https://developer.mozilla.org/en-US/docs/Web/API/Element/insertAdjacentHTML
I had the same problem, it seems like modifying the HTML will never work, regardless of how you do it (.innerHTML or .insertAdjacentHTML()).
The only way that worked for me is to append a child instead of editing the HTML, like so:
const span = document.createElement('span');
span.innerHTML = 'text and <b> html stuff </b>';
initialElement.appendChild(span);
And if you actually need to insert just pure text, then this works:
initialElement.append('just text');
Hope that helps.

How to access html form values from nested inputs

I'm trying to validate input from this form:
<form id = "mpath" name = "mpath" action = './../cgitest.cgi' method="POST" onsubmit = "return validateForm(this)">
Total Time (in ms): <input type = "text" name = "ttime">
Number of Cars (1-10): <input type = "text" name = "carnum">
Initial Speed (fps): <input type = "text" name = "initspeed"><br>
<!--extraRowTemplate will be repeated for every change in the accleration of the
head car -->
<p class = "extraRowTemplate" name = "extraRowTemplate">
Change:
<select name="change">
<option value="acc">Acceleration</option>
<option value="dec">Deceleration</option>
</select>
Start time: <input type = "text" name="starttime">
End time: <input type = "text" name="endtime">
Amount (in fps): <input type = "text" name="amount"><br>
</p>
<div id = 'container'></div>
<i class="icon-plus-sign"></i>Add Change<br>
<input type="submit" value="Load Head Car">
</form>
Using this function (I haven't written any of the actual validation):
<script type="text/javascript">
function validateForm(form){
var tt = document.forms[0].ttime.value;
var cn = document.forms[0].carnum.value;
var is = document.forms[0].initspeed.value;
var sta = form.elements[4].value;
console.log(tt);
console.log(cn);
console.log(is);
console.log(sta);
if(tt == ""){
alert("starttime must be filled out");
return false;
}
//return false;
}
</script>
But when I try to submit values, it only finds the values for ttime, carnum, and initspeed, and not the value of starttime, endtime, or amount. Also, the value of change is always "acc", even if I set it to "deceleration".
For those wondering why I don't simply remove extraRowTemplate, I need to have those input options in a nested section because I have an option to duplicate them.
I've tried to pass the form as an argument to the function (as shown) as well as just use document.forms[0] to access it. Neither produce the correct result.
Also, when I remove the .value from the form.elements[4].value and set:
var sta = form.elements[4];
The console prints out:
<input type = "text" name = "starttime">
Does anyone know how I can access the value of the nested inputs?
I suppose I should also say that the form works correctly in every other way, and when I send it to the cgitest.cgi, I can access all inputs. I just don't want to validate the inputs on the server side.
EDIT:
If instead of using an onsubmit function (validateForm in my case), I use an event listener:
<script type="text/javascript">
var button = document.querySelector('input[type=submit]')
button.addEventListener('click', function onClick(event) {
var ttime = document.querySelector('input[name=ttime]')
var carnum = document.querySelector('input[name=carnum]')
var initspeed = document.querySelector('input[name=initspeed]')
var change = document.querySelector('select[name=change]')
var starttime = document.querySelector('input[name=starttime]')
var endtime = document.querySelector('input[name=endtime]')
var amount = document.querySelector('input[name=amount]')
console.info('ttime', ttime.value)
console.info('carnum', carnum.value)
console.info('initspeed', initspeed.value)
console.info('change', change.value)
console.info('starttime', starttime.value)
console.info('endtime', endtime.value)
console.info('amount', amount.value)
event.preventDefault()
})
</script>
With the input ttime = 1, carnum = 2, initspeed = 3, change = "acc", starttime = 4, endtime = 5, amount = 6, I get the following console output:
(index):70 ttime 1
(index):71 carnum 2
(index):72 initspeed 3
(index):73 change acc
(index):74 starttime
(index):75 endtime
(index):76 amount
As can be seen, all values beyond initspeed (everything inside extraRowTemplate) are empty. Like I said before, they are not empty when sent to the form action url.
Can you try removing the extraRowTemplate and submit. If it's working, than you can try generating the elements inside with the different ids, because now you have duplicated items with no distinction.
You are currently accessing the elements in a bit of a roundabout way, using document.forms[0]. Also I don't see any code to get the value of the starttime input. You are testing tt in the if, but that was assigned the value of ttime.
document.querySelector
Might I suggest accessing the form elements by name directly, using document.querySelector? This method accepts a CSS selector and returns the first element that matches. Using a simple CSS3 selector we can select elements by name and assuming those names are unique on the page, we will get the right inputs. You could also use form.querySelector if the names are only unique within the form.
Example
var myInput = document.querySelector('input[name=ttime]')
I find document.querySelector and document.querySelectorAll (which gets all elements matching the CSS selector) very useful and use them all the time.
Runnable code snippet
Run this snippet and press the form submit button to print the values of the inputs. Try it and see how it works.
var button = document.querySelector('input[type=submit]')
button.addEventListener('click', function onClick(event) {
var ttime = document.querySelector('input[name=ttime]')
var carnum = document.querySelector('input[name=carnum]')
var initspeed = document.querySelector('input[name=initspeed]')
var change = document.querySelector('select[name=change]')
var starttime = document.querySelector('input[name=starttime]')
var endtime = document.querySelector('input[name=endtime]')
var amount = document.querySelector('input[name=amount]')
console.info('ttime', ttime.value)
console.info('carnum', carnum.value)
console.info('initspeed', initspeed.value)
console.info('change', change.value)
console.info('starttime', starttime.value)
console.info('endtime', endtime.value)
console.info('amount', amount.value)
event.preventDefault()
})
<form id = "mpath" name = "mpath" action = './../cgitest.cgi' method="POST" onsubmit = "return validateForm(this)">
Total Time (in ms): <input type = "text" name = "ttime">
Number of Cars (1-10): <input type = "text" name = "carnum">
Initial Speed (fps): <input type = "text" name = "initspeed"><br>
<!--extraRowTemplate will be repeated for every change in the accleration of the
head car -->
<p class = "extraRowTemplate" name = "extraRowTemplate">
Change:
<select name="change">
<option value="acc">Acceleration</option>
<option value="dec">Deceleration</option>
</select>
Start time: <input type = "text" name="starttime">
End time: <input type = "text" name="endtime">
Amount (in fps): <input type = "text" name="amount"><br>
</p>
<div id = 'container'></div>
<i class="icon-plus-sign"></i>Add Change<br>
<input type="submit" value="Load Head Car">
</form>
I can access the value of your "starttime" field in Firefox/Chrome/Opera using either
var sta = document.forms[0][4].value
or
var sta = document.forms[0].starttime.value
I was able to figure out what was going wrong. In my css I set:
.extraRowTemplate {
display: none;
}
which was preventing the input values from being sent. Once I removed this my problems went away. Setting "visibility : hidden" is a good alternative that allowed the values to be submitted and the template not visible.

Add element works but clears input value

I have a script below that adds an element to my form, another text input field. It adds the new text input field but if I type something into the first one then add a new field it removes the input text from the first one.
I cant see where im going wrong here, im fairly new to JavaScript so please go easy :)
function addAnother() {
var id = 1;
var elemebt = document.getElementById('quest');
var number = elemebt.getElementsByTagName('*').length;
var add = number + 1;
var element = '<input type="text" name="question[]" id="quest'+ add +
'" placeholder="Example: What previous experiance do you have?" class="form-control" id="cloan"><a id="name'+
add +'" onClick="removeEle('+ add +')">Remove</a>';
document.getElementById('quest').innerHTML += element;
}
In JavaScript, the following two statements are practically identical:
str = str + ' more text ';
str += ' more text ';
The key point here is that in the end, the value of str is COMPLETELY OVERWRITTEN.
In your case, that means the innerHTML of the "quest" element is overwritten and the browser completely recreates it's children nodes, thus reseting any state and input values.
To overcome this, you can use the appendChild method but you first need to create the element to append. The easiest way to do that given you have a string of your HTML is to inject that string into a dummy element using the innerHTML property:
var target = document.getElementById('target');
var tDiv = document.createElement('div');
var htmlString = '<input type="text"></input>';
tDiv.innerHTML = htmlString;
target.appendChild(tDiv.children[0]);
<div id="target">Keep my content safe!</div>

Generating additional rows in PHP form with alternative id and name

I am looking for a way to add the following row of inputs using a button (and I've found plenty of examples) BUT most of them renames the name of html element (e.g. name = 'price1', name = 'price2') but my javascript references the element's id, making it erroneous when new rows are added. Some helps are appreciated.
JS Fiddle just to see the rows
https://jsfiddle.net/n4h5uwvk/
the HTML code
<form action = "" method = "POST">
<label>Item : </label>
<select id = 'item_name' name = 'item_name' onChange = 'listMatch(this);fieldCheck();'
>
<option value = "" disabled = "disabled" selected="selected">Please Select</option>
<?php
while($row = mysqli_fetch_assoc($result)){
echo "<option value = '".$row['PRODUCT_ID']."' data-price ='
".$row['UNIT_PRICE']."' >".$row['PRODUCT_NAME']."</option>";
}
?>
</select>
<label>Price : </label>
<input type = 'text' id = 'item_price' name = 'item_price' value = '' disabled/>
<label>Quantity : </label>
<input type = "number" id = 'quantity' name = 'quantity' max = "150" min = "0" onChange = 'multiplier(value)' disabled/>
<label>Sub-Total : </label>
<input type = "number" id = 'sub-total' name = 'sub-total' disabled value = ''/>
and the Javascript
<script>
//lists the price according to selected item
function listMatch(product){
var x = product.options[product.selectedIndex].getAttribute('data-price');
document.getElementById('item_price').value = x;
}
//un-disable quantity field after item is selected
function fieldCheck(){
document.getElementById('quantity').removeAttribute('disabled');
}
//var z = quantity*price
function multiplier(value){
var x = document.getElementById('item_price').value;
var y = value;
var z = x*y;
document.getElementById('sub-total').value = z.toFixed(2);
}
//clone fields on 'add field' button click
Updated :
I found a code to clone my forms well, but I encounter another problem. The clone will always duplicate values of the first row, I want to create child rows that have empty values. Any ways around this code?
//global variable for duplication identification
var count = 1;
//clone form for multiple entries
(function() {
$('#add').click(function() {
var source = $('form:first'),
clone = source.clone();
clone.find(':input').attr('id', function(i, val) {
return val + count;
});
clone.insertBefore(this);
count++;
});
})();
As you know id has to be unique and adding numbers to the cloned form elements to keep the ids unique seems overdoing it.
Names don't have to be unique though, so you can have different forms with elements with the same name. And they can be accessed easily by their names:
<form name="form_1">
<input name="firstName" type="text" />
<input name="lasttName" type="text" />
</form>
<form name="form_2">
<input name="firstName" type="text" />
<input name="lasttName" type="text" />
</form>
You can use the form name to access specific element, to access the input with name="firstName" in form_1 and form_2 you can use:
var firstName1 = document.form_1.firstName;
var firstName2 = document.form_2.firstName;
So it will be easy to distinguish between different forms, although their elements have the same structure and names. You just create a new form with name="form_X" and use innerHTML to add the cloned elements.
And to clone an element you can use .cloneNode(true); (or jQuery's clone()).
EDIT:
You still seem to think of it that you need to store everything in a variable, here's an example to do it all, and you can see it's much simpler than you think. I give these forms class="contactForm" to separate them from other forms there might be. we can clone 10 .contactForm and have 100 other forms in the page as well.
To get number of forms you can use $('form.contactForm').length
To empty text inputs inside new form you can use: newForm.find('input[type=text]').val("");
jsfiddle DEMO

How would I use jQuery to manipulate a html form when there are nested elements involved?

I have an empty form that needs to be filled with what I'd like to call mini-forms dynamically based on a condition. For example,this can be a form that asks for the names and locations of restaurants. Now, based on the number of restaurants(let's say 'm'), I'd like to add to the big form 'm' mini-forms that asks for the name and location. How can I use jQuery to create each of these mini-forms, that take in the name and the location of the restaurant and append them each to the big form. The html would look something like this. But I need to create this dynamically based on how many forms the user would need, and if he would need any.
Edit - I have learned that we cannot nest forms. I have renamed the inner 'form' elements to 'div'.
<form>
<div id = 1>
Name: <input type = "text" name = "name">
Location: <input type = "text" name ="location>
</div>
<div id = 2>
Name: <input type = "text" name = "name">
Location: <input type = "text" name ="location>
</div>
...
</form>
First you need to look for changes to the input where the user enters the number of restaurants:
$('#noofrestaurants').change(function(){
Then you need to loop through the number inputted and create new inputs each time:
var restaurants = $('#noofrestaurants').val();
for (var i = 0; i < restaurants; i++){
$('#miniformcontainer').append('<input type="text" name="rest_name[]"/><input type="text" name="rest_loc[]"/>');
}
});
You could try something like this:
<script>
function addMiniForms(n)
{
for (i=0; i<n ; i++)
{
var $div = $("<div id='" + i + "'></div>");
var $labelName = $("<label for='name" + i + "'>Name</label>");
var $inputName = $("<input type='text' id='name" + i +' />");
var $labelLocation = $("<label for='location" + i + "'>Location</label>");
var $inputLocation = $("<input type='text' id='location" + i +' />");
$div.append($labelName);
$div.append($inputName);
$div.append($labelLocation);
$div.append($inputLocation);
$("#containerid").append($div);
};
};
</script>
I have not tested this code, so it might need some tweaking.
You can't nest forms. If you want to have repeated inputs in a form, give them array-style names:
<div id = 1>
Name: <input type = "text" name = "name[]">
Location: <input type = "text" name ="location[]">
</div>
The back-end should convert these into arrays. For instance, PHP will fill in $_POST['name'] with an array of all the Name inputs.
The jQuery looks like:
divnum++;
$("form").append("<div id='"+divnum+"'>Name: <input type='text' name='name[]'">Location: <input type='text' name='location[]'></div>");

Categories