Budget App

In this example below you will see how to do a Budget App with some HTML / CSS and Javascript

Thumbnail
This awesome code was written by erkand-imeri, you can see more from this user in the personal repository.
You can find the original code on Codepen.io
Copyright erkand-imeri ©

Technologies

  • HTML
  • CSS
  • JavaScript
<!DOCTYPE html>
<html lang="en" >

<head>
  <meta charset="UTF-8">
  <title>Budget App</title>
  
  
  <link rel='stylesheet prefetch' href='https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-beta.2/css/bootstrap.css'>
<link rel='stylesheet prefetch' href='http://code.ionicframework.com/ionicons/2.0.1/css/ionicons.min.css'>
<link rel='stylesheet prefetch' href='https://cdnjs.cloudflare.com/ajax/libs/ionicons/4.0.0-9/css/ionicons.css'>

      <link rel="stylesheet" href="css/style.css">

  
</head>

<body>

  
  <div class="headbudg">
  
<div class="contbud">
     <h5>Available budget in <span class="budget__title--month"></span>: </h5>
    <span class="budgetresult">+1240</span>
    <div class="income"><span>INCOME</span></div>
    <div class="expenses"><span>EXPENSES</span></div>
  </div>
  </div>
<div class="navbudg">
  <div class="subnav">
    
   
     <div class="form-group row">
    <select class="custom-select add_type">
  <option value="inc" selected>+</option>
  <option value="exp">-</option>
</select>
    
        
      
      
              <input class="form-control" type="text" placeholder="Add Description" id="addesc">

     
      
            <input class="form-control" type="number" value="" id="addvalue">

     
     
        <button class="add__btn"><i class="ion-ios-checkmark-outline"></i></button>
    
  </div>
   
  
    
  </div>
  
</div>


<div>
    <div class="leftp">
      <h4>INCOME</h4>
   <div class="income_list"></div>
    </div>
  <div class="rightp"><h4>EXPENSES</h4>
    
      <div class="expenses_list"></div>
    
  </div>
</div>
  
  

    <script  src="js/index.js"></script>




</body>

</html>

/*Downloaded from https://www.codeseek.co/erkand-imeri/budget-app-QaOrVN */
@import url('https://fonts.googleapis.com/css?family=Roboto');
@import url('https://fonts.googleapis.com/css?family=Open+Sans+Condensed:300');


/**********
HEADER
************/
h5 {
 margin-top: 10px;
  color: white;
text-align: center;
  font-family: 'Roboto', sans-serif;
  
}

.budgetresult
{
  display:table;
margin:0 auto;
  color: white;
  font-size: 47.5px;
  font-weight: bold;
  font-family: 'Open Sans Condensed', sans-serif;

}

.headbudg{
  width: 100%;
  height: 220px;
  background-image: url('http://i67.tinypic.com/msghzs.jpg');
  background-repeat: no-repeat;
  background-size: cover;
  background-position: center;
  float: left;
  position: relative;
}

.income{
  width: 300px;
  height: 35px;
  background-color: #26A69A;
  position: absolute;
  bottom: 0;
  margin-bottom: 60px;
    left: 50%;
-webkit-transform: translateX(-50%);
transform: translateX(-50%);
        box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);



}
.income span
{
  
    position: absolute;
  bottom: 0;
  margin-left: 10px;
  margin-bottom: 1.5%;
  font-family: 'Roboto', sans-serif;

}
.expenses{
   width: 300px;
  height: 35px;
  background-color: #F4511E;
  position: absolute;
  bottom: 0;
  margin-bottom: 20px;
  left: 50%;
-webkit-transform: translateX(-50%);
transform: translateX(-50%);
  
  box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);

  
}
.expenses span
{
  font-family: 'Roboto', sans-serif;

  margin-bottom: 1.5%;
  position: absolute;
  bottom: 0;
  margin-left: 10px;
}

.contbud{
  width: 370px;
  height: 200px;
 
 position: relative;
  margin-left: auto;
  margin-right: auto;
  margin-top: 10px;
}


/**********
NAVINPUT
************/
.navbudg{
  width: 100%;
  height: 50px;
  background-color: #f2f2f2;
  float: left;
  border-bottom: 1.5px solid #dedfe0;
  
 
}
.subnav
{
  width: 57%;
  height: 100%;
  padding-top: 5px;
  margin-left: 27.5%;
  
}

#addesc

{
  width: 50%;
  margin-left: 5px;
  height: 40px;
}

#addvalue
{
  width: 95px;
  margin-left: 5px;
  height: 40px;
}

.add__btn
{
  color: green;
  padding: 0;
border: none;
background: none;
  font-size: 35px;
  position: relative;
  margin-top: -5px;
   transition: all 0.5s ease;
  margin-left: 5px;
  padding-bottom: 5px !important;
 
}
*:focus {
    outline: 0 !important;
}
.add__btn:hover
{
  color: red;
  transform: rotate(360deg);
  cursor: pointer;
        text-shadow: 3px 3px 3px red;
}



/**********
LIST
************/

.leftp{
  width: 50%;
  float: left;
  border-right: 1 px solid black;
  text-align: center;
  
}
.leftp, .rightp
{
  margin-top: 20px;
}
.leftp h4, .rightp h4
{
    font-family: 'Roboto', sans-serif;

}
.leftp h4{
  color:  #26A69A;
}
.rightp h4{
  color: #F4511E;
}

.rightp
{
  width: 50%;
  float: right;
 
  text-align: center;
}



