2

It's hard to even describe the question. I can't reproduce a snippet, obviously because it requires using cookies, but I will try to reproduce it with a normal array, and show you how it should work, then I'll show you screenshots of my code, and the outcome it produces when used on real cookies.

function cookiename(name) { 
//var test5 = document.cookie.split(";");
var test5 = ["user=Jim Jordan", "color=blue", "cat=bella", "username=NikoaTesla"];
var username2 = name;   
var output = "";

if(test5[0].indexOf("user") == 0) { 
   output = test5[0].substring(username2.length, test5[0].length);
 } else alert("IT DOES NOT WORK");


alert(output);

}

cookiename("user");

This is pretty much what my code looks like, except that, instead of array, test5 is assigned to document.cookie.split(";"), and it contains two more cookies.

Now, the way it works is, you create a conditional statement with the array value, in this case, test5[0], which contains the value "user=Jim Jordan", and say, if the indexof("user") string is in position 0 inside the test5[0] string, which contains the value user=Jim Jordan, then execute the condition, if not, alert that it doesn't work.

Now, as you saw, it works great in the above example. It works as expected with any of the other array values. test5[1], test5[2] etc. will work the same way, of course in the above example they won't match the condition, but if you change the indexof string, it works.

Now, the issue I have is that, the test5 variable stores the document.cookie.split(";") array, and only the first array value works, while the others don't, even though the condition should be matching. However, the other values do work but only if the indexof string is intentionally wrong, and doesn't exist inside the array value, and the condition is of course -1. If the indexof string actually exists, both 0 and -1 conditions don't match. Very strange.

Here's a screenshot of my code, and subsequent result:

First array value

So, as you can see, the first value works as expected.

But then, when I try with another array value, it doesn't work. The third array value is called username=Sam Jones. This is what happens when I change indexof("user") with indexof("username").

Third array value

As you can see, the prior alert that I inserted displays that test5[2] contains the value of username=Sam Jones, but then when use it as a condition, the indexof("username") does not match it. It should be 0, but it's not. Even when I try -1, instead of 0, which matches strings that do not exist, it still produces the exact same outcome! Why!?

Now, watch what happens when I add a string in indexof that does not exist. Instead of the string username, I will add something random, and use -1 as a condition.

Different indexof string on Third array value

As you see, now the random indexof string matches the -1, because it doesn't exist. But why when the indexof string actually does exist, neither 0 nor -1 match the condition?

Why only the first array value work?

