Add and count object in cookie javascript - javascript

I'm creating Add to cart module. I have Add to cart button, when the user click on it, then it will register JSON data of the item to cookie.
This is the example of the item object:
item =
{
DepartmentID :56,
CategoryID:117,
BrandID:19,
BrandImage:" ",
BrandName:"General",
Quantity:5,
ID:706
};
This is what I have done with cookie :
$('#addToCart').click(function(){
addObjToCookie('Cart',item);
});
function serializeObjToJSON(obj) {
var json = $.toJSON(obj);
return json;
}
function deserializeJSONToObj(json) {
var obj = $.evalJSON(json);
return obj;
}
function addObjToCookie(cookieName, obj) {
var jsonObj = serializeObjToJSON(obj);
$.cookie(cookieName, jsonObj);
}
function getDataFromCookie(cookieName){
var obj = deserializeJSONToObj($.cookie(cookieName));
return obj;
}
How can I append the item object into $(cookie('Cart')) when user click on Add to cart button, with this format:
[{"DepartmentID":56,"CategoryID":117,"BrandID":19,"BrandImage":" ","BrandName":"General","Quantity":5,"ID":706},
{"DepartmentID":56,"CategoryID":117,"BrandID":19,"BrandImage":" ","BrandName":"General","Quantity":1,"ID":707}];
How to count the item in Cart cookie, in this example the result is 2.
If the item in Cart is exist, then increase Quantity + 1.
Any help would be much appreciated, thank you.

Here are tweaks to answer 1 & 2
function addObjToCookie(cookieName, obj) {
// When adding see what's in there
var currentCart = getDataFromCookie( cookieName );
// Add what's new
currentCart.push( obj );
// Save new contents
$.cookie(cookieName, serializeObjToJSON( currentCart ) );
}
function getDataFromCookie(cookieName){
var val = $.cookie(cookieName);
// Make sure this returns something valid if it's not there
if ( !val ) {
return [];
}
// No need to save off something if you're not doing anything with it
return deserializeJSONToObj( val );
}
As for #3, before actually saving the new cookie content, loop through the return value til you find a match and if you do modify that rather than pushing to the array.
If you try the loop and it doesn't work, please post your attempt. I like to help but not to write code from scratch, so you can learn some too.

Related

Remove entire array from local storage

How to remove the localStorage entirely without localStorage.clear(); method?
I have a cart where you can store the products you're about to buy and the storing happens with a local storage. Currently the "Clear Cart" button works with localStorage.clear(); method, but I also have a table where you can remove single products. However, if you remove the entire table with the "remove" button on the same row and it happens to be the last product, local storage will still have an empty array and is considered as NOT null.
This is my method to remove the item:
function removeItem(itemId) {
//removes the parent row of table
$('#product-table').on('click', '.remove-item', function(e) {
$(this).closest('tr').remove();
});
var index = -1;
var obj = JSON.parse(localStorage.getItem("items")) || {}; //fetch cart from storage
var items = obj || []; //get the products
$.each(items, function(key, value) {
if (key === itemId) {
items.splice(key, 1); //remove item from array
}
});
localStorage.setItem("items", JSON.stringify(obj)); //set item back into storage
sum = 0;
$.each(items, function(key, value) {
sum += value.itemPrice;
});
$("#summary").html(sum.toFixed(2) + "€");
updateCartCount();
}
It removes items correctly, but whenever I remove the last product, the table element and add a paragraph saying "Your cart is empty. Return to shop".
Following function is below:
function hideElements() {
if ($(".cart-wrapper").length) {
if (localStorage.getItem("items") === null) {
$("#products").css("display", "none");
$("#empty").css("display", "block");
$(".btn-clear").css("display", "none");
} else {
$("#products").css("display", "block");
$("#empty").css("display", "none");
$(".btn-clear").css("display", "block");
}
}
}
The hideElements function won't recognize the local storage as empty, since it shows that there is an empty array object.
How can I achieve this by removing the entire local storage, if the removed product was the last product on the cart? I tried out with localStorage.getItems("items").length != 0 and such with no avail.
The following image displays my "empty" local storage:
What localstorage.get() returns is a string rather than JSON so what you need to do is parse string i.e. localStorage.getItem('items') returns "[]" which has length equal to 2. What you need to do is JSON.parse(localstorage.getItem('item')).length
You're probably looking for localStorage.removeItem().
Better yet, you should refactor things so there are functions solely responsible for managing the items array in your local storage:
function loadItems() {
// Returns the value of items, or an empty array.
return JSON.parse(localStorage.getItem("items") || "[]");
}
function saveItems(itemsArr) {
localStorage.setItem("items", JSON.stringify(itemsArr));
}
// Remove item with given ID (assuming each element in the array is e.g. `{id: 123}`)
const itemId = 123;
saveItems(loadItems().filter(item => item.id !== itemId));
// Update cart HTML elements:
if ($(".cart-wrapper").length) {
const haveItems = loadItems().length > 0;
$("#products").toggle(!haveItems);
$("#empty").toggle(haveItems);
$(".btn-clear").toggle(!haveItems);
}

