Name href Label According to User Text Input JavaScript - javascript

In my app, I am letting the user add categories. Each category is a simple href with label that the user entered as a name of category. The problem I am having is the category name is shown (undefined). So I am not sure where is the problem. Also, when I click again on add category, the previously created one disappear!
var boxName="type here";
var inputt = document.getElementById("boxName").value;
function addInput()
{
// var boxName="type here";
document.getElementById('responce').innerHTML='<br/><input type="text" id="'+boxName+'" value="'+boxName+'" /><input type="button" onclick="addlinking()" value="Add"/><span id="Adding"></span>';
var inputt = document.getElementById("boxName").value;
addlinking(inputt);
}
function addlinking(tt){
document.getElementById('Adding').innerHTML = '<br/><input type="submit" onclick="addinghref()" value="'+tt+'"><i class="fa fa-angle-right"></i></a><span id="Linking"></span>';
}
function addinghref()
{
document.getElementById('Linking').innerHTML='';
}
<input type="button" onclick="addInput()" value="Add Category">
<span id="responce"></span>

var catTemplate = document.getElementById("adding-template")
.content
.querySelector(".category");
var createCatDiv = document.getElementById('create-cat');
var createCatInput = createCatDiv.querySelector("input[type=text]");
function addInput()
{
// Clear previous entry.
createCatInput.value = "";
// Show the div.
createCatDiv.classList.remove("hidden");
}
function addlinking()
{
// Hide the create cat div.
createCatDiv.classList.add("hidden");
// Import the category div from the template.
var catDiv = document.importNode(catTemplate, true);
document.getElementById("response").appendChild(catDiv);
// Set the input.
var input = catDiv.querySelector("input");
input.value = createCatInput.value;
// Replace duckduckgo by the address of your link.
input.onclick = location.assign.bind(location, "https://duckduckgo.com");
}
#create-cat {
margin-top: 1em;
}
#create-cat.hidden {
display: none;
}
.category{
margin-top: 1em;
}
.category input[type=button] {
background-color: lightblue;
border-style: solid;
border-color: gray;
border-width: 1px;
border-radius: 5px;
}
.category input[type=button]:hover {
background-color: blue;
color: white;
border-color: black;
}
.category input[type=button]:active {
background-color: black;
color: white;
border-color: black;
}
<template id="adding-template">
<div class="category">
<input type="button" />
</div>
</template>
<input type="button" onclick="addInput()" value="Add Category">
<div id="response"></div>
<div id="create-cat" class="hidden">
<input type="text" placeholder="type here" />
<input type="button" onclick="addlinking()" value="Add"/>
</div>

var boxName = "type here";
var id = boxName.replace(/\s/g, '_');
function addInput() {
document.getElementById('responce').innerHTML = '<br/><input type="text" id="' + id + '" value="' + boxName + '" /><input type="button" onclick="addlinking()" value="Add"/><span id="Adding"></span>';
}
function addlinking(tt) {
var inputt = document.getElementById(id).value;
document.getElementById('Adding').innerHTML = '<br/><input type="submit" onclick="addinghref()" value="' + inputt + '"><i class="fa fa-angle-right"></i></a><span id="Linking"></span>';
}
function addinghref() {
document.getElementById('Linking').innerHTML = 'Link';
}
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/4.1.1/normalize.min.css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.6.1/css/font-awesome.min.css">
<input type="button" onclick="addInput()" value="Add Category">
<span id="responce"></span>

Related

Javascript appended code comes as undefined

I have this code where I take the submissions from a form and append it to a HTML.
<!DOCTYPE html>
<html>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<head>
<style>
* {
box-sizing: border-box;
}
div {
padding: 10px;
background-color: #f6f6f6;
overflow: hidden;
}
input[type=text],
textarea,
select {
font: 17px Calibri;
width: 100%;
padding: 12px;
border: 1px solid #ccc;
border-radius: 4px;
}
input[type=button] {
font: 17px Calibri;
width: auto;
float: right;
cursor: pointer;
padding: 7px;
}
</style>
</head>
<body>
<div>
<div>
<input type="text" id="txtName" placeholder="Enter your name" />
</div>
<div>
<input type="text" id="txtAge" placeholder="Enter your age" />
</div>
<div>
<input type="text" id="txtEmail" placeholder="Enter your email address" />
</div>
<div>
<select id="selCountry">
<option selected value="">-- Choose the country --</option>
<option value="India">India</option>
<option value="Japan">Japan</option>
<option value="USA">USA</option>
</select>
</div>
<div>
<textarea id="msg" name="msg" placeholder="Write some message ..." style="height:100px"></textarea>
</div>
<div>
<input type="button" id="bt" value="Write" onclick="writeFile()" />
</div>
</div>
<p>Submission Number: <a id="clicks">1</a>
<div class="output-area">
<h4>Output</h4>
<div id="output" class="inner">
</div>
</div>
<span></span>
</body>
<script>
var clicks = 1;
let writeFile = () => {
const name = document.getElementById('txtName');
const age = document.getElementById('txtAge');
const email = document.getElementById('txtEmail');
const country = document.getElementById('selCountry');
const msg = document.getElementById('msg');
const submissions = document.getElementById('clicks');
let data = [
`<p>Name: ${name.value}</p>`,
`<p>Age: ${age.value}</p>`,
`<p>Email: ${email.value}</p>`,
`<p>Country: ${country.value}</p>`,
`<p>Message: ${msg.value}</p>`,
`<p>Submission No: ${submissions.value}</p>`];
$('#output').append("<br />" + "<br />");
data.forEach(line => $('#output').append(line));
clicks += 1;
document.getElementById("clicks").innerHTML = clicks;
}
</script>
</html>
In this code, I wanted to print the users' current submission number. So I made a click counter.
clicks += 1;
document.getElementById("clicks").innerHTML = clicks;
And then I tried to put it into a constant and append it.
const submissions = document.getElementById('clicks');
But issue I'm facing here is, when appended my submission field comes out as Submission No: undefined. Any help would be much appreciated.
Your submissions element is an anchor (<a>) element. These HTML elements do not have a value field.
You can read the value the same way you are writing it, via innerHTML.
E.g.
<!DOCTYPE html>
<html>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<head>
<style>
* {
box-sizing: border-box;
}
div {
padding: 10px;
background-color: #f6f6f6;
overflow: hidden;
}
input[type=text],
textarea,
select {
font: 17px Calibri;
width: 100%;
padding: 12px;
border: 1px solid #ccc;
border-radius: 4px;
}
input[type=button] {
font: 17px Calibri;
width: auto;
float: right;
cursor: pointer;
padding: 7px;
}
</style>
</head>
<body>
<div>
<div>
<input type="text" id="txtName" placeholder="Enter your name" />
</div>
<div>
<input type="text" id="txtAge" placeholder="Enter your age" />
</div>
<div>
<input type="text" id="txtEmail" placeholder="Enter your email address" />
</div>
<div>
<select id="selCountry">
<option selected value="">-- Choose the country --</option>
<option value="India">India</option>
<option value="Japan">Japan</option>
<option value="USA">USA</option>
</select>
</div>
<div>
<textarea id="msg" name="msg" placeholder="Write some message ..." style="height:100px"></textarea>
</div>
<div>
<input type="button" id="bt" value="Write" onclick="writeFile()" />
</div>
</div>
<p>Submission Number: <a id="clicks">1</a>
<div class="output-area">
<h4>Output</h4>
<div id="output" class="inner">
</div>
</div>
<span></span>
</body>
<script>
var clicks = 1;
let writeFile = () => {
const name = document.getElementById('txtName');
const age = document.getElementById('txtAge');
const email = document.getElementById('txtEmail');
const country = document.getElementById('selCountry');
const msg = document.getElementById('msg');
const submissions = document.getElementById('clicks');
let data = [
`<p>Name: ${name.value}</p>`,
`<p>Age: ${age.value}</p>`,
`<p>Email: ${email.value}</p>`,
`<p>Country: ${country.value}</p>`,
`<p>Message: ${msg.value}</p>`,
`<p>Submission No: ${submissions.innerHTML}</p>`]; // Use innerHTML here
$('#output').append("<br />" + "<br />");
data.forEach(line => $('#output').append(line));
clicks += 1;
document.getElementById("clicks").innerHTML = clicks;
}
</script>
</html>
Generally you could of course also insert the clicks variable directly (instead of the contents of the a element).
Note
It is highly insecure to render user-input into your HTML. It creates all sorts of vulnerabilities for malicious users so DON'T do this in production.
<a> tags don't have a value attribute. You'll have to use textContent or innerText to get the count.
console.log(document.getElementById('clicks').textContent);
<a id="clicks">2</a>
Ok, so submissions is not a input element and so it does not have the value method.
Instead of using submissions.value use submissions.innerHTML.
Also, rearrange the last few lines to make sure the clicks counter is updated before outputting all the data.
Edit: I did not realize your clicks counter was initially let clicks = 1; and not let clicks = 0;. The rearranging in the below JS will only work if clicks is initially set to 0.
I would generally advise to use let clicks = 0; because it makes more sense to potentially yourself and another person reading your code. If you think about it - when you make your counter (clicks), there have not been any clicks yet and so it would make more sense to have it initially set to 0.
let clicks = 0;
const writeFile = () => {
const name = document.getElementById('txtName');
const age = document.getElementById('txtAge');
const email = document.getElementById('txtEmail');
const country = document.getElementById('selCountry');
const msg = document.getElementById('msg');
const submissions = document.getElementById('clicks');
// ++ is same thing as += 1
clicks++;
submissions.innerHTML = clicks;
let data = [
`<p>Name: ${name.value}</p>`,
`<p>Age: ${age.value}</p>`,
`<p>Email: ${email.value}</p>`,
`<p>Country: ${country.value}</p>`,
`<p>Message: ${msg.value}</p>`,
`<p>Submission No: ${submissions.innerHTML}</p>`
];
$('#output').append("<br />" + "<br />");
data.forEach(line => $('#output').append(line));
}

