Deleting multiple values from cookie - javascript

I have a list of items, which has two values, a name and an id. Each list item is built using data extracted from a cookie. It also has a delete button, which basically looks at the HTML, and then removes that item from the cookie. It ain't pretty, but it works dandy.
Now all of a sudden, a third value (img src) is introduced. I've therefore made a new function to create the cookie and to build the list. Life is still pretty great.
My problem arise, however, when I attempt to delete the item from the array.
JS
$('.deleteNewCookie').on('click', function () {
var val = $(this).prev().prev().html(); // Search DOM for value
var cookieStr = cookieData.split('|');
createCookie('cokLocation', "", -1);
var newCookie = '';
$.each(cookieStr, function (index, value) {
if (value != '') {
var cookieAdd = value.split(',');
if (cookieAdd[1] != val) {
newCookie = newCookie + value + '|';
}
}
});
createCookie('cokLocation', newCookie, '300');
});
This is how one item in the cookie looks like:
ID,Name,/image.png|
Now, this works as intended when the markup was simpler and there was only the ID and Name, but when I click .deleteNewCookie now, the image sorce remains in the cookie. How would I go about deleting everything in that array (item)? Why does it apparently delete only the first two values?
Markup
<li>
<div class="myLocImg">
<img src="/image.png">
</div>
<div class="myLocInfo">
<h3>NAME</h3>
<span url="locationid=ID" class="btn">More details</span>
<a class="deleteNewCookie">Remove</a>
</div>
</li>
I'm somewhat reluctant to restructure my cookie (as it's being used other places), but I may be persuaded as a last resort. I'm also not using any plugins, and I am not really interested in importing any. Plain JS or jQuery solutions only, please. :)

Fiddle trying to reproduce issue. Code works as expected. Other parts of code are causing issue.
Issue turned out to be relating to "createCookie() and how the values were stored in the HTML itself."

Related

JavaScript: Writing Arrays localStorage Results in Duplicate Items - Why?

