Trying to get values from multiple inputs - javascript

I'm trying to make a very basic expense tracker by building off the foundation of a todo app with vanilla Javascript. I'm having trouble isolating the value of all three input bars and getting them to display on the page. At the moment I'm getting 3 [objectHTMLInputElement] and undefined. I'd just like to know if I'm on the right track or if there's an easier way to isolate multiple input values and get them to display on the page. If somebody could point me in the right direction that'd be awesome. Thanks!
let addButton = document.getElementById('add-btn');
addButton.addEventListener('click', add);
let inputName = document.getElementById('input-name');
let inputDate = document.getElementById('input-date');
let inputAmount = document.getElementById('input-amount');
let inputAll = document.querySelectorAll('.input-all');
let expenses = [
]
function add() {
let inputs = inputAll.value;
if (inputs == '') {
return true;
}
expenses.push(inputs);
displayExpenses();
}
function remove() {
}
function displayExpenses() {
let expensesUl = document.getElementById('expenses-ul');
expensesUl.innerHTML = `${inputName}${inputDate}${inputAmount}`;
for (var i = 0; i < expenses.length; i++) {
let expensesLi = document.createElement('li');
expensesLi.innerHTML = expenses[i];
expensesUl.appendChild(expensesLi);
}
}
* {
padding: 0;
box-sizing: border-box;
}
.headings {
text-align: center;
}
.headings h1 {
font-size: 3rem;
font-family: 'Courier New', Courier, monospace;
}
.headings h2 {
margin-top: -20px;
}
form {
text-align: center;
}
#input-name {
width: 50%;
}
#input-date {
width: 18%;
margin-right: 160px;
}
#input-amount {
width: 18%;
margin-left: 18px;
}
#add-btn {
margin-top: 50px;
margin-left: 800px;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="style.css">
<title>Expense Tracker</title>
</head>
<body>
<div class="headings">
<h1>Expense Tracker</h1>
<h2>Add A New Item</h2>
</div>
<form>
<label>Name:</label>
<input class="input-all" id="input-name">
<br>
<br>
<label>Date:</label>
<input class="input-all" id="input-date">
<label>Amount:</label>
<input class="input-all" id="input-amount">
</form>
<button id="add-btn">Add Expense</button>
<ul id="expenses-ul"></ul>
<script src="main.js"></script>
</body>
</html>

Try this
const btn = document.getElementById('btn');
btn.addEventListener('click', function (event) {
const form = document.getElementById('form');
const output = document.getElementById('output');
const data = Object.fromEntries(new FormData(form).entries());
output.innerHTML = JSON.stringify(data, undefined, 2);
});
.wrap{
display: flex;
}
#output{
margin-left:50px;
border-width:3px;
border-style:dashed;
border-color:#FFAC55;
padding:5px;
min-width: 150px;
min-height: 80px;
}
<div class="wrap">
<div>
<form id="form">
<label for="name">Name:</label><br>
<input type="text" id="name" name="name"><br>
<label for="date">Date:</label><br>
<input type="text" id="role" name="role"> <br>
<label for="lname">Amount:</label><br>
<input type="text" id="amount" name="amount"><br><br>
<input id="btn" type="button" value="Print all value">
</form>
</div>
<div>
<pre id="output">
</pre>
</div>
</div>

