Page 1 of 2 12 LastLast
Results 1 to 10 of 11

Thread: Adding cookie "remember" to this Javascript

  1. #1
    Join Date
    Sep 2011
    Posts
    14
    Thanks
    3
    Thanked 0 Times in 0 Posts

    Default Adding cookie "remember" to this Javascript

    Okay, my javascript knowledge is slim at best so I'm wondering if someone would be so kind as to take a look at this:

    Code:
    function HideContent(d) {
    document.getElementById(d).style.display = "none";
    }
    function ShowContent(d) {
    document.getElementById(d).style.display = "block";
    }
    function ReverseDisplay(d) {
    if(document.getElementById(d).style.display == "none") { document.getElementById(d).style.display = "block"; }
    else { document.getElementById(d).style.display = "none"; }
    }
    As you can see it's just a simple show/hide DIV script and it's toggled on and off with:

    Code:
    <a href="javascript:ReverseDisplay('uniqueid)">Toggle On/Off</a>
    I'm wondering if someone could show me how to add a cookie mechanism to this so that it will remember if the person had it set to on or off on a page reload or another visit. Probably remember indefinitely or a year; as the person can simply toggle it again to destroy the cookie if they change their mind.

    I really hope this makes sense because at this late hour, I may not be articulating my predicament very well.

    Thanks in advance for any help/comments!!

  2. #2
    Join Date
    Mar 2005
    Location
    SE PA USA
    Posts
    30,495
    Thanks
    82
    Thanked 3,449 Times in 3,410 Posts
    Blog Entries
    12

    Default

    A cookie is text data. So you can store the id(s) and/or display state(s) of your element(s) in one or more cookies. To figure out the most efficient method we need to know how many elements on the page could be toggled, and what their default (hard coded) display state(s) are, and if there's any unifying selector or parent element for them. But something very generic and less efficient can be written.

    Ready made functions to set and read cookies will come in handy. Other cookie functions might also be useful. There are at least several such functions already available around the web. here are mine:

    http://www.dynamicdrive.com/forums/blog.php?b=32

    Also it's good to know that all browsers that accept cookies will run a function onunload if there is one to set them. All but Opera. And that the onunload function is required for efficiency in some browsers. So we have to branch for Opera. Or ignore it.

    So we could have:

    Code:
    <!DOCTYPE html>
    <html>
    <head>
    <title></title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    
    </head>
    <body>
    <div id="one">One</div>
    <div id="two">Two</div>
    <a href="javascript:ReverseDisplay('one')">Toggle One On/Off</a> 
    <a href="javascript:ReverseDisplay('two')">Toggle Two On/Off</a>
    <script type="text/javascript">
    function HideContent(d) {
    document.getElementById(d).style.display = "none";
    cook.els[d] = 'none';
    if(window.opera){cook.gather();}
    }
    function ShowContent(d) {
    document.getElementById(d).style.display = "block";
    cook.els[d] = 'block';
    if(window.opera){cook.gather();}
    }
    function ReverseDisplay(d) {
    if(document.getElementById(d).style.display == "none") { document.getElementById(d).style.display = "block"; cook.els[d] = 'block'; }
    else { document.getElementById(d).style.display = "none"; cook.els[d] = 'none'; }
    if(window.opera){cook.gather();}
    }
    
    var cook = {
    	set: function(n, v, d){ // cook.set takes (name, value, optional_persist_days) - defaults to session if no days specified
    		if(d){var dt = new Date(); 
    			dt.setDate(dt.getDate() + d);
    		d = '; expires=' + dt.toGMTString();}
    		document.cookie = n + '=' + escape(v) + (d || '') + '; path=/';
    	},
    	get: function(n){ // cook.get takes (name)
    		var c = document.cookie.match('(^|;)\x20*' + n + '=([^;]*)');
    		return c? unescape(c[2]) : null;
    	},
    	kill: function(n){ // cook.kill takes (name)
    		cook.set(n, '', -1);
    	},
    	killall: function(){ // cook.killall takes no parameters
    		var cookies = document.cookie.split(';'), i = cookies.length - 1;
    		for (i; i > -1; --i){
    			cook.kill(cookies[i].split('=')[0]);
    		}
    	},
    	els: {},
    	gather: function(){
    		var ar = [], p;
    		for(p in cook.els){
    			ar.push(p + ':' + cook.els[p]);
    		}
    		if(ar.length){
    			cook.set('the_elements', ar.join(','));
    		}
    	}
    };
    
    if(!window.opera){onunload = cook.gather;}
    
    ;(function(){
    	var str = cook.get('the_elements'), ar = [], el, the_el;
    	if(str){
    		ar = str.split(',');
    		for (var i = ar.length - 1; i > -1; --i){
    			el = ar[i].split(':');
    			if((the_el = document.getElementById(el[0]))){
    				the_el.style.display = el[1];
    				cook.els[el[0]] = el[1];
    			}
    		}
    	}
    })();
    </script>
    </body>
    </html>
    There are a number of things I don't like about that code, still not perfect, but getting better:

    Code:
    <!DOCTYPE html>
    <html>
    <head>
    <title></title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    
    </head>
    <body>
    <div><a href="javascript:ReverseDisplay('one');">Toggle One On/Off</a></div>
    <div id="one">One</div>
    <div><a href="javascript:ReverseDisplay('two');">Toggle Two On/Off</a></div>
    <div id="two">Two</div>
    <script type="text/javascript">
    ;(function(){
    	var displayers = {
    		HideContent: function(d) {
    			document.getElementById(d).style.display = "none";
    			cook.els[d] = 'none';
    			if(window.opera){cook.gather();}
    		},
    		ShowContent: function(d) {
    			document.getElementById(d).style.display = "block";
    			cook.els[d] = 'block';
    			if(window.opera){cook.gather();}
    		},
    		ReverseDisplay: function(d) {
    			if(document.getElementById(d).style.display == "none") { document.getElementById(d).style.display = "block"; cook.els[d] = 'block'; }
    			else { document.getElementById(d).style.display = "none"; cook.els[d] = 'none'; }
    			if(window.opera){cook.gather();}
    		}
    	};
    
    	var cook = {
    		set: function(n, v, d){ // cook.set takes (name, value, optional_persist_days) - defaults to session if no days specified
    			if(d){var dt = new Date(); 
    				dt.setDate(dt.getDate() + d);
    			d = '; expires=' + dt.toGMTString();}
    			document.cookie = n + '=' + escape(v) + (d || '') + '; path=/';
    		},
    		get: function(n){ // cook.get takes (name)
    			var c = document.cookie.match('(^|;)\x20*' + n + '=([^;]*)');
    			return c? unescape(c[2]) : null;
    		},
    		kill: function(n){ // cook.kill takes (name)
    			cook.set(n, '', -1);
    		},
    		killall: function(){ // cook.killall takes no parameters
    			var cookies = document.cookie.split(';'), i = cookies.length - 1;
    			for (i; i > -1; --i){
    				cook.kill(cookies[i].split('=')[0]);
    			}
    		},
    		els: {},
    		gather: function(){
    			var ar = [], p;
    			for(p in cook.els){
    				ar.push(p + ':' + cook.els[p]);
    			}
    			if(ar.length){
    				cook.set('the_elements', ar.join(','));
    			}
    		},
    		addEvent: (function(){return window.addEventListener? function(el, ev, f){
    				el.addEventListener(ev, f, false);
    			}:window.attachEvent? function(el, ev, f){
    				el.attachEvent('on' + ev, f);
    			}:function(){return;};
    		})()
    	};
    
    	if(!window.opera){cook.addEvent(window, 'unload', cook.gather);}
    
    	var a = document.getElementsByTagName('a'), re = /(ShowContent|HideContent|ReverseDisplay)\('(.+)'\)/, func, i;
    	for (i = a.length - 1; i > -1; --i){
    		if((func = re.exec(a[i].href))){
    			(function(el, func){
    				cook.addEvent(el, 'click', function(e){
    					e = e || event;
    					if(e.preventDefault){e.preventDefault();}
    					e.returnValue = false;
    					displayers[func[1]](func[2]);
    					return false;
    				});
    			})(a[i], func);
    		}
    	}
    
    	var str = cook.get('the_elements'), ar = [], el, the_el;
    	if(str){
    		ar = str.split(',');
    		for (i = ar.length - 1; i > -1; --i){
    			el = ar[i].split(':');
    			if((the_el = document.getElementById(el[0]))){
    				the_el.style.display = el[1];
    				cook.els[el[0]] = el[1];
    			}
    		}
    	}
    })();
    </script>
    </body>
    </html>
    Last edited by jscheuer1; 10-03-2011 at 08:53 AM. Reason: add alternate
    - John
    ________________________

    Show Additional Thanks: International Rescue Committee - Donate or: The Ocean Conservancy - Donate or: PayPal - Donate

  3. The Following User Says Thank You to jscheuer1 For This Useful Post:

    Sartavius (10-03-2011)

  4. #3
    Join Date
    Sep 2011
    Posts
    14
    Thanks
    3
    Thanked 0 Times in 0 Posts

    Default

    Oddly enough, by using your second example of code it works fine when I C/P it straight out and test it.

    But when I paste it into my own setup it doesn't work and the Firefox error console gives me the old "Error: ReverseDisplay is not defined Source File: javascript:ReverseDisplay('one');"

    I'm stumped.

  5. #4
    Join Date
    Mar 2005
    Location
    SE PA USA
    Posts
    30,495
    Thanks
    82
    Thanked 3,449 Times in 3,410 Posts
    Blog Entries
    12

    Default

    Paste it in or link to it.
    - John
    ________________________

    Show Additional Thanks: International Rescue Committee - Donate or: The Ocean Conservancy - Donate or: PayPal - Donate

  6. #5
    Join Date
    Sep 2011
    Posts
    14
    Thanks
    3
    Thanked 0 Times in 0 Posts

    Default

    I think I've figured out the problem, but now I can't seem to set the expiration in your cookie function. It defaults to session if not set as you said, but WHERE in that code do you specify a number of days? lol

  7. #6
    Join Date
    Mar 2005
    Location
    SE PA USA
    Posts
    30,495
    Thanks
    82
    Thanked 3,449 Times in 3,410 Posts
    Blog Entries
    12

    Default

    Find this function in the code:

    Code:
    		gather: function(){
    			var ar = [], p;
    			for(p in cook.els){
    				ar.push(p + ':' + cook.els[p]);
    			}
    			if(ar.length){
    				cook.set('the_elements', ar.join(','));
    			}
    		},

    For one day persistence:

    Code:
    cook.set('the_elements', ar.join(','), 1);
    For one year:

    Code:
    cook.set('the_elements', ar.join(','), 365);
    Or to be able to set it at the beginning of the code:

    Code:
    cook.set('the_elements', ar.join(','), persist);
    And at the beginning:

    Code:
    ;(function(){
    	var persist = 10; //set persistence in days (unquoted integer), or use '' (empty string) for session only
    	var displayers = {
    		HideContent: function(d) {
    			document.getElementById(d).style.display = "none";
    			cook.els[d] = 'none';
    			if(window. . . .
    - John
    ________________________

    Show Additional Thanks: International Rescue Committee - Donate or: The Ocean Conservancy - Donate or: PayPal - Donate

  8. #7
    Join Date
    Sep 2011
    Posts
    14
    Thanks
    3
    Thanked 0 Times in 0 Posts

    Default

    Thanks for all the help! I'm thinking this might not be the route to go though after some playing. You see, I populate the name of the div (the one to be toggled on or off) with the php variable of the persons chat nickname. The problem is that the toggle on/off works fine and a cookie is stored but when I refresh the page (with a php function that receives new messages), it isn't remembering what I wanted to be toggled off for some reason.

    Plus I'm thinking this method won't work because a cookie would have to be set for EACH nickname that another chatter might want to ignore. So if chatter A wanted to ignore chatters Bob, Sally and Frank...I think this method will only store one cookie and each subsequent person they wanted to ignore would just overwrite the prior cookie.

    I suppose I will just have to go back to the drawing board and figure out a method to do this with PHP. Oh cruel world! hahaha.

  9. #8
    Join Date
    Sep 2011
    Posts
    14
    Thanks
    3
    Thanked 0 Times in 0 Posts

    Default

    And on a side note, I love your cookie functions! Now that I understand how they're working it beats the heck out of most of the other ways I've seen to deal with cookies in Javascript. You're a true master!

  10. #9
    Join Date
    Mar 2005
    Location
    SE PA USA
    Posts
    30,495
    Thanks
    82
    Thanked 3,449 Times in 3,410 Posts
    Blog Entries
    12

    Default

    Quote Originally Posted by Sartavius View Post
    I populate the name of the div (the one to be toggled on or off) with the php variable of the persons chat nickname. The problem is that the toggle on/off works fine and a cookie is stored but when I refresh the page (with a php function that receives new messages), it isn't remembering what I wanted to be toggled off for some reason.
    This code doesn't work off of the name of the div. It works off of the id of the div. So - say you're PHP code is making something like:

    Code:
    <div name="Bob">whatever</div>
    have it make instead:

    Code:
    <div name="Bob" id="Bob">whatever</div>
    Quote Originally Posted by Sartavius View Post
    Plus I'm thinking this method won't work because a cookie would have to be set for EACH nickname that another chatter might want to ignore. So if chatter A wanted to ignore chatters Bob, Sally and Frank...I think this method will only store one cookie and each subsequent person they wanted to ignore would just overwrite the prior cookie.
    It does make only one cookie, but that one cookie contains the id's and display states of all div's that were changed. And each time the page reloads, those stored preferences are added to the object that the cookie for next time will be made from. Unless changed, they will persist. If changed and only if changed, will the updated display state be used. Nothing is lost.

    If you have this up live somewhere for testing, I'd be happy to have a look.

    Oh and thanks for the vote of confidence on the cookie unit.
    Last edited by jscheuer1; 10-04-2011 at 03:47 PM. Reason: add - If you have this up live som . . .
    - John
    ________________________

    Show Additional Thanks: International Rescue Committee - Donate or: The Ocean Conservancy - Donate or: PayPal - Donate

  11. #10
    Join Date
    Sep 2011
    Posts
    14
    Thanks
    3
    Thanked 0 Times in 0 Posts

    Default

    Quote Originally Posted by jscheuer1 View Post
    If you have this up live somewhere for testing, I'd be happy to have a look.

    Oh and thanks for the vote of confidence on the cookie unit.
    That'd be great before I give up on this option entirely! I'll PM you the info you'll need to access the testing area.

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •