I have a script that randomly shows divs when you press a button. I would like to make a wish list page in order for people to keep track of what they liked.
I have set a session and a cookie for a day. this is my script and it doesn't work but I'm not sure why... Thanks for all your help.
$(".places").hide();
$("#button").click(function(){
"use strict";
var randomNumber = Math.floor(Math.random()*45);
var selectedDiv = "#place" + randomNumber;
$('.places').hide().filter(selectedDiv).show();
$(".wishlistbutton").click(localStorage.setItem(selectedDiv,JSON.stringify(wishlist)));
});
var wishlistkey = "wishlist";
var wishlist = localStorage.getItem(wishlistkey);
if($.isEmptyObject(wishlist)){
wishlist = new Array()
} else {
wishlist = JSON.parse(wishlist);
}
The $.isEmptyObject method does not work as you expected since you are providing a string as the argument(expected argument type is a plain JS object), actually which is unnecessary in your code.
var wishlist = localStorage.getItem(wishlistkey);
if(!wishlist){
wishlist = new Array()}
else {
wishlist = JSON.parse(wishlist);
}
Although you need to store the JSON string in localStorage with key as wishlist instead of the div id.
localStorage.setItem('wishlist', JSON.stringify(wishlist))
It looks like you're calling localStorage setItem and passing in a key, that is the name of the div (selectedDiv), but then you're trying to getItem on a key named "wishlist" Try setting item in storage like this
$(".wishlistbutton").click(localStorage.setItem("wishlist", JSON.stringify(wishlist))); });
Related
I'm trying to load an array from one page and then have the results appear on another using javascript/jQuery. So a user will make a selection from a dropdown. Based on this dropdown the "customers" address, phone, email, etc. will appear in a text field. I'm trying to store those results in to the array (name | address | etc in one index of the array), display the result on the second screen, and then allow the user to add more names if necessary.
At the moment I'm trying to use localStorage to store the values and then JSON.stringify to convert the results so they can be stored in the array.
I think these are all of the pertinent lines:
var customerArray = [];
var getName = $('#DropDownList1').val();
var getAddress = $('#DataList1').text().trim();
var getPhone = $('#DataList2').text().trim();
var getEmail = $('#DataList3').text().trim();
//store the variables
localStorage.setItem("name", getName);
localStorage.setItem("address", getAddress);
localStorage.setItem("phone", getPhone);
localStorage.setItem("email", getEmail);
//user will click #btnAdd to add the customers information
//into customerArray[]
$("#btnAdd").click(function () {
var setName = localStorage.getItem("name");
var setAddress = localStorage.getItem("address");
var setPhone = localStorage.getItem("phone");
var setEmail = localStorage.getItem("email");
var post = setName + setAddress + setPhone + setEmail;
if (customerArray.length == 0) {
customerArray[0] = post;
} else {
for (var i = 1; i < customerArray.length; ++i) {
//store results of 'post' into the array
customerArray.push(post);
localStorage.setItem("storedArray",JSON.stringify(customerArray));
}
}
}); //end #btnAdd click event
Form here the 2nd page will load with a text field that will (should) display the results of the array (customerArray). Unfortunately I can only get 1 value to appear.
At the moment this is the block being used to display the results:
$('#tbContactList').val(JSON.parse(localStorage.getItem("storedArray")));
If it matters I'm writing the application using Visual Studio Express 2012 for Web. The data that initially populates the customers information comes from a database that I've used ASP controls to get. I'm confident there is a perfectly simple solution using ASP/C# but I'm trying to solve this problem using javascript/jQuery - I'm more familiar with those languages than I am with C#.
Thank you.
Use Array.join() to turn your array into a string to store.
Then use Array.split() to turn your string back into an Array.
Example
var arr=['name','email','other'];
var localStorageString=arr.join(',');
localStorage.setItem('info',localStorageString);
var reassemble=localStorage.info.split(',');
for(var i=0;i<reassemble.length;i++){
document.body.innerHTML+=reassemble[i]+"<br/>";
}
http://jsfiddle.net/s5onLxd3/
Why does the user have to leave the current page though? IS a tabbed/dynamic interface not an option?
My app is built using AngularJS, Yeoman stack, connected to the Firebase, AngularFire database. In my app I am trying to upload and delete pictures as shown below
It works fine except when I delete any imgs in between other images it does not actually remove the img but replaces it with an img with width and height of 0 as such... or it seems (more info in the bottom)
and if I delete another "in-bewteen" img same deal
only when I delete the outer most img does the page really remove the imgs.
^^Notice how the one in between two other images on the top row did not delete because it is surrounded horizontally via other img objects. I had to firebase.remove the bottom two imgs to the right of the one I deleted very first and only then the whole bottom row was removed.
I am not sure why I am getting this bug, could anyone give me some feedback?
Here is my deleteImg and updateImg function in my controller
angular.module('myApp').controller('MainCtrl', ['$scope', '$firebase', '$filter', function($scope, $firebase, $filter) {
$scope.deleteImg = function(img) {
if (confirm('Are you sure you want to delete the img?') === true) {
var deletingID = img.id;
var deletingLink = fireRef + "/" + img.id;
var deleteRef = new Firebase(deletingLink);
deleteRef.remove();
$(".delete").remove();
location.reload();
}
};
$scope.updateImg = function(Img) {
if (confirm('Are you sure you want to update the Img?') === true) {
var updatingID = $scope.selectedImg.id;
var updatingLink = fireRef + "/" + $scope.selectedImg.id;
var updateRef = new Firebase(updatingLink);
var dataObject = {
"name" : $scope.selectedImg.name, "description": $scope.selectedImg.description, "type": $scope.selectedImg.type ... etc...
};
updateRef.set(dataObject);
location.reload();
}
};
}]);
Here is how I instantiate my array and Firebase database as well as create new $scope.selectedImg. I am currently grabbing the data from firebase database and instantiating an array of Img objects. I use the array as my img models in the app.
var fireRef = new Firebase('MY_FIREBASE_URL');
$scope.imgs = []; //<<< instantiate a new array
var imgNum = 0;
var toArrayFirebaseLink = fireRef + '/' + imgNum;
fireRef.once('value', function(allSnapshot) {
allSnapshot.forEach(function(imgSnapshot) {
var i = imgSnapshot.child('id').val();
if( i !== null ){
// set databaseSnapshot to our img array
$scope.imgs[i] = imgSnapshot.val();
}
});
});
$scope.instantiateImg = function(object) {
$scope.selectedImg = {};
// $scope.selectedImg.name = "";
$scope.selectedImg.etc = "";
$scope.selectedImg.etc = "";
};
//Created selectedImg with data retrieved from database to be used within the views.
$scope.selectImg = function(object) {
$scope.selectedImg = object;
};
Here is my html view
<div class="container">
<div class="col-xs-6 col-sm-4 col-md-4 col-lg-3 campaign-thumbs" ng-repeat="img in imgs track by $index" ng-animate="'animate'">
<button type="button" class="delete" ng-click="deleteImg(img)">
<span>×</span>
<span class="sr-only">Delete</span>
</button>
<img ng-click="selectImg(img)" src="{{img.imgSrc}}" class="img-responsive" data-toggle="modal" data-target="#imgModal">
</div>
</div>
Using the chrome AngularJS extension I identified that the elements that I deleted within the database using the firebase remove() function, my $scope.imgs array still has a "null" element within the space in which I removed it. See below picture
How do I get past this bug?
EDIT1:
I followed #m.e.conroy's advice and added the splice functionality and thought it worked perfectly, especially because I removed the location.reload() and in the view it showed that the pictures were getting deleted without a refresh. However, when I do refresh the page the same "ghost" imgs and its delete buttons are showing up again.
When I checked the AngularJS chrome extension for the scope models, it was showing that the outermost img (the img that is to the right of the "in-between" ghost imgs) is taking over the deleted images, meaning the deleted images are getting set with the same name, id, and other attributes of the outer most img object. Once again, according to the chrome extension the array elements are not removed but only replaced. Once I refresh though it goes back to the same issue I had before of "null" element in array. This is weird because in my Firebase dashboard it shows that the imgs are indeed deleted however it does not reflect on my view until the outer most img is deleted. Below is a view of my Firebase dashboard and index. Only when the img 24 is deleted does the changes actually apply.
EDIT2:
As referenced by #katowulf in this article (https://www.firebase.com/blog/2014-04-28-best-practices-arrays-in-firebase.html), I am having the exact problem he describes in the "Good Use Cases for Storing Data in Arrays" section. Currently, I am trying to target each and every one of the imgs after the one that I delete and change their IDs to id - 1 as well as the imgs location in the fire ref to firebar_url/ref - 1 but I feel like I am trying to force an implementation rather than finding the correct solution. Should I try to refactor my code to utilize objects like he suggests? (I tried that initially but I wasn't able to grab the objects and its attributes therefore had to rely on firebase snapshots to instantiate and create my array. Reference: How would I convert my new Object data I am retrieving from Firebase into the JSON form as I had before). Any feedback is welcome.
MY SOLUTION: To manually change index values as well as corresponding 'id' attributes to -1 for all img objects following the one that has been deleted.
$scope.deleteImg = function(index, img) {
if (confirm('Are you sure you want to delete the Img?') === true) {
$scope.imgs.splice(index,1); //remove objects in array
var i;
for(i = index; i < $scope.imgs.length; i++) {
//I want to grab the next img object
var previousIndexID = i; //start from the picture right after the one deleted and change its id to id-1
var newIndexID = i+1;
var previousIndexLink = fireRef + "/" + previousIndexID;
var newIndexLink = fireRef + "/" + newIndexID;
var previousIndexRef = new Firebase(previousIndexLink);
var newIndexRef = new Firebase(newIndexLink);
var idIndexLink = fireRef + "/" + previousIndexID + "/id";
var idIndexRef = new Firebase(idIndexLink);
console.log(previousIndexRef.toString()); // element[index] that got deleted
console.log(newIndexRef.toString()); // element[index] next img object
//copy the next img object into the location of the object that just got removed() 'url/num-1' and 'url/id' value
newIndexRef.once('value', function(snap) {
var i = snap.val();
previousIndexRef.set(i);
});
idIndexRef.once('value', function(snap) {
var i = snap.val();
idIndexRef.set(i-1);
});
};
// until the length is reached and then I want it to delete the last one
var lengthID = $scope.imgs.length;
var lengthLink = fireRef + "/" + lengthID;
var lengthRef = new Firebase(lengthLink);
lengthRef.remove();
}
};
Next time I will most definitely use services/object style but for this app this works great. It was fun to solve it anyway :) Thanks for all the help #Kato and #m.e.conroy
You need to create a method for ng-click that passes the $index from the ng-repeat then in your controller method called by ng-click remove the image from the array (of course after the user confirms) and remove it from the database. removing it from the array will automatically trigger ng-repeat to re-render.
Currently you're using jQuery to remove the object from the DOM but it still exists in the Angular array. Angular doesn't know you used jQuery to remove the object from the view. If you do what is describe above you won't even need to use jQuery or manipulate the DOM, Angular will do it for you. You should not have to do a $location.reload either.
$scope.deleteImg = function(i,id){
if(confirm('..') === true){
$scope.imgs.splice(i,1);
// do firebase deletion
}
};
In template:
<button type="button" class="delete" ng-click="deleteImg($index,img.id)">
...
</button>
EDIT
Actually you'll only need to pass the $index parameter to the method since splice returns the removed element and that will be your image object. i.e.:
$scope.deleteImg = function(i){
var _img = $scope.imgs.splice(i,1);
// use _img.id with your firebase delete statement
};
and then the template is simply just:
<button type="button" class="delete" ng-click="deleteImg($index)">...
Not sure what is Firebase, but as i understan you delete item in array, that become null. And you need to .splice() $scope.imgs array to really remove an item from ngRepeat
I am trying to do the folowing with Asp.net 3.5/IIS
A web form with a top level repeatable form. So basically a Order->Products->ProductsParts kinda of scenerio. Order is only one. Product is repeatable. Each product has repeatable products parts. The product and product part have a whole bunch of fields so I cannot use a grid.
So, I have add/remove buttons for Product and within each product add/remove buttons for each product part.
That is my requirement. I have been able to achieve add/remove after some research using jquery/js. How, do i capture this data on the server? Since javascript is adding and removing these controls they are not server side and I don't know how to assign name attributes correctly. I am trying following javascript but it ain't working:
function onAddProperty(btnObject){
var previous = btnObject.prev('div');
var propertyCount = jquery.data(document.body, 'propertyCount');
var newDiv = previous.clone(true).find("*[name]").andSelf().each(function () { $(this).attr("name").replace(($(this).attr("name").match(/\[[0-9]+\]/), cntr)); }); ;
propertyCount++;
jquery.data(document.body, 'propertyCount', propertyCount);
//keep only one unit and remove rest
var children = newDiv.find('#pnlUnits > #pnlUnitRepeater');
var unitCount = children.length;
var first = children.first();
for (i = 1; i < unitCount; i++) {
children[i].remove();
}
newDiv.id = "pnlPropertySlider_" + propertyCount;
newDiv.insertBefore(btnObject);
}
I need to assign name property as array so that I can read it in Request.Form
Fix for not updating ids not working:
var newDiv = previous.clone(true).find("input,select").each(function () {
$(this).attr({
'name': function () {
var name = $(this).attr('name');
if (!name) return '';
return name.replace(/property\[[0-9]+\]/, 'property' + propertyCount);
}
});
}).end().insertBefore(btnObject);
The issue looks like the following line:
$(this).attr("name").replace(($(this).attr("name").match(/\[[0-9]+\]/), cntr));
This statement doesn't do anything. Strings in JavaScript an immutable, and .replace only returns the string with something replaced.
You would then have to actually set the attr("name") to the new string that has the replaced value:
http://api.jquery.com/attr/
I can't help much more without seeing your HTML.
/* Helper function to clean up any current data we have stored */
function insertSerializedData(ids, type) {
// Get anything in the current field
current_data = $('#changes').val();
if (!current_data) {
var data = new Array();
data[type] = ids;
$('#changes').val(JSON.stringify(data));
} else {
var data = JSON.parse($('#changes').val());
data[type] = ids;
$('#changes').val(JSON.stringify(data));
}
console.log($('#changes').val());
}
I am using the following function to either add data to a current JSON object or create a new JSON object all together to be used in PHP later. Is the stringify() method only for FF? I am using google chrome and I am being given an empty object when using the conosole.log() function...
Also what happens if you try to store two values with the same key? I assume it will overwrite...so I should add a random math number at the end array in order to keep duplicates from showing up?
Thanks :)
These lines may cause problems:
var data = new Array();
data[type] = ids;
... because arrays in JavaScript are not quite like arrays in PHP. I suppose what you meant is better expressed by...
var data = {};
data[type] = ids;
Besides, current_data seems to be local to this function, therefore it also should be declared as local with var. Don't see any other problems... except that similar functionality is already implemented in jQuery .data() method.
UPDATE: here's jsFiddle to play with. ) From what I've tried looks like the array-object mismatch is what actually caused that Chrome behavior.
I reformatted it a bit, but and this seems to work. It will set the "value" attribute of the #changes element to a JSON string. I assume that the type argument is supposed to be the index of the array which you're trying to assign?
function insertSerializedData(ids, type) {
var changes = jQuery('#changes'), arr, val = changes.val();
if (!val) {
arr = [];
arr[type] = ids;
changes.val(JSON.stringify(arr));
} else {
arr = JSON.parse(val);
arr[type] = ids;
changes.val(JSON.stringify(arr));
}
console.log(changes);
}
with localstorage i have a load of unspecified items saved with dynamic names using a data namespace like so:
localStorage["myAppName.settings.whatever"] = something.whatever;
//and this:
localStorage["myAppName.data."+dynObj.name] = dynObj.data;
I want to keep the settings but not the data. However I won't ever know what all of the names inside of my data object are so I cannot clear them individually. I need to clear these each time my app is loaded but I must keep the settings so
localstorage.clear() is not an option.
I have tried:
localstorage.removeItem("myAppName.data")
but no dice.
Anyone have any thoughts on how to clear dynamically named portions of localstorage?
You can loop through the keys in the localStorage and target them with a reg exp:
Object.keys(localStorage)
.forEach(function(key){
if (/^(myAppName.data.)/.test(key)) {
localStorage.removeItem(key);
}
});
Here's a similar question: HTML5 Localstorage & jQuery: Delete localstorage keys starting with a certain word
try something like
var i = localStorage.length, key;
while (i--) {
key = localStorage.key(i);
if (key.slice(0, 19) !== "myAppName.settings.") {
localStorage.remove(key);
}
}
Tried something like this?
// Select current settings
var settings = localStorage["myAppName.settings"] || {};
// Clear localStorage
localStorage.clear();
// Add settings to localStorage
localStorage["myAppName.settings"] = settings;
Assuming a this.namespace present (in my case 'session') and the underscore library:
_.each(_.keys(localStorage), function(key) {
if (RegExp("^" + this.namespace + "\\.").test(key)) {
return localStorage.removeItem(key);
}
});
And with CoffeeScript:
_.each _.keys(localStorage), (key) ->
if ///^#{#namespace}\.///.test(key)
localStorage.removeItem(key)