Skip to content

Instantly share code, notes, and snippets.

@kolyaflash
Created April 16, 2014 18:57
Show Gist options
  • Save kolyaflash/10920640 to your computer and use it in GitHub Desktop.
Save kolyaflash/10920640 to your computer and use it in GitHub Desktop.
'use strict';
/*
Vanilla js here
*/
var urlParams;
(window.onpopstate = function () {
var match,
pl = /\+/g, // Regex for replacing addition symbol with a space
search = /([^&=]+)=?([^&]*)/g,
decode = function (s) { return decodeURIComponent(s.replace(pl, " ")); },
query = window.location.search.substring(1);
urlParams = {};
while (match = search.exec(query))
urlParams[decode(match[1])] = decode(match[2]);
})();
var serialize = function(obj) {
var str = [];
for(var p in obj)
if (obj.hasOwnProperty(p)) {
str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
}
return str.join("&");
}
/*
App code here
*/
// Declare app level module which depends on filters, and services
var storeApp = angular.module('storeApp', [
// 'ngRoute',
'storeControllers',
'extraControllers',
'storeServices',
]);
storeApp.config(['$interpolateProvider', function($interpolateProvider) {
$interpolateProvider.startSymbol('{[{');
$interpolateProvider.endSymbol('}]}');
}]);
var storeControllers = angular.module('storeControllers', []);
var extraControllers = angular.module('extraControllers', []);
var storeServices = angular.module('storeServices', []);
storeServices.service('urlParamsService', ['$rootScope', '$location',
function ($rootScope, $location) {
this._params = urlParams;
this.getParam = function (name) {
if (!name in this._params) {
return false;
}
return this._params[name];
};
this.setParam = function (name, value) {
this._params[name] = value;
};
this.searchParam = function (value) {
if (! value == "" && !value) {
return this.getParam('search');
}
// Go to first page when search new value
if (!this.getParam('search') || this.getParam('search') == value) {
this.setParam('page', false);
}
this.setParam("search", value);
this.followPath = "/products/";
this._follow_location();
};
this.sortParam = function (value) {
if (!value) {
return this.getParam('sort');
}
this.setParam("sort", value);
this._follow_location();
};
this.getAllParams = function (exclude) {
var result = {};
if (!exclude) {
exclude = [];
}
angular.forEach(this._params, function (val, name) {
if (exclude.indexOf(name) != -1) {
return;
}
result[name] = val;
});
return result;
};
this._follow_location = function () {
if (!this.followPath) {
this.followPath = window.location.pathname;
}
var _urlParams = {};
angular.forEach(this._params, function (paramVal, paramName) {
if (!paramVal) {
return;
}
_urlParams[paramName] = paramVal;
});
var queryString = serialize(_urlParams);
window.location.replace(this.followPath + '?' + queryString);
//document.location.search = queryString;
};
}]);
storeServices.factory('cartService', ['$http', function ($http) {
var resourceUrl = '/api/v1/cart/';
var CartItem = function (object, cart) {
var self = this;
cart = cart,
this.id = object.id,
this.product = object.product,
this.name = object.product.title,
this.quantity = object.quantity,
this.option = object.option,
this.option_text = object.option_text,
this.remove = function () {
cart.remove(self.id);
},
this.getTotal = function () {
return this.product.price * this.quantity;
},
this.checkCanBuy = function (quantity) {
var self = this;
var result = false;
var max_quantity = null;
angular.forEach(self.product.options, function(opt) {
if (opt.id == self.option || self.product.options.length == 1) {
if (opt.is_unlimited) {
result = true;
} else if (opt.stock >= quantity) {
result = true;
} else {
max_quantity = opt.stock;
}
}
});
return {
"can_buy": result,
"max_quantity": max_quantity,
};
},
this.changeQuantity = function (e) {
var new_quantity = parseInt(this.quantity);
if (new_quantity != 0 && (!new_quantity || new_quantity < 0)) {
return;
}
var canBuy = this.checkCanBuy(new_quantity);
console.log(canBuy);
if (! canBuy.can_buy) {
console.log("Too big quantity!");
new_quantity = canBuy.max_quantity;
}
var item_id = this.id;
$http.post(resourceUrl, {
"action": "set_quantity",
"item": item_id,
"quantity": new_quantity,
}, {
method: "POST",
responseType: "json",
}
).success(function (data, status, headers, config) {
cart.reload();
});
}
};
var currentTotal = 0;
var currentTotalItems = 0;
if (typeof(Storage) !== "undefined") {
var currentTotal = localStorage.currentTotal;
var currentTotalItems = localStorage.currentTotalItems;
}
var Cart = function () {
var self = this;
/* Save this to localstorage */
this.total = currentTotal,
this.totalItems = currentTotalItems,
this.items = [],
/**/
// "Model" methods
this.fetch = function (callback) {
var self = this;
$http.get(resourceUrl, {
method: "GET",
responseType: "json",
}).success(function (data, status, headers, config) {
var items = [];
self.total = 0;
var totalItems = 0;
angular.forEach(data.objects, function(obj) {
var item = new CartItem(obj, self);
items.push(item);
self.total += item.product.price * item.quantity;
totalItems += item.quantity;
});
self.items = items;
self.totalItems = totalItems;
localStorage.currentTotal = self.total;
localStorage.currentTotalItems = self.totalItems;
if (callback) {
callback(items);
}
self.fireEvent("updated", items);
});
},
this.reload = function () {
this.fetch();
},
this.add = function (productId, option, callback) {
var self = this;
$http.post(resourceUrl, {
"action": "add",
"product": productId,
"option": option,
"no_error_outofstock": true,
}, {
method: "POST",
responseType: "json",
}
).success(function (data, status, headers, config) {
if (data.out_of_stock) {
messages.warning("Больше добавить нельзя");
return;
}
self.reload();
var product_name = data.product.title;
messages.success(product_name + " добавлен в корзину");
});
},
this.remove = function(itemId) {
var self = this;
$http.post(resourceUrl, {
"action": "delete",
"item": itemId,
}, {
method: "POST",
responseType: "json",
}
).success(function (data, status, headers, config) {
self.reload();
});
},
// Observer realization
this.subscribers = [],
this.subscribe = {
updated: function (callback) {
self.subscribers.push({
"callback": callback,
"event": "updated",
});
},
},
this.fireEvent = function (eventName, data) {
angular.forEach(self.subscribers, function(subscriber) {
if (subscriber.event == eventName) {
subscriber.callback(data);
}
});
}
};
return new Cart();
}]);
storeControllers.controller('CartCtrl', ['$scope', '$rootScope', '$filter', '$location', 'cartService',
function($scope, $rootScope, $filter, $location, cartService) {
$scope.foundProducts = [];
$scope.cart = cartService;
$scope.cart.items = [];
$scope.template = {
url: "/_partials/mini_cart/",
};
$scope.cartBlockLoaded = function () {
};
function updateCartItems (items) {
console.log("cart.items in scope now", items);
$scope.cart.items = items;
}
cartService.fetch(function (data) {
cartService.subscribe.updated(function (data) {
updateCartItems(data);
});
});
}]);
storeControllers.controller('ProductsListCtrl', ['$scope', '$rootScope', '$filter', '$location', 'cartService',
function($scope, $rootScope, $filter, $location, cartService) {
$scope.products = [];
$scope.registerProduct = function (productId) {
$scope.products.push(productId);
$scope["in_cart_" + productId] = false;
};
$scope.addToCart = function (productId) {
cartService.add(productId, $scope['productOption_'+productId]);
};
cartService.subscribe.updated(function (items_in_cart) {
angular.forEach($scope.products, function(productId, key){
$scope["in_cart_" + productId] = false;
});
angular.forEach(items_in_cart, function(item, key){
$scope["in_cart_" + item.product.id] = true;
});
});
}]);
storeControllers.controller('SearchCtrl', ['$scope', 'urlParamsService',
function($scope, urlParamsService) {
$scope.searchValue = '';
$scope.searchProduct = function (value) {
if (value == undefined || value == null) {
value = $scope.searchValue;
}
urlParamsService.searchParam(value);
};
}]);
storeControllers.controller('ProductCtrl', ['$scope', '$rootScope', '$filter', '$location', 'cartService',
function($scope, $rootScope, $filter, $location, cartService) {
$scope.addToCart = function (productId) {
var option = $scope['productOption_' + productId.toString()];
cartService.add(productId, option);
};
$scope.productOption = null;
}]);
storeControllers.controller('SortCtrl', ['$scope', 'urlParamsService',
function($scope, urlParamsService) {
$scope.sortOptions = [
{
"name": "от дешевых к дорогим",
"value": "price-asc",
},
{
"name": "от дорогих к дешевым",
"value": "price-desc",
},
{
"name": "новые",
"value": "last-added",
},
{
"name": "популярные",
"value": "rating",
}
];
$scope.sortValue = urlParamsService.getParam('sort') || 'last-added';
$scope.selectSort = function () {
urlParamsService.sortParam($scope.sortValue);
};
}]);
storeControllers.controller('PaginationCtrl', ['$scope', 'urlParamsService',
function($scope, urlParamsService) {
$scope.init = function (currentPage) {
if (currentPage) {
urlParamsService.setParam("page", currentPage);
}
};
$scope.additionalParams = '&' + serialize(urlParamsService.getAllParams(['page']));
$scope.getPaginationUrl = function (base_url) {
return base_url + $scope.additionalParams;
};
}]);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment