diff --git a/dist/ngCart.js b/dist/ngCart.js index 758d3ed..b0f6605 100644 --- a/dist/ngCart.js +++ b/dist/ngCart.js @@ -38,15 +38,15 @@ angular.module('ngCart', ['ngCart.directives']) }; }; - this.addItem = function (id, name, price, quantity, data) { + this.addItem = function (id, name, price, quantity, quantityMax, data) { var inCart = this.getItemById(id); if (typeof inCart === 'object'){ //Update quantity of an item if it's already in the cart - inCart.setQuantity(quantity, false); + inCart.setQuantity(quantity, false, quantityMax); } else { - var newItem = new ngCartItem(id, name, price, quantity, data); + var newItem = new ngCartItem(id, name, price, quantity, quantityMax, data); this.$cart.items.push(newItem); $rootScope.$broadcast('ngCart:itemAdded', newItem); } @@ -186,7 +186,7 @@ angular.module('ngCart', ['ngCart.directives']) _self.$cart.tax = storedCart.tax; angular.forEach(storedCart.items, function (item) { - _self.$cart.items.push(new ngCartItem(item._id, item._name, item._price, item._quantity, item._data)); + _self.$cart.items.push(new ngCartItem(item._id, item._name, item._price, item._quantity, item._maxQuantity, item._data)); }); this.$save(); }; @@ -199,11 +199,12 @@ angular.module('ngCart', ['ngCart.directives']) .factory('ngCartItem', ['$rootScope', '$log', function ($rootScope, $log) { - var item = function (id, name, price, quantity, data) { + var item = function (id, name, price, quantity, maxQuantity, data) { this.setId(id); this.setName(name); this.setPrice(price); this.setQuantity(quantity); + this.setMaxQuantity(maxQuantity); this.setData(data); }; @@ -247,13 +248,15 @@ angular.module('ngCart', ['ngCart.directives']) }; - item.prototype.setQuantity = function(quantity, relative){ + item.prototype.setQuantity = function(quantity, relative, quantityMax){ var quantityInt = parseInt(quantity); if (quantityInt % 1 === 0){ if (relative === true){ - this._quantity += quantityInt; + if (typeof quantityMax === "undefined" || quantityMax >= (this._quantity + quantityInt)) { + this._quantity += quantityInt; + } } else { this._quantity = quantityInt; } @@ -271,6 +274,16 @@ angular.module('ngCart', ['ngCart.directives']) return this._quantity; }; + item.prototype.setMaxQuantity = function (maxQuantity) { + if (maxQuantity) this._maxQuantity = maxQuantity; + else { + $log.error('A max quantity must be provided'); + } + }; + + item.prototype.getMaxQuantity = function () { + return this._maxQuantity; + }; item.prototype.setData = function(data){ if (data) this._data = data; }; @@ -291,6 +304,7 @@ angular.module('ngCart', ['ngCart.directives']) name: this.getName(), price: this.getPrice(), quantity: this.getQuantity(), + maxQuantity: this.getMaxQuantity(), data: this.getData(), total: this.getTotal() } @@ -332,179 +346,179 @@ angular.module('ngCart', ['ngCart.directives']) }]) .value('version', '1.0.0'); -;'use strict'; - - -angular.module('ngCart.directives', ['ngCart.fulfilment']) - - .controller('CartController',['$scope', 'ngCart', function($scope, ngCart) { - $scope.ngCart = ngCart; - }]) - - .directive('ngcartAddtocart', ['ngCart', function(ngCart){ - return { - restrict : 'E', - controller : 'CartController', - scope: { - id:'@', - name:'@', - quantity:'@', - quantityMax:'@', - price:'@', - data:'=' - }, - transclude: true, - templateUrl: function(element, attrs) { - if ( typeof attrs.templateUrl == 'undefined' ) { - return 'template/ngCart/addtocart.html'; - } else { - return attrs.templateUrl; - } - }, - link:function(scope, element, attrs){ - scope.attrs = attrs; - scope.inCart = function(){ - return ngCart.getItemById(attrs.id); - }; - - if (scope.inCart()){ - scope.q = ngCart.getItemById(attrs.id).getQuantity(); - } else { - scope.q = parseInt(scope.quantity); - } - - scope.qtyOpt = []; - for (var i = 1; i <= scope.quantityMax; i++) { - scope.qtyOpt.push(i); - } - - } - - }; - }]) - - .directive('ngcartCart', [function(){ - return { - restrict : 'E', - controller : 'CartController', - scope: {}, - templateUrl: function(element, attrs) { - if ( typeof attrs.templateUrl == 'undefined' ) { - return 'template/ngCart/cart.html'; - } else { - return attrs.templateUrl; - } - }, - link:function(scope, element, attrs){ - - } - }; - }]) - - .directive('ngcartSummary', [function(){ - return { - restrict : 'E', - controller : 'CartController', - scope: {}, - transclude: true, - templateUrl: function(element, attrs) { - if ( typeof attrs.templateUrl == 'undefined' ) { - return 'template/ngCart/summary.html'; - } else { - return attrs.templateUrl; - } - } - }; - }]) - - .directive('ngcartCheckout', [function(){ - return { - restrict : 'E', - controller : ('CartController', ['$rootScope', '$scope', 'ngCart', 'fulfilmentProvider', function($rootScope, $scope, ngCart, fulfilmentProvider) { - $scope.ngCart = ngCart; - - $scope.checkout = function () { - fulfilmentProvider.setService($scope.service); - fulfilmentProvider.setSettings($scope.settings); - fulfilmentProvider.checkout() - .success(function (data, status, headers, config) { - $rootScope.$broadcast('ngCart:checkout_succeeded', data); - }) - .error(function (data, status, headers, config) { - $rootScope.$broadcast('ngCart:checkout_failed', { - statusCode: status, - error: data - }); - }); - } - }]), - scope: { - service:'@', - settings:'=' - }, - transclude: true, - templateUrl: function(element, attrs) { - if ( typeof attrs.templateUrl == 'undefined' ) { - return 'template/ngCart/checkout.html'; - } else { - return attrs.templateUrl; - } - } - }; - }]); -; -angular.module('ngCart.fulfilment', []) - .service('fulfilmentProvider', ['$injector', function($injector){ - - this._obj = { - service : undefined, - settings : undefined - }; - - this.setService = function(service){ - this._obj.service = service; - }; - - this.setSettings = function(settings){ - this._obj.settings = settings; - }; - - this.checkout = function(){ - var provider = $injector.get('ngCart.fulfilment.' + this._obj.service); - return provider.checkout(this._obj.settings); - - } - - }]) - - -.service('ngCart.fulfilment.log', ['$q', '$log', 'ngCart', function($q, $log, ngCart){ - - this.checkout = function(){ - - var deferred = $q.defer(); - - $log.info(ngCart.toObject()); - deferred.resolve({ - cart:ngCart.toObject() - }); - - return deferred.promise; - - } - - }]) - -.service('ngCart.fulfilment.http', ['$http', 'ngCart', function($http, ngCart){ - - this.checkout = function(settings){ - return $http.post(settings.url, - { data: ngCart.toObject(), options: settings.options}); - } - }]) - - -.service('ngCart.fulfilment.paypal', ['$http', 'ngCart', function($http, ngCart){ - - -}]); +;'use strict'; + + +angular.module('ngCart.directives', ['ngCart.fulfilment']) + + .controller('CartController',['$scope', 'ngCart', function($scope, ngCart) { + $scope.ngCart = ngCart; + }]) + + .directive('ngcartAddtocart', ['ngCart', function(ngCart){ + return { + restrict : 'E', + controller : 'CartController', + scope: { + id:'@', + name:'@', + quantity:'@', + quantityMax:'@', + price:'@', + data:'=' + }, + transclude: true, + templateUrl: function(element, attrs) { + if ( typeof attrs.templateUrl == 'undefined' ) { + return 'template/ngCart/addtocart.html'; + } else { + return attrs.templateUrl; + } + }, + link:function(scope, element, attrs){ + scope.attrs = attrs; + scope.inCart = function(){ + return ngCart.getItemById(attrs.id); + }; + + if (scope.inCart()){ + scope.q = ngCart.getItemById(attrs.id).getQuantity(); + } else { + scope.q = parseInt(scope.quantity); + } + + scope.qtyOpt = []; + for (var i = 1; i <= scope.quantityMax; i++) { + scope.qtyOpt.push(i); + } + + } + + }; + }]) + + .directive('ngcartCart', [function(){ + return { + restrict : 'E', + controller : 'CartController', + scope: {}, + templateUrl: function(element, attrs) { + if ( typeof attrs.templateUrl == 'undefined' ) { + return 'template/ngCart/cart.html'; + } else { + return attrs.templateUrl; + } + }, + link:function(scope, element, attrs){ + + } + }; + }]) + + .directive('ngcartSummary', [function(){ + return { + restrict : 'E', + controller : 'CartController', + scope: {}, + transclude: true, + templateUrl: function(element, attrs) { + if ( typeof attrs.templateUrl == 'undefined' ) { + return 'template/ngCart/summary.html'; + } else { + return attrs.templateUrl; + } + } + }; + }]) + + .directive('ngcartCheckout', [function(){ + return { + restrict : 'E', + controller : ('CartController', ['$rootScope', '$scope', 'ngCart', 'fulfilmentProvider', function($rootScope, $scope, ngCart, fulfilmentProvider) { + $scope.ngCart = ngCart; + + $scope.checkout = function () { + fulfilmentProvider.setService($scope.service); + fulfilmentProvider.setSettings($scope.settings); + fulfilmentProvider.checkout() + .success(function (data, status, headers, config) { + $rootScope.$broadcast('ngCart:checkout_succeeded', data); + }) + .error(function (data, status, headers, config) { + $rootScope.$broadcast('ngCart:checkout_failed', { + statusCode: status, + error: data + }); + }); + } + }]), + scope: { + service:'@', + settings:'=' + }, + transclude: true, + templateUrl: function(element, attrs) { + if ( typeof attrs.templateUrl == 'undefined' ) { + return 'template/ngCart/checkout.html'; + } else { + return attrs.templateUrl; + } + } + }; + }]); +; +angular.module('ngCart.fulfilment', []) + .service('fulfilmentProvider', ['$injector', function($injector){ + + this._obj = { + service : undefined, + settings : undefined + }; + + this.setService = function(service){ + this._obj.service = service; + }; + + this.setSettings = function(settings){ + this._obj.settings = settings; + }; + + this.checkout = function(){ + var provider = $injector.get('ngCart.fulfilment.' + this._obj.service); + return provider.checkout(this._obj.settings); + + } + + }]) + + +.service('ngCart.fulfilment.log', ['$q', '$log', 'ngCart', function($q, $log, ngCart){ + + this.checkout = function(){ + + var deferred = $q.defer(); + + $log.info(ngCart.toObject()); + deferred.resolve({ + cart:ngCart.toObject() + }); + + return deferred.promise; + + } + + }]) + +.service('ngCart.fulfilment.http', ['$http', 'ngCart', function($http, ngCart){ + + this.checkout = function(settings){ + return $http.post(settings.url, + { data: ngCart.toObject(), options: settings.options}); + } + }]) + + +.service('ngCart.fulfilment.paypal', ['$http', 'ngCart', function($http, ngCart){ + + +}]); diff --git a/dist/ngCart.min.js b/dist/ngCart.min.js index 67c24d2..f536e02 100644 --- a/dist/ngCart.min.js +++ b/dist/ngCart.min.js @@ -1,2 +1,2 @@ /*! ngCart v1.0.0 */ - "use strict";angular.module("ngCart",["ngCart.directives"]).config([function(){}]).provider("$ngCart",function(){this.$get=function(){}}).run(["$rootScope","ngCart","ngCartItem","store",function(a,b,c,d){a.$on("ngCart:change",function(){b.$save()}),angular.isObject(d.get("cart"))?b.$restore(d.get("cart")):b.init()}]).service("ngCart",["$rootScope","ngCartItem","store",function(a,b,c){this.init=function(){this.$cart={shipping:null,taxRate:null,tax:null,items:[]}},this.addItem=function(c,d,e,f,g){var h=this.getItemById(c);if("object"==typeof h)h.setQuantity(f,!1);else{var i=new b(c,d,e,f,g);this.$cart.items.push(i),a.$broadcast("ngCart:itemAdded",i)}a.$broadcast("ngCart:change",{})},this.getItemById=function(a){var b=this.getCart().items,c=!1;return angular.forEach(b,function(b){b.getId()===a&&(c=b)}),c},this.setShipping=function(a){return this.$cart.shipping=a,this.getShipping()},this.getShipping=function(){return 0==this.getCart().items.length?0:this.getCart().shipping},this.setTaxRate=function(a){return this.$cart.taxRate=+parseFloat(a).toFixed(2),this.getTaxRate()},this.getTaxRate=function(){return this.$cart.taxRate},this.getTax=function(){return+parseFloat(this.getSubTotal()/100*this.getCart().taxRate).toFixed(2)},this.setCart=function(a){return this.$cart=a,this.getCart()},this.getCart=function(){return this.$cart},this.getItems=function(){return this.getCart().items},this.getTotalItems=function(){var a=0,b=this.getItems();return angular.forEach(b,function(b){a+=b.getQuantity()}),a},this.getTotalUniqueItems=function(){return this.getCart().items.length},this.getSubTotal=function(){var a=0;return angular.forEach(this.getCart().items,function(b){a+=b.getTotal()}),+parseFloat(a).toFixed(2)},this.totalCost=function(){return+parseFloat(this.getSubTotal()+this.getShipping()+this.getTax()).toFixed(2)},this.removeItem=function(b){this.$cart.items.splice(b,1),a.$broadcast("ngCart:itemRemoved",{}),a.$broadcast("ngCart:change",{})},this.removeItemById=function(b){var c=this.getCart();angular.forEach(c.items,function(a,d){a.getId()===b&&c.items.splice(d,1)}),this.setCart(c),a.$broadcast("ngCart:itemRemoved",{}),a.$broadcast("ngCart:change",{})},this.empty=function(){a.$broadcast("ngCart:change",{}),this.$cart.items=[],localStorage.removeItem("cart")},this.isEmpty=function(){return this.$cart.items.length>0?!1:!0},this.toObject=function(){if(0===this.getItems().length)return!1;var a=[];return angular.forEach(this.getItems(),function(b){a.push(b.toObject())}),{shipping:this.getShipping(),tax:this.getTax(),taxRate:this.getTaxRate(),subTotal:this.getSubTotal(),totalCost:this.totalCost(),items:a}},this.$restore=function(a){var c=this;c.init(),c.$cart.shipping=a.shipping,c.$cart.tax=a.tax,angular.forEach(a.items,function(a){c.$cart.items.push(new b(a._id,a._name,a._price,a._quantity,a._data))}),this.$save()},this.$save=function(){return c.set("cart",JSON.stringify(this.getCart()))}}]).factory("ngCartItem",["$rootScope","$log",function(a,b){var c=function(a,b,c,d,e){this.setId(a),this.setName(b),this.setPrice(c),this.setQuantity(d),this.setData(e)};return c.prototype.setId=function(a){a?this._id=a:b.error("An ID must be provided")},c.prototype.getId=function(){return this._id},c.prototype.setName=function(a){a?this._name=a:b.error("A name must be provided")},c.prototype.getName=function(){return this._name},c.prototype.setPrice=function(a){var c=parseFloat(a);c?0>=c?b.error("A price must be over 0"):this._price=c:b.error("A price must be provided")},c.prototype.getPrice=function(){return this._price},c.prototype.setQuantity=function(c,d){var e=parseInt(c);e%1===0?(d===!0?this._quantity+=e:this._quantity=e,this._quantity<1&&(this._quantity=1)):(this._quantity=1,b.info("Quantity must be an integer and was defaulted to 1")),a.$broadcast("ngCart:change",{})},c.prototype.getQuantity=function(){return this._quantity},c.prototype.setData=function(a){a&&(this._data=a)},c.prototype.getData=function(){return this._data?this._data:void b.info("This item has no data")},c.prototype.getTotal=function(){return+parseFloat(this.getQuantity()*this.getPrice()).toFixed(2)},c.prototype.toObject=function(){return{id:this.getId(),name:this.getName(),price:this.getPrice(),quantity:this.getQuantity(),data:this.getData(),total:this.getTotal()}},c}]).service("store",["$window",function(a){return{get:function(b){if(a.localStorage[b]){var c=angular.fromJson(a.localStorage[b]);return JSON.parse(c)}return!1},set:function(b,c){return void 0===c?a.localStorage.removeItem(b):a.localStorage[b]=angular.toJson(c),a.localStorage[b]}}}]).controller("CartController",["$scope","ngCart",function(a,b){a.ngCart=b}]).value("version","1.0.0"),angular.module("ngCart.directives",["ngCart.fulfilment"]).controller("CartController",["$scope","ngCart",function(a,b){a.ngCart=b}]).directive("ngcartAddtocart",["ngCart",function(a){return{restrict:"E",controller:"CartController",scope:{id:"@",name:"@",quantity:"@",quantityMax:"@",price:"@",data:"="},transclude:!0,templateUrl:function(a,b){return"undefined"==typeof b.templateUrl?"template/ngCart/addtocart.html":b.templateUrl},link:function(b,c,d){b.attrs=d,b.inCart=function(){return a.getItemById(d.id)},b.inCart()?b.q=a.getItemById(d.id).getQuantity():b.q=parseInt(b.quantity),b.qtyOpt=[];for(var e=1;e<=b.quantityMax;e++)b.qtyOpt.push(e)}}}]).directive("ngcartCart",[function(){return{restrict:"E",controller:"CartController",scope:{},templateUrl:function(a,b){return"undefined"==typeof b.templateUrl?"template/ngCart/cart.html":b.templateUrl},link:function(a,b,c){}}}]).directive("ngcartSummary",[function(){return{restrict:"E",controller:"CartController",scope:{},transclude:!0,templateUrl:function(a,b){return"undefined"==typeof b.templateUrl?"template/ngCart/summary.html":b.templateUrl}}}]).directive("ngcartCheckout",[function(){return{restrict:"E",controller:["$rootScope","$scope","ngCart","fulfilmentProvider",function(a,b,c,d){b.ngCart=c,b.checkout=function(){d.setService(b.service),d.setSettings(b.settings),d.checkout().success(function(b,c,d,e){a.$broadcast("ngCart:checkout_succeeded",b)}).error(function(b,c,d,e){a.$broadcast("ngCart:checkout_failed",{statusCode:c,error:b})})}}],scope:{service:"@",settings:"="},transclude:!0,templateUrl:function(a,b){return"undefined"==typeof b.templateUrl?"template/ngCart/checkout.html":b.templateUrl}}}]),angular.module("ngCart.fulfilment",[]).service("fulfilmentProvider",["$injector",function(a){this._obj={service:void 0,settings:void 0},this.setService=function(a){this._obj.service=a},this.setSettings=function(a){this._obj.settings=a},this.checkout=function(){var b=a.get("ngCart.fulfilment."+this._obj.service);return b.checkout(this._obj.settings)}}]).service("ngCart.fulfilment.log",["$q","$log","ngCart",function(a,b,c){this.checkout=function(){var d=a.defer();return b.info(c.toObject()),d.resolve({cart:c.toObject()}),d.promise}}]).service("ngCart.fulfilment.http",["$http","ngCart",function(a,b){this.checkout=function(c){return a.post(c.url,{data:b.toObject(),options:c.options})}}]).service("ngCart.fulfilment.paypal",["$http","ngCart",function(a,b){}]); \ No newline at end of file +"use strict";angular.module("ngCart",["ngCart.directives"]).config([function(){}]).provider("$ngCart",function(){this.$get=function(){}}).run(["$rootScope","ngCart","ngCartItem","store",function(t,e,n,r){t.$on("ngCart:change",function(){e.$save()}),angular.isObject(r.get("cart"))?e.$restore(r.get("cart")):e.init()}]).service("ngCart",["$rootScope","ngCartItem","store",function(t,e,n){this.init=function(){this.$cart={shipping:null,taxRate:null,tax:null,items:[]}},this.addItem=function(n,r,i,a,o,s){var c=this.getItemById(n);if("object"==typeof c)c.setQuantity(a,!1,o);else{var u=new e(n,r,i,a,o,s);this.$cart.items.push(u),t.$broadcast("ngCart:itemAdded",u)}t.$broadcast("ngCart:change",{})},this.getItemById=function(t){var e=this.getCart().items,n=!1;return angular.forEach(e,function(e){e.getId()===t&&(n=e)}),n},this.setShipping=function(t){return this.$cart.shipping=t,this.getShipping()},this.getShipping=function(){return 0==this.getCart().items.length?0:this.getCart().shipping},this.setTaxRate=function(t){return this.$cart.taxRate=+parseFloat(t).toFixed(2),this.getTaxRate()},this.getTaxRate=function(){return this.$cart.taxRate},this.getTax=function(){return+parseFloat(this.getSubTotal()/100*this.getCart().taxRate).toFixed(2)},this.setCart=function(t){return this.$cart=t,this.getCart()},this.getCart=function(){return this.$cart},this.getItems=function(){return this.getCart().items},this.getTotalItems=function(){var t=0,e=this.getItems();return angular.forEach(e,function(e){t+=e.getQuantity()}),t},this.getTotalUniqueItems=function(){return this.getCart().items.length},this.getSubTotal=function(){var t=0;return angular.forEach(this.getCart().items,function(e){t+=e.getTotal()}),+parseFloat(t).toFixed(2)},this.totalCost=function(){return+parseFloat(this.getSubTotal()+this.getShipping()+this.getTax()).toFixed(2)},this.removeItem=function(e){this.$cart.items.splice(e,1),t.$broadcast("ngCart:itemRemoved",{}),t.$broadcast("ngCart:change",{})},this.removeItemById=function(e){var n=this.getCart();angular.forEach(n.items,function(t,r){t.getId()===e&&n.items.splice(r,1)}),this.setCart(n),t.$broadcast("ngCart:itemRemoved",{}),t.$broadcast("ngCart:change",{})},this.empty=function(){t.$broadcast("ngCart:change",{}),this.$cart.items=[],localStorage.removeItem("cart")},this.isEmpty=function(){return this.$cart.items.length>0?!1:!0},this.toObject=function(){if(0===this.getItems().length)return!1;var t=[];return angular.forEach(this.getItems(),function(e){t.push(e.toObject())}),{shipping:this.getShipping(),tax:this.getTax(),taxRate:this.getTaxRate(),subTotal:this.getSubTotal(),totalCost:this.totalCost(),items:t}},this.$restore=function(t){var n=this;n.init(),n.$cart.shipping=t.shipping,n.$cart.tax=t.tax,angular.forEach(t.items,function(t){n.$cart.items.push(new e(t._id,t._name,t._price,t._quantity,t._maxQuantity,t._data))}),this.$save()},this.$save=function(){return n.set("cart",JSON.stringify(this.getCart()))}}]).factory("ngCartItem",["$rootScope","$log",function(t,e){var n=function(t,e,n,r,i,a){this.setId(t),this.setName(e),this.setPrice(n),this.setQuantity(r),this.setMaxQuantity(i),this.setData(a)};return n.prototype.setId=function(t){t?this._id=t:e.error("An ID must be provided")},n.prototype.getId=function(){return this._id},n.prototype.setName=function(t){t?this._name=t:e.error("A name must be provided")},n.prototype.getName=function(){return this._name},n.prototype.setPrice=function(t){var n=parseFloat(t);n?0>=n?e.error("A price must be over 0"):this._price=n:e.error("A price must be provided")},n.prototype.getPrice=function(){return this._price},n.prototype.setQuantity=function(n,r,i){var a=parseInt(n);a%1===0?(r===!0?("undefined"==typeof i||i>=this._quantity+a)&&(this._quantity+=a):this._quantity=a,this._quantity<1&&(this._quantity=1)):(this._quantity=1,e.info("Quantity must be an integer and was defaulted to 1")),t.$broadcast("ngCart:change",{})},n.prototype.getQuantity=function(){return this._quantity},n.prototype.setMaxQuantity=function(t){t?this._maxQuantity=t:e.error("A max quantity must be provided")},n.prototype.getMaxQuantity=function(){return this._maxQuantity},n.prototype.setData=function(t){t&&(this._data=t)},n.prototype.getData=function(){return this._data?this._data:void e.info("This item has no data")},n.prototype.getTotal=function(){return+parseFloat(this.getQuantity()*this.getPrice()).toFixed(2)},n.prototype.toObject=function(){return{id:this.getId(),name:this.getName(),price:this.getPrice(),quantity:this.getQuantity(),maxQuantity:this.getMaxQuantity(),data:this.getData(),total:this.getTotal()}},n}]).service("store",["$window",function(t){return{get:function(e){if(t.localStorage[e]){var n=angular.fromJson(t.localStorage[e]);return JSON.parse(n)}return!1},set:function(e,n){return void 0===n?t.localStorage.removeItem(e):t.localStorage[e]=angular.toJson(n),t.localStorage[e]}}}]).controller("CartController",["$scope","ngCart",function(t,e){t.ngCart=e}]).value("version","1.0.0"),angular.module("ngCart.directives",["ngCart.fulfilment"]).controller("CartController",["$scope","ngCart",function(t,e){t.ngCart=e}]).directive("ngcartAddtocart",["ngCart",function(t){return{restrict:"E",controller:"CartController",scope:{id:"@",name:"@",quantity:"@",quantityMax:"@",price:"@",data:"="},transclude:!0,templateUrl:function(t,e){return"undefined"==typeof e.templateUrl?"template/ngCart/addtocart.html":e.templateUrl},link:function(e,n,r){e.attrs=r,e.inCart=function(){return t.getItemById(r.id)},e.q=e.inCart()?t.getItemById(r.id).getQuantity():parseInt(e.quantity),e.qtyOpt=[];for(var i=1;i<=e.quantityMax;i++)e.qtyOpt.push(i)}}}]).directive("ngcartCart",[function(){return{restrict:"E",controller:"CartController",scope:{},templateUrl:function(t,e){return"undefined"==typeof e.templateUrl?"template/ngCart/cart.html":e.templateUrl},link:function(){}}}]).directive("ngcartSummary",[function(){return{restrict:"E",controller:"CartController",scope:{},transclude:!0,templateUrl:function(t,e){return"undefined"==typeof e.templateUrl?"template/ngCart/summary.html":e.templateUrl}}}]).directive("ngcartCheckout",[function(){return{restrict:"E",controller:["$rootScope","$scope","ngCart","fulfilmentProvider",function(t,e,n,r){e.ngCart=n,e.checkout=function(){r.setService(e.service),r.setSettings(e.settings),r.checkout().success(function(e){t.$broadcast("ngCart:checkout_succeeded",e)}).error(function(e,n){t.$broadcast("ngCart:checkout_failed",{statusCode:n,error:e})})}}],scope:{service:"@",settings:"="},transclude:!0,templateUrl:function(t,e){return"undefined"==typeof e.templateUrl?"template/ngCart/checkout.html":e.templateUrl}}}]),angular.module("ngCart.fulfilment",[]).service("fulfilmentProvider",["$injector",function(t){this._obj={service:void 0,settings:void 0},this.setService=function(t){this._obj.service=t},this.setSettings=function(t){this._obj.settings=t},this.checkout=function(){var e=t.get("ngCart.fulfilment."+this._obj.service);return e.checkout(this._obj.settings)}}]).service("ngCart.fulfilment.log",["$q","$log","ngCart",function(t,e,n){this.checkout=function(){var r=t.defer();return e.info(n.toObject()),r.resolve({cart:n.toObject()}),r.promise}}]).service("ngCart.fulfilment.http",["$http","ngCart",function(t,e){this.checkout=function(n){return t.post(n.url,{data:e.toObject(),options:n.options})}}]).service("ngCart.fulfilment.paypal",["$http","ngCart",function(){}]); diff --git a/src/ngCart.js b/src/ngCart.js index 974fc5a..70c0ba4 100644 --- a/src/ngCart.js +++ b/src/ngCart.js @@ -38,15 +38,15 @@ angular.module('ngCart', ['ngCart.directives']) }; }; - this.addItem = function (id, name, price, quantity, data) { + this.addItem = function (id, name, price, quantity, quantityMax, data) { var inCart = this.getItemById(id); if (typeof inCart === 'object'){ //Update quantity of an item if it's already in the cart - inCart.setQuantity(quantity, false); + inCart.setQuantity(quantity, false, quantityMax); } else { - var newItem = new ngCartItem(id, name, price, quantity, data); + var newItem = new ngCartItem(id, name, price, quantity, quantityMax, data); this.$cart.items.push(newItem); $rootScope.$broadcast('ngCart:itemAdded', newItem); } @@ -186,7 +186,7 @@ angular.module('ngCart', ['ngCart.directives']) _self.$cart.tax = storedCart.tax; angular.forEach(storedCart.items, function (item) { - _self.$cart.items.push(new ngCartItem(item._id, item._name, item._price, item._quantity, item._data)); + _self.$cart.items.push(new ngCartItem(item._id, item._name, item._price, item._quantity, item._maxQuantity, item._data)); }); this.$save(); }; @@ -199,11 +199,12 @@ angular.module('ngCart', ['ngCart.directives']) .factory('ngCartItem', ['$rootScope', '$log', function ($rootScope, $log) { - var item = function (id, name, price, quantity, data) { + var item = function (id, name, price, quantity, maxQuantity, data) { this.setId(id); this.setName(name); this.setPrice(price); this.setQuantity(quantity); + this.setMaxQuantity(maxQuantity); this.setData(data); }; @@ -247,13 +248,15 @@ angular.module('ngCart', ['ngCart.directives']) }; - item.prototype.setQuantity = function(quantity, relative){ + item.prototype.setQuantity = function(quantity, relative, quantityMax){ var quantityInt = parseInt(quantity); if (quantityInt % 1 === 0){ if (relative === true){ - this._quantity += quantityInt; + if (typeof quantityMax === "undefined" || quantityMax >= (this._quantity + quantityInt)) { + this._quantity += quantityInt; + } } else { this._quantity = quantityInt; } @@ -271,6 +274,16 @@ angular.module('ngCart', ['ngCart.directives']) return this._quantity; }; + item.prototype.setMaxQuantity = function (maxQuantity) { + if (maxQuantity) this._maxQuantity = maxQuantity; + else { + $log.error('A max quantity must be provided'); + } + }; + + item.prototype.getMaxQuantity = function () { + return this._maxQuantity; + }; item.prototype.setData = function(data){ if (data) this._data = data; }; @@ -291,6 +304,7 @@ angular.module('ngCart', ['ngCart.directives']) name: this.getName(), price: this.getPrice(), quantity: this.getQuantity(), + maxQuantity: this.getMaxQuantity(), data: this.getData(), total: this.getTotal() } diff --git a/src/ngCart_test.js b/src/ngCart_test.js index 0cf8175..3790f0e 100644 --- a/src/ngCart_test.js +++ b/src/ngCart_test.js @@ -25,8 +25,8 @@ describe('ngCart module', function() { var $scope; var controller; - function addItem(id, name, price, quantity, data){ - $scope.ngCart.addItem(id, name, price, quantity, data); + function addItem(id, name, price, quantity, quantityMax, data){ + $scope.ngCart.addItem(id, name, price, quantity, quantityMax, data); } beforeEach(function() { @@ -41,7 +41,7 @@ describe('ngCart module', function() { it('should be able to add an item', function() { - addItem(1, 'Test Item', 10, 2); + addItem(1, 'Test Item', 10, 2, 5); expect($scope.ngCart.getItems().length).toEqual(1); }); @@ -64,9 +64,9 @@ describe('ngCart module', function() { $scope.ngCart.setTaxRate(7.5); $scope.ngCart.setShipping(12.50); - addItem(1, 'Work boots', 189.99, 1); - addItem(2, 'Hockey gloves', 85, 2); - addItem('cpBow', 'Compound bow', 499.95, 1); + addItem(1, 'Work boots', 189.99, 1, 2); + addItem(2, 'Hockey gloves', 85, 2, 99); + addItem('cpBow', 'Compound bow', 499.95, 1, 1); }); @@ -174,9 +174,15 @@ describe('ngCart module', function() { it('should relatively update quantity', function() { expect(ngCartItem.getQuantity()).toEqual(1); - ngCartItem.setQuantity(1, true); + ngCartItem.setQuantity(1, true, 5); expect(ngCartItem.getQuantity()).toEqual(2); }); + + it('should not update quantity above max', function() { + expect(ngCartItem.getQuantity()).toEqual(1); + ngCartItem.setQuantity(1, true, 1); + expect(ngCartItem.getQuantity()).toEqual(1); + }); it('should get total', function() { @@ -184,7 +190,7 @@ describe('ngCart module', function() { }); it('should update total after quantity change', function() { - ngCartItem.setQuantity(1, true); + ngCartItem.setQuantity(1, true, 5); expect(ngCartItem.getTotal()).toEqual( 79.98 ); }); diff --git a/template/ngCart/addtocart.html b/template/ngCart/addtocart.html index ebf00db..656e164 100644 --- a/template/ngCart/addtocart.html +++ b/template/ngCart/addtocart.html @@ -9,7 +9,7 @@ ng-options=" v for v in qtyOpt"> diff --git a/template/ngCart/cart.html b/template/ngCart/cart.html index 4b1d6a0..f69d0ec 100644 --- a/template/ngCart/cart.html +++ b/template/ngCart/cart.html @@ -47,7 +47,8 @@    {{ item.getQuantity() | number }}   - + {{ item.getPrice() | currency}} {{ item.getTotal() | currency }}