I'm stuck on a simple thing of removing an item(object) from an array in JavaScript. I am also using jQuery.
I'm trying to build RSS feed and for that I'm storing bookmark/favorites functionality in localStorage. I need to add/remove items from loalStorage array as and when user clicks of the glyphicon-star and glyphicon-star-empty respectively.
The problem I'm facing is during unfavoriting an item. i.e: removing object from array. THe user may click on any favorited item(random order) to unfavorite it. For that I need to remove the respective item from localstorage by value as the index may not always be known. I did search for a valid solution using grep and implemented in my code, but it doesn't seem to work for me.
This is what I found and implemented but it doesn't work:
$(document).on('click', '.glyphicon-star', function(){
var y = arr;
var removeItem = obj;
arr = $.grep(arr, function(value) {
return value != obj;
});
localStorage.favorite = JSON.stringify(arr);
console.log(arr);
for (i=0; i<arr.length; i++)
{
console.log(arr[i]);
}
});
Here is the working: Fiddle
fix for your fiddle
arr = $.grep(arr, function(value) {
return JSON.stringify(value) != JSON.stringify(obj);
localStorage.favorite = JSON.stringify(arr);
console.log(arr);
});
demo here
Object comparison is a little bit tricky to achieve, check this post for info and samples: LINK
You can just add that function to your code and edit your $.grep as follows:
arr = $.grep(arr, function(value) {
return isEquivalent(value, obj) === false;
});
Fiddle here
Related
I'm trying to remove an object from an array by it's key/value of ID. I would normally just splice by index, however the index might be changing quite a bit because multiple users will be manipulating and updating the object so I want to hook onto something more concrete - aka the id. So I have a bit of logic to check if it still exists and if so remove it by it's ID. However I can't seem to get the syntax quite correct. I Am using underscore.js, I don't know if it's easier with/without it but it's worth mentioning.
Here's what I have -
$scope.toggleSelection = function(typeId,name,index){
//check if exists in array
check = $scope.multipleTypes.some( function( el ) {
return el.name === name;
});
//checked on/off actions
if($scope.items[index].checked == false || $scope.items[index].checked == undefined ){
//IS cecked
if(check){
//already exists, do nothing
}else{
$scope.multipleTypes.push({id:typeId, name:name, checked: true});
}
}else{
//IS not checked
if(check){
var list = _.filter($scope.multipleTypes, function(element){
return element.id != typeId;
}
$scope.multipleTypes = list;
}else{
//is not there, do nothing
}
}
};
So if it does exist and is checked off, it gets pushed. If it does exist and is unchecked, I want to remove it from $scope.multipleTypes by it's ID. I think I Am doing this wrong, all I want to do is remove that one object that has the matching ID from $scope.multipleTypes. Would appreciate any help. Thanks for reading!
If you can use UnderScore Js, You can do it very easily.
Here is an Example:
var someArray= [{Employee:'ved',id:20},
{Employee:"ved",age:25},
{Employee:"p",age:2}];
var a = _.findWhere(someArray,{id:25});//searching Element in Array
var b= _.indexOf(someArray,a);// getting index.
someArray.splice(b,1);// removing.
I normally find the object by id, then splice it out. Note that angularjs adds other properties to the object .
e.g
$scope.items = [......]
var findItemByID = function(id, items){
angular.forEach(items, function(item){
if(item.id === id){
return item;
}
})
return null;
}
var removeItemByID = function(id, items){
var item = findItemByID(id);
if(item){
items.splice(items.indexOf(item), 1);
}
}
//you can now do removeItemByID(id, $scope.items);
//I have not tested this code and it may have syntax errors. hope you get the idea.
Josh
Problem : Uncaught TypeError: Object #<Object> has no method 'push' in console.
Code in http://jsfiddle.net
Change storage item id(Cart) and try again, looks like previously stored item under "Cart" id is not json array as #dc5 suggested in comment section
UPD: Try this http://jsfiddle.net/vJkBQ/4/
HTML
<div id='cart'></div>
<input type="button" id="add" value="Add To Cart item 1" />
<input type="button" id="add2" value="Add To Cart item 2" />
Javascript
//TODO: move from globals
var storageName = 'myCART';
$(document).ready(function () {
var item = {
DepartmentID :333,
CategoryID:117,
BrandID:19,
BrandImage:" ",
BrandName:"General",
ID:711
};
var item2 = {
DepartmentID :123,
CategoryID:321,
BrandID:18,
BrandImage:" ",
BrandName:"Common",
ID:712
};
localStorage.clear(storageName);
$('#add').click(function(){
addToCart(item);
});
$('#add2').click(function(){
addToCart(item2);
});
});
function addToCart(item){
//by #slebetman
var items = JSON.parse(localStorage.getItem(storageName));
if (! (items instanceof Array) ) {
items = [];
}
var itemIndex = getItemIndexById(items, item.ID);
if(typeof(itemIndex) === 'number'){
items[itemIndex].quantity++;
}
else{
item.quantity = 1;
items.push(item);
}
localStorage.setItem(storageName, JSON.stringify(items));
console.log(localStorage.getItem(storageName));
}
//find search item index
function getItemIndexById(items, id){
for(var i = 0; i < items.length; i++){
if(items[i].ID == id){
return i;
}
}
return false;
}
The expression:
JSON.parse(localStorage.getItem(storageName))
is most likely not returning an array. In which case the statement:
var oldStorage = JSON.parse(localStorage.getItem(storageName)) || [];
is insufficient.
What you should do instead is something like this:
var oldStorage = JSON.parse(localStorage.getItem(storageName));
if (! (oldStorage instanceof Array) ) {
oldStorage = [];
}
This is a simple way to detect arrays. There are more advanced methods such as checking for the existance of .length etc. that detects arrays and array like objects as well as detect arrays in cases where the Array object have been overwritten or works across iframes.
Additional answer:
You've changed the code a lot but the problem is still the same. The line:
if (items != null) {
is not sufficient to check that items is an array. You should instead do:
if ( items instanceof Array ) {
to make sure that it really is an array.
Also, in the else block:
}else{
console.log('Cart is empty, preparing new cart array');
items.push(item);
The console.log message says that a new array is being prepared. However it lies as the code doesn't initialize a new array but uses the items variable as if it was an array. You should instead do this:
}else{
console.log('Cart is empty, preparing new cart array');
items = [];
items.push(item);
Warning:
However, after all that, please heed the the commenters to my question. If you wrote this whole thing from scratch than doing the things I advised would solve all your problems. But if what you're doing is modifying someone else's code then it's probable that Cart was stored in a different format than what you expected.
Please do console.log(localStorage['Cart']) before calling JSON.parse and post your results here. The problem is with your local storage on your browser and cannot usually be reproduced on other people's machines.
Does
JSON.parse(localStorage.getItem(storageName))
always return an array? If so, the issue is that not all browsers support the push method. You can add use this snippet to add it if it is missing:
if(!Array.prototype.push){
Array.prototype.push=function(x){
this[this.length]=x;
return true
}
};
This code is just a start, you can definitely improve it
You can use you can invoke Array.prototype.push() on an object using call().
JSFiddle
JavaScript
function appendToStorage(storageName, data){
var oldStorage = JSON.parse(localStorage.getItem(storageName)) || [];
Array.prototype.push.call(oldStorage, data);
localStorage.setItem(storageName,JSON.stringify(oldStorage));
}
JSON.parse returns an object or null. So here you don't know if you have an object or an Array.
JSON.parse(localStorage.getItem(storageName)) || [];
You can use this instead:
function appendToStorage(storageName, data){
var oldStorage = JSON.parse(localStorage.getItem(storageName)) || {};
if (oldStorage != null){
$(oldStorage).extend(data);
localStorage.setItem(storageName,JSON.stringify(oldStorage));
}
}
$.extend() will add your item to another JSON object. Info here
Your 'item' is not an array, and you cannot use a push method with it.
Object do not have 'push' method,you can do like this!
function appendToStorage( storageName, data ) {
var oldStorage = JSON.parse( localStorage.getItem( storageName ) ) || {},
push = Array.prototype.push;
push.call( oldStorage, data );
// oldStorage.data = data;
localStorage.setItem(storageName,JSON.stringify(oldStorage));
}
I might have written a pretty confusing title but my question is rather simple.
I'm looking for an efficient way to remove an item from an array. But my array is full objects that has been stringified (I'm writing my app on Node.js and I'm using JSON.stringify method). So my array is like this;
"{\"userID\":\"15\",
\"possibleFollowers\":[
{\"followerID\":\"201\",\"friends\":716},
{\"followerID\":\"202\",\"friends\":11887},
{\"followerID\":\"203\",\"friends\":11887}],
\"name\":\"John\",
\"lon\":\"Doe\"}"
My question is on Javascript(or Node). If I wanted to remove the from possibleFollowers with "followerID: 202", how would I be able to do that efficiently?
var string = "…";
var obj = JSON.parse(string);
obj.possibleFollowers = obj.possibleFollowers.filter(function(fol) {
return fol.followerID != "202";
});
string = JSON.stringify(obj);
var data = "{\"userID\":\"15\",\"possibleFollowers\":[{\"followerID\":\"201\",\"friends\":716},{\"followerID\":\"202\",\"friends\":11887},{\"followerID\":\"203\",\"friends\":11887}],\"name\":\"John\",\"lon\":\"Doe\"}";
var dataObject = JSON.parse(data);
dataObject.possibleFollowers = dataObject.possibleFollowers.filter(function(follower) {
return !(follower.followerID == "202");
});
data = JSON.stringify(dataObject);
In javascript, the splice method is used to delete an array element by index.
see :
http://www.roseindia.net/java/javascript-array/javascript-array-remove-index.shtml
try just to delete it by using "delete"
for (var i in possibleFollowers) {
if (possibleFollowers[i]['followerId'] == '216') {
delete possibleFollowers[i];
}
}
HTML:
<input id="sdata" type="hidden" value='{"1651":["12","1"],"1650":["30","0"],"1649":["20","0"],"1648":["13","2"],"1647":["11","0"],"1646":["10","0"],"1645":["12","0"],"1644":["8","0"],"1643":["16","1"],"1642":["10","1"],"1641":["10","0"],"1640":["18","3"]}' />
JS:
var data = $.parseJSON($('#sdata').val());
$.each(data, function(id, sc) {
alert(id);
}
OUT: 1640, 1641, 1642, ..., 1651
How to make it in reverse order (ex. 1651, 1650...)?
As it is, you can't in any reliable manner. Because you are enumerating an Object, there is never a guaranteed order.
If you want a guaranteed numeric order, you would need to use an Array, and iterate backwards.
EDIT: This will convert your Object to an Array, and do a reverse iteration.
Note that it will only work if all the properties are numeric.
var data = $.parseJSON($('#sdata').val());
var arr = [];
for( var name in data ) {
arr[name] = data[name];
}
var len = arr.length;
while( len-- ) {
if( arr[len] !== undefined ) {
console.log(len,arr[len]);
}
}
There is another solution, a fairly easy one:
$(yourobject).toArray().reverse();
That's it.
I tried this and it worked perfectly for me.
var data = $.parseJSON($('#sdata').val());
$.each(data.reverse(), function(id, sc) {
alert(id);
});
The only change is the "reverse()" in line 2.
If all you need to do is generate some HTML out of your JSON and put generated elements into a container in reverse order you can use jQuery's prependTo method when building your HTML.
var container = $('<div />');
$.each(data, function (key, value) {
$('<div>' + value + '</div>').prependTo(container);
});
For Objects
If you are dealing with an object, reverse() won't work! Instead you can do this to maintain the order.
$.each(Object.keys(myObj).reverse(),function(i,key){
var value = myObj[key];
//you have got your key and value in a loop that respects the order, go rock!
});
You can use javascript function sort() or reverse()
var data = $.parseJSON($('#sdata').val());
data.reverse();
$.each(data, function(id, sc) {
alert(id);
}
I don't know, but for the simple stuff I work with, this function does the job. It doesn't rely on numeric keys. And will flip simple objects top to bottom. I don't understand complex Objects, so I don't know how "robust" it is.
function flipObject(obj){
var arr = [];
$.each(obj, function(key, val){
var temp = new Object;
temp['key'] = key;
temp['val'] = val;
arr.push(temp);
delete temp;
delete obj[key];
});
arr.reverse();
$.each(arr, function(key, val){
obj[val['key']] = val['val'];
});
}
jsonObj = [];
$.each(data.reverse(), function (i, dt) {
jsonObj.push({
'id': dt.id
});
Here's an option that seemed to have worked for me. Hope this helps someone. Obviously only works on simple objects (non-nested) but I suppose you could figure out way to make something more complicated with a little extra work.
var reversed_object = {};
Object.keys(original_object).reverse().forEach(function(key)
{ reversed_object[key] = original_object[key]; });
I'm splitting a string into an array, then I want to remove the white space around each element. I'm using jQuery. I'm able to do this successfully with 2 arrays but I know it's not correct. How do I loop thru an array and trim each element so the elements keep that change. Thanks for any tips. Here is my working code using two array. Please show me the correct way to do this.
var arVeh = vehicleText.split("|");
var cleanArry = new Array();
$.each(arVeh, function (idx, val) {
cleanArry.push($.trim(this));
});
Cheers,
~ck in San Diego
You don't even really need the idx or val parameters. This appears to work on jsFiddle:
var cleanVehicles = [];
$.each(vehicleText.split("|"), function(){
cleanVehicles.push($.trim(this));
});
EDIT: Now that I've seen what you're really after, try using map:
var cleanVehicles = $.map(vehicleText.split("|"), $.trim);
I'm going to suggest not using the overhead of jQuery for a simple for-loop...
var arVeh = vehicleText.split("|");
for (var i = 0, l = arVeh.length; i < l; ++i) {
arVeh[i] = $.trim(arVeh[i]);
});
Alternatively, get rid of the whitespace from the beginning, and avoid the need for another loop at all.
var arVeh = $.trim(vehicleText).split(/\s*\|\s*/);
Without 'creating' an array in the javascript code (an array will nevertheless be created in memory)
vehicles = $.map(vehicleText.split("|"), function(e,i) { return $.trim(e) });
var my_arr = [' cats', 'dogs ', ' what '];
$.each(my_arr, function (id, val) {
my_arr[id] = $.trim(val);
});
console.log(my_arr);
This will trim the value and set it to the indexed item.
You don't have to use JQuery. Here is your vanilla solution:
testArray.map(Function.prototype.call, String.prototype.trim);
Function.prototype.call calls trim() on each of the elements of the testArray. As simple as that!
Could you not just do this?
var arVeh = vehicleText.split("|");
$.each(arVeh, function (idx, val) {
arVeh[idx] = $.trim(this);
});
//a simple function
function trimArray(dirtyArray){
$.map(dirtyArray.split("|"), function(idx, val){
return $.trim(this);
});
}
trimArray(vehicleArray);
should do the trick
Or you could use some of the awesome power of javascript and use array.prototype. I'm still a little new at using the .prototype of any object... so this isnt guaranteed to work (but it certainly can be done).
Array.prototype.trim = function (){
$.map(dirtyArray.split("|"), function(idx, val){
return $.trim(this);
});
}
someArray.trim()
You need these two jQuery functions:
1.) iterate through array element with ability to edit items:
http://api.jquery.com/jquery.map/
2.) remove blank spaces from beginning and end of a string:
http://api.jquery.com/jQuery.trim/
Use them this way:
array = $.map(array, function(value) { return value.trim();});
Check this JSFiddle:
https://jsfiddle.net/L00eyL4x/49/