.icome__title { color: #28B9B5; }
.expenses__title { color: #FF5049; }

.item {
    padding: 13px;
    border-bottom: 1px solid #e7e7e7;
}

.item:first-child { border-top: 1px solid #e7e7e7; }
.item:nth-child(even) { background-color: #f7f7f7; }

.item__description {
    float: left;
}

.item__value {
    float: left;
    transition: transform 0.3s;
}

.item__percentage {
    float: left;
    margin-left: 20px;
    transition: transform 0.3s;
    font-size: 11px;
    background-color: #FFDAD9;
    padding: 3px;
    border-radius: 3px;
    width: 32px;
    text-align: center;
}

.income .item__value,
.income .item__delete--btn {
    color: #28B9B5;
}

.expenses .item__value,
.expenses .item__percentage,
.expenses .item__delete--btn {
    color: #FF5049;
}


.item__delete {
    float: left;
}

.item__delete--btn {
    font-size: 22px;
    background: none;
    border: none;
    cursor: pointer;
    display: inline-block;
    vertical-align: middle;
    line-height: 1;
    display: none;
}

.item__delete--btn:focus { outline: none; }
.item__delete--btn:active { transform: translateY(2px); }

.item:hover .item__delete--btn { display: block; }
.item:hover .item__value { transform: translateX(-20px); }
.item:hover .item__percentage { transform: translateX(-20px); }


.unpaid {
    background-color: #FFDAD9 !important;
    cursor: pointer;
    color: #FF5049;

}

.unpaid .item__percentage { box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 0.1); }
.unpaid:hover .item__description { font-weight: 900; }

/*Downloaded from https://www.codeseek.co/erkand-imeri/budget-app-QaOrVN */

//Budget Controller
var budgetApp=(function(){
  
  var Expense=function(id,desc,value){
    this.id=id;
    this.desc=desc;
    this.value=value;
  }
  
    var Income=function(id,desc,value){
    this.id=id;
    this.desc=desc;
    this.value=value;
  }
  
 var data={
   allItems:{
     inc: [],
     exp: []
   },
   totals: {
     inc: 0,
     exp: 0
   }
 }
 
 
 return {
   addItem: function(type,des,val){
     var newItem,id;
     if(data.allItems[type].length>0)
       {
id=data.allItems[type][data.allItems[type].length-1].id+1;
       }
     else{
            id=0;       
     }
     
     
     if(type=='exp'){
        
     newItem=new Expense(id,des,val);
     }else if(type=='inc'){
       newItem=new Income(id,des,val);
     }
     
     data.allItems[type].push(newItem);
     
    return newItem;
   },
   testing: function(){
     console.log(data);
   }
 }
  
})();
// UI Controller
var UIController=(function(){
  
  var DOMvar={
    addtype: ".add_type",
    description: "#addesc",
    value: "#addvalue",
    addbtn: ".add__btn",
    incomeContainer:'.income_list',
    expensesContainer: '.expenses_list'
  }  
    var formatNumber = function(num, type) {
        var numSplit, int, dec, type;
        /*
            + or - before number
            exactly 2 decimal points
            comma separating the thousands

            2310.4567 -> + 2,310.46
            2000 -> + 2,000.00
            */

        num = Math.abs(num);
        num = num.toFixed(2);

        numSplit = num.split('.');

        int = numSplit[0];
        if (int.length > 3) {
            int = int.substr(0, int.length - 3) + ',' + int.substr(int.length - 3, 3); //input 23510, output 23,510
        }

        dec = numSplit[1];

        return (type === 'exp' ? '-' : '+') + ' ' + int + '.' + dec;

    };
  
  return {
    getInput: function(){
      return{
        type:document.querySelector(DOMvar.addtype).value,
     description:document.querySelector(DOMvar.description).value,
     value :document.querySelector(DOMvar.value).value
      }
     
    },
    getMonth: function(){
     
      var months=["January","February","March","April","May","June","July","August","September",
 "October","November","December"];
      
      var d = new Date();
    var n = d.getMonth();
      
      return months[n];
    }, 
    addListItem:function(obj,type){
      //Create HTML string with placeholder text
    var html,newHTML,element;
      
      if(type==="inc")
      {
        element=DOMvar.incomeContainer;
                      html = '<div class="item clearfix" id="inc-%id%"> <div class="item__description">%description%</div><div class="right clearfix"><div class="item__value">%value%</div><div class="item__delete"><button class="item__delete--btn"><i class="ion-ios-close-outline"></i></button></div></div></div>';

      }
      else if(type==='exp')
        {
           element=DOMvar.expensesContainer;
       html = '<div class="item clearfix" id="exp-%id%"><div class="item__description">%description%</div><div class="right clearfix"><div class="item__value">%value%</div><div class="item__percentage">21%</div><div class="item__delete"><button class="item__delete--btn"><i class="ion-ios-close-outline"></i></button></div></div></div>';
        }
      //Replace placeholder text with some  actual data
      
      newHTML=html.replace('%id%',obj.id);
      newHTML=newHTML.replace('%description%',obj.desc);
      newHTML=newHTML.replace('%value%',formatNumber(obj.value, type));
      
      
      //Insert HTML into the DOM
      
    document.querySelector(element).insertAdjacentHTML('beforeend', newHTML);
    },
    
    clearFields: function(){
      var fields,fieldsArr;
      
      fields=document.querySelectorAll(DOMvar.description + ',' + DOMvar.value);
      
     fieldsArr= Array.prototype.slice.call();
                                           
        fieldsArr.forEach(function(current,index,array){
              current.value="";
     });
      
      fieldsArr[0].focus();
    },
    
    getDOMstrings: function() {
            return DOMvar;
        }
  }
  
})();

//Main Controller

var mcontroller=(function(budgetController,UICtrl){

 
  
  var ctrlAddItem=function(){
    var input, newItem;
    //1.Get the field data
   var input=UICtrl.getInput();
    //2. Add the item to the budget controller
    newItem=budgetApp.addItem(input.type,input.description,input.value);
    //3.Add the item to the UI
    
    UICtrl.addListItem(newItem,input.type);
    //4.Clear the fields
    UICtrl.clearFields();
    //4.Calculate the budget
    
    //5.Display the budget on the UI
    

  };
  var domvar=UICtrl.getDOMstrings();
  document.querySelector(domvar.addbtn).addEventListener('click',ctrlAddItem);
  document.querySelector('.budget__title--month').textContent =UICtrl.getMonth();
  
  
})(budgetApp,UIController);

document.addEventListener('keypress',function(event){
  if(event.keycode===13 && event.which===13)
    {
      ctrlAddItem();
      
      
    }
});

Comments