When using document.querySelectorAll it's return a [NodeList] that consists of all selected elements on the other side there's also document.getElementsByClassName that return [HTMLCollection] - whatever you used you need to loop through to get the value of every selected input
When you passed [HTMLInputElement] as innerHTML of expensesUl it's will return the element object name not the value of this element because you are not selected any property of this object so you can't set an object as innerHTML of html element
if you want the right way of this part it's will be like that
let inputName = document.getElementById('input-name');
let inputDate = document.getElementById('input-date');
let inputAmount = document.getElementById('input-amount');
let expensesUl = document.getElementById('expenses-ul');
//this will give you empty string because they aren't get a value yet
expensesUl.innerHTML = `name = ${inputName.value}, date = ${inputDate.value}, amoute = ${inputAmount.value}`;
but now because we are selected all elements we are not need to select every input one by one anymore we will make a loop so we will loop through inputAll var to get the value of [HTMLInputElement] object
let addButton = document.getElementById('add-btn');
addButton.addEventListener('click', add);
function add() {
let inputAll = document.querySelectorAll('.input-all');
for(var i of inputAll) {
if (i.value == '') {
return "Sorry you need to fill all inputs"
}
}
displayExpenses(inputAll);
}
function displayExpenses(elements) {
let expensesUl = document.getElementById('expenses-ul');
for (var i = 0; i < elements.length; i++) {
let expensesLi = document.createElement('li');
expensesLi.innerHTML = elements[i].value
expensesUl.appendChild(expensesLi);
}
}
at the example above i removed expenses array but if you want to use it to take the value of the inputs you can make it like that
let addButton = document.getElementById('add-btn');
addButton.addEventListener('click', add);
function add() {
let inputAll = document.querySelectorAll('.input-all');
let expenses = []
for(var i of inputAll) {
if (i.value == '') {
return "Sorry you need to fill all inputs"
}
expenses.push(i.value)
}
displayExpenses(expenses);
}
function displayExpenses(values) {
let expensesUl = document.getElementById('expenses-ul');
for (var i = 0; i < values.length; i++) {
let expensesLi = document.createElement('li');
expensesLi.innerHTML = values[i]
expensesUl.appendChild(expensesLi);
}
}
the whole code should to be like that
let addButton = document.getElementById('add-btn');
addButton.addEventListener('click', add);
let inputName = document.getElementById('input-name');
let inputDate = document.getElementById('input-date');
let inputAmount = document.getElementById('input-amount');
let inputAll = document.querySelectorAll('.input-all');
let expenses = []
function add() {
for(var i of inputAll) {
if (i.value == '') {
return true
}
expenses.push(i.value)
}
displayExpenses();
}
function displayExpenses() {
let expensesUl = document.getElementById('expenses-ul');
expensesUl.innerHTML = `${inputName.value}, ${inputDate.value}, ${inputAmount.value}`;
for (var i = 0; i < expenses.length; i++) {
let expensesLi = document.createElement('li');
expensesLi.innerHTML = expenses[i];
expensesUl.appendChild(expensesLi);
}
}
about document.getElementsByClassName, document.querySelectorAll one deferant is that you can use array methods like forEach() with document.querySelectorAll while you can't do that with document.getElementsByClassName

Related

How to delete DOM element and related array index at same time?

Edit: Never mind...I give up...I'm done with studying web dev...
I have an array (myLibrary) of "book" objects that are pushed into said array when a user submits input from a form.
let myLibrary = [];
function Book(title, author, pages, read) {
this.title = title;
this.author = author;
this.pages = pages;
this.read = read;
}
function addToLibrary() {
let Newbook = new Book(
titleInput.value,
authorInput.value,
pagesInput.value,
readInput.checked
);
myLibrary.push(Newbook);
}
Upon submitting, a card is also generated on the DOM displaying the information from the form. I also add a delete button on each dynamically generated card. I am able to delete the card itself using an event listener (in bold), but I am unable to also delete the related object in the array.
function renderBookCard() {
const newCard = document.createElement("div");
const removeBook = document.createElement("img");
const bookTitleDiv = document.createElement("div");
const titleLabel = document.createElement("p");
const dynamicTitle = document.createElement("p");
const authorDiv = document.createElement("div");
const authorLabel = document.createElement("p");
const dynamicAuthor = document.createElement("p");
const pagesDiv = document.createElement("div");
const pagesLabel = document.createElement("p");
const dynamicPages = document.createElement("p");
const readDiv = document.createElement("div");
const dynamicRead = document.createElement("p");
//
MainBookContainer.appendChild(newCard);
newCard.appendChild(removeBook);
removeBook.classList.add("trash");
removeBook.setAttribute(
"src",
"./Images/delete_FILL0_wght400_GRAD0_opsz48.svg"
);
newCard.classList.add("book-card-container");
newCard.appendChild(bookTitleDiv);
bookTitleDiv.classList.add("book-title");
newCard.appendChild(titleLabel);
titleLabel.textContent = `Title:`;
newCard.appendChild(dynamicTitle);
newCard.appendChild(authorDiv);
authorDiv.classList.add("book-author");
newCard.appendChild(authorLabel);
authorLabel.textContent = `Author:`;
newCard.appendChild(dynamicAuthor);
newCard.appendChild(pagesDiv);
pagesDiv.classList.add("book-pages");
newCard.appendChild(pagesLabel);
pagesLabel.textContent = `Pages:`;
newCard.appendChild(dynamicPages);
newCard.appendChild(readDiv);
readDiv.classList.add("book-read");
newCard.appendChild(dynamicRead);
//
let i;
for (i = 0; i < myLibrary.length; i++) {
dynamicTitle.textContent = myLibrary[i].title;
dynamicAuthor.textContent = myLibrary[i].author;
dynamicPages.textContent = myLibrary[i].pages;
if (!readInput.checked) {
dynamicRead.textContent = "Unread";
} else {
dynamicRead.textContent = "Read";
}
}
//
**newCard.addEventListener("click", function (e) {
if (e.target.classList.contains("trash")) {
newCard.remove();
myLibrary.splice([i], 1);**
}
});
}
How am I able to delete the card and the related object in the array? I hope I was able to ask in a clear way. If not I apologize.
Here is my example. I think it might help you.
*If you have many elements to append to your HTML feel free to use insertAdjacentHTML or other methods, this will help you easily to organize your code.
*In my case, I use the filter method to update my list.
let bookList = [];
const addBook = document.querySelector("#add_book");
const bookWrap = document.querySelector("#book_wrap");
addBook.addEventListener("click", () => {
const bookName = document.querySelector("#book_name");
const bookAuthor = document.querySelector("#book_author");
bookList.push({
book_name: bookName.value,
book_author: bookAuthor.value
})
const bookTemplate = `
<div class="book">
<div>
<h2>${bookName.value}</h2>
<p>${bookAuthor.value}</p>
</div>
<div>
<button id="trash_${bookName.value}">Trash</button>
</div>
</div>`;
bookWrap.insertAdjacentHTML("beforeend", bookTemplate);
// console.log(bookList)
document.querySelector(`#trash_${bookName.value}`)
.addEventListener("click", (e) => {
e.target.closest(".book").remove();
bookList = [...bookList.filter(item => item.book_name !== e.target.id.split("_")[1])]
// console.log(bookList)
})
bookName.value = null;
bookAuthor.value = null;
})
.book-wrap {
min-width: 250px;
min-height: 200px;
border-radius: 10px;
border: 1px solid black;
margin: 20px 0;
padding: 20px;
}
.book {
display: flex;
justify-content: space-between;
width: 200px;
gap: 40px;
margin-bottom: 20px;
}
h2,
p{
margin: 0;
}
p {
color: #999;
}
<div>
<div style="margin-bottom: 10px;">
<label for="book_name">Book name:</label><br/>
<input id="book_name" type="text" />
</div>
<div style="margin-bottom: 10px;">
<label for="book_author">Author name:</label><br/>
<input id="book_author" type="text" />
</div>
<div>
<button id="add_book">Add Book</button>
</div>
<div id="book_wrap" class="book-wrap"></div>
</div>
Hope this might help you.
Enjoy the journey into Web dev.