Use JS to determine if all form fields are filled and correctly

*Edit: Fixed so that all inputs are now validated on one form. However, I can only add one variable to check if blank, as soon as I add more, none of the submit functions work. I have been trying multiple things.
function validateForm() {
var inputVelocity = document.getElementById("dzCalculator").inputVelocity.value;
var inputYellowPhase = document.getElementById("dzCalculator").inputYellowPhase.value;
var inputRedPhase = document.getElementById("dzCalculator").inputInterPhase.value;
var inputReactionTime = document.getElementById("dzCalculator").inputReactionTime.value;
if(inputVelocity === "" && inputYellowPhase === "" && inputRedPhase === "" && inputReactionTime === ""){
alert("Input all fields to calculate.");
return false;
}
}
I have checked the HTML matches - it does. But I found I could not use onsubmit="return validateForm" as this wouldn't work at all.
This is only 4 of the form values, there are seven all up. But when I can get the four working, I can get them all working.
How can I use JS to make sure that no input is left blank or empty? I already have made it so that it will only accept numbers and decimal points. So no one can add an incorrect field. But currently, they can leave a field blank which means my calculator generates a NaN response.
Also, how can I make sure one of my fields can not accept a number greater than 1 or less than 0. I tried min="0" max="1" in the input tag, but because I have removed spinners, this doesn't work.
So, in summary, I am looking to make sure when a button is clicked that all the form sections are filled in and that one of the fields doesn't accept a number greater that 1 or less than zero.
there are 2 options for this.
You can select all the inputs (inside the form tag) using querySelector and check the value of each input by looping through them.
use this trick selector to get all the invalid inputs
document.querySelectorAll('input:not([value]):not([value=""])');
replace input with more precise selector.
Can you please give more detail about how your form is in multiple places?
For input I think you need to use step attribute
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/number#step
Reference: javascript_form_validation
Depends when would you like to validate form fields
For example: Form validation on submit
function validateForm() {
var x = document.forms["myForm"]["fname"].value;
if (x == "") {
alert("Name must be filled out");
return false;
}
}
<html>
<body>
<form name="myForm" action="/action_page.php" onsubmit="return validateForm()" method="post">
Name: <input type="text" name="fname">
<input type="submit" value="Submit">
</form>
</body>
</html>
Give name to your form using name attribute such as <form name="myForm" ..>
Then using document.forms["myForm"] you can have access to your form
There you can validate your input fields value. return true if validates
This works for me. You can use it, style it however you want or not. You do need JQuery. It has powerful selectors.
<!DOCTYPE html>
<html lang="en">
<head>
<style type="text/css">
body{
font-size: 12px;
}
.main-container{
display: flex; /* DO NOT CHANGE */
height: 100vh; /* DO NOT CHANGE */
width: 100%; /* DO NOT CHANGE */
}
.c-message{
display: flex; /* DO NOT CHANGE */
position: fixed; /* DO NOT CHANGE */
top: 0px; /* DO NOT CHANGE */
left: 0px; /* DO NOT CHANGE */
width: 100%; /* DO NOT CHANGE */
height: 100%; /* DO NOT CHANGE */
}
.c-msgbox{
padding: 30px;
text-align: center;
margin: auto; /* DO NOT CHANGE */
background-color: #e4e4e4;
border-radius: 4px;
border: 1px solid #adadad;
-webkit-box-shadow: 0px 0px 50px rgba(0, 0, 0, 0.60);
-moz-box-shadow: 0px 0px 50px rgba(0, 0, 0, 0.60);
box-shadow: 0px 0px 20px rgba(0, 0, 0, 0.40);
}
.standerd-button2{
border: none;
font-family: arial,helvetica,clean,sans-serif;
font-size: 10px;
font-weight: 600;
color: white;
background: #1A709F;
padding: 3px;
text-align: center;
vertical-align: middle;
-webkit-border-radius: 3px;
width: max-content;
min-width: 50px;
margin: 2px;
}
.standerd-button2:hover{
background: crimson;
cursor: default;
}
.f-table {
display: table;
width: max-content;
padding: 5px;
border-spacing: 2px;
}
.f-tablerow {
display: table-row;
}
.f-tablecell{
display: table-cell;
}
.label-cell-r{
text-align: right;
}
.dd-required{
margin: auto;
color: red;
}
input, select{
border: 1px solid lightgrey;
}
</style>
<script type="text/javascript" src="JQuery.js"></script>
</head>
<body>
<div class="main-container">
<div>
<form id="f1" name="f1">
<div class="f-table">
<div class="f-tablerow">
<div class="f-tablecell label-cell-r">
<label for="firstname">First Name</label>
</div>
<div class="f-tablecell input-cell">
<input id="firstname" name="firstname" type="text" data-er="First Name"/>
<span class='dd-required'>*</span>
</div>
</div>
<div class="f-tablerow">
<div class="f-tablecell label-cell-r">
<label for="lastname">Last Name</label>
</div>
<div class="f-tablecell input-cell">
<input id="lastname" name="lastname" type="text" data-er="Last Name"/>
<span class='dd-required'>*</span>
</div>
</div>
<div class="f-tablerow">
<div class="f-tablecell label-cell-r">
<label for="company">Company</label>
</div>
<div class="f-tablecell input-cell">
<select id="company" name="company" data-er="Company Name">
<option value="0"> - Select Comapny - </option>
<option value="1">Company 1</option>
<option value="2">Company 2</option>
<option value="3">Company 3</option>
<option value="4">Company 4</option>
</select>
<span class='dd-required'>*</span>
</div>
</div>
</div>
<input id="b1" type="submit" value="Submit" />
</form>
</div>
<div>
<script type="text/javascript">
$.fn.CustomAlert = function (options, callback) {
var settings = $.extend({
message: null,
detail: null,
yesno: false,
okaytext: null,
yestext: null,
notext: null
}, options);
var frm = "";
detail = "<b>" + settings.detail + "</b>";
message = "<b>" + settings.message + "</b>";
if (settings.detail === null) {
detail = "";
};
frm = frm + message + "<div style='text-align: left; margin-top: 15px; margin-bottom: 15px;'>" + detail + "</div>";
if (settings.yesno === false) {
frm = frm + "<input id='ok' type='button' value='" + settings.okaytext + "' class='standerd-button2' />";
} else {
frm = frm + "<div><input id='yes' type='button' value='" + settings.yestext + "' name='yes' class='standerd-button2' />" +
"<input id='no' type='button' value='" + settings.notext + "' name='no' class='standerd-button2' /></div>";
};
var frmesg = "<div id='cmessage' name='cmessage' class='c-message'>" +
"<div class='c-msgbox'>" +
"<form>" + frm + "</form>" +
"</div>" +
"</div>";
$(".main-container").append(frmesg);
if (!settings.yesno) {
$("#cmessage #ok").click(function () {
$("#cmessage").remove();
callback(false);
});
} else {
$("#cmessage #yes").click(function () {
$("#cmessage").remove();
callback(true);
});
$("#cmessage #no").click(function () {
$("#cmessage").remove();
callback(false);
});
};
};
$.fn.JsFormCheck = function () {
var MessData = "";
this.find('select, input').each(function () {
if ($(this).attr("data-er")) {
m = $(this).attr("data-er");
switch ($(this).get(0).tagName) {
case "INPUT":
if ($(this).val().length === 0) {
MessData = MessData + "- " + m + "<br>";
$(this).css('border-bottom', '2px solid green');
};
break;
case "SELECT":
if ($(this).val() === "0") {
MessData = MessData + "- " + m + "<br>";
$(this).css('border-bottom', '2px solid green');
};
break;
};
};
});
if (MessData.length > 0) {
MessData = "<b>" + MessData + "</b>";
x = $().CustomAlert({message: "<b>Please fill in the following required fields to continue.</b>",
detail: MessData,
okaytext: "Close",
yesno: false});
return true;
} else {
return false;
};
};
$('#f1 #b1').click(function(event){
event.preventDefault();
Error = $("#f1").JsFormCheck();
if(Error === false){
null;
//Do Something
};
});
</script>
</body>

