PHP, Jquery and cookies

tommieonos84

New Member
Messages
18
Reaction score
1
Points
0
I want to make something where you can select which tab(s) you want to show. I thougt to make this with Jquery, PHP and cookies.
Code:
$(function(){
	$('#gHide').click(function(){
		$.cookie('tabs[0]', 'true');
	});
	//and so on
});
and a piece of php:
Code:
<?php
	if ($_COOKIE['tabs'][0] == true){
		include 'include.php';
	}
	//and so on
?>
but tabs[0] gets translated to tabs%5B1%5D. any ideas how to set an array in a Jquery cookie?

btw you can see the tabs on www.epicpwnz0r.co.cc
 

essellar

Community Advocate
Community Support
Messages
3,295
Reaction score
227
Points
63
You may not be able to put an array into a cookie, but you can use a proxy value to represent the array. Since you seem to be using the array only to store a boolean true/false value, you have any number of schemes open to use. That could be a comma-delimited list of tab indexes to hide, or a string made up of Ts and Fs -- anything that will let you get all of the information from point A to point B. It's just a matter of having your JavaScript and PHP code agree on the encoding/decoding (which is trivial), then you're free to use a proper array in the main body of your code at both ends.
 

misson

Community Paragon
Community Support
Messages
2,572
Reaction score
72
Points
48
Since you seem to be using the array only to store a boolean true/false value, you have any number of schemes open to use.

Bitset! Assuming there are at most 32 tabs (just watch for sign issues with the MSB), the set could be stored in an integer value.
 

essellar

Community Advocate
Community Support
Messages
3,295
Reaction score
227
Points
63
Of course, that (a bitset using a bitwise AND to check individual flag values) would be the most compact and elegant way of doing it, but I've had a difficult time trying to explain it to other "developers". (And by that, I mean "professionals" working at the low-hanging-fruit level, like VB/VBS/ASP -- where OR is always bitwise -- Java, and PHP. It's not that the languages make people dumb, but that the bar to entry is set low, so that beginning developers are rarely exposed to binary unless they want to be.) There seems to be some reluctance to believe that multiple flag values based on 2^n won't cause ambiguities when stored in an int/long.

If you understand that 1335 can only happen if the bits representing 1024, 256, 32, 16, 4, 2 and 1 (or 2^10, 2^8, 2^5, 2^4, 2^2, 2^1 and 2^0) are "on" and all others are "off" (since 1335 in binary, as a 4-byte integer, is 00000000 00000000 00000101 00110111) then you can send the equivalent of "show the zeroth, first, second, fourth, fifth, eighth and tenth tabs" from system to system using just the value 1335. Remember to work from right to left -- that way your array indices will correspond exactly with the exponent.

You can build the value to send using either simple addition or a bitwise OR. 0 | 256 results in 256, just as 0 + 256 does. And on the decoding side, 1335 & 256 will result in 256, since the only "true" bit common to both numbers is the one representing 256. The actual implementation I'll leave as an exercise for the reader -- your code may be such that using a zero-fill bitwise right shift and looking at the least significant bit in a loop may work best, or the flag values may be different enough in meaning that defining constants and doing a direct AND comparison may be the best approach.

I'd stick to a max of 31 bits, though, since maintaining signed/unsigned across languages/databases isn't always reliable (unsigned values aren't always available in the target environment, but 32-bit signed integers are something you can pretty much count on), making the use of the high-order bit a gamble. Misson mentioned that in his post (it's also the primary reason for the guard check and early return on the log2 function he posted in another thread). If you're dealing with a signed data type, a 1 in the most significant bit indicates a negative number, and the mantissa of a negative number is (usually) the two's complement of the positive number. That's another way of saying the numbers get weird and unintuitive (bitwise ops still work but arithmetic ops don't) so it's best to avoid the issue altogether by sticking to the lower 31 bits.
 

descalzo

Grim Squeaker
Community Support
Messages
9,373
Reaction score
326
Points
83
Why the worry over the size? A string of 31 letters, Y and N or T and F doesn't take up that much space.
If all 31 bits are on, your bitset is an integer with 10 places. Stored in a cookie, it takes up 10 characters. If saving 21 characters is of vital importance, fine.

Also, Javascript bitwise manipulation is horribly inefficient. The numbers are stored as floats. If you do bitwise manipulation, the float is converted to a 32 bit integer, the bitwise manipulation is done, and the result is converted back to a float.
 

krunalp4199391

New Member
Messages
74
Reaction score
2
Points
0
Of course, that (a bitset using a bitwise AND to check individual flag values) would be the most compact and elegant way of doing it, but I've had a difficult time trying to explain it to other "developers". (And by that, I mean "professionals" working at the low-hanging-fruit level, like VB/VBS/ASP -- where OR is always bitwise -- Java, and PHP. It's not that the languages make people dumb, but that the bar to entry is set low, so that beginning developers are rarely exposed to binary unless they want to be.) There seems to be some reluctance to believe that multiple flag values based on 2^n won't cause ambiguities when stored in an int/long.

If you understand that 1335 can only happen if the bits representing 1024, 256, 32, 16, 4, 2 and 1 (or 2^10, 2^8, 2^5, 2^4, 2^2, 2^1 and 2^0) are "on" and all others are "off" (since 1335 in binary, as a 4-byte integer, is 00000000 00000000 00000101 00110111) then you can send the equivalent of "show the zeroth, first, second, fourth, fifth, eighth and tenth tabs" from system to system using just the value 1335. Remember to work from right to left -- that way your array indices will correspond exactly with the exponent.