Pushing object to Array makes parameter empty

I'm trying to solve problem of merging two arrays of objects, so I wrote a pretty simple function
function mergeShowtimes(movies) {
var existing_halls = [];
return movies.reduce(function(acc, movie) {
var movies_with_hallid,
movies_seats;
if (existing_halls.indexOf(movie.hallId) === -1) {
movies_with_hallid = _.filter(movies, function(filter_movie) {
return movie.hallId === filter_movie.hallId;
});
movies_seats = _.map(movies_with_hallid, 'seats');
movie.seats = _.union.apply(this, movies_seats);
acc.push(movie);
existing_halls.push(movie.hallId);
}
return acc;
}, []);
}
problem is, whenever I check the value of movie and movie.seats, field 'seats' in movie is empty, but movie.seats is not, for some reason
If I'll remove acc.push(movie); everything will start working as planned
What am I doing wrong?
Thanks for any feedback!

Persist cookie form values across multiple pages

The setting: I have a form that captures$thisSearch.val(), saves it as a cookie, and pushes to an array. The form is an overlay triggered from a menu item in the header so this can appear on any page in the site.
The issue is that it only seems to save/persist the input values on/from that page it was entered on. I'm trying to collect all these values into one list.items() array that can be entered anywhere in the site.
I've tried pushing the string to the array myself instead of the add function and moved the dom around for the search form.
I can update question when I know what to specifically ask. Any pointers / concepts I should be aware of for this would be great.
var cookieList = function(cookieName) {
var cookie = $.cookie(cookieName);
var items = cookie ? cookie.split(/,/) : new Array();
return {
"add": function(val) {
items.push(val);
$.cookie(cookieName, items.join(','));
},
"items": function() {
return items;
}
}
}
var list = new cookieList("PreviousSearches");
$searchSubmit.on('click', function() {
var $thisSearch = $(this).prev().find($searchInput);
if( $thisSearch.val() == '' ) {
alert('Please enter a search term');
console.log( list );
return false;
} else {
searchTerm = $thisSearch.val()
list.add( searchTerm );
}
});
var searchTerms = list.items();
var total = searchTermsFiltered;
var searchTermsFiltered = searchTerms.filter(Boolean).slice( - 5 ).reverse();
var searchtermClean = searchTermsFiltered.join();
$.each($(searchTermsFiltered), function(i,v){
if (!window.location.origin)
window.location.origin = window.location.protocol+"//"+window.location.host;
var lastURLRaw = window.location.origin+'/bch/?s='+v;
var lastURL = lastURLRaw.replace(/ /g, '+');
listItem = '<li>'+v+'</li>';
$('.tags, .search-tags').append(listItem );
});
I found the path specifier from jquerys $.cookie in this top answer below.
$.cookie(cookieName, items.join(',') , { path: '/' }); from my code.
why are my jquery cookies not available across multiple pages?

AngularFire unshift items in AngularJS array

