I am trying to calculate the sum of a dynamic div for different categories, and then place that value in a div. What I don't understand, is how to figure out the total based on different categories. Here is a screencast of what I am talking about https://www.screencast.com/t/js8LBNfXo9sa. Here is also a link to my code pen which houses my code https://codepen.io/nfinsand/project/full/ZLNEon/.
var addListItem = document.getElementById("add-more");
addListItem.addEventListener("click", function() {
createNewItem();
});
//Display Month and Day
var today = new Date();
var dd = today.getDate();
var mm = today.getMonth() + 1;
today = mm + "/" + dd;
document.getElementById("current-date").innerHTML = today;
//Creates new elements
function createNewItem() {
var u = document.getElementById("full-item-list");
var l = document.createElement("li");
var elinput = document.createElement('input');
var expenseName = document.createElement('input');
var icon = document.createElement('img');
var optionsArray = [{
'itemText': 'Category',
'itemDisabled': true,
'itemSelected': true
},
'Auto & Transport',
'Health & Fitness',
'Home',
'Personal Care',
'Pets',
'Shopping',
'Entertainment',
'Investments'
];
var selectElem = document.createElement('select');
selectElem.setAttribute('name', 'selectThis');
// iterate through the array of options
optionsArray.forEach(function(item) {
var text = (typeof(item) === 'string') ? item : item.itemText;
var option = document.createElement('option');
var optionText = document.createTextNode(text);
option.appendChild(optionText);
if (typeof(item) === 'object') {
// handle custom attributes
Object.keys(item).forEach(function(key) {
switch (key) {
case 'itemDisabled':
if (item[key]) {
option.setAttribute('disabled', true);
}
break;
case 'itemSelected':
if (item[key]) {
option.setAttribute('selected', true);
}
break;
default:
break;
}
});
}
selectElem.appendChild(option);
});
expenseName.setAttribute('type', 'text');
expenseName.setAttribute('placeholder', 'Expense name');
expenseName.setAttribute('class', 'expense-input-name')
expenseName.setAttribute('name', 'totalExpense');
elinput.setAttribute('type', 'number');
elinput.setAttribute('class', 'li-input');
elinput.setAttribute('placeholder', 'Enter amount');
elinput.setAttribute('name', 'qty');
l.setAttribute('class', 'list-item');
l.setAttribute('name', 'li-name');
icon.setAttribute('class', 'remove-icon');
icon.setAttribute('src', 'https://s3-us-west-2.amazonaws.com/s.cdpn.io/375261/System_Delete.ico');
icon.setAttribute("id", "icon-id");
icon.addEventListener('click', function(e) {
thaticon(e);
}, false);
l.appendChild(selectElem);
l.appendChild(expenseName);
l.appendChild(elinput);
l.appendChild(icon);
u.appendChild(l);
}
//Deletes elements
function thaticon(e) {
console.log("test");
var el = e.target;
var elListItem = el.parentNode;
elFullList = elListItem.parentNode;
elFullList.removeChild(elListItem);
}
//Calculates and displays results
function displayResult() {
var arr = document.getElementsByName("qty");
var wage = document.getElementById("inputWage").value;
var jumboDiv = document.getElementById("jumbo-results").style.display = "block";
var tot = 0;
for (var i = 0; i < arr.length; i++) {
if (parseFloat(arr[i].value)) tot += parseFloat(arr[i].value);
}
document.getElementById("result").innerHTML = "Total Expenses: $" + tot.toFixed(2);
document.getElementById("left").innerHTML = "Left Over: $" + ((wage - tot).toFixed(2));
}
//Resets and clears entire entry
function resetForm() {
var jumboDiv = document.getElementById("jumbo-results").style.display = "none";
document.getElementById("full-item-list").innerHTML = "";
document.getElementById("inputWage").value = "";
document.getElementById("result").innerHTML = "";
document.getElementById("left").innerHTML = "";
document.getElementById("number-display").innerHTML = "";
}
//Displays the selected categories by user with the total sum for each one
function displayCategory() {
}
//Capture screen shots
/*function captureScreen() {
html2canvas(document.querySelector("#capture")).then(canvas => {
document.body.appendChild(canvas)
});
}*/
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Expense Tracker</title>
<link rel="stylesheet" href="css/style.css">
<link rel='stylesheet prefetch' href='https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.1/css/bootstrap.css'>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<link href="https://fonts.googleapis.com/css?family=Raleway:300" rel="stylesheet">
</head>
<body>
<div id="capture" class="container-fluid">
<div class="centerDiv">
<p class="mainHeading">Expense Calculator</p>
<p id="current-date"></p>
<div class="jumbotron jumbo2">
<h4>Categories</h4>
<div id="category-display"><br>
<div class="flex-container">
<div id="color-1"></div>
<div class="categoryItem">Auto & Transport</div>
<div class="well">$0.00</div>
</div>
<div class="flex-container">
<div id="color-2"></div>
<div class="categoryItem">Health & Fitness</div>
<div class="well">$0.00</div>
</div>
<div class="flex-container">
<div id="color-3"></div>
<div class="categoryItem">Home</div>
<div class="well">$0.00</div>
</div>
<div class="flex-container">
<div id="color-4"></div>
<div class="categoryItem">Personal Care</div>
<div class="well">$0.00</div>
</div>
<div class="flex-container">
<div id="color-5"></div>
<div class="categoryItem">Pets</div>
<div class="well">$0.00</div>
</div>
<div class="flex-container">
<div id="color-6"></div>
<div class="categoryItem">Shopping</div>
<div class="well">$0.00</div>
</div>
<div class="flex-container">
<div id="color-7"></div>
<div class="categoryItem">Entertainment</div>
<div class="well">$0.00</div>
</div>
<div class="flex-container">
<div id="color-8"></div>
<div class="categoryItem">Investments</div>
<div class="well">$0.00</div>
</div>
</div>
</div>
<div class="jumbotron">
<label class="expenseLabel">Income:</label><br>
<input id="inputWage" type="number" placeholder="Paycheck Amount"><br><br><br>
<label>Expenses:</label>
<ul id="full-item-list"></ul>
<div class="listItem">
<button id="add-more" class='btn btn-warning addExpenseBtn'>Add Expense</button>
<button class="btn btn-warning submitExpenseBtn" type="button" onclick="displayResult(); displayCategory()">Submit</button>
<button class="btn btn-warning resetExpenseBtn" type="button" onclick="resetForm()">Reset</button>
</div>
</div>
<div id="jumbo-results" class="jumbotron">
<p id="result"></p><br>
<p id="left"></p>
</div>
<button class="btn btn-warning captureBtn" onclick="captureScreen()">Save Me</button>
</div>
</div>
<footer>
<small>© Copyright 2018, Noble Finsand</small>
</footer>
<script src='https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js'></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.1/js/bootstrap.min.js'></script>
<script src="js/index.js"></script>
<script src="js/html2canvas.js"></script>
<script src="js/html2canvas.min.js"></script>
</body>
</html>
In order to calculate the total based on the categories, you will need to create a list of objects that have all the data the user entered.
From a code hygiene perspective creating the list and performing calculations on it should be separate tasks.
Similar to how you are looping through all the qty fields entered by the user in displayResult you can build out your list of expenses and then process that final result. Handling validation of each part will be challenging as they are all different fields and not guaranteed to have valid data.
Something like Angular can make this a lot easier as the hard part of binding input fields to a model is taken care of for you.
Regardless of how you create the list calculating the total by category is simple.
Assuming you create a list like this
var myExpenses = [
{'category': 'Home', name: 'rent', 'amount': 500},
{'category': 'Pets', name: 'cat food', 'amount': 45},
{'category': 'Home', name: 'utilities', 'amount': 200},
{'category': 'Pets', name: 'vet', 'amount': 42},
{'category': 'Home', name: 'trash', 'amount': 50},
{'category': 'Entertainment', name: 'date night', 'amount': 80}
];
Then these functions will be able to return you the grand total of all the expenses and each expense based on your categories.
function totalExpenses (expenses) {
return expenses.reduce(function (total, expense) {
return total + expense.amount;
}, 0);
}
function totalExpenseByCategory(categories, expenses) {
var categorizedExpenses = [];
categories.map(function (category) {
var currentExpenses = expenses.filter(function (expense) {
return expense.category === category;
});
var total = totalExpenses(currentExpenses);
categorizedExpenses.push({'category': category, 'amount': total})
});
return categorizedExpenses;
}
These functions use Filter, Map and Reduce on arrays to calculate the totals. You can learn more about them here.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce
Related
I am having some difficulty filtering through a list of tasks in To Do List project.
I use an object to store the core properties of each task created like the id, content, completed, and date.
The filter should occurs after the user selects an option in a drop down menu.
I use an Event Listener to catch the id of the option selected, but I don't know what to do with that Id. For example, when the user selects the option 'completed' the app should only display the completed task, or the tasks that have a property of 'completed:true'.
I also want to filter the list in a fancy way such as make tasks fade out when filtering.
URL: https://alonzocarlos95.github.io/WDD-330/
//html
<!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">
<!--ClockPicker libraries-->
<link rel="stylesheet" href="https://weareoutman.github.io/clockpicker/dist/jquery-clockpicker.min.css"></link>
<!-- <script src="http://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script> -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<!-- Moment JS library CDN -->
<!-- <script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.25.1/moment.min.js"></script> -->
<!--Material Icons and Fonts-->
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Poppins:ital,wght#0,200;1,100&display=swap" rel="stylesheet">
<!--Small view-->
<link rel="stylesheet" href="css/small.css" media="screen">
<title>Document</title>
</head>
<body>
<header>
<nav>
<ul>
<li><span class="material-icons">done</span></li>
<li class="drop-down" ><div class="dropdown"><button class="dropbtn" onclick="showModal()">All Lists<span class="material-icons" style="vertical-align: middle;">arrow_drop_down</span></button><div id="myDropdown" class="dropdown-content"><span id="select1">All Lists</span><span id="select2">Active</span><span id="select3">Completed</span></div></div></li>
<li><span class="label_list">BYU-Idaho To do List</span></li>
<li><span class="material-icons">search</span></li>
<li><img src="images/b2-removebg-preview.png" alt="logo"></li>
</ul>
</nav>
</header>
<main>
<div class="notes">
<img id="no_tasks" src="images/palms-300x220.png" alt="No tasks">
</div>
<div class="main_list" id="main_list">
<ul id="parentList">
</ul>
</div>
<div class="new_task_container" id="container_schedule">
<div class="new_task" id="new_todo">
<label>What is to be done?</label>
<div class="new_input">
<input type="text" name="todo" id="todo" placeholder="Enter task here">
<span class="material-icons">keyboard_voice</span>
</div>
<label>Due Date</label>
<input type="date" id="date" name="date" placeholder="Date not set">
</div>
<div class="new_task_group2">
<div class="new_time" id="new_time_container">
<input type="text" name="time" id="time" placeholder="Time not set(all day)">
<span class="material-icons">schedule</span>
<!-- <input type="checkbox" style="display: none;"> -->
</div>
</div>
</div>
</main>
<div class="add_task">
<button id="add" class="bounce">+</button>
</div>
<script src="https://weareoutman.github.io/clockpicker/dist/jquery-clockpicker.min.js"></script>
<script src="js/todo.js"></script>
</body>
</html>
//Javacript
let toDoList = [];
let options = {weekday:'long', year:'numeric', month:'long', day:'numeric'};
let indicador = 0;
let list_container = document.getElementById('main_list');
document.getElementById('container_schedule').style.display = 'none';
const chosenDate = document.getElementById("date");
const time = document.getElementById('new_time_container');
let ulTasks = document.getElementById('parentList');
time.style.display = 'none';
document.getElementById('add').addEventListener('click', () => {
document.getElementById('container_schedule').style.display = 'block';
document.getElementById('add').innerHTML = '<span class="material-icons">done</span>';
let inputNewTask = document.getElementById("todo");
let valInputNewTask = inputNewTask.value;
let valInputNewTask2 = inputNewTask.value;
let dateSet = document.getElementById('date').value;
if(indicador === 0){
indicador = 1;
list_container.style.display = "none";
}else {
if(!isBlank(valInputNewTask)){ //Valida si el valor del input no es null o undefined o whitespace
indicador = 0;
inputNewTask.value = "";
inputNewTask.focus();
let newDateSet = valDate(dateSet);
taskCreated();
manageTask(valInputNewTask2,newDateSet);
}
else {
alert("Enter task at first.");
}
}
} );
document.getElementById('date').addEventListener('change',() => {
// alert("New date");
time.style.display = 'flex';
});
function taskCreated(){
document.getElementById('container_schedule').style.display = 'none';
// debugger;
if(document.getElementsByClassName('notes').length >= 1){
document.getElementsByClassName('notes')[0].remove();
}
document.getElementById('add').textContent = '+';
}
/*Clock picker functionality*/
$("input[name=time]").clockpicker({
placement: 'bottom',
align: 'left',
autoclose: true,
default: 'now',
donetext: "Select",
init: function() {
console.log("colorpicker initiated");
},
beforeShow: function() {
console.log("before show");
},
afterShow: function() {
console.log("after show");
},
beforeHide: function() {
console.log("before hide");
},
afterHide: function() {
console.log("after hide");
},
beforeHourSelect: function() {
console.log("before hour selected");
},
afterHourSelect: function() {
console.log("after hour selected");
},
beforeDone: function() {
console.log("before done");
},
afterDone: function() {
console.log("after done");
}
});
function isBlank(str) {
//debugger;
return (!str || /^\s*$/.test(str));
}
function valDate(dateToDo){
// debugger;
if(dateToDo === null || dateToDo === ''){
dateToDo = "No date";
return dateToDo;
}
else {
dateToDo = new Date(dateToDo);
dateToDo.setDate(dateToDo.getDate()+1);
// testDate = new Date(Date.UTC(dateToDo));
dateToDo = dateToDo.toLocaleString('en-US',options);
return dateToDo;
}
}
function manageTask(getTask,dateSet){
const todo = {
id: Date.now(),
content: getTask,
completed: false,
date: dateSet
}
toDoList.push(todo);
addToLocalStorage(toDoList);
// storeData(todo);
}
function addToLocalStorage(toDoList){
// debugger;
localStorage.setItem('toDoList',JSON.stringify(toDoList));
renderTodos(toDoList);
}
function renderTodos(toDoList){
// debugger;
ulTasks.innerHTML = '';
toDoList.forEach(function(valInputNewTask2,index){
console.log(index);
const checked = toDoList.completed ? 'checked': null;
let currentTasks = document.createElement('li');
currentTasks.id = valInputNewTask2.id;
currentTasks.setAttribute('style','display:flex;background-color:#519872;width:100%;border-radius:7px;margin:0 0 10px 0;padding:6px 4px 6px 4px;min-height:3em;box-shadow: rgba(14, 30, 37, 0.12) 0px 2px 4px 0px, rgba(14, 30, 37, 0.32) 0px 2px 16px 0px;');
currentTasks.innerHTML = '<input id='+index+' type = "checkbox" class="checkInactive"><div style="display:flex;flex-direction:column;flex-grow:2;"><span style="margin-left:2em;">'+valInputNewTask2.content+'</span><span style="margin-left:2em;color:#17301C;">'+valInputNewTask2.date+'</span></div><div class="clear"><span class="material-icons">clear</span></div>';
if(valInputNewTask2.completed === true){
currentTasks.classList.add('checkActive');
currentTasks.firstChild.checked = true;
}
document.getElementById('parentList').appendChild(currentTasks);
});
list_container.style.display = "block";
}
function getFromLocalStorage(){
const getReference = localStorage.getItem('toDoList');
if(getReference){
document.querySelector('.notes').style.display = 'none';
toDoList = JSON.parse(getReference);
renderTodos(toDoList);
}
}
function showModal(){
document.getElementById('myDropdown').classList.toggle('show');
}
getFromLocalStorage();
function toggle(id){
toDoList.forEach(function(item){
if(item.id == id){
item.completed = !item.completed;
}
});
addToLocalStorage(toDoList);
}
function deleteToDo(id){
debugger
// alert(id);
toDoList = toDoList.filter(function(getTask){
return getTask.id != id;
});
addToLocalStorage(toDoList);
}
debugger;
ulTasks.addEventListener('click',function(event){
debugger;
if(event.target.type === 'checkbox'){
toggle(event.target.parentElement.getAttribute('id'));
}
if(event.target.parentElement.classList.contains('clear')){
debugger;
deleteToDo(event.target.parentElement.parentElement.getAttribute('id'));
}
});
//Close the dropdown if the user clicks outside it
window.onclick = function(e) {
if (!e.target.matches('.dropbtn')) {
var myDropdown = document.getElementById("myDropdown");
if (myDropdown.classList.contains('show')) {
myDropdown.classList.remove('show');
}
}
}
//Drop down Events
document.getElementById("myDropdown").addEventListener('click',function(event){
debugger;
if(event.target.localName === 'span'){
alert(event.target.id);
}
});
I don't know about the animations but at least for the filtering:
Ideally you should be using the select html element to create a dropdown menu and use the value attribute of the option elements to perform actions when an option is selected. Read more here: https://www.w3schools.com/tags/tag_select.asp
In your case, we can use the text inside the span tag, instead of the id to see which option was selected and render the todos based on the selected option.
We can then use the JS ES6 array function .filter(item => condition), which loops over the items in the array and returns a new array with all the items that match the provided condition.
document.getElementById('myDropdown').addEventListener('click', function(event) {
if (e.target.localName === 'span'){
let selectedOption = e.target.innerText;
if(selectedOption === 'All Tasks')
renderToDos(toDoList); // render everything
else if(selectedOption === 'Active'){
let activeToDos = toDoList.filter(todo => todo.completed === false);
renderToDos(activeToDos); // only render the todos which have not been completed
}
else if(selectedOption === 'Completed'){
let completedToDos = toDoList.filter(todo => todo.completed === true);
renderToDos(completedToDos); // only render the todos which have not been completed
}
}
});
I'm not sure how to add a new building by array. I'm a beginner javascript person.
I added saving/loading among other things to the back end but the client side is giving me issues for some reason.
I think it has something to do with me not under standing arrays correctly but if you could point me in the right direction i would love to learn.
I want to add a second building called
loadbuilding("taco stand")
Here is the code:
var Timer = window.setInterval(function() {
Tick()
}, 1000);
var buildings = [];
//The object declaration for game saves
function GameSave() {
this.money = 0;
this.buildings = [];
for (var i = 0; i < buildings.length; i++) {
this.buildings[i] = 0;
}
}
//The object declaration for buildings
function Building() {
this.Name = "Lemonade Stand";
this.Cost = 10;
this.PerSec = 1;
}
//The function to initialise all buildings
function InitBuildings() {
LoadBuilding("Lemonade Stand", 10, 1);
LoadBuilding("Taco Stand", 100, 1);
}
//The function to automatically load a building into the buildings array
function LoadBuilding(name, cost, persec) {
var cur = buildings.length;
buildings[cur] = new Building();
buildings[cur].Name = name;
buildings[cur].Cost = cost;
buildings[cur].PerSec = persec;
}
//The function used to gather money
function GatherMoney() {
game.money++; //++ tells javascript to add 1 to the variable
//Display the player's current money
document.getElementById("money").innerHTML = game.money;
}
//The function that gets run every second
function Tick() {
for (var i = 0; i < buildings.length; i++) {
game.money += game.buildings[i] * buildings[i].PerSec;
}
document.getElementById("money").innerHTML = game.money;
}
//The function to buy a lemonade stand
function Build(id) {
if (game.money >= buildings[id].Cost) { //Check if the player has enough money, then subtract it and add a new building if they do
game.money -= buildings[id].Cost;
game.buildings[id] = game.buildings[id] + 1;
document.getElementById("money").innerHTML = game.money;
document.getElementById("Building1Qty").innerHTML = game.buildings[id];
}
}
//Run this code once the page has loaded fully
window.onload = function() {
InitBuildings();
window.game = new GameSave();
};
<!--Pleae refer to Lesson 9.txt for a full description on this lesson -->
<html>
<head>
<title>Basic Incremental Game</title>
<link rel="stylesheet" type="text/css" href="css/Incremental.css">
<script src="js/Incremental.js"></script>
</head>
<body>
<div id="page">
<div id="header">
<div id="game-title">
Basic Incremental Game
</div>
</div>
<div id="content">
<div id="stats" class="block">
<div class="label">Money:</div>
<div id="money" class="label">0</div>
</div>
<div id="clickables" class="block">
<input type="button" value="Click Me!" onclick="GatherMoney();">
</div>
<div id="buildings" class="block">
<div id="Building1">
<input type="button" value="Lemonade Stand" onclick="Build(0);">
<div>
<div class="label">Cost:</div>
<div id="Building1Cost" class="label">10</div>
</div>
<div>
<div class="label">Per Sec:</div>
<div id="Building1PerSec" class="label">1</div>
</div>
<div>
<div class="label">Quantity:</div>
<div id="Building1Qty" class="label">0</div>
</div>
</div>
<div id="Building2">
<input type="button" value="Taco Stand" onclick="Build(1);">
<div>
<div class="label">Cost:</div>
<div id="Building2Cost" class="label">10</div>
</div>
<div>
<div class="label">Per Sec:</div>
<div id="Building2PerSec" class="label">1</div>
</div>
<div>
<div class="label">Quantity:</div>
<div id="Building2Qty" class="label">0</div>
</div>
</div>
</div>
<div id="upgrades" class="block">
This is where our upgrades will go!
</div>
</div>
</body>
EDIT:
i tried changing the but tit didnt work
buildings[]
to
buildings["Lemonade Stand", "Taco Stand"]
How about,
LoadBuilding("myBuilding", 12, 1);
Because you have this factory function,
function LoadBuilding(name, cost, persec) {
var cur = buildings.length;
buildings[cur] = new Building();
buildings[cur].Name = name;
buildings[cur].Cost = cost;
buildings[cur].PerSec = persec;
}
You could build an array of Building objects then iterate through them using a while loop.
See JSFIDDLE, or attached code.
Let me know if that helps.
class Building {
constructor(name, cost, persec) {
this.name = name;
this.cost = cost;
this.persec = persec;
}
}
var buildings = [];
buildings.push(new Building('Building One', '$10', '1'));
buildings.push(new Building('Building Two', '$20', '0.5'));
buildings.push(new Building('Building Three', '$25', '2'));
var count = 0;
while(count < buildings.length) {
document.getElementById('stores').innerHTML += '<p>' + buildings[count].name + '<br />' + buildings[count].cost + '<br />' + buildings[count].persec + '</p>';
count++;
}
<div id="stores">
</div>
I'm not sure if I'm asking the question the right way, exactly, so try to bear with me. What I mean is like if someone clicks a button that says "1", I want it to display a "1" on the display area. I'm attempting to build a simple calculator, just for my own practice. Sorry if it's a bad question, I'll delete it once it's answered if it is, I just could not find an answer on Google or anything.
So here is my HTML and JS code so far:
HTML:
<body>
<div id="calcBod">
<div id="display"><p id="displayTxt"></p></div>
<div id="numBtns">
<div id="buttonsRow1">
<button id="Btn1">1</button>
<button id="Btn2">2</button>
<button id="Btn3">3</button>
<button id="plusBtn">+</button>
</div>
<div id="buttonsRow2">
<button id="Btn4">4</button>
<button id="Btn5">5</button>
<button id="Btn6">6</button>
<button id="minBtn">-</button>
</div>
<div id="buttonsRow3">
<button id="Btn7">7</button>
<button id="Btn8">8</button>
<button id="Btn9">9</button>
<button id="multBtn">x</button>
</div>
<div id="buttonsRow4">
<button id="decBtn">.</button>
<button id="Btn0">0</button>
<button id="eqlBtn">=</button>
<button id="divBtn">÷</button>
</div>
<div id="clrDel">
<button id="delBtn">Delete</button>
<button id="clrBtn">Clear</button>
</div>
</div>
</div>
</body>
JS:
var btn1=document.getElementById("Btn1");
var btn2=document.getElementById("Btn2");
var btn3=document.getElementById("Btn3");
var btn4=document.getElementById("Btn4");
var btn5=document.getElementById("Btn5");
var btn6=document.getElementById("Btn6");
var btn7=document.getElementById("Btn7");
var btn8=document.getElementById("Btn8");
var btn9=document.getElementById("Btn9");
var btn0=document.getElementById("Btn0");
var decBtn=document.getElementById("decBtn");
var eqlBtn=document.getElementById("eqlBtn");
var plusBtn=document.getElementById("plusBtn");
var minBtn=document.getElementById("minBtn");
var multBtn=document.getElementById("multBtn");
var divBtn=document.getElementById("divBtn");
var delBtn=document.getElementById("delBtn");
var clrBtn=document.getElementById("clrBtn");
function displayText(){
}
Here's my answer for you.
First answer is to put data-attribute in your buttons.
Seconds answer is to get the innerText to your buttons.
function clickThis(event) {
var target = event.target;
console.log(target.getAttribute("data-value"));
console.log(target.innerText);
console.log("TEST");
}
document.getElementById("numBtns").addEventListener("click", clickThis)
I don't know much about these things, but maybe like this ?
function Calculator(id) {
var xContainer = document.getElementById(id);
var xDisplay = document.createElement('div');
var elements = [
'1', '2', '3', '+',
'4', '5', '6', '-',
'7', '8', '9', '*',
'.', '0', '=', '/',
'del', 'clear',
];
var click = function(event) {
event.preventDefault();
var value = this.innerText;
if (value == '=') {
xDisplay.innerText = eval(xDisplay.innerText); // jshint ignore:line
} else if (value == 'del') {
xDisplay.innerText = xDisplay.innerText.slice(0, -1);
} else if (value == 'clear') {
xDisplay.innerText = '';
} else {
xDisplay.innerText += value;
}
};
xContainer.appendChild(xDisplay);
var xRow;
elements.forEach(function(element, index) {
if (index % 4 === 0) {
xRow = document.createElement('div');
xContainer.appendChild(xRow);
}
var xElement = document.createElement('button');
xElement.innerText = element;
xRow.appendChild(xElement);
xElement.addEventListener('click', click);
});
}
var calc = new Calculator('calculator');
<div id="calculator"></div>
I have an array of items in form of service - as I know it's like proper way to keep data you use in different controllers.I watched tutorial and did the filtering by brands. But I have an obstacle with filtering of my Items by another parameters, such as price, length and frequency... So I have made sliders by another example but I have no idea how to tie up it with my array of Items. Please do me a favour, show how to tie up even one of my parameters, price for example.
http://angular.zxcvbn.ru
services.js:
myApp.service('ProductDataService', function() {
//sample data
var items = [
{ name:'Picachoo', id:1, price:25000, pict:'http://www.metrord.do/_internal/gxml!0/2qijkhn0ctpwx8acoz5fxkpvtmr4nbh$r05jcw5nnz5dt1u7odn7q01jm5k3ezo/screen-shot-2016-07-24-at-11-55-41-am.jpeg', len: 250, friq: 5000, brand: 'came' },
{ name:'Tortule', id:2, price:30000, pict:'https://encrypted-tbn3.gstatic.com/images?q=tbn:ANd9GcR2APj6_uBfhHRXLn1dZN58ZocpzMxGMFLZmuqHEU5SybKN4QAVfg', len: 250, friq: 300, brand: 'came' },
{ name:'Dragon', id:3, price:33500, pict:'https://encrypted-tbn1.gstatic.com/images?q=tbn:ANd9GcSJotIxkjgXgm9m3m-0FuUxN6g9fGGXmP84VDRrPZoWa-x8Dqqd', len: 350, friq: 300, brand: 'came' },
{ name:'encrypted1', id:4, price:45000, pict:'http://gaidi.ru/wp-content/uploads/2016/07/kak-pravilno-lovit-pokemonov-v-pokemon-go.jpg', len: 400, friq: 3000, brand: 'came' },
{ name:'pravilno', id:5, price:48600, pict:'http://vignette3.wikia.nocookie.net/pokemon/images/2/2e/009Blastoise_Dream.png/revision/latest?cb=20140812050618', len: 550, friq: 2000, brand: 'came' },
{ name:'images', id:6, price:30000, pict:'https://encrypted-tbn2.gstatic.com/images?q=tbn:ANd9GcSqywi0lMtmf1sAR-20rg0HXETMueY3H71iJP35WsdsPHGVokK41g', len: 550, friq: 1000, brand: 'bft' },
{ name:'Foxy', id:7, price:38000, pict:'http://vgtimes.ru/uploads/posts/2016-07/1468938437_pk_vulpix.png', len: 350, friq: 10000, brand: 'bft' },
{ name:'Pteradactys', id:8, price:43000, pict:'https://encrypted-tbn3.gstatic.com/images?q=tbn:ANd9GcRJBXypwhl8-z4IsAZokgQlqPx_vZymtENBdlPy1HhN34uODEZ5', len: 800, friq: 10000, brand: 'bft' },
{ name:'encrypted', id:9, price:35800, pict:'https://encrypted-tbn1.gstatic.com/images?q=tbn:ANd9GcQZNKoA9LMtQHhgU4Toy7xXfzGEp6Rb4Kv6I16RgMjWO0Dnb36EFA', len: 1200, friq: 3000, brand: 'faac' },
{ name:'Jidjfj', id:10, price:14000, pict:'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRPBKrRLvhYm9y-LxwRM4Qc_psMjd_luij_04ChmmQjcrdxgmcG3w', len: 800, friq: 5000, brand: 'fors' }
];
brands = {came : true, bft : true, faac : true, fors : true} ;
this.getItems = function() {
return items;
};
this.getBrands = function() {
return brands;
};
this.maxPrice = function() {
var max;
var producto;
for(var i = 0; i < items.length-1; i++) {
for(var j = 0; j < items.length-i-1; j++){
if (producto[j] > producto[j+1]) {
max = producto[j];
producto[j] = producto[j+1];
producto[j+1] = b;
}
}
}
return max;
}
this.minPrice = function() {
var min;
var producto;
for(var i = 0; i < items.length-1; i++) {
for(var j = 0; j < items.length-i-1; j++){
if (producto[j] < producto[j+1]) {
min = producto[j];
producto[j] = producto[j+1];
producto[j+1] = b;
}
}
}
return min;
}
});
slider_price.js:
myApp.controller('priceCtrl', function($scope, ProductDataService) {
$scope.search = { price_min : '', price_max : '', amount_min : 14000, amount_max : 48600 };
});
/* Range Slider
Input with default values:
-min=0 // Min slider value
-max=100 // Max slider value
-step=1 // Steps
Output / Input model
-value-min // Default value #min
-value-max // Default value #max
example:
<slider-range min="0" max="100" step="5" value-min="scope.form.slider_value_min" value-max="scope.form.slider_value_max"></slider-range>
*/
myApp.directive('priceRange', ['$document',function($document) {
// Move slider handle and range line
var moveHandle = function(handle, elem, posX) {
$(elem).find('.handle.'+handle).css("left",posX +'%');
};
var moveRange = function(elem,posMin,posMax) {
$(elem).find('.range').css("left",posMin +'%');
$(elem).find('.range').css("width",posMax - posMin +'%');
};
return {
template: '<div class="slider horizontal">'+
'<div class="range"></div>'+
'<a class="handle min" ng-mousedown="mouseDownMin($event)"></a>'+
'<a class="handle max" ng-mousedown="mouseDownMax($event)"></a>'+
'</div>',
replace: true,
restrict: 'E',
scope:{
valueMin:"=",
valueMax:"="
},
link: function postLink(scope, element, attrs) {
// Initilization
var dragging = false;
var startPointXMin = 0;
var startPointXMax = 0;
var xPosMin = 0;
var xPosMax = 0;
var settings = {
"min" : (typeof(attrs.min) !== "undefined" ? parseInt(attrs.min,10) : 0),
"max" : (typeof(attrs.max) !== "undefined" ? parseInt(attrs.max,10) : 100),
"step" : (typeof(attrs.step) !== "undefined" ? parseInt(attrs.step,10) : 1)
};
if ( typeof(scope.valueMin) == "undefined" || scope.valueMin === '' )
scope.valueMin = settings.min;
if ( typeof(scope.valueMax) == "undefined" || scope.valueMax === '' )
scope.valueMax = settings.max;
// Track changes only from the outside of the directive
scope.$watch('valueMin', function() {
if (dragging) return;
xPosMin = ( scope.valueMin - settings.min ) / (settings.max - settings.min ) * 100;
if(xPosMin < 0) {
xPosMin = 0;
} else if(xPosMin > 100) {
xPosMin = 100;
}
moveHandle("min",element,xPosMin);
moveRange(element,xPosMin,xPosMax);
});
scope.$watch('valueMax', function() {
if (dragging) return;
xPosMax = ( scope.valueMax - settings.min ) / (settings.max - settings.min ) * 100;
if(xPosMax < 0) {
xPosMax = 0;
} else if(xPosMax > 100) {
xPosMax = 100;
}
moveHandle("max",element,xPosMax);
moveRange(element,xPosMin,xPosMax);
});
// Real action control is here
scope.mouseDownMin = function($event) {
dragging = true;
startPointXMin = $event.pageX;
// Bind to full document, to make move easiery (not to lose focus on y axis)
$document.on('mousemove', function($event) {
if(!dragging) return;
//Calculate handle position
var moveDelta = $event.pageX - startPointXMin;
xPosMin = xPosMin + ( (moveDelta / element.outerWidth()) * 100 );
if(xPosMin < 0) {
xPosMin = 0;
} else if(xPosMin > xPosMax) {
xPosMin = xPosMax;
} else {
// Prevent generating "lag" if moving outside window
startPointXMin = $event.pageX;
}
scope.valueMin = Math.round((((settings.max - settings.min ) * (xPosMin / 100))+settings.min)/settings.step ) * settings.step;
scope.$apply();
// Move the Handle
moveHandle("min", element,xPosMin);
moveRange(element,xPosMin,xPosMax);
});
$document.mouseup(function(){
dragging = false;
$document.unbind('mousemove');
$document.unbind('mousemove');
});
};
scope.mouseDownMax = function($event) {
dragging = true;
startPointXMax = $event.pageX;
// Bind to full document, to make move easiery (not to lose focus on y axis)
$document.on('mousemove', function($event) {
if(!dragging) return;
//Calculate handle position
var moveDelta = $event.pageX - startPointXMax;
xPosMax = xPosMax + ( (moveDelta / element.outerWidth()) * 100 );
if(xPosMax > 100) {
xPosMax = 100;
} else if(xPosMax < xPosMin) {
xPosMax = xPosMin;
} else {
// Prevent generating "lag" if moving outside window
startPointXMax = $event.pageX;
}
scope.valueMax = Math.round((((settings.max - settings.min ) * (xPosMax / 100))+settings.min)/settings.step ) * settings.step;
scope.$apply();
// Move the Handle
moveHandle("max", element,xPosMax);
moveRange(element,xPosMin,xPosMax);
});
$document.mouseup(function(){
dragging = false;
$document.unbind('mousemove');
$document.unbind('mousemove');
});
};
}
};
}]);
app.js:
var myApp = angular.module("filterApp", []);
myApp.controller('ExampleController', ['$scope', '$window', function($scope, $window) {
$scope.greeting = 'Hello, World!';
$scope.doGreeting = function(greeting) {
$window.alert(greeting);
};
}]);
myApp.controller('coolCtrl', function($scope) {
$scope.whoAmI = function(){
console.log("This is whoAmI function in the coolCtrl!");
};
});
myApp.controller('mainCtrl', function($scope, ProductDataService){
$scope.helloWorld = function(){
console.log("This is helloWorld function in the mailCtrl!");
};
$scope.items = ProductDataService.getItems();
$scope.brands = ProductDataService.getBrands();
$scope.refresh = function(){
location.reload();
};
$scope.showPopUpMsg = false;
$scope.openPopUp = function( text ) {
$scope.showPopUpMsg = true;
$scope.popUpMsgContent = text;
$scope.minimun = 123;
};
});
jilters.js:
myApp.filter('brandsfilter', function () {
return function(input, filter) {
var result = [];
angular.forEach(input, function (item) {
angular.forEach(filter, function (isfiltered, brand) {
if (isfiltered && brand === item.brand) {
result.push(item);
}
});
});
return result;
};
});
index.php:
<?php
require 'scripts/mail_script.php';
?>
<!doctype html>
<html class="no-js" lang="">
<head>
<meta charset="utf-8">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<title></title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="apple-touch-icon" href="apple-touch-icon.png">
<!-- Place favicon.ico in the root directory -->
<link rel="stylesheet" href="styles/normalize.css">
<link rel="stylesheet" href="styles/main.css">
<link rel="stylesheet" href="styles/bootstrap.css">
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script> <!-- for slider work -->
</head>
<body ng-app="filterApp" ng-controller='mainCtrl'>
<!--[if lt IE 8]>
<p class="browserupgrade">You are using an <strong>outdated</strong> browser. Please upgrade your browser to improve your experience.</p>
<![endif]-->
<!-- Add your site or application content here -->
<div class="container">
<section class='top' >
<h1>Filter</h1>
<!-- //// http://embed.plnkr.co/woqn3i/ /// -->
<!-- ///////// -->
<div class="row" id='items'>
<div>
<div class="col-md-4" ><h2>params:</h2>
<div ng-controller="priceCtrl">
<p>Choose price:</p>
<p>min: <input type="number" ng-model="search.amount_min"/> $</p>
<p>max: <input type="number" ng-model="search.amount_max"/> $</p>
<slider-range min="14000" max="48600" step="100" value-min="search.amount_min" value-max="search.amount_max"></slider-range>
</div>
<hr>
<p>По названию:</p>
<p><input type="text" ng-model="price" /></p>
<p>Brand:</p>
<ul >
<li ng-repeat="(brand, value) in brands">
<input type="checkbox" ng-model="brands[brand]" /> {{brand}}
</li>
</ul>
<hr>
<!-- //// http://embed.plnkr.co/woqn3i/ /// -->
<div ng-controller="filterCtrl">
<p>length:</p>
<p>От: <input type="text" ng-model="search.price_min"/> meters</p>
<p>До: <input type="text" ng-model="search.price_max"/> meters</p>
<slider-range min="2.5" max="12" value-min="search.price_min" value-max="search.price_max"></slider-range>
<hr>
<p>friquincy:</p>
<p>Min: <input type="number" ng-model="search.amount_min"/> times</p>
<p>Max: <input type="number" ng-model="search.amount_max"/> times</p>
<slider-range min="300" max="10000" step="100" value-min="search.amount_min" value-max="search.amount_max"></slider-range>
</div>
<hr>
<!-- ///////// -->
<div class="actions"/>
<input type="button" value="Сбросить" ng-click='refresh()'>
</div>
</div>
<div class="col-md-8"><h2>______ kinds</h2>
<?php
if($success) echo '<h4 class="bg-success text-center">'.'Сообщение отправлено!' . '</h4>';
if($error_message) echo '<h4 class="bg-danger text-center">'.'Сообщение не отправлено:' . $error_message. '</h4>';
?>
<div class="row">
<!-- LOOP.-->
<div ng-repeat="item in items | filter:price | orderBy:price | brandsfilter:brands ">
<div class="col-md-4 col-sm-6 col-sx-12">
<div class="item-inner">
<div class="image-product">
<div class="caption">
<div class="box-view">
<div class="name">{{item.name}}</div>
</div>
</div>
<img src="{{item.pict}}" alt="{{item.name}}" title="{{item.name}}" class="img-responsive">
<p class="price"><span class="price">Price: {{item.price}} $.</span></p>
<p class="description">{{item.name}} - just another piece of information, first preporty is {{item.len}} m. <br>another is: {{item.friq}} per day. </p>
</div>
</div>
</div><!-- col -->
</div> <!-- ng-repeat -->
</div> <!-- row -->
</div>
</div> <!-- mainCtrl -->
</section>
</div>
<div class="panel-footer">
<script src="vendor/angular.js"></script>
<script src="scripts/app.js"></script>
<script src="scripts/services.js"></script>
<script src="scripts/filters.js"></script>
<script src="scripts/slider.js"></script>
<script src="scripts/slider_price.js"></script>
<script src="vendor/jquery.js"></script>
<script src="vendor/bootstrap.js"></script>
<!-- Google Analytics: change UA-XXXXX-X to be your site's ID. -->
</div>
</body>
</html>
AngularJS built-in filter which you already used supports multiple keywords filter see, you only need to implement comparator function to fulfill your needs.
First, change your filter in template to
<div ng-repeat="item in items | filter:myFilters:myComparator | orderBy:price">
then inside your filterCtrl you need to define myFilters and myComparator
$scope.myFilters = {price: 4000, brand: 'abc'};
$scope.myComparator = function(actual, expected) {
if (actual == parseInt(actual)) {
return actual > expected;
}
else {
return actual == expected;
}
}
Inside myComparator you can customise how you want to filter it (exact match, arithmetic comparison or partial match, just remember to return Boolean.
Just update $scope.myFilters whenever your filter keywords changed, the result will be updated in next digest cycle.
My submit button is finally working. However, it is not counting all of the votes in the results. How do I get my submit button to sort all of the votes?
HTML:
<!DOCTYPE html>
<html>
<link rel="stylesheet" text="text/css" href="movies.css">
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js">
</script>
<title>
Movie List
</title>
</head>
<body>
<h1>My Favorite Movies</h1>
<div id = "first">
<input type="text" id="movie" placeholder="Movie">
<button id="enter">Enter</button>
</div>
<div id="left">
<div id="list"><u>Chosen Films:</u></div>
<!-- <div>Chosen Films: <span id="list"></span></div> -->
<!-- <div id="films"></div> -->
<div id="best"><u>You're Best Films:</u></div>
<button id="submit">Submit</button>
</div>
<div id= "results"><u>Results</u></div>
<script type="text/javascript" src="movies.js"></script>
</body>
</html>
Javascript:
$(document).ready(function() {
var films = [];
// with working vote button
$("#enter").click(function () {
var movie = $("#movie").val();
var $btn = $('<button />', {
id: "vote",
type: "button",
text: "Vote",
value: movie,
click: function(){
var vote = this.value;
$("#best").append('<p>'+vote+'</p>');
films.push(vote);
}
});
var $p = $('<p />');
$p.append($btn, " ", movie);
$p.appendTo("#list");
});
});
So here is where the trouble is:
This code should allow the submit button to take the listed films under "your best films" and arrange them in a third list under "results" in order of their votes.
$("#submit").click(function () {
var ballot = {};
for (var i = 1; i < films.length; i++) {
var key = films[i];
ballot[key] = (ballot[key] || 0) + 1;
}
var elect = [];
for (key in ballot) elect.push({key: key, freq: ballot[key]});
elect.sort(function(a,b){return b.freq - a.freq});
console.log(elect);
for (var i = 0; i < elect.length; i++){
console.log(elect[i].key);
$("#results").append('<p>' + elect[i].key + '</p>');
}
});
Any suggestions or ideas would be appreciated!
$("#submit").click(function () {
var ballot = {};
for ( var i = 0; i < films.length; i++) {
var key = films[i];
ballot[key] = (ballot[key] || 0) + 1;
}
var elect = [];
for (key in ballot) elect.push({key: key, freq: ballot[key]});
elect.sort(function(a,b){return b.freq - a.freq});
console.log(elect);
for (var j = 0; j < elect.length; j++){
console.log(elect[j].key);
$("#results").append('<p>' + elect[j].key + '</p>');
}