Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save aaronksaunders/491c138601f0d20259e4 to your computer and use it in GitHub Desktop.
Save aaronksaunders/491c138601f0d20259e4 to your computer and use it in GitHub Desktop.
A Pen by Alex Whapham.

AngularJS Shopping List Widget

AngularJS Shopping List Widget is an AngularJS widget that allows a user to manually enter items of a shopping list, along with prices and coupons, and then print it.

A Pen by Alex Whapham on CodePen.

License.

<div class="wrapper" ng-app="shoppingListApp">
<div class="box">
<h1>AngularJS Shopping List Widget</h1>
<p>AngularJS Shopping List Widget is an AngularJS widget that allows a user to manually enter items of a shopping list, along with prices and coupons, and then print it.</p>
<p>It runs entirely in AngularJS, and updates in real time.</p>
<div class="demoWrapper" ng-controller="listController">
<h2>Demo</h2>
<div class="shoppingList">
<h3>Your Shopping List</h3>
<ul>
<li ng-repeat="item in listItems">
<div class="listItem">{{item.description}}</div>
<div class="listPrice">${{item.price}}</div>
<div class="closeListItem"><a ng-click="maximizeCouponEnter(item)"><img src="https://cdn4.iconfinder.com/data/icons/kitchen-cooking-dining/256/coupon-512.png" height="20"><a ng-click="removeListItem(item)">x</a></div>
<ul class="enterCoupon">
<li>
<input type="text" placeholder="Coupon Description/Name" class="newCouponName" ng-model="newCouponDesc">
<input type="text" placeholder="Discount" class="newCouponPrice" ng-model="newCouponDiscount">
<a class="addCouponButton" ng-click="addCoupon(item, newCouponDesc, newCouponDiscount)">Add</a>
<a class="minimize" ng-click="minimizeCouponEnter(item)">&ndash;</a>
</li>
</ul>
<ul class="couponsList">
<li class="couponItem" ng-repeat="coupon in item.coupons">
<div class="thisCouponDescription">
{{ coupon.name }} </div>
<div class="thisCouponDiscount">-${{ coupon.discount }}<a ng-click="removeCoupon(item, coupon)">x</a></div>
</li>
</ul>
</li>
</ul>
</div>
<div class="addItemModule">
<h3>Add an Item</h3>
<label class="addItemDesc">Description</label>
<form name="addForm">
<input type="text" class="addItemTBox" placeholder="Enter a product" ng-model="newDescription">
<label class="addItemPrice">Price</label>
<input type="text" class="addItemTBox" placeholder="Enter price" ng-model="newPrice">
<a ng-click="addListItem(newDescription, newPrice)">Add Item</a>
</form>
<p>Don't worry about adding coupons here, you'll have an opportunity to do that once you add the item to your list and a coupon clip icon appears next to it.</p>
<label class="totalPrice">Total Cost(Before Tax)</label>
<input type="text" ng-model="totalBeforeTax" class="addItemTBox" disabled>
<label class="stateTaxLabel">State Tax</label>
<select ng-model="taxState" class="taxState" id="taxStateSelected" ng-options="s.name for s in states" ng-change="toggleOtherTax(taxState.tax)">
</select>
<div id="OtherTax">
<label>Other Tax</label>
<input type="text" class="addItemTBox" id="otherTaxBox" ng-model="otherTax" ng-keyup="addOtherTax()">
</div>
<p>If you do not live in the U.S., or the tax of your jurisdiction is the U.S. is different from that of your state, please select "Other" from above and a box will appear below it to allow you to input your own tax.</p>
<label class="totalPricePlusTax">Total Cost(After Tax)</label>
<input ng-model="costAfterTax" type="text" class="addItemTBox" disabled>
<label class="totalPricePlusTax">Total Coupon Savings</label>
<input type="text" ng-model="couponSavings" class="addItemTBox" disabled>
<label class="totalPricePlusTax">Final Price</label>
<input type="text" class="addItemTBox" ng-model="finalPriceModel" disabled>
</div>
</div>
</div>
</div>
var shoppingListApp = angular.module('shoppingListApp', []);
shoppingListApp.controller('listController', function($scope) {
// Set the demo item array.
$scope.listItems = [
{description: 'Your First Item', price: 2.49, coupons: [{name: 'Great Coupon', discount: .99}]}];
// Set the state taxes array.
$scope.states = [
{name: 'AL', tax: 4},{name: 'AK', tax: 0},{name: 'AZ', tax: 5.6},{name: 'AR', tax: 6.5},{name: 'CA', tax: 7.5},
{name: 'CO', tax: 2.9},{name: 'CT', tax: 6.35},{name: 'DE', tax: 0},{name: 'DC', tax: 5.75},{name: 'FL', tax: 6},{name: 'GA', tax: 4},{name: 'HI', tax: 4},{name: 'ID', tax: 6},{name: 'IL', tax: 6.25},{name: 'IN', tax: 7},{name: 'IA', tax: 6},{name: 'KS', tax: 6.15},{name: 'KY', tax: 6},{name: 'LA', tax: 4},{name: 'ME', tax: 5.5},{name: 'MD', tax: 6},{name: 'MA', tax: 6.25},{name: 'MI', tax: 6},{name: 'MN', tax: 6.875},{name: 'MS', tax: 7},{name: 'MO', tax: 4.225},{name: 'MT', tax: 0},{name: 'NE', tax: 5.5},{name: 'NV', tax: 6.85},{name: 'NH', tax: 0},{name: 'NJ', tax: 7},{name: 'NM', tax: 5.125},{name: 'NY', tax: 4},{name: 'NC', tax: 4.75},{name: 'ND', tax: 5},{name: 'OH', tax: 5.75},{name: 'OK', tax: 4.5},{name: 'OR', tax: 0},{name: 'Other', tax: '99'},{name: 'PA', tax: 6},{name: 'RI', tax: 7},{name: 'SC', tax: 6},{name: 'SD', tax: 4},{name: 'TN', tax: 7},{name: 'TX', tax: 6.25},{name: 'UT', tax: 4.7},{name: 'VT', tax: 6},{name: 'VA', tax: 4.3},{name: 'WA', tax: 6.5},{name: 'WV', tax: 6},{name: 'WI', tax: 5},{name: 'WY', tax: 4}];
// Set the default tax rate. 1 = total is multiplied by 1 (aka no tax)
$scope.taxRate = 1;
// Script to update the cost before tax
$scope.getBeforeTax = function () {
var total = 0;
for (t=0; t<$scope.listItems.length; t++) {
total = total + Number($scope.listItems[t].price);
}
$scope.totalBeforeTax = total.toFixed(2);
}
// Script to update the cost after tax
$scope.getAfterTax = function (rate) {
var totalAfterTax = Number($scope.totalBeforeTax) * Number(rate);
$scope.costAfterTax = totalAfterTax.toFixed(2);
}
// Script to remove an item from the shopping list
$scope.removeListItem = function (itemToRemove) {
var arrayIndex = this.listItems.indexOf(itemToRemove);
this.listItems.splice(arrayIndex, 1);
$scope.getBeforeTax();
$scope.getAfterTax(this.taxRate);
$scope.updateCouponSavings();
$scope.getFinalCost();
};
// Script to add an item to the shopping list
$scope.addListItem = function (descriptionToPush, price) {
if (typeof price == 'string') {
price = Number(price.replace(/[^\d\.]/g,''));
price = price.toFixed(2);
}
this.listItems.push({description: descriptionToPush, price: price, coupons: []});
this.newDescription = "";
this.newPrice = "";
$scope.getBeforeTax();
$scope.getAfterTax(this.taxRate);
$scope.updateCouponSavings();
$scope.getFinalCost();
};
// Script to see if tax selected is "Other" and show Other Tax option field.
$scope.toggleOtherTax = function (taxes) {
if (Number(taxes) == 99) {
$('#OtherTax').toggle(500);
this.taxRate = 1;
$scope.getAfterTax(this.taxRate);
}
if (Number(taxes) != 99 && $('#OtherTax').css('display') != 'none') {
$('#OtherTax').toggle(500);
}
if (Number(taxes) != 99) {
this.taxRate = 1 + (Number(taxes) / 100);
$scope.getAfterTax(this.taxRate);
}
$scope.getFinalCost();
}
// Script to listen for keypresses in the other tax field and update accordingly the AfterTax and Final Cost fields.
$scope.addOtherTax = function () {
var newRate = Number($scope.otherTax.replace(/[^\d\.]/g,''));
newRate = 1 + (newRate / 100);
$scope.getAfterTax(newRate);
$scope.getFinalCost();
}
// Script to add a coupon.
$scope.addCoupon = function(thisItem, thisDesc, thisDisc) {
var arrayIndex = this.listItems.indexOf(thisItem);
var newDisc = Number(thisDisc.replace(/[^\d\.]/g,''));
this.listItems[arrayIndex].coupons.push({name: thisDesc, discount: newDisc});
$('.enterCoupon:eq('+arrayIndex+')').toggle(200);
$scope.updateCouponSavings();
$scope.getFinalCost();
}
// Script to show the coupon entry <ul><li>
$scope.maximizeCouponEnter = function(thisItem) {
var arrayIndex = this.listItems.indexOf(thisItem);
$('.enterCoupon:eq('+arrayIndex+')').toggle(200);
}
// Script to minimize the coupon entry <ul><li>
$scope.minimizeCouponEnter = function(thisItem) {
var arrayIndex = this.listItems.indexOf(thisItem);
$('.enterCoupon:eq('+arrayIndex+')').toggle(200);
}
// Script to remove a coupon.
$scope.removeCoupon = function(thisItem, thisCoupon) {
var arrayIndex = this.listItems.indexOf(thisItem);
var couponIndex = this.listItems[arrayIndex].coupons.indexOf(thisCoupon);
this.listItems[arrayIndex].coupons.splice(couponIndex, 1);
$scope.updateCouponSavings();
$scope.getFinalCost();
}
// Script to calculate coupon savings
$scope.updateCouponSavings = function() {
var totalSavings = 0;
for (t=0; t<$scope.listItems.length; t++) {
for (c=0; c<$scope.listItems[t].coupons.length; c++) {
totalSavings = totalSavings + Number($scope.listItems[t].coupons[c].discount);
}
}
$scope.couponSavings = totalSavings.toFixed(2);
$scope.getFinalCost();
}
// Script to update the Final Cost
$scope.getFinalCost = function() {
var finalPrice = Number($scope.costAfterTax) - Number($scope.couponSavings);
finalPrice = finalPrice.toFixed(2);
$scope.finalPriceModel = finalPrice;
}
// Functions to run on module load.
$scope.getBeforeTax();
$scope.getAfterTax(1);
$scope.updateCouponSavings();
$scope.getFinalCost();
});
@mainFonts: 'Quicksand', Arial, Helvetica, sans-serif;
// mixins
.centeredOnPage(@mtop) {
margin: @mtop auto;
}
.clearfix() {
zoom: 1;
&:before { content: ''; display: block; }
&:after { content: ''; display: table; clear: both; }
}
// styles
html, body {
padding: 0;
margin: 0;
}
a {
cursor: pointer;
}
h1 {
font-family: @mainFonts;
padding: 10px 0px 10px 0px;
font-size: 36px;
font-weight: 400;
color: #000;
}
h2 {
font-family: @mainFonts;
padding: 10px 0px 10px 0px;
font-size: 24px;
font-weight: 700;
color: #333;
border-bottom: 1px solid #ddd;
}
h3 {
font-family: @mainFonts;
font-size: 19px;
font-weight: 700;
color: #3A98D6;
padding: 0px 0px 10px 0px;
border-bottom: 1px solid #ddd;
}
p {
font-family: @mainFonts;
padding: 10px 0px 10px 0px;
font-weight: 300;
font-size: 20px;
color: #777;
}
.demoWrapper {
.clearfix();
}
.box {
width: 800px;
.centeredOnPage(60px);
}
.shoppingList {
width: 480px;
margin: 0px 20px 0px 0px;
float: left;
font-family: @mainFonts;
ul {
list-style-type: none;
margin: 0;
padding: 0;
font-size: 19px;
color: #999;
}
li {
display: block;
padding: 0px;
margin: 0px 0px 7px 0px;
width: 100%;
.clearfix();
}
.listItem {
float: left;
width: 47%;
}
.listPrice {
float: left;
width: 40%;
text-align: right;
}
.closeListItem {
float: right;
width: 10%;
text-align: right;
a {
color: #2376AD;
font-weight: 700;
text-decoration: none;
}
img {
display: inline-block;
margin-right: 6px;
}
}
}
.addItemModule {
width: 300px;
float: left;
margin: 0;
font-family: @mainFonts;
label {
font-size: 18px;
color: #999;
display: block;
padding: 5px 0px 5px 0px;
}
.addItemTBox {
border: 1px solid #ddd;
border-radius: 2px;
padding: 10px 0px 10px 5px;
width: 100%;
font-family: @mainFonts;
font-size: 18px;
font-weight: 700;
&:disabled {
background-color: #fff;
}
}
p {
font-size: 14px;
font-weight: 400;
color: #bbb;
}
a {
margin-top: 10px;
display: block;
padding: 10px;
text-align: center;
background-color: #2376AD;
border-radius: 3px;
border-bottom: 3px solid #155885;
text-decoration: none;
color: #fff;
font-weight: 700;
}
select {
border: 1px solid #ddd;
border-radius: 2px;
padding: 10px 0px 10px 5px;
width: 100%;
font-family: @mainFonts;
font-size: 18px;
font-weight: 700;
}
}
#OtherTax {
display: none;
}
.enterCoupon {
list-style-type: none;
display: none;
}
.enterCoupon li {
display: block;
input {
border: 1px solid #ddd;
border-radius: 3px;
padding: 4px 8px 4px 8px;
font-size: 16px;
font-family: @mainFonts;
font-weight: 700;
display: inline-block;
}
.newCouponName {
width: 45%;
}
.newCouponPrice {
width: 16%;
text-align: right;
}
.addCouponButton {
padding: 3px 10px 3px 10px;
text-align: center;
background-color: #2376AD;
border-radius: 3px;
border-bottom: 3px solid #155885;
text-decoration: none;
color: #fff;
font-size: 16px;
font-weight: 700;
}
.minimize {
padding: 3px 10px 3px 10px;
text-align: center;
background-color: #ddd;
border-radius: 3px;
border-bottom: 3px solid #bbb;
text-decoration: none;
color: #2376AD;
font-size: 16px;
font-weight: 700;
}
}
.couponsList {
list-style-type: none;
}
.couponsList .couponItem {
display: block;
margin: 0;
padding: 0;
width: 100%;
font-size: 15px;
font-weight: 700;
}
.couponsList li .thisCouponDescription {
display: inline-block;
width: 210px;
margin-left: 111px;
text-align: left;
}
.couponsList li .thisCouponDiscount {
display: inline-block;
width: 105px;
text-align: right;
}
.couponsList li a {
text-decoration: none;
display: inline-block;
width: 10px;
margin-left: 5px;
color: #2376AD;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment