Save html form as html file with submitted values - javascript

First I'd like to say I read the answers to similar questions including this how to save the content of html form as .html page but that did not solve my problem.
I'm building a reporting system that allows users to use templates to create reports. These templates are html forms and can be developed my any external application or manually. What my application does is, it imports these templates and presents them to the user when he is creating his reports and I want to save the submitted report as as an html file with all the values the user selected, be it text fields or checkboxes.
The above answer suggests using $('#myForm').html(). What this does is get the html of the form but does not include any values entered by the user. How can I achieve this?
Update
I'd like to say this templates are developed by an external application and could have any structure depending on what the user is reporting. So I don't know of any id or name attribute of any of the form inputs used by the creator of the form. The only think I know of is that all the forms are always in a
<div id="reportTemplate"></div>
so that's the only thing I can access with javascript.

Javascript
function CreateHtml(){
var field1 = $("#field1").val();
var field2 = $("#field2").val();
var fieldn = $("#fieldn").val();
var form = $("#myForm").clone();
$(form).find("#field1").val(field1);
$(form).find("#field2").val(field2);
$(form).find("#fieldn").val(fieldn);
$('#btn_download').attr('download', 'sampleFile.html');
$('#btn_download').attr('href', 'data:text/html,' + form);
$('#btn_download').show();
}
HTML
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<div>
<input placeholder="field1" id="field1" type="text" />
<br/>
<input placeholder="field2" id="field2" type="text" />
<br/>
<button type="button" onclick="CreateHtml();">Submit</button>
<br>
<a href="" id="btn_download" hidden>Download</a>
</div>

You can wrap the html content in a variable and export it using anchor tag like below.
function CreateHtml() {
var htmlContent = "";
htmlContent = "<h1>Name - " + $('#name').val() + "</h1><br>" +
"<p>Email - " + $('#email').val() + "</p>";
$('#btn_download').attr('download', 'sampleFile.html');
$('#btn_download').attr('href', 'data:text/html,' + htmlContent);
$('#btn_download').show();
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<div>
<input placeholder="Name" id="name" type="text" />
<br/>
<input placeholder="Email" id="email" type="text" />
<br/>
<button type="button" onclick="CreateHtml();">Submit</button>
<br>
<a href="" id="btn_download" hidden>Download</a>
</div>
Updated:
function CreateHtml() {
var htmlContent = TraverseThroughReport();
$('#btn_download').attr('download', 'sampleFile.html');
$('#btn_download').attr('href', 'data:text/html,' + htmlContent);
$('#btn_download').show();
}
function TraverseThroughReport() {
var elements = document.getElementById("report").elements;
var htmlContent = "";
for (var i = 0, element; element = elements[i++];) {
if (element.type === "text")
//console.log("it's an empty textfield")
htmlContent = "<h1>" + element.value + "</h1>";
}
//You can add as many conditions for placeholder etc to detect the form element type
return htmlContent;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<div id="report">
<input placeholder="Name" id="name" type="text" />
<br/>
<input placeholder="Email" id="email" type="text" />
<br/>
<button type="button" onclick="CreateHtml();">Submit</button>
<br>
<a href="" id="btn_download" hidden>Download</a>
</div>

If I had asked my question properly or searched for existing questions using "innerHtml with form values" instead of "how to save html for as files" I would have been taken to this link jquery get all form elements: input, textarea & select with already good answers of which this particular one worked for me
$('input:text, input:hidden, input:password').each(function() {
var v=this.value;
$(this).attr("magicmagic_value",v).removeAttr("value").val(v);
});
$('input:checkbox,input:radio').each(function() {
var v=this.checked;
if(v) $(this).attr("magicmagic_checked","checked");
$(this).removeAttr("checked");
if(v) this.checked=true;
});
$('select option').each(function() {
var v=this.selected;
if(v) $(this).attr("magicmagic_selected","selected");
$(this).removeAttr("selected");
if(v) this.selected=true;
});
$('textarea').each(function() {
$(this).html(this.value);
});
var magic=$('form').html().replace(/magicmagic_/g,"");
$('[magicmagic_value]').removeAttr('magicmagic_value');
$('[magicmagic_checked]').attr("checked","checked").
removeAttr('magicmagic_checked');
$('[magicmagic_selected]').attr("selected","selected").
removeAttr('magicmagic_selected');
alert(magic);

Related

Use html form input to build URL that the page directs to upon submitting using JavaScript

I am attempting to take user input from an html form and then form a URL from that input that the user is directed to upon submitting the form. Currently, I have the following html form:
<form>
<br />
<div class="form-group">
<label for="cityInput">City</label>
<input type="text" class="form-control" id="cityInput" name="cityInput">
</div>
<div class="form-group">
<label for="stateCodeInput">State Code</label>
<input type="text" class="form-control" id="stateCodeInput" name="stateCodeInput">
</div>
<button type="submit" class="btn btn-primary" name="submitLocation "id="submitLocation" onclick="costOfLivingURL()">Submit</button>
</form>
Then I have the following JavaScript function that is setting values that will make the URL, as well as building the URL:
async function costOfLivingURL() {
let searchedCity = await getCity();
let searchedStateCode = await getStateCode();
var currentCity = document.getElementById('cityInput').value.trim();
var currentStateCode = document.getElementById('stateCodeInput').value.trim();
window.location.href = "https://www.bestplaces.net/cost-of-living/" + currentCity + "-" + currentStateCode + "/" + searchedCity + "-" + searchedStateCode + "/50000";
}
However, when I click on the button, nothing is happening at all.
I am not sure if my redirection is incorrect and I am also not sure if this is the correct way to use input data. If anyone can help me with this, I would greatly appreciate it!

JavaScript only changes text of first iteration with thymeleaf

I hope you are all well.
I have a school assignment, and I want to dynamically be able to change the name of a 'project'. This assignment is about projects. The way I've done it right now works with the first 'project' from a list of 'projects' iterated through with thymeleaf. I'm aware that what I've done right now is absolutely bad code behavior, but we have had no teaching in JS yet. But I really wanted this feature.
I don't know how to make this work for each project preview, right now it works for the first preview, but for the rest it just erases the project name from database. (see picture)
<div class="projects" th:each="projectNames : ${listOfProjects}">
<form action="deleteProjectPost" method="post">
<input type="hidden" th:value="${projectNames.projectID}" name="deleteID">
<input type="image" src="delete.png" alt="Submit" align="right" class="deleteProject" onclick="return confirm('Are you sure that you want to delete this project?')">
</form>
<form action="/editProjName" method="post">
<input type="hidden" name="projectID" th:value="${projectNames.projectID}">
<input type="hidden" id="oldName" th:value="${projectNames.projectName}">
<input type="hidden" id="newName" name="projectName">
<input type="image" src="edit.png" alt="Submit" onclick="change_text()" align="right" class="editProject">
</form>
<form action="/projectPost" method="post">
<input class="projectInfo" name="projectID" type="text" th:value="'Project No.: ' + ${projectNames.projectID}" readonly="readonly">
<input class="projectInfo" type="text" th:value="'Project name: ' + ${projectNames.projectName}" readonly="readonly">
<input class="projectInfo" type="text" th:value="${projectNames.projectStartDate} + ' - ' + ${projectNames.projectEndDate}" readonly="readonly">
<input type="submit" value="OPEN" class="openProject">
</form>
</div>
<script>
function change_text() {
var changedText;
var projectName = prompt("Please enter name of project:");
var oldName = document.getElementById("oldName").value;
if (projectName === null || projectName === "") {
changedText = oldName;
} else {
changedText = projectName;
}
document.getElementById("newName").value = changedText;
}
</script>
First form in HTML is the red cross to delete an entire 'project'. Second form is what is intended to change the name displayed on the 'project preview', but only works on first preview and deletes project name from the rest. Last form is the actual preview. I couldn't find another way to have multiple forms and do different POSTS while working with Java Spring and Thymeleaf.
My wish is to make the change_text() function work for each 'project preview'
Best regards!
function change_text(imageInput) {
var changedText;
var projectName = prompt("Please enter name of project:");
var oldName = imageInput.parentNode.querySelector('.old-name').value;
if (projectName === null || projectName === "") {
changedText = oldName;
} else {
changedText = projectName;
}
imageInput.parentNode.querySelector('.new-name').value = changedText;
}
<form action="/editProjName" method="post">
<input type="hidden" name="projectID" th:value="${projectNames.projectID}">
<input type="hidden" class="old-name" id="oldName" th:value="${projectNames.projectName}">
<input type="hidden" class="new-name" id="newName" name="projectName">
<input type="image" src="edit.png" alt="Submit" onclick="change_text(this)" align="right" class="editProject">
</form>
Ok so I made a few changes. First, notice the inputs with oldName and newName now have classes on them. These can be repeated. If you are not using the ids for anything other than the script, you should remove them. Otherwise if you have styling rules for them you should consider changing those CSS rules to use the class instead so you can remove the invalid repeating ids.
Secondly, the onlick of the image now passes in this. What that does is it passes in the actual input that the user clicked, so you have some context into which form element the user is interacting with.
Then looking at the logic, the method now accepts in imageInput which is the this from the onclick.
Using imageInput.parentNode we go up the DOM Tree to the parent element of the input, which is the form in this case. We can then turn around and use querySelector to find the other element in the form we want to manipulate. And it will only find the element in our particular form because that is what we are selecting off of.

Add user input to list on button click in JavaScript

I'm trying to create an HTML form which takes the text from multiple textboxes (in this case, 3) and adds the content of each to a list in a separate div, as well as create a new object "employee", all via the click of a button. My goal is to imitate adding employees to a database, using an employee id, first name, and last name as variables. I am looking to accomplish this using pure javascript.
What I have so far is:
<form>
ID Number:
<br>
<input type="text" id="idNumber">
<br>First name:
<br>
<input type="text" id="firstName">
<br>Last name:
<br>
<input type="text" id="lastName">
</form>
<br>
<button type="submit" onclick="myFunction(list)">Submit</button>
<div id="container">
<ul id="list"></ul>
</div>
In a separate JavaScript file:
function myFunction(list){
var text = document.getElementById("idNumber","fName","lName").value;
var li = "<li>" + text + "</li>";
document.getElementById("list").replaceChild(li);
}
When I debug my code it seems to be setting the values fine, but I receive no actual output of my list.
None of the input elements you selected had a class name. You can also do this with document.getElementById. Just add ids to all your form elements.
Your code should look something like this.
function myFunction(list){
var text = "";
var inputs = document.querySelectorAll("input[type=text]");
for (var i = 0; i < inputs.length; i++) {
text += inputs[i].value;
}
var li = document.createElement("li");
var node = document.createTextNode(text);
li.appendChild(node);
document.getElementById("list").appendChild(li);
}
http://jsfiddle.net/nb5h4o7o/3/
Your list wasn't being appended to because you weren't actually creating the elements. replaceChild should have been appendChild and you should have created a list element with document.createElement.
Your code is full of problems, look at the document.getElementById and Node.replaceChild docs.
I've created a version for you that we get all the input elements of your form (using querySelectorAll), and then we use Array.prototype.map to turn them into "<li>[value]</li>", and then Array.prototype.join to turn that array into a single string.
Then, we get that string and set the #list.innerHTML property.
document.querySelector('button').addEventListener('click', function(e) {
var form = document.querySelector('form'),
list = document.getElementById('list');
list.innerHTML = [].map.call(form.querySelectorAll('input'), function(el) {
return '<li>' + el.value + '</li>';
}).join('');
});
<form>
ID Number:
<br>
<input type="text" id="idNumber">
<br>First name:
<br>
<input type="text" id="firstName">
<br>Last name:
<br>
<input type="text" id="lastName">
</form>
<br>
<button type="submit">Submit</button>
<div id="container">
<ul id="list"></ul>
</div>

JavaScript Not Displaying Compiled Text

I'm trying to put together a little script to save some typing for some stuff we type repetitively at my office. Basically the idea is that you select a couple options and then the page displays a paragraph inserting some of the selected custom text at various places.
Anyways, this is what I have, and it isn't working. I've tried putting some console.logs in the JavaScript, and they aren't doing anything. Why?
<!DOCTYPE html>
<html>
<head>
<script>
function write() {
var name1 = document.getElementById("firstname");
var name = name1.options[name1.selectedIndex].text;
var gender1 = document.getElementById("gender");
var gender = gender1.options[gender1.selectedIndex].text;
var authentication1 = document.getElementById("authentication");
var name = authentication1.options[authentication1.selectedIndex].text;
var answer = name + gender + authentication; // There will be some other text added in here eventually
document.getElementById("text").innerHTML += answer;
}
</script>
</head>
<body>
<form>
<input type="text" name="firstname" placeholder="Name"><br /><br />
<select name="gender">
<option value="his">His</option>
<option value="her">Her</option>
</select><br /><br />
<select name="authentication">
<option value="questions">security questions</option>
<option value="firstyear">first year attended</option>
<option value="birthday">birthday and mailing address</option>
</select><br /><br />
<input type="submit" value="Submit" onClick="write(); return false;">
</form>
<h2 id="text"></h2>
</body>
</html>
write is a method of document. It will never work, it will just paint a blank page
function writeThis() {
var name = document.forms[0].firstname.value;
var gender = document.forms[0].gender.options[document.forms[0].gender.selectedIndex].text;
var authentication = document.forms[0].authentication.options[document.forms[0].authentication.selectedIndex].text;
document.getElementById("text").innerHTML += (name + " " + gender + " " + authentication);
}
I renamed your function as writeThis() so make sure in your html :
<input type="submit" value="Submit" onClick="writeThis();return false">
Also, the new function show you how to get the values. Review it that way you learn how to do it. Finally, it's a better practice if you close always your html tags <input /> not <input>.
And the fiddle: http://jsfiddle.net/xr7vqsfm/4/

Dynamically remove a dynamically added input (type=file)

I have a form where user can add files to be uploaded. Change event on that input adds new input the same type and so on. But the new inputs have to have "X" character with click event attached to it to be able to remove the input field and the X chracter.
The form:
<form id="upload_form">
<div class="p_file">
<p class="icon">X</p>
<input type="file" name="userfile1" size="40" class="required" />
</div>
</form>
and the JavaScript:
$('#upload_form input[type="file"]').change(function(){
addUploadField($(this));
});
function addUploadField($field)
{
$current_count = $('#upload_form input[type="file"]').length
$next_count = $current_count + 1;
$field.parent('p').after('
<div class="p_file" >
<p class="icon">X</p>
<input type="file" name="userfile'+$next_count+'" size="40" />
</div>
');
$field.unbind('change');
$nextField = $('#upload_form input[type="file"]').last();
$nextField.bind('change',function(){
addUploadField($(this));
});
$("#upload_form .icon").on('click',function(){
removeUploadField($field);
});
}
function removeUploadField($field)
{
$field.parent('p').remove();
}
The code above remove all the fields after the clicked 'X' character. What I want to do is to remove only the next input field.
I tried to prepare this example in jsFiddle, but I can't make this work. Anyhow maybe this would help.
Putting "div" tag inside "p" tag is the main problem
Remove is corrected in this code
Note: In your html code "div" is is added inside "p" tag, this is invalid practice
HTML:
<form id="upload_form">
<div class="p_file">
<div class="icon">X</div>
<input type="file" name="userfile1" size="40" class="required" />
</div>
</form>
Script:
$('body')
.delegate('#upload_form input[type="file"]', 'change', inputChanged)
.delegate('#upload_form .icon', 'click', removeField);
function inputChanged() {
$current_count = $('#upload_form input[type="file"]').length;
$next_count = $current_count + 1;
$(this).closest('.p_file').after(
'<div class="p_file" ><div class="icon">X</div>' +
'<input type="file" name="userfile'
+ $next_count + '" size="40" /></div>');
}
function removeField(){
$(this).closest('.p_file').remove();
return false;
}
Link: http://jsfiddle.net/cBrQX/2/

Categories