Does anyone have any idea what is happening here?

  • Plenty of scripts out there to read cookies, why reinvent the wheel? https://stackoverflow.com/questions/4825683/how-do-i-create-and-read-a-value-from-cookie – epascarello Feb 11 '21 at 17:39
  • I am not. I am just now learning about reading cookies, and I am experimenting. Can you help me understand what's wrong with my code? Is the issue in my code, or is it something else? It should work, but it doesn't. I want to understand why. –  Feb 11 '21 at 18:27
  • console.log() is your friend. Not sure what your problem is with your code other than you are not accounting for the `=` And cookies are encoded, so you are not accounting for removing that. Other issue you have is your code will fail if username is before user. The user will match username – epascarello Feb 11 '21 at 18:30
  • Your approach is flawed since you are expecting that the cookie will always be in the same order. You are also checking for the start of a string equals. When you have user, it will also match username. You are not accounting for the `=` and you are not removing the encoding. – epascarello Feb 11 '21 at 18:44
  • console does not produce any error. I know I'm not accounting for the `=`. The code you're seeing in the screenshot in a trim version of the original one. I had to get rid of the unnecessary parts, and only show you the relevant parts to the issue I am having. Why is `indexof("username")` not matching the `test5[2]`? `username` is the first string, yet it's not matched. What's more weird is that neither 0 nor -1 match. Why? Do you have any ideas? –  Feb 11 '21 at 19:01
  • username is at index of 3, so why would it match? `[2]` is `"cat=bella"` You are making a bold assumption that your cookies will always be in an exact order, that is not the case. – epascarello Feb 11 '21 at 19:04
  • Please read the question again. I am not matching `user` with `username`. I am matching `test5[2]` which contains the value `username=sam jones` with `indexof("username") == 0`. The `username` string is at place 0, so it should match, just like `indexof("user") == 0 matches the `test5[0]` which contained the value of `user=some name`. –  Feb 11 '21 at 19:05
  • `username` is at index2 as shown by the prior insertion of alert, which alerts `test5[2]` and it shows the value of `username=sam jones`. You are forgetting that the counting starts from 0, not 1. I told you, I am not making that assumption, this is not my final product. In my original code, I have used a `for loop` to go through the entire array, and it works great with an array, but when I turn cookies into array, for some reason, only the first array value works. So I trimmed the code and boiled it down to the issue parts only. –  Feb 11 '21 at 19:08
  • Also, I said that the document.cookie contains different values, not necessarily in the same order as the demo array I created here. The value of `test5[2]` is shown in the alert right before the `if` condition. –  Feb 11 '21 at 19:10
  • Hard to know you use a for loop when we do not see a for loop. You need to debug and find out why it does not match. We can not guess by looking at an image. `console.log(test5[2], test5[2].indexOf("username"), test5[2].indexOf("username") == 0, escape("username"), escape(test5[2]));` Something does not match so you need to figure out what is different. – epascarello Feb 11 '21 at 19:16
  • Well, as I said, the console does not register any errors. The fact that the `else` statement is executed means that the code works correctly, but the `if condition` is simply not met. How can I find out WHY it's not met? It should be met. I can see no logical reason it's not. I couldn't think of anything else, so I came here to ask you guys. The code you are seeing is the code I am seeing on my editor. I've removed the `for loop` right now. –  Feb 11 '21 at 20:55
  • You need to debug like the console.log() I showed in my previous comment. Look at the values, add a debugger statement and inspect. We can not guess, you need to look at the data and see what is there. Something is different. It is impossible for me to tell by looking at an image. – epascarello Feb 11 '21 at 20:57
  • I am sorry, I haven't studied how to use `console.log` statement yet. How do I use it to test my code? –  Feb 11 '21 at 21:02
  • Put it in the code before the if and look at the console....stop using alerts to debug. It is not 1990 anymore. – epascarello Feb 11 '21 at 21:03
  • I copied that statement you wrote above into the function, and then run the code, and checked the browser console. It says this `username=Sam%20Jones 1 false username %20username%3DSam%2520Jones`. What is that supposed to mean? –  Feb 11 '21 at 21:04
  • So `%20` is a space.... You have a space `" username" !== "username"` Debugging solved your mystery. – epascarello Feb 11 '21 at 21:06
  • but again, I do not have a space. Look at the screenshot above. The alert shows `username=sam jones` right before the `if` condition. No space there. And also, It's not just `username=sam jones` that doesn't work. Non of the cookie values work except the first one. So it's not the space. –  Feb 11 '21 at 21:10
  • YES YOU DO..... The alert does NOT show the whitespace. The `%20` in the escape code is clearly showing it there. – epascarello Feb 11 '21 at 21:11
  • https://imgur.com/a/So4kRrN here's a screenshot of all the cookie values. non of them except the first one meet the condition. –  Feb 11 '21 at 21:11
  • The cookie is like this `"foo=123; bar=456;"` When you do `split(";")` you have `["foo=123", " bar=456"]` – epascarello Feb 11 '21 at 21:13
  • I just created a new cookie value called `laptop=hp` NO SPACES. And i tested it, and again, it does not meet the conditions. –  Feb 11 '21 at 21:14
  • I just tested `indexof(" laptop")` and `("laptop ")` both don't work. They keep not meeting the condition. Where do I add that supposed space, or remove it? –  Feb 11 '21 at 21:15
  • oh my god, it worked! –  Feb 11 '21 at 21:16
  • I forgot to change the array value. I just did, and then added space in front like this `(" laptop")` and it worked. –  Feb 11 '21 at 21:17
  • So, is there a way to get rid of this empty space? –  Feb 11 '21 at 21:17
  • But that is not the solution.... – epascarello Feb 11 '21 at 21:17
  • Use trim() or better, change your split() to account for the space. – epascarello Feb 11 '21 at 21:18
  • adding space in split() works fine. I haven't studied trim() yet. –  Feb 11 '21 at 21:21
  • Really thanks a lot. You helped me so much. –  Feb 11 '21 at 21:21
  • I'm sorry can I ask you one more thing? So, I did my whole code as I wanted it, but for some reason, when I change the `i < test5.length` condition into `i <= test5.length`, it produces an error saying `Cannot read property 'indexOf' of undefined`. Why? Why is the code breaking when I change `smaller than` into `smaller or equal to`? Here's a screenshot again - https://imgur.com/a/wMCZ6Do When it's just `<` it works perfectly. But when I make it `<=` it stops working, and says the above message. `<=` works if it's a primitive number, not a length. –  Feb 11 '21 at 21:45
  • because as you told me earlier index starts at 0. – epascarello Feb 12 '21 at 00:33
  • @epascarello Yeah, I already figured it out last night :) Thanks again. –  Feb 12 '21 at 17:37

3 Answers3

0

What you want is to find cookies starting with name, correct?

Firstly, you are probably aware, but it is good to note that if your cookies come this way: cookies = "user=Jim Jordan; color=blue; cat=bella; username=NikoaTesla";, you have to split for "; " instead of just ";".

Once your splits are correct, already without any leading spaces, you only need:

test5.filter(c=>c.trim().startsWith("user"));

I believe startsWith is cleaner than using indexOf.

Another solution, without split:

For the "; " case:

const cookiestr='; '+cookies+';';
while (true) { i=cookiestr.indexOf('; user',i+1); if (i<0) break; console.log(cookiestr.substring(i+2,cookiestr.indexOf(';',i+1))); }

For the ";" case:

const cookiestr=';'+cookies+';';
while (true) { i=cookiestr.indexOf(';user',i+1); if (i<0) break; console.log(cookiestr.substring(i+1,cookiestr.indexOf(';',i+1))); }
brunoff
  • 4,161
  • 9
  • 10
  • I haven't studied `startsWith` method yet. For now, my question is why is only the first value work, while the others don't. I want to understand what is the problem with my code. It makes no sense, and it should work. I am matching a string that exists, yet the condition does not match. Do you have any ideas what's wrong with my code? –  Feb 11 '21 at 18:26
0

Your approach is flawed since you are expecting that the cookie will always be in the same order. You are also checking for the start of a string equals. When you have user, it will also match username. You are not accounting for the = and you are not removing the encoding.

So to do it with your approach with indexOf and substring, you would need to loop over and check that it has a match

function getCookie(key) {
  // var myCookies = document.cookie.split(/;\s?/g);
  var myCookies = ["user=Jim%20Jordan", "color=blue", "cat=bella", "username=NikoaTesla"];
  for (var i = 0; i < myCookies.length; i++) {
    var current = myCookies[i];
    if (current.indexOf(key + "=") === 0) {
      return decodeURIComponent(current.substr(key.length+1));
    }
  }
}

console.log('user', getCookie('user'));
console.log('username', getCookie('username'));
console.log('funky', getCookie('funky'));

Most approaches would use a regular expression.

function getCookie(key) {
  // var myCookies = document.cookie;
  var myCookies = "user=Jim%20Jordan;color=blue;cat=bella;username=NikoaTesla";
  var cookieValue = myCookies.match(`(?:(?:^|.*; *)${key} *= *([^;]*).*$)|^.*$`)[1]
  return cookieValue ? decodeURIComponent(cookieValue) : null;
}

console.log('user', getCookie('user'));
console.log('username', getCookie('username'));
console.log('funky', getCookie('funky'));

If I have to read multiple values I would map it to an object

function getCookieValues() {
  // var myCookies = document.cookie.split(/;\s?/g);
  var myCookies = ["user=Jim%20Jordan", "color=blue", "cat=bella", "username=NikoaTesla"];
  return myCookies.reduce(function (obj, item) {
    var parts = item.split("=");
    obj[parts[0]] = decodeURIComponent(parts[1]);
    return obj;
  }, {});
}

var myCookies = getCookieValues();
console.log('user', myCookies['user']);
console.log('username', myCookies['username']);
console.log('funky', myCookies['funky']);
epascarello
  • 204,599
  • 20
  • 195
  • 236
0

In your conditional, test5[2] = “cat=bella”, not “username=NikolaTesla”. That’s at index 3. Could try that? Also check for white spaces being being added to the front of end of each string like someone mentioned already.

JTorres
  • 24
  • 2
  • Please look at the screenshot pictures below. The first snippet demonstrates an array, not the actual document.cookies object. In the below screenshot, when I change the `indexof` string, It's on the actual `document.cookie`, and I insert an alert to display the value of `test5[2]` prior to the `if condition` so you can see it's `username= sam jones`. The second value, `test5[2]` on the original document.cookie array is `username=sam jones`. –  Feb 11 '21 at 20:58