jQuery issue for deleting input field

I'm trying to add an input field when clicking on add, and it should be removed when clicking on delete click.
Here is JS Bin link:
JS issue with deletion
var newTextBoxDiv;
var rowCount = 0;
var counter = 1;
var delCounter = 1;
$(document).ready(function() {
$(document).on('focus', '.txtFocus', function() {
$(this).next('.clearContent').hide()
});
$(document).on('focusout', '.txtFocus', function() {
$('.clearContent').show()
})
});
function addTags(obj) {
var newTextBoxDiv = '<div class="col-md-4 TextBoxMainDiv"><div style=""><div class="input-group" id="" style="width: 40%;margin: 0;padding: 0;padding: 2px;float:left;width:80%;"><input type="text" name="textbox' + counter + '" id="textbox' + counter + '" value="" class="txtFocus" required placeholder="Add Tag" autocomplete="false" style="width: 100%" ><span class="clearContent"><i class="fas fa-times"></i></span> </div><div style="width: 15%;display: inline-block;text-align:right;"><span id="addMore" onClick="addTags(this);"><i class="fas fa-plus-square"></i></span></div></div></div>';
$(obj).hide();
$("#tagElement").append(newTextBoxDiv);
$('.txtFocus').focus();
counter++;
if (counter == 1) {
$(obj).show()
}
}
function deleteTag(obj) {
$(obj).closest('.TextBoxMainDiv').last().find('#addMore').show();
$(obj).closest('.TextBoxMainDiv').last().find('#addMore').css('display', 'block');
$(obj).closest('.TextBoxMainDiv').remove();
counter--;
if (counter == 1) {
$('#addMore').show()
}
}
<div class="row">
<div id="tagElement">
<div> </div>
<div class="col-md-4 TextBoxMainDiv">
<div style="">
<div class="input-group" id="" style="width: 40%;margin: 0;padding: 0;padding: 2px;float:left;width:80%;">
<input type="text" class="txtFocus" required placeholder="Add Tag" id="textBox" autocomplete="false" autofocus="autofocus" style="width: 100%">
<span class="clearContent">
Add
</span>
</div>
<div style="width: 15%;display: inline-block;text-align:right;">
<span id="addMore" onClick="addTags(this);">
cancel
</span>
</div>
</div>
</div>
</div>
</div>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<script src="https://code.jquery.com/jquery-3.1.0.js"></script>
I manage to add the input fields properly, but have issues deleting them. They seem to be deleted randomly.
I think the add and delete button are mixed up, but I couldn't spend time on analysing the code because it's too much code for something that does very little. The following demo:
has a single button that adds a row of form controls:
a checkbox
a text input
a button that deletes it's own row as well as itself.
Demo
var index = 0;
var template = `
<figure class='frame'><input class='status' type='checkbox'><label class='tag'></label><input class='text' type='text' placeholder='Enter New Task'><button class='del' type='button'>➖</button></figure>`;
$('.set').on('click', 'button', function(e) {
if ($(this).hasClass('add')) {
index++;
$('.set').prepend(template);
$('.status:eq(0)').attr('id', 'chx' + index);
$('.tag:eq(0)').attr('for', 'chx' + index);
} else {
$(this).prevUntil('.del, .add').add(this).remove();
}
});
.set {
position: relative;
padding: 2px 0 1px 2px;
min-height: 28px;
border-radius:7px;
}
.frame {
padding: 0;
margin: 0;
min-width:90vw;
}
.add {
position: absolute;
right: 6px;
top: 3px;
display:block;
}
.status {
display: none
}
.tag {
display: inline-table;
font-size: 28px;
line-height: 1;
vertical-align: middle
}
.tag::before {
content: '\2610';
}
.status:checked+.tag::before {
content: '\2611'
}
.text {
display:inline-table;
width: 75%;
margin: 2px 5px 0
}
<form id='ui'>
<fieldset class='set'>
<figure class='frame'>
<input id='chx0' class='status' type='checkbox'>
<label for='chx0' class='tag'></label>
<input class='text' type='text' placeholder='Enter New Task' style='margin:2.5px 2px 0 0' autofocus>
<button class='del' type='button'>➖</button>
</figure>
<button class='add' type='button'>➕</button>
</fieldset>
</form>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
I think your code's logic is working, however, the icon for addition and deletion of inputs is not being rendered.
You can replace your newTextBoxDiv with this:
var newTextBoxDiv = `
<div class="col-md-4 TextBoxMainDiv">
<div style="">
<div class="input-group" id="" style="width: 40%;margin: 0;padding: 0;padding: 2px; float:left; width:80%;">
<input type="text" name="textbox${counter}" id="textbox${counter}" value="" class="txtFocus" required placeholder="Add Tag" autocomplete="false" style="width: 100%" >
<span class="clearContent">
Delete<i class="fas fa-times"></i>
</span>
</div>
<div style="width: 15%;display: inline-block;text-align:right;">
<span id="addMore" onClick="addTags(this);">
Add
</span>
</div>
</div>`;
Notice that I added the word "Add" and "Delete" between the tags, so that you have something to click on
Also, I think you need to swap the word "Add" and "Cancel" in the initial HTML to convey a clearer message, as they are now doing the opposite thing.
Another fix that's needed is to replace the id="addMore" with class="addMore"
<span class="addMore" onClick="addTags(this);">
Since id is meant to be unique. In your code, however, when you append new element, you added new elements with duplicate id, making jquery's selector not selecting the element you want.
After replacing id with class, you also need to change the deleteTag function to select the last "addMore" span and show it.
function deleteTag(obj) {
$(obj).closest('.TextBoxMainDiv').last().find('.addMore').show();
$(obj).closest('.TextBoxMainDiv').last().find('.addMore').css('display', 'block');
$(obj).closest('.TextBoxMainDiv').remove();
counter--;
$('.addMore').last().show();
}
For the layout, you need to do it with css, removing float and setting the div tag with appropriate width and display: inline-block. I suggest you use a separate css file to style the elements instead of doing it inline.
function deleteTodo() {
$(this).parent().remove();
}
function addTodo() {
var inputTemplate =
'<div class="todo-input-wrapper">' +
'<input class="todo-input" type="text" placeholder="Add Tag" />' +
'<button class="delete-button">Delete</button>' +
'</div>';
$('.todo-wrapper').append(inputTemplate);
$('.delete-button').last().on('click', deleteTodo);
$('.todo-input').last().focus();
}
$(document).ready(function () {
$('.delete-button').on('click', deleteTodo);
$('.add-button').on('click', addTodo);
});
.todo-wrapper {
display: inline-block;
width: max-content;
font-size: 0;
}
.todo-input-wrapper {
margin: 10px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="todo-wrapper">
<div class="todo-input-wrapper">
<input class="todo-input" type="text" placeholder="Add Tag" />
<button class="delete-button">Delete</button>
</div>
</div>
<button class="add-button">Add</button>

Cannot get table height to contstrain with in div

I've played around with a number of options, but I can't keep the table height from growing as I add lines dynamically.
This is a small section, part of a more complex page. Basically I have several div tags within the larger container div.
As more lines are added the table pushes the button below outside the boundaries of the div. Run the code snippet to observe the problem.
function onBodyLoader(obj) {
g.c.assignEventListners();
}
var g = {};
g.formClass = function() {
/*
----------------------------------
Properties for formClass
----------------------------------
*/
this.tr;
this.td;
this.elist = [];
/*
----------------------------------
Methods for formClass
----------------------------------
*/
this.assignEventListners = function() {
this.tbody = document.getElementById('emailDist');
g.sbAddELine = document.getElementById('sbAddELine');
g.sbAddELine.addEventListener("click", function(evt) {
g.c.addBlank();
}, false);
/*event listener for all links on the email list body*/
g.dataUpdate = document.querySelector("#emailDist");
g.dataUpdate.addEventListener("click", g.c.tableBodyRouter, false);
};
this.tableBodyRouter = function(e) {
/*
called from clicks on keyTable or task links
*/
if (e.target !== e.currentTarget)
if (e.target.id.indexOf('eRemove') > -1)
g.c.removeEmail(e);
e.stopPropagation();
};
this.redrawElist = function() {
/*delete current table*/
while (this.tbody.rows.length > 1)
this.tbody.deleteRow(1);
/*redraw table*/
for (var i = 0; i < this.elist.length; i++) {
this.rowLayout();
}
};
this.addBlank = function() {
/*add blank to this.elist array*/
this.elist.push({
eEmail: '',
eFirst: '',
eLast: '',
});
this.rowLayout();
}
this.removeEmail = function(e) {
var x = e.target.id.substr(7);
this.elist.splice(x, 1);
this.redrawElist();
};
this.rowLayout = function() {
var rowCnt = this.tbody.rows.length - 1;
this.tr = this.tbody.insertRow(this.tbody.rows.length);
this.td = this.tr.insertCell(this.tr.cells.length);
this.td.innerHTML = '<input type="text" id="eFirst' + rowCnt + '" maxlength="20" size="20" value=""/>';
this.td = this.tr.insertCell(this.tr.cells.length);
this.td.innerHTML = '<input type="text" id="eLast' + rowCnt + '" maxlength="20" size="20" value="" />';
this.td = this.tr.insertCell(this.tr.cells.length);
this.td.innerHTML = '<input type="text" id="eEmail' + rowCnt + '" maxlength="50" size="50" value="" />';
this.td = this.tr.insertCell(this.tr.cells.length);
this.td.innerHTML = '<input type="button" id="eRemove' + rowCnt + '" value="Remove" ">';
document.getElementById("eFirst" + rowCnt).focus();
document.getElementById("eFirst" + rowCnt).select();
}
}
g.c = new g.formClass;
table {
height: 60%;
max-height: 60%;
width: 100%;
display: inline-table;
border-style: none;
}
tbody {
font-size: 10pt;
display: block;
height: 90%;
overflow-y: scroll;
}
#container {
position: absolute;
width: 98%;
top: 40px;
height: 90%;
}
#dataEntryDiv {
border: medium groove;
position: absolute;
top: 0.5em;
height: 95%;
padding-left: 1em;
padding-right: 1em;
}
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Email List</title>
</head>
<body id="intactRolesBody" onLoad="onBodyLoader(this);">
<form id='intactRolesForm' method="post" action="" onSubmit="return false;">
<div id="container">
<div id="dataEntryDiv">
<input type="button" id='sbAddELine' value="Add non-company contact"><br>
<p>Email Distribution List</p>
<table>
<tbody id='emailDist'>
<tr>
<th>First Name</th>
<th>Last Name</th>
<th>email</th>
<th>remove from list</th>
</tr>
</tbody>
</table>
<input type="button" id='SaveEmailList' value="Save email List">
</div>
</div>
</form>
</body>
</html>
This is the basic behavior of a table. it shrinks and expand acording to its content.
What you can do to manage height is to reset the display.
it can be anything but table/inline-table/table-cell/table-row/.. . nor inline.
You used inline-table, inline-block might be fine:
function onBodyLoader(obj) {
g.c.assignEventListners();
}
var g = {};
g.formClass = function() {
/*
----------------------------------
Properties for formClass
----------------------------------
*/
this.tr;
this.td;
this.elist = [];
/*
----------------------------------
Methods for formClass
----------------------------------
*/
this.assignEventListners = function() {
this.tbody = document.getElementById('emailDist');
g.sbAddELine = document.getElementById('sbAddELine');
g.sbAddELine.addEventListener("click", function(evt) {
g.c.addBlank();
}, false);
/*event listener for all links on the email list body*/
g.dataUpdate = document.querySelector("#emailDist");
g.dataUpdate.addEventListener("click", g.c.tableBodyRouter, false);
};
this.tableBodyRouter = function(e) {
/*
called from clicks on keyTable or task links
*/
if (e.target !== e.currentTarget)
if (e.target.id.indexOf('eRemove') > -1)
g.c.removeEmail(e);
e.stopPropagation();
};
this.redrawElist = function() {
/*delete current table*/
while (this.tbody.rows.length > 1)
this.tbody.deleteRow(1);
/*redraw table*/
for (var i = 0; i < this.elist.length; i++) {
this.rowLayout();
}
};
this.addBlank = function() {
/*add blank to this.elist array*/
this.elist.push({
eEmail: '',
eFirst: '',
eLast: '',
});
this.rowLayout();
}
this.removeEmail = function(e) {
var x = e.target.id.substr(7);
this.elist.splice(x, 1);
this.redrawElist();
};
this.rowLayout = function() {
var rowCnt = this.tbody.rows.length - 1;
this.tr = this.tbody.insertRow(this.tbody.rows.length);
this.td = this.tr.insertCell(this.tr.cells.length);
this.td.innerHTML = '<input type="text" id="eFirst' + rowCnt + '" maxlength="20" size="20" value=""/>';
this.td = this.tr.insertCell(this.tr.cells.length);
this.td.innerHTML = '<input type="text" id="eLast' + rowCnt + '" maxlength="20" size="20" value="" />';
this.td = this.tr.insertCell(this.tr.cells.length);
this.td.innerHTML = '<input type="text" id="eEmail' + rowCnt + '" maxlength="50" size="50" value="" />';
this.td = this.tr.insertCell(this.tr.cells.length);
this.td.innerHTML = '<input type="button" id="eRemove' + rowCnt + '" value="Remove" ">';
document.getElementById("eFirst" + rowCnt).focus();
document.getElementById("eFirst" + rowCnt).select();
}
}
g.c = new g.formClass;
table {
height: 60%;
max-height: 60%;
width: 100%;
display: inline-block;/*... or block : do not use table display if you need to constrain height */
border-style: none;
}
tbody {/* this CSS could have been set to table directly :) */
font-size: 10pt;
display: block;
height: 90%;
overflow-y: scroll;
}
#container {
position: absolute;
width: 98%;
top: 40px;
height: 90%;
}
#dataEntryDiv {
border: medium groove;
position: absolute;
top: 0.5em;
/*left: 37em; removed for demo */
height: 95%;
padding-left: 1em;
padding-right: 1em;
}
<body id="intactRolesBody" onLoad="onBodyLoader(this);">
<form id='intactRolesForm' method="post" action="" onSubmit="return false;">
<div id="container">
<div id="dataEntryDiv">
<input type="button" id='sbAddELine' value="Add non-company contact"><br>
<p>Email Distribution List</p>
<table>
<tbody id='emailDist'>
<tr>
<th>First Name</th>
<th>Last Name</th>
<th>email</th>
<th>remove from list</th>
</tr>
</tbody>
</table>
<input type="button" id='SaveEmailList' value="Save email List">
</div>
</div>
</form>
</body>
Note: You did use display:block on tbody, you could have apply this directly to the table element and reset tbody to display:table :) (defaut is table-row-group )
Add
#dataEntryDiv {
overflow: auto;
}
To get a simplified version of the situation, I would suggest writing something like this - instead of putting in the code from your actual project. This way, you can get away from trying to 'fix' something - and possibly see a better way to build the layout - or at least make the use-case more specific.
https://stackoverflow.com/help/how-to-ask
markup
<section class="table-wrapper">
<header>
I'm a table wrapper thing
</header>
<main>
<table>
<!-- populate this -->
</table>
</main>
<footer>
<button>button (add row)</button>
</footer>
</section>
styles
.table-wrapper {
height: 300px; /* arbitrary */
border: 2px solid red;
}
.table-wrapper main {
height: 260px; /* likely you'd use flexbox or percentages or JS */
border: 2px solid blue;
overflow: auto;
}
js
var $table = $('.table-wrapper').find('table');
var $moreButton = $('.table-wrapper').find('button');
var counter = 0;
function addRow() {
counter = counter + 1;
$table.prepend('<tr><td>row and data ' + counter + '</td></tr>');
}
addRow();
// populate some things to start
$moreButton.on('click', function() {
addRow();
});
https://jsfiddle.net/sheriffderek/b6z4ep46/