Please help me prepend items when they are pushed over Firebase RESTful service, new item should be on top order when the are displayed in DOM with ng-repeat.
//post.js service
var ref = new Firebase(FIREBASE_URL + 'posts');//creates posts object on root of url
var posts = $firebase(ref);//we get posts Object from firebase
....
var Post = {
create: function(post){
return posts.$add(post);
}
.....
//posts.js controller
$scope.submitPost = function(){
Post.create($scope.post).then(function(){
console.log('success! post submitted');
});
}
HTML:
<div class="col-xs-12" ng-repeat="(postId, post) in posts">
{{post.title}}
{{post.url}}
</div>
But in DOM the newest item goes at the bottom, where as I need the new item should be on the top.
Is there any unshift method in AngularFire ($firebase) ?
If you don't want to get into setting priorities, a simple solution is to let Firebase order your list naturally and reverse it on the client side using a filter such as:
angular.module("ReverseFilter",[])
.filter('reverse', function() {
function toArray(list) {
var k, out = [];
if( list ) {
if( angular.isArray(list) ) {
out = list;
}
else if( typeof(list) === 'object' ) {
for (k in list) {
if (angular.isObject(list[k])) { out.push(list[k]); }
}
}
}
return out;
}
return function(items) {
return toArray(items).slice().reverse();
};
});
Add this module dependency to your app and you'll have a filter that you can use in the ng-repeat attribute like this:
(ng-repeat="(idx, entry) in journal.months[0] | reverse")
Keeping in mind that Firebase stores JSON objects, never arrays, it should make sense that it's not possible to perform an unshift operation against a list. (What would that mean to an object whose keys are sorted lexicographically?) You'll need to utilize priorities and ordered data if you want your item to appear first. Or, if the list is terse, just sort client side.
Here's a quick and dirty way to implement unshift, although this will almost always be inferior to utilizing proper data ordering or simply using endAt():
app.factory('OrderedList', function($FirebaseArray, $firebase, $firebaseUtils) {
var OrderedList = $FirebaseArray.$extendFactory({
unshift: function(data) {
var self = this, list = this.$list;
self.$add(data).then(function(ref) {
var newId = ref.name();
var pos = self.$indexFor(newId);
if( pos > 0 ) {
// place the item first in the list
list.splice(0, 0, list.splice(pos, 1)[0]);
// set list priorities to match
self.reorder();
}
});
},
// order items by their current index in the list
reorder: function() {
var list = this.$list;
angular.forEach(list, function(rec, i) {
rec.$priority = i;
list.$save(rec);
});
}
});
return function(ref) {
return $firebase(ref, {arrayFactory: OrderedList}).$asArray();
}
});
Keep in mind that this particular example is not concurrency safe (if multiple users are modifying the same list at the same time, it's going to have some unpredictable results). Implementing a concurrency-safe solution is similar, but use-case specific (the method for generating the priorities will depend on the use case).

How to convert values of an array into recursive field names of another variable in Javascript

I need to convert values from one Array variable into fields of another variable in Javascript.
My variable is
field = ["entries", "body"]
and it needs to become something like
req.body.entries.body
I tried doing something like
field.forEach(function(prop){
req.body[prop] = "...";
}
but that works only on req.body.entries and req.body.body. And I need it to go all the way to req.body.entries.body
I'm doing this to get the data from a form in a document field (named entries[body]), do some cleaning up on that data, and then pass it back to node.js as if it was the request that was originally made.
UPDATE
All I need to do is to basically
exports.sanitize = function(field){
// field = ["entry","body"];
return function(req, res, next){
val = getField(req, field); // val = "Some string with data"
val = some_process(val); // some_process is a function that cleans up the string
req.body.entry.body = val; // HOW TO TAKE entry.body from the field array???
next();
}
};
As you can see, all I want is to NOT hard code entry.body but take it from field array values that passes the name of the field for processing.
If you can think of a more elegant solution to do this, please, let me know.
Thanks!
This works:
var fields = [ "field1", "field2", "field3", "field4" ];
var obj = req.body;
fields.forEach(function(prop) {
obj[prop] = {};
obj = obj[prop];
});
You want
var obj = req.body;
for (var i=0; i<fields.length-1; i++)
obj = obj[fields[i]];
var prop = fields[i];
obj[prop] = cleanUp(obj[prop]);
This will work only if req.body.entries.body is already defined:
field = ["entries","body"];
var toeval="req.body";
field.forEach(function(prop){
toeval+="."+prop;
});
toeval+="=\"...\"";
eval(toeval);
I was able to accomplish this using recursion. Hope this helps!
var foo = {
bar: {}
};
var fields = ['foobar', 'barfoo'];
function setVar (currentVar, arr, counter) {
if (arr[counter] === undefined) {
return;
}
currentVar[arr[counter]] = {};
setVar(currentVar[arr[counter]], arr, counter + 1);
}
setVar(foo.bar, fields, 0);

Categories

Resources