Display slider when you hover over array elements and give value to the array elements

I have done the part where you have to generate the array elements when you enter them from textbox, what I struggle with now is to display a slider on hover over each array element and give the array element a value, also what I struggle with is to delete each generated array element individually, my delete function deletes the entire array on click not just the single element I click.
Here is how it should look like:
enter image description here
Here is my code so far:
let names = [];
let nameInput = document.getElementById("name");
let messageBox = document.getElementById("display");
function insert ( ) {
names.push( nameInput.value );
clearAndShow();
}
function remove()
{
var element = document.getElementById("display");
element.parentNode.removeChild(element);
}
function clearAndShow () {
let printd=""
nameInput.value = "";
messageBox.innerHTML = "";
names.forEach(function(element){
if(element != ''){
var _span = document.createElement('span');
_span.style.borderStyle = "solid"
_span.style.borderColor = "blue"
_span.style.width = '50px'
_span.style.marginLeft = "5px"
_span.appendChild(document.createTextNode(element))
messageBox.appendChild(_span)
printd +="''" + element + "''" + "," + " ";
document.getElementById("labelprint").innerHTML=(printd)
}
})
}
h3 {
color: rgb(0, 174, 255);
}
.container {
border: solid 2px;
display: block;
margin-left: 200px;
margin-right: 200px;
margin-top: 50px;
}
<div class="container">
<form>
<h1>Enter Search</h1>
<input id="name" type="text" />
<input type="button" value="Search" onclick="insert()" />
</form>
<br/>
<div onclick="remove(this)" id="display"></div>
<br/>
<label >You have Selected: </label>
<h3 id="labelprint"></h3>
</div>
I am not being rude I just got confused on how you stated your message but what I think you are saying is to do this:
var names = [];
var nameInput = document.getElementById("name");
var messageBox = document.getElementById("display");
function insert ( ) {
names.push( nameInput.value );
// add value to array val: names[names.length - 1] = PutValueHere
clearAndShow();
}
function remove(this){
document.getElementById("display").parentNode.firstChild.remove(); // If you want it to remove the last child with the id 'display' then do .parentNode.lastChild.remove()
//if you are trying to remove the last val in the array do this: names.splice(names.length-1,1) for the first do this names.splice(0,1)
}
function clearAndShow () {
var printd=""
nameInput.value = "";
messageBox.innerHTML = "";
names.forEach(function(element){
if(element != ''){
var _span = document.createElement('span');
_span.id = '_spanId'
$('_spanId').css('border-style',solid');
$('_spanId').css('border-color',blue');
$('_spanId').css('width',50+'px');
$('_spanId').css('margin-left',5+'px');
_span[0].appendChild(document.createTextNode(element))
messageBox[0].appendChild(_span)
printd += "''" + element + "'', ";
document.getElementById("labelprint").innerHTML = printd
}
})
}
I have tried to implement something that i hope it's close to what are you looking for:
HTML:
<div class="container">
<form>
<h1>Add new slider</h1>
<input id="sliderName" type="text" />
<input type="button" value="Add" onclick="insertSlider()" />
</form>
<div id="display"></div>
</div>
CSS:
h3 {
color: rgb(0, 174, 255);
}
.container {
border: solid 2px;
display: block;
margin-left: 200px;
margin-right: 200px;
margin-top: 50px;
}
JS:
let messageBox = document.getElementById("display");
function deleteFn(id) {
const element = document.getElementById(id)
if(element) element.outerHTML="";
}
function onChangeSlideId(id){
const elementSlide = document.getElementById('slider-'+id+'')
if(elementSlide){
const value = elementSlide.value
const elementSlideText = document.getElementById('slider-value-'+id+'')
elementSlideText.innerText = '('+value+')'
}
}
function insertSlider(){
const name = document.getElementById("sliderName")
const nameValue = name.value
const newLabel = document.createElement('label')
newLabel.setAttribute('for',nameValue)
newLabel.innerText = nameValue
const newSlider = document.createElement('input')
newSlider.setAttribute('id','slider-'+nameValue+'')
newSlider.setAttribute('type','range')
newSlider.setAttribute('name',nameValue)
newSlider.setAttribute('onchange','onChangeSlideId("'+nameValue+'")')
const sliderValue = document.createElement('span')
sliderValue.setAttribute('id','slider-value-'+nameValue+'')
sliderValue.innerText = '('+newSlider.value+')'
const newContainer = document.createElement('div')
newContainer.setAttribute('id',nameValue)
newContainer.setAttribute('style','display: grid')
newContainer.appendChild(newSlider)
newContainer.appendChild(newLabel)
newContainer.appendChild(sliderValue)
const newDeleteButton = document.createElement('input')
newDeleteButton.setAttribute('type', 'button')
newDeleteButton.setAttribute('value', 'Delete ' + nameValue + '')
newDeleteButton.setAttribute('onclick', 'deleteFn("'+nameValue+'")')
newContainer.appendChild(newDeleteButton)
messageBox.appendChild(newContainer)
}
You can try it by yourself in this codepen

Function calls not working in Event listeners

I don't know why this code is not working, neither it is throwing any Error.
function rotateArray(arr){
return function(){
var newMod = [];
for(let i = 0; i<arr.length; i++){
if(i===0){
newMod[i] = arr[arr.length - 1];
}else{
newMod[i] = arr[i-1];
}
}
return arr = newMod;
}
}
var btns = {
btn1: 1,
btn2: 2,
btn3: 3,
btn6: 6,
btn9: 9,
btn8: 8,
btn7: 7,
btn4: 4,
}
var rotfunc = rotateArray([1,2,3,6,9,8,7,4]);
document.getElementById('btn5').addEventListener('click',() => {
let rot = rotfunc()
for(let i in btns){
btns[i] = rot.shift();
}
for(let i in btns){
document.getElementById(i).innerHTML = btns[i];
}
});
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Buttons Grid</title>
<style type="text/css">
.buttonContainer {
width: 75%;
}
.buttonContainer > .buttonClass {
width: 30%;
height: 48px;
font-size: 24px;
}
</style>
</head>
<body>
<div class = "buttonContainer" id = "btns">
<button id = "btn1" class = "buttonClass">1</button>
<button id = "btn2" class = "buttonClass">2</button>
<button id = "btn3" class = "buttonClass">3</button>
<button id = "btn4" class = "buttonClass">4</button>
<button id = "btn5" class = "buttonClass">5</button>
<button id = "btn6" class = "buttonClass">6</button>
<button id = "btn7" class = "buttonClass">7</button>
<button id = "btn8" class = "buttonClass">8</button>
<button id = "btn9" class = "buttonClass">9</button>
</div>
<script src="script.js" type="text/javascript"></script>
</body>
</html>
I am trying to rotate outer circle of Numbers clockwise when clicking on button-5. But it only happens one and then I am losing all values in my 'rot' array.
Maybe I am missing something. Can anyone help?
When you call rot.shift(), you're modifying the array that's saved in the rotfunc closure. So the next time you call rotfunc(), the array is empty.
Make a copy of the array before modifying it, using the slice() method.
function rotateArray(arr){
return function(){
var newMod = [];
for(let i = 0; i<arr.length; i++){
if(i===0){
newMod[i] = arr[arr.length - 1];
}else{
newMod[i] = arr[i-1];
}
}
return arr = newMod;
}
}
var btns = {
btn1: 1,
btn2: 2,
btn3: 3,
btn6: 6,
btn9: 9,
btn8: 8,
btn7: 7,
btn4: 4,
}
var rotfunc = rotateArray([1,2,3,6,9,8,7,4]);
document.getElementById('btn5').addEventListener('click',() => {
let rot = rotfunc().slice()
let rot_index = 0;
for(let i in btns){
btns[i] = rot.shift();
}
for(let i in btns){
document.getElementById(i).innerHTML = btns[i];
}
});
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Buttons Grid</title>
<style type="text/css">
.buttonContainer {
width: 75%;
}
.buttonContainer > .buttonClass {
width: 30%;
height: 48px;
font-size: 24px;
}
</style>
</head>
<body>
<div class = "buttonContainer" id = "btns">
<button id = "btn1" class = "buttonClass">1</button>
<button id = "btn2" class = "buttonClass">2</button>
<button id = "btn3" class = "buttonClass">3</button>
<button id = "btn4" class = "buttonClass">4</button>
<button id = "btn5" class = "buttonClass">5</button>
<button id = "btn6" class = "buttonClass">6</button>
<button id = "btn7" class = "buttonClass">7</button>
<button id = "btn8" class = "buttonClass">8</button>
<button id = "btn9" class = "buttonClass">9</button>
</div>
<script src="script.js" type="text/javascript"></script>
</body>
</html>

Sort the divs by content

I have a problem.
.titel
{
display: inline-block;
padding:5px 0 ;
}
#sort div div
{
display: inline-block;
padding:5px 0 ;
}
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<div>
<div class="titel achternaam" >Achternaam</div>
<div class="titel voornaam" >Voornaam</div>
<div class="titel kantoor" >Kantoor</div>
</div>
<div class="spann">
<span class="ui-icon ui-icon-circle-triangle-n"></span>
<span class="ui-icon ui-icon-circle-triangle-s"></span>
<span class="ui-icon ui-icon-circle-triangle-n"></span>
<span class="ui-icon ui-icon-circle-triangle-s"></span>
<span class="ui-icon ui-icon-circle-triangle-n"></span>
<span class="ui-icon ui-icon-circle-triangle-s"></span>
</div>
<div id="sort">
<div class="someaspcode" onClick="someaspcodethatifyouclickitwilgotothepage">
<div class="achternaam">bill</div>
<div class="voornaam">gates</div>
<div class="kantoor">123</div>
</div>
<div class="someaspcode" onClick="someaspcodethatifyouclickitwilgotothepage">
<div class="achternaam">jhonny</div>
<div class="voornaam">depp</div>
<div class="kantoor">43321</div>
</div>
The data from div with id sort comes from a database (thats the reason ,that I show it like this)
What I whant to do is :
If I click on the first icon it shows the list sorted by voornaam(asc)
If I click on the second icon it shows the list sorted by voornaam(desc)
If I click on the third icon it shows the list sorted by achternaam (asc)
and so further
I have tried everything that I found on stackoverflow and google but none of it worked.
Can someone give me a good piece of advice.
what i whant is something like this
http://jsfiddle.net/7sgw21hn/1/
but it must read the content
things i tried
jQuery - Sorting div contents
https://www.sitepoint.com/community/t/sort-div-order-alphabetically-based-on-contents/39955/2
and many more (can't find it right now)
this is before i click
and this is after
can we do something about this
Here's the demo: http://output.jsbin.com/gojopuh
As mentioned, the first two buttons sort asc and desc on first name.
The second two buttons sort asc and desc on last name.
My code uses bubble sort and takes advantage of replaceChild for performance benefits.
Also with the code below, adding more controls for this data is now trivial.
Code below, any questions just ask.
var controls = document.querySelectorAll('.spann > span');
var dataContainer = document.querySelector('#sort');
var data = document.querySelectorAll('#sort > div');
// select controls
var ascAchternaam = controls[0];
var descAchternaam = controls[1];
var ascVoornaam = controls[2];
var descVoornaam = controls[3];
var ascKantoor = controls[4];
var descKantoor = controls[5];
var ascVerjaardag = controls[6];
var descVerjaardag = controls[7];
// define a user type
function User(achternaam, voornaam, kantoor, verjaardag, elem) {
this.achternaam = achternaam;
this.voornaam = voornaam;
this.kantoor = kantoor;
this.verjaardag = verjaardag;
this.elem = elem;
}
function bubbleSort(order, data, prop) {
// copy data array
var sortingArr = Array.prototype.slice.call(data);
for (var i = sortingArr.length - 1; i >= 0; i--) {
for (var j = 1; j <= i; j++) {
var birthdayA = sortingArr[j-1][prop].split('-');
var birthdayB = sortingArr[j][prop].split('-');
if (order == 'asc') {
if (birthdayA.length > 1) {
if (parseFloat(birthdayA[1], 10) > parseFloat(birthdayB[1], 10) || parseFloat(birthdayA[0], 10) > parseFloat(birthdayB[0], 10)) {
var temp = sortingArr[j-1];
sortingArr[j-1] = sortingArr[j];
sortingArr[j] = temp;
}
} else {
if (sortingArr[j-1][prop] > sortingArr[j][prop]) {
var temp = sortingArr[j-1];
sortingArr[j-1] = sortingArr[j];
sortingArr[j] = temp;
}
}
} else {
if (birthdayA.length > 1) {
if (parseFloat(birthdayA[1], 10) < parseFloat(birthdayB[1], 10) || parseFloat(birthdayA[0], 10) < parseFloat(birthdayB[0], 10)) {
var temp = sortingArr[j-1];
sortingArr[j-1] = sortingArr[j];
sortingArr[j] = temp;
}
} else {
if (sortingArr[j-1][prop] < sortingArr[j][prop]) {
var temp = sortingArr[j-1];
sortingArr[j-1] = sortingArr[j];
sortingArr[j] = temp;
}
}
}
}
}
return sortingArr;
}
// event action
function sortOnClick(order, data, prop) {
var sorted = bubbleSort(order, data, prop);
for (var i = 0; i < sorted.length; i++) {
var user = sorted[i];
var wrapper = user.elem.cloneNode(true);
dataContainer.replaceChild(wrapper, dataContainer.children[i]);
}
return sorted;
}
// used to make the data into a format we need
function formatUsers(data) {
var userData = [];
for (var i = 0; i < data.length; i++) {
var userElem = data[i];
var fname = userElem.querySelector('.achternaam').textContent;
var lname = userElem.querySelector('.voornaam').textContent;
var office = userElem.querySelector('.kantoor').textContent;
var birthday = userElem.querySelector('.verjaardag').textContent;
userData.push(new User(fname, lname, office, birthday, userElem));
}
return userData;
}
// sorter
function initSorter(data) {
// reshape our data
var userData = formatUsers(data);
// add event listeners to controls
ascAchternaam.addEventListener('click', function() {
sortOnClick('asc', userData, 'achternaam');
});
descAchternaam.addEventListener('click', function() {
sortOnClick('desc', userData, 'achternaam');
});
ascVoornaam.addEventListener('click', function() {
sortOnClick('asc', userData, 'voornaam');
});
descVoornaam.addEventListener('click', function() {
sortOnClick('desc', userData, 'voornaam');
});
ascKantoor.addEventListener('click', function() {
sortOnClick('asc', userData, 'kantoor');
});
descKantoor.addEventListener('click', function() {
sortOnClick('desc', userData, 'kantoor');
});
ascVerjaardag.addEventListener('click', function() {
sortOnClick('asc', userData, 'verjaardag');
});
descVerjaardag.addEventListener('click', function() {
sortOnClick('desc', userData, 'verjaardag');
});
}
// init our sorter
initSorter(data);
Let's give this a try then.
You do have to edit your HTML structure so that each 'record' of first name, last name and office has a seperate container. If you also have to go counting the amout of divs that make up one record, the code grows even larger.
I opted for a list as the wrappers, as it's more or less the standard way.
Also added a data-sort attribute to each of the icons so I don't have to go through the hassle of reading the sort type from the header.
<!DOCTYPE html>
<html lang="en">
<head>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.wrap-3, .wrap-6 {
border: 1px solid black;
width: 50%;
}
.wrap-3 > * {
display: inline-block;
width: 32%;
}
.wrap-6 > * {
display: inline-block;
width: 16%;
}
ul {
border: 1px solid black;
list-style: none;
width: 50%;
}
li {
display: block;
width: 100%;
}
li > * {
display: inline-block;
width: 32%;
}
</style>
</head>
<body>
<div class="wrap-3">
<span class="titel achternaam" >Achternaam</span>
<span class="titel voornaam" >Voornaam</span>
<span class="titel kantoor" >Kantoor</span>
</div>
<div id="icons-sort" class="wrap-6">
<span class="ui-icon ui-icon-circle-triangle-n" data-sort="achternaam-asc">up</span>
<span class="ui-icon ui-icon-circle-triangle-s" data-sort="achternaam-desc">down</span>
<span class="ui-icon ui-icon-circle-triangle-n" data-sort="voornaam-asc">up</span>
<span class="ui-icon ui-icon-circle-triangle-s" data-sort="voornaam-desc">down</span>
<span class="ui-icon ui-icon-circle-triangle-n" data-sort="kantoor-asc">up</span>
<span class="ui-icon ui-icon-circle-triangle-s" data-sort="kantoor-desc">down</span>
</div>
<ul>
<li>
<span class="achternaam">Gates</span>
<span class="voornaam">Bill</span>
<span class="kantoor">123</span>
</li>
<li>
<span class="achternaam">Zuckerberg</span>
<span class="voornaam">Mark</span>
<span class="kantoor">456</span>
</li>
<li>
<span class="achternaam">Resig</span>
<span class="voornaam">John</span>
<span class="kantoor">789</span>
</li>
</ul>
<script>
var clear = function clear( node ) {
while (node.firstChild) {
node.removeChild(node.firstChild);
}
return node;
};
document.querySelector('#icons-sort').addEventListener('click', function( event ) {
var list, records, fragment, sortType, field, order;
if (event.target && event.target.hasAttribute('data-sort')) {
list = document.querySelector('ul'),
records = Array.prototype.slice.call(list.querySelectorAll('li')),
fragment = document.createDocumentFragment(),
sortType = event.target.getAttribute('data-sort').split('-'),
field = '.' + sortType[0],
order = sortType[1];
records = records.sort(function( first, second ) {
var firstVal = first.querySelector(field).innerHTML,
secondVal = second.querySelector(field).innerHTML;
if (firstVal < secondVal) return -1;
else if (firstVal > secondVal) return 1;
});
if (order === 'desc') records.reverse();
records.forEach(function( listItem ) {
fragment.appendChild(listItem);
});
clear(list).appendChild(fragment);
}
});
</script>
</body>
</html>

[HTML DOM].style undefinded? (html5 app: address book)

so basically I can't figure out why is giving me the folling error, when I call add() function (when you click on add button)...
it says: status.style is undefined
status is an html dom, an html tag
I think the error is located almost at the end of the sheet
var myArray = []; // * used to store all the data
myArray[0] = ['John', 'Doe', '1980'];
myArray[1] = ['Jane','Malloy','1982'];
myArray[2] = ['Vincent','Malloy','1988'];
var firstName = document.getElementById('firstName');
var secondName = document.getElementById('secondName');
var bornYear = document.getElementById('bornYear');
var output = document.getElementById('output');
var form1 = document.getElementById('form1');
var status = document.getElementById('status');
var add = function() { //calls statusMessagge()
// check if input[] its not empty...
if ( firstName.value.length>0 && secondName.value.length>0 && bornYear.value.length>0 ) {
// * adding inputs to myArray
myArray[myArray.length] = [firstName.value ,secondName.value ,bornYear.value ];
//clearBoxes();
// * status messagge
statusMessagge('good');
alert('is good');
}
else {
statusMessagge('bad');
alert('is bad');
}
};
var statusMessagge = function(arg) { // * it is been called by: add(), show()
// * selecting the messagge to appear
switch (arg) {
case 'good':
status.innerHTML = 'Person added successfully.';
break;
case 'bad':
status.innerHTML = 'Please fill all the fields.';
break;
case 'loading':
status.innerHTML = 'Loading...';
break;
case 'loaded':
status.innerHTML = 'Finish.';
break;
}
// * do opacity effect slow: show|hide
status.style.opacity = 1; // this is the part that I get the error.
setTimeout (function() {
status.removeAttribute('style');
}, 1000);
};
body {
background: lightgray;
font-family: consolas;
font-size: 13px;
padding: 0;
margin: 0;
}
main {
background: #dbcdcd;
margin: 0 auto;
}
form:nth-of-type(1) {
float: left;
}
form:nth-of-type(2) {
float: left;
}
label { /* for alining elements correctly */
display: inline-block;
width: 77px;
text-align: right;
}
input[type="text"]:not(:first-of-type) {
margin-top: 5px;
}
#status {
opacity: 0;
transition: opacity .20s;
clear: both;
}
<!doctype html>
<html lang="es-ES">
<head>
<title>.:_My Exercise_:.</title>
<link rel="stylesheet" type="text/css" href="style.css"/>
<meta charset="utf-8"/>
</head>
<body>
<main>
<form id="form1" action=""> <!--action="#" onsubmit="return false"-->
<fieldset>
<legend>Please introduce new person...</legend>
<label>firstName:</label>
<input id="firstName" type="text" autofocus tabindex="1"/>
<input type="button" value="Add" onclick="add()"/> <br/>
<label>secondName:</label>
<input id="secondName" type="text" tabindex="2"/>
<input type="button" value="Show" onclick="show()"/> <br/>
<label>bornYear:</label>
<input id="bornYear" type="text" tabindex="3"/>
<input type="button" value="Sort" onclick="sort()"/>
</fieldset>
</form>
<form>
<fieldset>
<legend>Sort...</legend>
<input type="button" value="a-z" onclick=""/>
<input type="button" value="z-a" onclick=""/>
</fieldset>
</form>
<p id="status"></p>
<p id="output"></p>
</main>
<script src="script.js"></script>
</body>
</html>
I think that what you want is to display a message in console. Use console.log() for that. It worked in Firefox for me.
Example:
// ... (your previous code)
if ( firstName.value.length>0 && secondName.value.length>0 && bornYear.value.length>0 ) {
myArray[myArray.length] = [firstName.value ,secondName.value ,bornYear.value ];
console.log("good");
alert('is good');
}
else {
console.log("bad");
alert('is bad');
}
// ...
I passed the element through to the statusMessage function allowing me to set it's innerHTML value.
We get the elements on the time of click rather onload to prevent the variables to be undefined.
var myArray = []; // * used to store all the data
myArray[0] = ['John', 'Doe', '1980'];
myArray[1] = ['Jane','Malloy','1982'];
myArray[2] = ['Vincent','Malloy','1988'];
var add = function() { //calls statusMessagge()
var firstName = document.getElementById('firstName');
var secondName = document.getElementById('secondName');
var bornYear = document.getElementById('bornYear');
var output = document.getElementById('output');
var form1 = document.getElementById('form1');
var status = document.getElementById('status');
// check if input[] its not empty...
if ( firstName.value.length>0 && secondName.value.length>0 && bornYear.value.length>0 ) {
// * adding inputs to myArray
myArray[myArray.length] = [firstName.value ,secondName.value ,bornYear.value ];
//clearBoxes();
// * status messagge
statusMessage(status, 'good');
}
else {
statusMessage(status, 'bad');
}
};
var statusMessage = function(element, arg) { // * it is been called by: add(), show()
element.style.opacity = 1;
switch (arg) {
case 'good':
element.innerHTML = 'Person added successfully.';
break;
case 'bad':
element.innerHTML = 'Please fill all the fields.';
break;
case 'loading':
element.innerHTML = 'Loading...';
break;
case 'loaded':
element.innerHTML = 'Finish.';
break;
default:
element.innerHTML = "";
break;
}
// * do opacity effect slow: show|hide
setTimeout (function() {
element.removeAttribute('style');
}, 1000);
};
body {
background: lightgray;
font-family: consolas;
font-size: 13px;
padding: 0;
margin: 0;
}
main {
background: #dbcdcd;
margin: 0 auto;
}
form:nth-of-type(1) {
float: left;
}
form:nth-of-type(2) {
float: left;
}
label { /* for alining elements correctly */
display: inline-block;
width: 77px;
text-align: right;
}
input[type="text"]:not(:first-of-type) {
margin-top: 5px;
}
#status {
opacity: 0;
transition: opacity .20s;
clear: both;
}
<!doctype html>
<html lang="es-ES">
<head>
<title>.:_My Exercise_:.</title>
<link rel="stylesheet" type="text/css" href="style.css"/>
<meta charset="utf-8"/>
</head>
<body>
<main>
<form id="form1" action=""> <!--action="#" onsubmit="return false"-->
<fieldset>
<legend>Please introduce new person...</legend>
<label>firstName:</label>
<input id="firstName" type="text" autofocus tabindex="1"/>
<input type="button" value="Add" onclick="add()"/> <br/>
<label>secondName:</label>
<input id="secondName" type="text" tabindex="2"/>
<input type="button" value="Show" onclick="show()"/> <br/>
<label>bornYear:</label>
<input id="bornYear" type="text" tabindex="3"/>
<input type="button" value="Sort" onclick="sort()"/>
</fieldset>
</form>
<form>
<fieldset>
<legend>Sort...</legend>
<input type="button" value="a-z" onclick=""/>
<input type="button" value="z-a" onclick=""/>
</fieldset>
</form>
<p id="status"></p>
<p id="output"></p>
</main>
<script src="script.js"></script>
</body>
</html>
Different approach:
I run your code on chrome, with one difference: run script.js after event 'DOMContentLoaded', the event holds your script until browser informs that loaded all html:
document.addEventListener('DOMContentLoaded', function(){
var myArray = []; // * used to store all the data
myArray[0] = ['John', 'Doe', '1980'];
myArray[1] = ['Jane','Malloy','1982'];
myArray[2] = ['Vincent','Malloy','1988'];
var firstName = document.getElementById('firstName');
var secondName = document.getElementById('secondName');
var bornYear = document.getElementById('bornYear');
var output = document.getElementById('output');
var form1 = document.getElementById('form1');
var status = document.getElementById('status');
window.add = function() { //calls statusMessagge()
// check if input[] its not empty...
if ( firstName.value.length>0 && secondName.value.length>0 && bornYear.value.length>0 ) {
// * adding inputs to myArray
myArray[myArray.length] = [firstName.value ,secondName.value ,bornYear.value ];
//clearBoxes();
// * status messagge
statusMessagge('good');
alert('is good');
}
else {
statusMessagge('bad');
alert('is bad');
}
};
var statusMessagge = function(arg) { // * it is been called by: add(), show()
// * selecting the messagge to appear
switch (arg) {
case 'good':
status.innerText = 'Person added successfully.';
break;
case 'bad':
status.innerText = 'Please fill all the fields.';
break;
case 'loading':
status.innerText = 'Loading...';
break;
case 'loaded':
status.innerText = 'Finish.';
break;
}
// * do opacity effect slow: show|hide
status.style.opacity = 1; // this is the part that I get the error.
setTimeout (function() {
status.removeAttribute('style');
}, 1000);
};
});
In function statusMessagge() you assign status with string, so it isn't html element anymore.
Try do:
status.innerText = 'some text';

Categories

Resources