trying to write a javascript quiz for my coding bootcamp. having some issues with retrieving and saving previous high scores from local storage. can someone please explain to me why the below code writes the newScore TWICE to the highScores arrayItems array into local storage? obviously i would not like duplicates. everything else works great except for this! please help me. thank you so much!
// load any existing high scores from local storage as array
let scoresArray = localStorage.getItem('highScores') ? JSON.parse(localStorage.getItem('highScores')) : [];
// save the score and intials to local storage in array
let newScore = [document.querySelector("#initialsInput").value, '' + countdownTimer + ''];
scoresArray.push(newScore);
localStorage.clear("highScores");
localStorage.setItem('highScores', JSON.stringify(scoresArray));
// run the high scores function which will show all high scores, storted and give the user a chance to play again
showHighScores();
thanks for your quick replies. im sorry i was able to supply you with all of the info you needed, but i thought i gave you enough to work with.
i was just writing to let you know i did figure out a work around. while i'm still getting the duplicate entries into the array, before writing it to localstorage i am using a very simple jquery method to remove any duplicates from my array. here's what i ended up doing:
var uniqueNames = [];
$.each(scoresArray, function (i, el) {
if ($.inArray(el, uniqueNames) === -1) uniqueNames.push(el);
})
The clear() method of the Storage interface clears all keys stored in
a given Storage object.
https://developer.mozilla.org/en-US/docs/Web/API/Storage/clear
I guess you don't need to clear the localStorage.
I believe you need to add the scenario of how triggering this implementation of adding array to the local storage, as I think you might add it twice instead (I mean if the code you showed us is inside a function or how it's executed exactly)
but from the code above, everything seems to be working fine, I'd like to have more code from your side please to better understand what's going on. also you can remove localStorage.clear as localStorage.setItem will override any existing key with new value
lame work around using jquery to remove duplicates from the array:
var uniqueNames = [];
$.each(scoresArray, function (i, el) {
if ($.inArray(el, uniqueNames) === -1) uniqueNames.push(el);
})

How to add and remove items in localStorage?

I am trying to build a logic where we click a button and save an ID in localStorage. We could have 2 ids max. However, we can also remove an ID from it and add a new one. Finally, we cannot add more than 2 and these ids must be unique. These IDs will be then set as an input value in a form.
So I have four steps page:
Homepage page
Search result page
Single article page
Form result page
Each page has:
<form id="post_form_id" method="post" action="/test/compare/">
<input id="input_post_id" type="hidden" name="varPostId" value="">
<button type="submit" class="btn btn-link nav-link" id="jikubox"></i>
<span class="badge badge-secondary">0</span></button>
</form>
Saved IDs will be set in name="varPostId" value=""
Now the tricky part which is confusing me, so localStorage can only have strings so first of all on each page load I do:
var lines = localStorage.getItem("lines") ?
JSON.parse(localStorage.getItem("lines")) : [];
Then since in the article page I have a save button to add the current article id in the array, I do:
<button type="button" class="save_post">SAVE</button>
JS
$(".save_post").on("click", function(e) {
e.stopImmediatePropagation();
if (localStorage.getItem("attempts") >= 2) {
alert('nope');
return;
} else {
// Here I set the id for each article which I saved before via php in a span
var thisId = $(".my_post_id").attr("data-id");
var lines = localStorage.getItem("lines") ? JSON.parse(localStorage.getItem("lines")) : [];
lines.push(thisId);
localStorage.setItem("lines", JSON.stringify(lines));
console.log(lines);
$("#input_post_id").val(JSON.parse(localStorage.getItem("lines")));
var attempts = Number(localStorage.getItem("attempts"));
localStorage.setItem("attempts", ++attempts);
console.log(localStorage.getItem("attempts"));
$("#jikubox span").text(localStorage.getItem("attempts"));
}
});
Notice I have another localStorage: attempts, that is used to add or remove a number I set in a counter badge, basically an indicator which tells how many items I have in my "bag". Remember: max 2 and unique.
So finally on the form result page I have a button to remove added items and the following js is used:
$(".removeJiku").on("click", function(){
// Here I set the id for each article, I do that with php
// <span class="removeId" data-thisPostId="<?php echo $idThisPost; ?>"></span>
var removeThisId = $(".removeId").attr("data-thisPostId");
$(this).parent().fadeOut();
var attempts = Number(localStorage.getItem("attempts"));
localStorage.setItem("attempts", --attempts);
$("#jikubox span").text(localStorage.getItem("attempts"));
lines.splice($.inArray(removeThisId, lines), 1);
localStorage.getItem("lines", lines);
localStorage.setItem("lines", lines);
console.log(localStorage.getItem("lines"));
});
The logic is kinda ok but after I try few times, I eventually get empty lines array and the ids are not set to the input value. I think I over complicated the logic and I was wondering where and how I could simplify and correct it. I am looking into a single general bit of code which handles all of this without complicating the logic.
UPDATE
Thanks to an answer, one bit of code has been simplified and the counter will be set by checking the length of the ids in lines array so We can remove the whole code for the attempts local storage logic
$("#jikubox span").text(lines.length);
Assume you store your IDs in an array-
var idList=["123","456"];
You can store IDs like this -
localStorage.setItem("idList",JSON.stringify(idList));
and fetch idList like this-
JSON.parse(localStorage.getItem("idList")).length
Just make sure to put validations all around.
P.S. No need to count the "attempts" as you can anytime use the below code to find the length of the idList, which can be 2 or any number you want
JSON.parse(localStorage.getItem("idList")).length
UPDATE:
To remove IDs-
function removeId(array, element) {
const index = array.indexOf(element);
array.splice(index, 1);
}
Fetch array from localStorage and pass it into this function -
idList = JSON.parse(localStorage.getItem("idList"))
and call the function like this -
removeId(idList,idToBeDeleted)
This block isn't doing what you want:
lines.splice($.inArray(removeThisId, lines), 1);
localStorage.getItem("lines", lines);
localStorage.setItem("lines", lines);
The second line is getting something from localStorage but isn't doing anything with it. It could be the equivalent of
lines.splice($.inArray(removeThisId, lines), 1);
['one line', 'another line'];
localStorage.setItem("lines", lines);
Just some random value that proceeds to get ignored by the interpreter.
The other problem is that you're setting localStorage.lines to the plain lines variable, not to JSON.stringify(lines).
Note that you can simplify your syntax noise just by doing
localStorage.lines = JSON.stringify(lines);
and
const lines = JSON.parse(localStorage.lines || '[]');
localStorage.getItem('item') only accepts one parameter, which will return the value if it exists in the local storage and will return null item doesn't exist.
localStorage.setItem(item, value) accepts two parameters. item which is a key and the value which is to be saved for the key. If item is already set it will overwrite the value.

Select2 v4 .val() does not maintain order of elements in data object

I have a select2 (v4) select box where people are choosing codes, and the order must be maintained. This works great when they originally add the elements:
However, this is a popup that is used for many different elements on the page. That means I must clear this array and load it with stored data objects on the fly.
My data object preserves the order as var codeArray = ['7990', '268'].
But when I use:
$(element).val(codeArray).trigger("change")
I get the following:
How can I maintain the order on load? Is there a sneaky workaround?
Okay, the fix was pretty hacky, but I'll post what I have:
function rebuildForm(codeArray) {
clearFormContents();
$.each(codeArray, function(j,obj){
var found = false;
code_list.some(function(el){
if (el.value == obj) {
var str = (el.text).split(")");
$("element option[value=" + el.value + "]").remove();
$(element).append(new Option("(" + el.value + ")" + str[1] , obj));
found = true;
}
})
if (!found) {
$(element).append(new Option("(" + obj + ") Custom Tag" , obj));
}
$(element).val(codeArray).trigger("change");
}
Sorry if the above code doesn't work perfectly, I had to clean it up to remove some fluff and hide the client/project identity.
Basically, on the rebuild of the form, I clear the old form contents then loop through the array grabbing each value/object. Then, if the value exists in the original code list of options in the select2 element I delete the option and rebuild it. This appends it to the bottom of the element list so that the order is maintained in the box. I also add any free form text tags using the 'found' boolean.
Once the new list of options are created in the "correct" order, then I am able to add the values back into the select input DOM element and trigger the select2 change to build the tags.
This thread posted by #RohitS in the comments showed the concept: https://github.com/select2/select2/issues/3106
I just adapted it to my needs.

If username is invalid, hide links

This is my first time doing much with anything but perl and vb so please bear with me.
I am able to compare two fields which need to match, and if they don't, then I need to hide HTML links completely. How would this be written?
This grabs the first userid
($("#trid").val());
($("#pxuserid").text());
var test = $("#pxuserid").text().indexOf("-");
var username = $("#pxuserid").text().substring(test + 1);
(username);
This grabs the second userid and changes it from all uppercase to lowercase.
($("[name=vsvadm]").val());
var str = $("[name=vsvadm]").text("checked", true).val().toLowerCase();
(str);
These are what I need to show/hide
<div class="pxcontent" id="sarea">
<div class="pxvtab" id="pxform">
<div class="pxvtablinks">
Directories
Accounting
Advanced
Security
I'm trying to get the script to say "If userid1 does not equal userid2, then hide Page 5, 6, and 7, but show only page 2, otherwise keep going"
Hopefully I didn't confuse anyone and someone could help out!
Give all the <a> tags a class:
Directories
Accounting
Advanced
Security
And then check for the condition and hide it:
if (userid1 != userid2)
$(".nav-links").hide();
Note: This should be really handled on the server side than the client side. Experienced users (and almost everyone now) can access the hidden elements by using the Dev Tools.
Assuming str and username are what you want to compare..
if(str !== username) $("a").hide();
This hides ALL links, as your question stated, but should not be used to prevent users from viewing them. If your links need to be secure then auth should be done on server side.
Also you can get rid of all the free-standing statements that you wrapped in perens. Those don't serve any purpose.
You need to compare the strings and then loop over the links
var username1 = 'username1'
var username2 = 'username2'
// Do compare
if (username1 !== username2) {
// Loop over the links
$.each($('.pxvtablinks a'), function() {
// If it doesn't have a rel attribute equal to '#page2'...
if ($(this).attr('rel') !== '#page2') {
// hide it.
$(this).hide()
}
})
}
Example: https://codepen.io/mark_c/pen/mAQwpE

Values of all textboxes on a page - without knowing the ID?

I am developing a Chrome Extension that, when the user leaves the page, saves all the text from the textboxes on that page and outputs it to a file.
If I knew the IDs of the textboxes on the page, then it wouldn't be a problem, but the issue is that I need the extension to get the values of all of the textboxes on the page without knowing the IDs, as it will be a different website each time the extension is used.
Also, how would the information be collected? In a string? It would be nice to go down the page and add each textbox to a file, one by one, instead of one huge string.
I've never used jQuery or understood it, and there's probably a solution in it staring me in the face. If anyone suggests using it, please could you explain it a little bit?
Thanks in advance. I would post my code, but I don't know where to start - ergo I don't have any.
you could store it in array using $.each, as :
var valsArr = [];
$("input[type=text]").each(function() {
valsArr.push( $(this).val() );
});
or create object with name as key and value as its value, like:
var valsObj = {};
$("input[type=text]").each(function() {
valsObj[this.name] = $(this).val();
});
You can do it like this:
function onClick(){
var areas = document.getElementsByTagName("textarea");
for(var i = 0; i < areas.length; i++){
alert(areas[i].value);
}
}
<textarea></textarea>
<textarea></textarea>
<button onclick="onClick()">Gather information</button>
Also see this regarding your "save to a file" question Using HTML5/Javascript to generate and save a file
Use the selector and apply it in an each cycle.
$(":text").each(function(){
alert($(this).val());
});
Make a for loop
for(i=0; i < $("input[type='text']").length; i++){
$("input[type='text']").index(i).value();
}
You can use .map() : It returns an array.
var arr = $(":text").map(function() {
return this.value
}).get(); //add join(',') after get() to get a simple comma separated list.
Instead of input[type="text"] you could also use :text pseudo selector.
Demo

Categories