You can build the value to send using either simple addition or a bitwise OR. 0 | 256 results in 256, just as 0 + 256 does. And on the decoding side, 1335 & 256 will result in 256, since the only "true" bit common to both numbers is the one representing 256. The actual implementation I'll leave as an exercise for the reader -- your code may be such that using a zero-fill bitwise right shift and looking at the least significant bit in a loop may work best, or the flag values may be different enough in meaning that defining constants and doing a direct AND comparison may be the best approach.

I'd stick to a max of 31 bits, though, since maintaining signed/unsigned across languages/databases isn't always reliable (unsigned values aren't always available in the target environment, but 32-bit signed integers are something you can pretty much count on), making the use of the high-order bit a gamble. Misson mentioned that in his post (it's also the primary reason for the guard check and early return on the log2 function he posted in another thread). If you're dealing with a signed data type, a 1 in the most significant bit indicates a negative number, and the mantissa of a negative number is (usually) the two's complement of the positive number. That's another way of saying the numbers get weird and unintuitive (bitwise ops still work but arithmetic ops don't) so it's best to avoid the issue altogether by sticking to the lower 31 bits.
Nice info................

Helped me TOO..................

:):):):):):)
 

misson

Community Paragon
Community Support
Messages
2,572
Reaction score
72
Points
48
@descalzo: it's mostly because bitsets are cool.

Point taken about JS's inefficient handling of integer values, though (in practice) it shouldn't be noticeable for the original problem. Since set operations happen so infrequently (only 1 bit would change with each click), the inefficiency won't have a measurable impact on the user's experience.

Another potential inefficiency is that numbers are serialized by default into a base 10 representation, so (e.g.) the bitset 0x7FFFFFFF would be sent as 10 characters. By not relying on JS's standard number-to-string conversion, one could cut this down to 6 using Number.toString(36), which gets you a base 36 encoding (the largest supported by Number.toString and parseInt). Base64 also gets you down to 6 characters. Using all valid cookie-value characters (90 in total), one could represent a bitset in floor(log(0x7FFFFFFF) / log(90)) + 1 = 5 characters.

If JS had mutable strings, one could use strings to store the bit vector (base-N encoded when stored in a cookie), which would do away with the restriction on size and penalties for converting between integers and floating point numbers. An array of characters (such as JS has) could take the place of a mutable string.

Lastly, an array of booleans could be used client-side, serialized as a base-N bit string for transport efficiency.

Code:
/* Simplest bit set implementation, for illustrative purposes.
 * Doesn't enforce 31 element limit
 */
function Bitset31(bits) {
    this.bits = bits || 0;
};

Bitset31.prototype.contains = function(n) {
    return (this.bits >>> n) & 1;
};
Bitset31.prototype.add = function(n) {
    this.bits |= 1 << n;
};
Bitset31.prototype.remove = function(n) {
    this.bits &= ~(1 << n);
};
Bitset31.prototype.invert = function() {
    this.bits = (~this.bits) & 0x7FFFFFFF;
};
Bitset31.prototype.toList = function() {
    var bitlist = [];
    /* Note: an alternative to checking every prospective element
     * would be to adapt floorlg to find the least significant bit and 
     * looping over a copy of the bitset, applying lsb to get the next 
     * element (passing in the previous value as the initial value for the
     * lower bound), then using 'bitset &= bitset-1' to clear it. This will
     * have complexity O(onecount(bitset) * lg(bitset)). If bitsets are
     * likely to be sparse, that would be the better approach. If not, 
     * the current implementation will likely perform better in real life.
     */
    for (var i=0; i < 31; ++i) {
        if (this.contains(i)) {
	    bitlist.push(i);
        }
    }
    return bitlist;
};
Bitset31.prototype.fromList = function(bitlist) {
    this.bits = 0;
    for (var i=0; i < bitlist.length; ++i) {
        this.add(bitlist[i]);
    }
    return this;
}
Bitset31.prototype.toString = function () {
    return Base.encode(this.bits);
};
Bitset31.prototype.fromString = function (data) {
    this.bits = Base.decode(data);
    return this;
};

var tabs = new Bitset31(0xA69),
tabs.toList(); # result: [0, 3, 5, 6, 9, 11]
tabs.add(7);
tabs.remove(6);
tabs.toList(); # result: [0, 3, 5, 7, 9, 11]
Implementation of Base left as an exercise.

As for developers disbelieving that a 32-bit integer can unambiguously store a set containing 31 elements, have them consider how many different sets you can make out of 31 elements (i.e. the number of subsets of a set with 31 elements, or the size of the power set of a 31 element set). Of course, this may require a mini set-theory tutorial, but that can't hurt. For those that disbelieve, it's 2**31, or 2147483648, subsets. Any scheme numbering these subsets will map between exactly one of those subsets and one number; (hopefully) you'll see that this means all the numbered sets can be unambiguously accounted for by a single 32-bit integer, due to a counterpart to the pigeonhole principle (N items can be placed in N boxes such that no two share a box). An arbitrary numbering scheme actually lets subsets of 32 elements be identified unambiguously by a 32-bit integer, though (for the bitset) we don't want an arbitrary scheme, hence the restriction to 31 elements in the design.


That's another way of saying the numbers get weird and unintuitive (bitwise ops still work but arithmetic ops don't) [...]

Reminds me of this jewel from HAKMEM 154:
By this strategy, consider the universe, or, more precisely, algebra:
let X = the sum of many powers of two = ...111111
now add X to itself; X + X = ...111110
thus, 2X = X - 1 so X = -1
therefore algebra is run on a machine (the universe) which is twos-complement.
 
Last edited:
Top