I want to display an array of numbers, after that if he users wishes to change any of the numbers in array then he/she should write the desired value in its place and click submit button the array gets updated and display the updated array.
I have tried this till now, and gone through numerous articles to find a solution but i couldn't find one which fits here.
This is what my code looks like, it is a bit long but I dont know how much code is adequate so this is it.. please help me get this.
making grid editable
<style>
#container{
display:grid;
grid-template-columns: repeat(9, 8%);
margin-left: 35%;
margin-right:25%;
margin-top:10%;
}
</style>
<body style="background-color:grey">
<div id='container'>
</div>
<input id="someInput" type="text" value=<p id="output"></p>>
<input type="button" value="submit" onClick="doStuff()">
</body>
<script>
var myContainer = document.getElementById('container')
grid=[0,1,4,6,3,0,9,3,2];
for(var i=0;i<9;i++){
var myInput = document.createElement('input')
//we want to add position of an input box as id
myInput.id= `${i}`
var num=grid[i];
myInput.value=num;
myContainer.appendChild(myInput)
}
var x = document.createElement("BUTTON");
function doStuff(){
var nameElement = document.getElementById("someInput");
a = nameElement.value
b = nameElement.id
new_grid=[];
for(var j=0;j<9;j++){
if(j==b){
new_grid[j]=a;
}
else{
new_grid[j]=grid[j];
}
}
for(var i=0;i<9;i++){
var myInput = document.createElement('input')
//we want to add position of an input box as id
myInput.id= `${i}`
var num=new_grid[i];
myInput.value=num;
myContainer.appendChild(myInput)
}
}
window.onload = function() {
//when the document is finished loading, replace everything
//between the <a ...> </a> tags with the value of splitText
document.getElementById("output").innerHTML=grid[4];
}
</script>
'''
then I tried to add a input box so that i can show the array numbers in value attribute of it and when users updates it and clicks submit button it gets updated but then i wasn't able to get array numbers in value attribute of input tag.
This will update your grid array values with the user inputted values on button click.
var myContainer = document.getElementById('container');
grid = [0,1,4,6,3,0,9,3,2];
for(var i=0; i < grid.length; i++){
var myInput = document.createElement('input')
//we want to add position of an input box as id
myInput.id = `${i}`
myInput.value = grid[i];
myContainer.appendChild(myInput);
}
var x = document.createElement("BUTTON");
x.textContent = "UPDATE";
myContainer.appendChild(x);
x.addEventListener("click", UpdateGridFromUserInput, false);
function UpdateGridFromUserInput() {
var allinputs = document.getElementById('container').getElementsByTagName('input');
for(var j = 0; j < allinputs.length; j++) {
grid[j] = allinputs[j].value;
}
console.log(grid);
}
<div id="container">
</div>
Here's an example. I just use input number fields. You can set the min max and add an onChange event if you want to change the value of the nums array.
const nums = [1, 2, 3, 4, 5];
const container = document.querySelector(".container");
nums.forEach(num => {
const numElm = document.createElement("input");
numElm.classList.add("number");
numElm.type = "number";
numElm.min = 1;
numElm.max = 9;
numElm.value = num;
container.appendChild(numElm);
});
.container {
display: flex;
justify-content: space-between;
}
.number {
padding: .5rem;
width: 2rem;
text-align: center;
border: 2px solid grey;
border-radius: 10px;
}
<div>
<p>Selected numbers</p>
<div class="container" />
</div>
I think you have got relevant solutions already, but I would like to show you "little another way" which save a few rows of code and it is more optimal with larger arrays.
Instead of the iterating array when you want to change a single number, you can add an event listener to it. You save an ID to the element by the index of the array, so it is easy to approach the actual position in the array.
First thing first, I would like to comment on a few things in your code, which could be better (we all learn!)
for(var i=0;i<9;i++){var myInput = document.createElement('input') ...
You want to create an input for each element in the array. As a programmer, you know that there will be 9 elements, but (as a programmer :)) you don't always want to remember and count how many elements the array has. It is better to use grid.length which returns the actual length of the array.
function doStuff(){...}
Always name your functions as what they are really doing. It really helps!
var nameElement = document.getElementById("someInput");
a = nameElement.value
b = nameElement.id
Always name your properties as what they actually mean. You could use "input", "inputValue", "inputId". Helps too :)
In doStuff() function, you are creating other inputs again. I think it is not really necessary when you have already created them.
Second thing second let's look at how it looks like as I described before.
Here is the code (use and learn ES6, it's better, trust me):
let array = [0, 1, 4, 6, 3, 0, 9, 3, 2];
let container = document.getElementById("container");
let output = document.getElementById("arrayResult");
output.innerHTML = array;
//create inputs for the array
for (let i = 0; i < array.length; i++) {
let inputElement = document.createElement("input");
inputElement.type = "number";
inputElement.id = i;
inputElement.value = array[I];
//if an user change the value, update the array at its position
inputElement.addEventListener("input", () => {
let id = inputElement.id;
array[id] = inputElement.value;
})
container.appendChild(inputElement);
}
//create submit button
let submit = document.createElement("input");
submit.type = "submit";
submit.value = "Change";
container.appendChild(submit);
//update output
submit.addEventListener("click", () => {
output.innerHTML = array;
});
<div id="container">
</div>
<div>
<label>Result:</label>
<label id="arrayResult"></label>
</div>
Related
I've tried this code that was posted but I can't get it to work the way I need. I can get it to create both fields but I can't make them look the same as the format of the first fields. How can I Add the entire section and make it look the same? and control the maximum number of activities inserted.
TIA
This is what I'm trying to acomplish
const addActivity = document.getElementById("add");
var i = 0;
const activityDiv = document.getElementById("Activity");
addActivity.addEventListener("click", function() {
i++;
const newspan = document.createElement('div');
newspan.className = "activityGroup";
const removeButton = document.createElement('button');
removeButton.addEventListener('click', function(e) {
e.target.closest(".activityGroup").remove();
});
removeButton.className = "delbtn";
removeButton.innerHTML = "X";
//
const txtfield = document.createElement('input');
const txtarea = document.createElement('textarea');
//
txtfield.id = 'activity_' + i;
txtfield.placeholder = "Activity " + i;
newspan.appendChild(txtfield);
//
newspan.appendChild(txtarea);
txtarea.id = 'activity_description_' + i;
txtarea.placeholder = "Activity Description " + i;
newspan.appendChild(removeButton);
activityDiv.appendChild(newspan);
});
.delbtn{color:red;}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="Activity">
<div class="activityGroup">
<input placeHolder="Type your activity" />
<br>
<br>
<textarea rows="5" cols="50" placeHolder="Type your descvription"></textarea>
<button class="delbtn">X</button>
</div>
<!-- Remove button -->
</div>
<button id="add">Add Activity</button>
First, the problems:
I can get it to create both fields but I can't make them look the same as the format of the first fields...
This is likely because in your original .activityGroup there are a number of <br> elements between the <input> and the <textarea> elements – incorrectly – used for spacing which you haven't inserted into the copy.
Also, two of the attributes of the original <textarea> (rows="5", and cols="50") are omitted from the one you create within the function, not to mention the line-breaks and other white-space.
This can be rectified by simply creating, and appending, those other elements:
// first, some utility functions to simplify life:
const D = document,
get = (sel, ctx = D) => ctx.querySelector(sel),
getAll = (sel, ctx = D) => [...ctx.querySelectorAll(sel)],
create = (tag, props) => Object.assign(D.createElement(tag), props),
// renamed variables for consistency between JavaScript
// and the HTML upon which it acts:
addBtn = get("#addBtn"),
activity = get("#activity"),
// creating a generator function to use as a counter;
// fundamentally this is little different from the
// original i = 0 and then incrementing in the function
// body, but the generator can't be affected by an
// accidental decrement:
iterator = function*() {
// initial value:
let count = 1;
// a deliberate infinite loop, but the
// generator function exits/pauses at
// every yield so while this is an 'infinite
// function' it doesn't cause any blocking:
while (true) {
// yields value and then increments it:
yield count++
}
},
// getting a reference to the generator function:
counter = iterator(),
remove = (e) => e.currentTarget.closest('div').remove();
addBtn.addEventListener("click", function() {
// getting the current count of all elements matching
// the selector within the document:
const currentCount = getAll('.activityGroup').length,
// retrieving the next value from the
// generator function:
i = counter.next().value;
// if the currentCount is greater than 4 (again, using
// a Yoda condition):
if (4 < currentCount) {
// exit the function:
return false;
}
// creating a new <div>:
const activityGroup = create('div', {
// assigning the class-name of 'activityGroup':
className: 'activityGroup'
}),
// creating a new <button>:
removeButton = create('button', {
// assigning the class-name of 'delBtn',
className: 'delBtn',
// and the text-content of 'X':
textContent: 'X'
}),
input = create('input', {
type: 'text',
id: `activity_${i}`,
placeholder: `Activity ${i}`
}),
textarea = create('textarea', {
id: `activity_description_${i}`,
placeholder: `Activity description ${i}`
});
// binding the remove() function as the'click' event-handler
// on the removeButton:
removeButton.addEventListener('click', remove);
// using the HTMLElement.dataset API to set the
// custom data-count attribute to the current
// value of the i variable (for use in the CSS):
activityGroup.dataset.count = i;
// using Element.append() to append multiple elements
// in one call:
activityGroup.append(input, textarea, removeButton);
activity.appendChild(activityGroup);
});
/* caching common values (useful for theming and
maintenance): */
:root {
--bg-primary: hsl(0 0% 0% / 0.3);
--columns: 2;
--fs: 16px;
--spacing: 0.5em;
}
/* a simple CSS reset to remove default
margins and padding, and to have all
elements sized in a way that includes
their padding and border-widths in the
assigned size: */
*,::before,::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-size: var(--fs);
}
#activity {
/* using CSS Grid for layout: */
display: grid;
/* setting a space - held in the custom
property - between adjacent elements: */
gap: var(--spacing);
/* creating a number of columns (equal to the value held
in the --columns property) of equal width, each of one
fraction of the remaining space) */
grid-template-columns: repeat(var(--columns), 1fr);
padding: var(--spacing);
}
.activityGroup {
/* aligning an element in the grid to the start of that
grid (alignment is on the cross-axis of the inline-
axis, the inline-axis being the writing direction
of the language of the user's browser): */
align-self: start;
border: 0.2em solid var(--bg-primary);
display: grid;
gap: inherit;
padding: var(--spacing);
}
.activityGroup::before {
background-color: var(--bg-primary);
/* setting the content of the ::before pseudo element to the
string of 'Activity ' concatenated with the attribute-value
of the data-count attribute: */
content: "Activity " attr(data-count);
display: block;
/* spanning all three grid-columns: */
grid-column: span 3;
/* applying padding to the start of the inline axis: */
padding-inline-start: var(--spacing);
/* moving the element outwards with negative margins,
to place the content against the outer edges of the
element, despite the spacing on that element: */
margin-block-start: calc(-1 * var(--spacing));
margin-inline: calc(-1 * var(--spacing));
}
input,
textarea {
grid-column: span 3;
padding: 0.5em;
}
textarea {
min-block-size: 5em;
resize: vertical;
}
.delBtn {
color: red;
grid-column: 3;
}
/* using a simple media query to modify the values of the CSS Custom
properties as required to improve the experience on different
devices: */
#media screen and (max-width: 700px) {
:root {
--columns: 1;
--fs: 18px;
}
}
<!-- we don't appear to be using jQuery, so I removed that <script> element -->
<!-- switching id and classes to use camelCase rather than
having arbitrary mixed-case format; choose a style you
prefer, but remember that consistency matters more than
the choice you make: -->
<div id="activity">
<div class="activityGroup">
<input placeHolder="Type your activity" />
<!-- removed the <br> elements, as well as the "rows" and "cols"
attributes from the <textarea>: -->
<textarea placeHolder="Type your description"></textarea>
<button class="delBtn">X</button>
</div>
<!-- Remove button -->
</div>
<!-- changed the id from "add" to "addBtn," purely for consistency
but, again, make your own choice on that: -->
<button id="addBtn">Add Activity</button>
As to your question:
How can I [add an] entire section and...control the maximum number of activities inserted[?]
Controlling the number of total activities/sections on the page is relatively easy and simply requires you to check the number of existing sections before adding a new one:
const addActivity = document.getElementById("add");
var i = 0;
const activityDiv = document.getElementById("Activity");
addActivity.addEventListener("click", function() {
// using document.querySelectorAll() to retrieve a NodeList of all
// elements matching the supplied CSS selector, and then retrieving
// the length of that NodeList:
let currentCount = document.querySelectorAll('.activityGroup').length;
// using a "Yoda condition" to see if the currentCount is greater than
// 4 (this approach guards against the most likely error of an assessment,
// that of accidentally assigning a value instead of comparing); if it is:
if (4 < currentCount) {
// we exit the function here:
return false;
}
i++;
const newspan = document.createElement('div');
newspan.className = "activityGroup";
// creating a <br> element:
const br = document.createElement('br');
const removeButton = document.createElement('button');
removeButton.addEventListener('click', function(e) {
e.target.closest(".activityGroup").remove();
});
removeButton.className = "delbtn";
removeButton.innerHTML = "X";
//
const txtfield = document.createElement('input');
const txtarea = document.createElement('textarea');
//
txtfield.id = 'activity_' + i;
txtfield.placeholder = "Activity " + i;
newspan.appendChild(txtfield);
// appending a clone of the <br> element:
newspan.appendChild(br.cloneNode());
// appending the <br> element:
newspan.appendChild(br);
//
newspan.appendChild(txtarea);
txtarea.id = 'activity_description_' + i;
txtarea.placeholder = "Activity Description " + i;
// setting the rows and cols attributes:
txtarea.setAttribute('rows', 5);
txtarea.setAttribute('cols', 50);
// appending white-space (approximating what's in the HTML):
newspan.append(document.createTextNode('\n '));
newspan.appendChild(removeButton);
activityDiv.appendChild(newspan);
});
.delbtn {
color: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="Activity">
<div class="activityGroup">
<input placeHolder="Type your activity" />
<br>
<br>
<textarea rows="5" cols="50" placeHolder="Type your descvription"></textarea>
<button class="delbtn">X</button>
</div>
<!-- Remove button -->
</div>
<button id="add">Add Activity</button>
Now, I'd like to improve the above functions as follows with explanatory comments in the code itself:
const addActivity = document.getElementById("add");
var i = 0;
const activityDiv = document.getElementById("Activity");
addActivity.addEventListener("click", function() {
// using document.querySelectorAll() to retrieve a NodeList of all
// elements matching the supplied CSS selector, and then retrieving
// the length of that NodeList:
let currentCount = document.querySelectorAll('.activityGroup').length;
// using a "Yoda condition" to see if the currentCount is greater than
// 4 (this approach guards against the most likely error of an assessment,
// that of accidentally assigning a value instead of comparing); if it is:
if (4 < currentCount) {
// we exit the function here:
return false;
}
i++;
const newspan = document.createElement('div');
newspan.className = "activityGroup";
// creating a <br> element:
const br = document.createElement('br');
const removeButton = document.createElement('button');
removeButton.addEventListener('click', function(e) {
e.target.closest(".activityGroup").remove();
});
removeButton.className = "delbtn";
removeButton.innerHTML = "X";
//
const txtfield = document.createElement('input');
const txtarea = document.createElement('textarea');
//
txtfield.id = 'activity_' + i;
txtfield.placeholder = "Activity " + i;
newspan.appendChild(txtfield);
// appending a clone of the <br> element:
newspan.appendChild(br.cloneNode());
// appending the <br> element:
newspan.appendChild(br);
//
newspan.appendChild(txtarea);
txtarea.id = 'activity_description_' + i;
txtarea.placeholder = "Activity Description " + i;
// setting the rows and cols attributes:
txtarea.setAttribute('rows', 5);
txtarea.setAttribute('cols', 50);
// appending white-space (approximating what's in the HTML):
newspan.append(document.createTextNode('\n '));
newspan.appendChild(removeButton);
activityDiv.appendChild(newspan);
});
.delbtn {
color: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="Activity">
<div class="activityGroup">
<input placeHolder="Type your activity" />
<br>
<br>
<textarea rows="5" cols="50" placeHolder="Type your descvription"></textarea>
<button class="delbtn">X</button>
</div>
<!-- Remove button -->
</div>
<button id="add">Add Activity</button>
JS Fiddle demo.
References:
CSS:
align-self.
box-sizing.
content.
CSS custom properties.
CSS logical properties.
display.
gap.
grid-column.
grid-template-columns.
grid-template-rows.
inline-size.
margin.
margin-block.
margin-inline.
min-block-size.
padding.
padding-block.
padding-inline.
repeat().
var().
JavaScript:
document.createElement().
document.querySelector().
document.querySelectorAll().
Element.append().
Element.querySelector().
Element.querySelectorAll().
Element.remove().
Event.target.
Event.currentTarget.
EventTarget.addEventListener().
Generator functions.
HTMLElement.dataset.
Node.appendChild().
Object.assign().
yield.
Do you mean "If I have Activity 1, 2, 3, 4, 5 and Delete 3 I want to be able to get Activities 1, 2, 4, 5?"
From what I've gathered, you want a button that adds and deletes activities but you only want it to work when previous activity isn't empty.
In the javascript, when you handle the buttons click event check previous activity, if it's empty, return, if it isn't empty, execute the add/delete code.
I am trying to do append() function. i have a table of data. i run a loop to first remove text in cell then i will append a new tag.this usecase is to create a progress bar. for an example
data sample inside cell is e.g 39% 39% 82% etc etc
let cf_percent;
let cf_regex;
for(let i = 0 ;i < tbl[0].length;i++){
cf_percent = tbl[0][i].innerHTML
cf_regex = cf_percent.replace(/[`~%]/gi, '');
console.log(cf_regex)
//Clear fields
tbl[0][i].innerHTML = ''
tbl[0][i].append('<p>Textfield</p>');
}
It should return texfield but instead, it is returning '<p> textfield </p>' in table cell.it should return textField. i have tried .html() but this does not work for this usecase.
in d3.js append function appends a new element with the specified name as the last child of each element in the current selection, returning a new selection containing the appended elements.
So to append p element use: tbl[0][i].append("p") and to set text use .text() further: e.g.
tbl[0][i].append("p").text("Textfield")
I will suggest to use:
let cf_percent;
let cf_regex;
for(let i = 0 ;i < tbl[0].length;i++){
cf_percent = tbl[0][i].innerHTML
cf_regex = cf_percent.replace(/[`~%]/gi, '');
console.log(cf_regex)
//Clear fields
tbl[0][i].innerHTML = ''
tbl[0][i].innerHTML += `<p>Textfield</p>`;
}
You have 2 options. The first is along what you are trying to do where you set the innerHTML to a string. The second is actually generating an element and then appending it. Your current scenario seems to be mixing the two.
const div1 = document.getElementById('sample1'),
div2 = document.getElementById('sample2'),
p = document.createElement('p');
div1.innerHTML = '<p>This set the innerHTML</p>';
p.innerText = 'This is a p appended to a div';
div2.appendChild(p);
#sample1 {
background-color: red;
}
#sample2 {
background-color: yellow;
}
<div id="sample1"></div>
<div id="sample2"></div>
I don't know how to solve that problem, If anyone knows how to solve that then please let me know. If required, then I will send the code personally to figure out the mistakes.
There are two containers: left and right. In Left, there is a from where I take values of title, description and status(active/inactive) from text boxes and radio buttons(active/inactive). Then after pressing submit button all values are filled in table of right-container with edit and delete button attached after clicking submit button every time. I want to delete specific row where delete button is clicked. But I don't know how to access that button while onclick function(doDelete()) is same in all the buttons.
function fillData() {
var table = document.getElementById("myTable");
var counter = table.querySelectorAll('tr').length;
var key = counter;
var row = table.insertRow(counter);
row.id = "row-" + key;
var titleCell = row.insertCell(0);
var descCell = row.insertCell(1);
var statusCell = row.insertCell(2);
var actionCell = row.insertCell(3);
var editButton = document.createElement("button");
editButton.innerText = "Edit";
editButton.id = "edit-" + key;
editButton.setAttribute("onclick", "doEdit()");
var delButton = document.createElement("button");
delButton.innerText = "Delete";
delButton.id = "delete-" + key;
delButton.setAttribute("onclick", "doDelete()");
titleCell.innerHTML = document.getElementById("panel-title").value;
descCell.innerHTML = document.getElementById("panel-description").value;
statusCell.innerHTML = (function () {
var radios = document.getElementsByName("status");
for (i = 0, len = radios.length; i < len; i++) {
if (radios[i].checked) {
return radios[i].value;
}
}
}());
actionCell.appendChild(editButton);
actionCell.appendChild(delButton);
var delBtnArr = document.querySelectorAll('input[type="button"]');
console.log(delBtnArr);
}
Actual Results: After pressing delete button, the whole rows are deleted.
Expected Results: After pressing delete button, the specific row is deleted where button is clicked.
Javascript also sends the assosiated event as parameter and in this way you can get id by using event utilities. You can get the clicked button id as below. By getting that id I think you can also get the associated row. After that you can delete the row.
doDelete(event){
let clickedButtonId = e.target.id;
//get row id. I think you can get it.
document.removeElement(rowId);
}
Event Delegation
Bind/Register the Ancestor to Event
Dynamically added tags cannot bind to an event handler/listener, only tags that have existed since the page was loaded can. So for multiple dynamically added tags such as the buttons you have to find an ancestor tag that they all share incommon and bind it to whatever event you need to listen for. For your buttons it can be the closest ancestor table* (recommended) to the furthest window:
// On-event property. ALWAYS PASS THE EVENT OBJECT
table.onclick = function(event) {...
OR
// Event Listener. Abbreviating the [Event Object][2] is OK, but you must be consistent.
table.addEventListener('click', function(e) {...
Do not use on-event attributes <button onclick="func()"...
✱Technically the closest ancestor is tbody even if you didn't add it to the table, the browser will add it by default.
Use Event.target and Event.currentTarget Properties
Remember to pass the Event Object because you'll need it to...
...find out which button you actually clicked with event.target property.
...get a reference to the table with event.currentTarget property.
...possibly prevent default behavior such as stopping a form from submitting to a server with event.preventDefault() method.
Review the demo, it will have specific details on the event handlers.
Demo
Details commented in demo
var table = document.querySelector("table");
document.forms[0].onsubmit = fillData;
/*
This onevent property handler has two functions note it is bound
to the table NOT the buttons.
There's two conditionals and they only focus on classNames of
either .del or .edit. Once it's determined if the clicked tag has
one of these classes then the appropriate function is called.
If neither class was clicked there's no opportunity for anything
else to act on the click because both conditionals end with
return false thereby terminating the event handler.
*/
table.onclick = function(e) {
if (e.target.className === 'del') {
delRow(e);
return false;
}
if (e.target.className === 'edit') {
editRow(e);
return false;
}
};
function fillData(e) {
var ui = e.target.elements;
e.preventDefault();
var idx = table.rows.length;
var row = table.insertRow();
row.id = 'r-' + idx;
var cell1 = row.insertCell(0);
var data1 = ui.title.value;
cell1.textContent = data1;
var cell2 = row.insertCell(1);
var data2 = ui.desc.value;
cell2.textContent = data2;
var cell3 = row.insertCell(2);
var data3 = ui.chk.checked ? 'Active' : 'Inactive';
cell3.textContent = data3;
var cell4 = row.insertCell(3);
var btns = `
<button class='edit'>📝</button>
<button class='del'>❌</button>`;
cell4.innerHTML = btns;
}
/*
Reference the .closest() row from clicked button
Get that row's id and split() it at the dash and pop() the number.
Then get a reference to the bound ancestor (table) and deleteRow() with the new number you just got.
*/
function delRow(e) {
var row = e.target.closest('tr');
var idx = row.id.split('-').pop();
e.currentTarget.deleteRow(idx);
}
/*
Same as before get the index number from the closest row's id.
Reference the table and use the .rows property and number.
This reference will now allow you to use the .cells property.
Use the .cells property to toggle the contenteditable attribute
on the first three cells.
*/
function editRow(e) {
var row = e.target.closest('tr');
var idx = row.id.split('-').pop();
var R = e.currentTarget.rows[idx];
for (let c = 0; c < 3; c++) {
var cell = R.cells[c];
if (cell.hasAttribute('contenteditable')) {
cell.removeAttribute('contenteditable');
} else {
cell.setAttribute('contenteditable', true);
}
}
}
body {
font: 400 16px/25px Consolas;
display: flex;
justify-content: space-between;
}
fieldset {
width: fit-content
}
input,
label,
textarea {
font: inherit
}
input,
label,
button {
display: inline-block;
height: 25px;
}
#title {
width: 27.5ch;
}
#chk {
display: none;
}
#chk+label::after {
content: '\2610';
font-size: 20px;
vertical-align: middle;
}
#chk:checked+label::after {
content: '\2611';
}
[type='reset'] {
margin-left: 5%
}
td {
min-width: 60px;
border-bottom: 1px solid #000;
height: 25px;
}
tr td:last-child {
border-bottom-color: transparent;
}
button {
width: 35px;
text-align: center;
}
<form id='data'>
<fieldset>
<legend>Enter Data</legend>
<input id='title' type='text' placeholder='Title'><br>
<textarea id='desc' rows='3' cols='25' placeholder='Description'></textarea><br>
<input id='chk' type='checkbox'>
<label for='chk'>Active </label>
<input type='reset'>
<input type='submit'>
</fieldset>
</form>
<hr>
<table></table>
So I have this blueprint object:
function User (theName, theEmail) {
this.name = theName;
this.email = theEmail;
this.quizScores = [];
this.currentScore = 0;
}
I create a new user like this var user1 = new User (theName.value, theEmail.value); which is inside a function for event listener when user types in his name and email. Now there are questions and a button for next question. Everytime user clicks next question button, I want to increment currentScore by one. Problem is that it stays 0 all the time. I do it like this:
scoretag = document.createElement("p");
scoretag.innerHTML = user1.currentScore;
body.appendChild(scoretag);
Event listener and main loop:
for (var i = 0; i < theChoices[question1.theChoices].length; i++) {
var arrayQ = document.createElement("p");
arrayQ.innerHTML = theChoices[question1.theChoices][i];
list.appendChild(arrayQ);
var radio = document.createElement("input");
radio.type = "radio";
listOptions.appendChild(radio);
dbtn.addEventListener("click", function() {
//list.removeChild(arrayQ);
//listOptions.removeChild
list.removeChild(list.firstChild);
list.removeChild(list.lastChild);
user1.currentScore = user1.currentScore+1;
scoretag = document.createElement("p");
scoretag.innerHTML = user1.currentScore;
body.appendChild(scoretag);
})
}
UPDATE: I putted the code for appending a child to a body element inside the loop after incrementation of score, but this results in many numbers printed on the page one after another.
But like I said, when I try t increment by one on button click, it still keeps showing 0 on the screen. Any help?
Every time you increment the score, you need to update the HTML element. This is an idea:
function User (theName, theEmail) {
this.name = theName;
this.email = theEmail;
this.quizScores = [];
this.currentScore = 0;
}
var user1 = new User ("aa","bb");
function updateScore(){
user1.currentScore++;
document.getElementById('score').innerText = user1.currentScore;
}
<button id="btn" onclick="updateScore()">next</button>
<p id="score">0</p>
I'm trying to repeat a div, the number of times dependent on the number chosen in a number input field, but currently when the number input is changed the values are being multiplied. So if you go from 2 to 3 it repeats the div 6 times instead of just 3. How can I reset the loop so it's using only the current number?
http://jsfiddle.net/deliciouslycheesy/6rb94mry/
$('#numRepeat').on('change keyup input', function () {
var el = $(".repeat-me").get(0);
var numRepeat = $("#numRepeat").val();
for(var i = 1;i < numRepeat;i++){
var newEl = $(el).after(el.cloneNode(true));
}
}).change();
You need to remove the ones that were added before:
$('#numRepeat').bind('change keyup input', function () {
var el = $(".repeat-me").get(0);
$(".repeat-me:not(:first)").remove();
var numRepeat = $("#numRepeat").val();
for(var i = 1;i < numRepeat;i++){
var newEl = $(el).after(el.cloneNode(true));
}
}).change();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="number" id="numRepeat" value="2"/>
<div class="repeat-me">REPEAT</div>
JSFiddle
I'm not sure why you're using three event change keyup input, just input event will detect changes inside input field, check the Updated fiddle.
I suggest to separate the model of repeated div from the result, i think that will make code more clear, and because you're using JQuery you can replace cloneNode() by clone().
Hope this helps.
$('#numRepeat').on('input', function () {
var el = $("#model-div .repeat-me");
var numRepeat = $(this).val();
$('#result-div').empty(); //Clear the result div
for(var i = 0 ; i < numRepeat ; i++)
{
$('#result-div').append( $(el).clone(true) );
}
})
#model-div{
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="number" id="numRepeat" value="0"/>
<div id="model-div">
<div class="repeat-me">REPEAT</div>
</div>
<div id="result-div"></div>