Multiple plus and minus buttons

I am using - and + buttons to change the number of the text box, I am having troubles dealing with different text fields, here is my code:
var unit = 0;
var total;
// if user changes value in field
$('.field').change(function() {
unit = this.value;
});
$('.add').click(function() {
unit++;
var $input = $(this).prevUntil('.sub');
$input.val(unit);
unit = unit;
});
$('.sub').click(function() {
if (unit > 0) {
unit--;
var $input = $(this).nextUntil('.add');
$input.val(unit);
}
});
button {
margin: 4px;
cursor: pointer;
}
input {
text-align: center;
width: 40px;
margin: 4px;
color: salmon;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id=field1>
field 1
<button type="button" id="sub" class=sub>-</button>
<input type="text" id="1" value=0 class=field>
<button type="button" id="add" class=add>+</button>
</div>
<div id=field2>
field 2
<button type="button" id="sub2" class=sub>-</button>
<input type="text" id="2" value=0 class=field>
<button type="button" id="add2" class=add>+</button>
</div>
And here's the DEMO
You can see in the demo that the values change correctly only if you click buttons on the same field, but if you alternate between fields the values don't change properly.
This should be all you need:
$('.add').click(function () {
$(this).prev().val(+$(this).prev().val() + 1);
});
$('.sub').click(function () {
if ($(this).next().val() > 0) $(this).next().val(+$(this).next().val() - 1);
});
By using the unit variable you were tying both inputs together. And the plus in +$(this) is a shorthand way to take the string value from the input and convert it to a number.
jsFiddle example
You're using the same variable to hold the values of your two inputs. One simple option would be to use two variables instead of one:
var unit_1 = 0;
$('#add1').click(function() {
unit_1++;
var $input = $(this).prev();
$input.val(unit_1);
});
/* Same idea for sub1 */
var unit_2 = 0;
$('#add2').click(function() {
unit_2++;
var $input = $(this).prev();
$input.val(unit_2);
});
/* Same idea for sub2 */
and unit = unit just assigns the value of unit to itself, so that's no very useful and you can certainly leave it out.
An alternative approach is to use data attributes and have each element store its own value. Edit: it already stores its own value. Just access it.
var total;
// if user changes value in field
$('.field').change(function() {
// maybe update the total here?
}).trigger('change');
$('.add').click(function() {
var target = $('.field', this.parentNode)[0];
target.value = +target.value + 1;
});
$('.sub').click(function() {
var target = $('.field', this.parentNode)[0];
if (target.value > 0) {
target.value = +target.value - 1;
}
});
button {
margin: 4px;
cursor: pointer;
}
input {
text-align: center;
width: 40px;
margin: 4px;
color: salmon;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id=field1>
field 1
<button type="button" id="sub" class=sub>-</button>
<input type="text" id="1" value=0 class=field>
<button type="button" id="add" class=add>+</button>
</div>
<div id=field2>
field 2
<button type="button" id="sub2" class=sub>-</button>
<input type="text" id="2" value=0 class=field>
<button type="button" id="add2" class=add>+</button>
</div>

Categories