1,804 articles and 14,766 comments as of Tuesday, April 19th, 2011

EndUserSharePoint has combined resources with NothingButSharePoint.com. You can now find End User (Mark Miller), Developer (Jeremy Thake) and IT Pro SharePoint (Joel Oleson) content all in one place!

This site is a historical archive and is no longer being updated. Please update your favorites, bookmarks and RSS feeds.

NothingButSharePoint.com
Wednesday, April 8, 2009

JQuery for Everyone: Cookies and Plugins

JQuery plugin patterns are great. The recommended pattern allows for an options object to pass into the methods during invocation with a bunch of defaults to make options, well, optional.

But options don’t play well with cookies. In this article, I’ll tell you a little about why options are great, why you might want to store them in a cookie, and how to do that using SharePoint’s built-in functions.

Building Options with $.extend()

One jQuery utility in particular makes this simple to build. The $.extend() function allows you to merge multiple objects. Let’s say we’re making a cool new jQuery method to color-code SharePoint calendar items. We’ll start with a template like this:

<script type="text/javascript">
(function(){
	jQuery.fn.colorCal = function(options){
		//do something
	}
})();
</script>

We’re telling the browser we want to add a method to the jQuery object using prototype (we’re using the .fn notation as an alias but it means the same thing).

Try this: Open Firebug to a page with jQuery on it (or use the jQueryify bookmarklet). Type “jQuery” into your console window. What was returned? Now type jQuery(). Did you see a difference?

To make use of options (or to just leave a placeholder for future functionality) we add this:

<script type="text/javascript">
(function(){
	var defaults = {
			'background-color': 'red'
	};
	jQuery.fn.colorCal = function(options){
		opts = $.extend({},defaults,options);
		//do something with opts
	}
})();
</script>

We created a new variable called defaults. Since it’s inside our closure, only colorCal() will have access to it. We then create the variable opts which combines (in order) an empty set, defaults, and any options. The order is important since later parameters with the same name will overwrite the previous ones.

Try this: Open Firebug on a page with jQuery loaded. Create a global object by typing: myObj = {test: “1″} and clicking Run. Call your object with myObj, myObj.test, and myObj['test']. Now extend your object with this: $.extend({test:”2″},myObj,{test:”3″, anothertest:”1″}) and click Run. Try to call your object again, what happened to the value of the test parameter?

Using Options

To actually make this work, and understand how options make things awesome, let’s put some code in the function where it says “do something.”

<script type="text/javascript">
(function(){
	var defaults = {
			'background-color': 'red'
	};
	jQuery.fn.colorCal = function(options){
		opts = $.extend({},defaults,options);
		this.each(function(i,e){ //using this
			$(e).css(opts); //using e, a single object in this
			console.log(stringObj(opts));
		});
	};
})();
</script>

If you recall from the previous article, this refers to the objects collected by the $() function. There could be one or more than one DOM object in that array, so we use the .each() method to iterate over them doing something–in this case, applying the opts parameter to the element’s CSS.

Note: You can run that function in your Firebug console without the script tags. Remember when setting parameters in object notation, if the parameter has a character like “-” you have to put the parameter in quotes.

Try this: Put the above function on a default Calendar view (monthly) page with jQuery using a CEWP or run everything from Firebug. Now start using your custom method: $(”td.ms-cal-noworkitem”).colorCal(); Did anything change? Try these commands next: $(”td.ms-cal-noworkitem”).colorCal({’background-color’:'black’}); $(”td.ms-cal-topday”).colorCal({’text-align’:'center’}); Did you guess what was going to happen before it happened?

Saving Options With Cookies

Ok, let’s pretend that someone uses this method to create some links on a Calendar to highlight specific days of the month. If you drill down into the day view then come back to the month view, the links must be clicked again. Users might expect their preferences to be stored (at least for the current browser session).

The challenge is that cookies only store strings, not objects. So we need to add a function to our solution that can do that for us.

<script type="text/javascript">
(function(){
	var stringObj = function(obj){
		var str = "{";
		var len=0;
		for (var name in obj){
			if (obj.hasOwnProperty(name)){
				len++;
				str += (len>1)?',':"";
				str += name+':"'+ obj[name]+'"';
			}
		}
		str += "}";
		return(str);
	},
	defaults = {
			'background-color': 'red'
	};
	jQuery.fn.colorCal = function(options){
		opts = $.extend({},defaults,options);
		console.log(stringObj(opts)); //watch the options come back as a string
		this.each(function(i,e){
			$(e).css(opts);
		});
	};
})();
</script>

Try This: the stringObj() function is a private variable. Open Firebug console and try to call it with stringObj or stringObj() and click Run. Type $() and click Run. Find colorCal in the list of methods, do you see stringObj() there?

We can make use of the built-in SharePoint function, SetCookie() to create a cookie for the current session. But there’s a trap, the equal sign. When the browser sees “=” in a cookie string, it thinks you’re done with the string. So, we need to use a RegEx replace to swap = for something else. I use ~ but you can use whatever, just be consistent because you will need to decode it when you read the cookie. I tried using other entity references but the parser always saw an “=” underneath and broke my cookies.

SetCookie("cookie_name",stringObj(o).replace(/\=/g,"~"), "/");

Note: for help on regular expressions, I recommend the RegExr adobe AIR app.

When we want to retrieve our cookie (like on the document.ready event) we use something like this:

var g = GetCookie("cookie_name");

Only, now we have to convert that string into an object. Here’s where you may digress into factions. I use eval(). Per the JavaScript authorities on this planet, eval() is evil. There are other parsers to convert strings into object literals (mainly because of JSON). But I’d rather use the eval() shortcut as I think the risks to browser security in this situation are very low.

...
	getOptions = function(str){
		if (str.indexOf("{")===0){
			return eval('('+str+')');
		}
	},
...

getOptions, another private variable, will make sure the first character is a curly brace then try to evaluate the string, which converts a string in object notation into an object.

To call our custom method with the cookie’s options we have do something like:

getOptions(g.replace(/\~/g,"=").replace(/([^,|"|'])\s/g,"$1%20"));

The second .replace() method is for yet another trap. Sometimes, when converting things like URLs, whitespace is preserved when you want to use it as %20. This expression only allows whitespace at the beginning of a value segment to remain.

Paul Grenier

View all entries in this series: PaulGrenier-JQuery for Everyone»
Entries in this series:
  1. JQuery for Everyone: Accordion Left Nav
  2. JQuery for Everyone: Print (Any) Web Part
  3. JQuery for Everyone: HTML Calculated Column
  4. JQuery for Everyone: Dressing-up Links Pt1
  5. JQuery for Everyone: Dressing-up Links Pt2
  6. JQuery for Everyone: Dressing-up Links Pt3
  7. JQuery for Everyone: Cleaning Windows Pt1
  8. JQuery for Everyone: Cleaning Windows Pt2
  9. JQuery for Everyone: Fixing the Gantt View
  10. JQuery for Everyone: Dynamically Sizing Excel Web Parts
  11. JQuery for Everyone: Manually Resizing Web Parts
  12. JQuery for Everyone: Total Calculated Columns
  13. JQuery for Everyone: Total of Time Differences
  14. JQuery for Everyone: Fixing Configured Web Part Height
  15. JQuery for Everyone: Expand/Collapse All Groups
  16. JQuery for Everyone: Preview Pane for Multiple Lists
  17. JQuery for Everyone: Preview Pane for Calendar View
  18. JQuery for Everyone: Degrading Dynamic Script Loader
  19. JQuery for Everyone: Force Checkout
  20. JQuery for Everyone: Replacing [Today]
  21. JQuery for Everyone: Whether They Want It Or Not
  22. JQuery for Everyone: Linking the Attachment Icon
  23. JQuery for Everyone: Aspect-Oriented Programming with jQuery
  24. JQuery for Everyone: AOP in Action - loadTip Gone Wild
  25. JQuery for Everyone: Wiki Outbound Links
  26. JQuery for Everyone: Collapse Text in List View
  27. JQuery for Everyone: AOP in Action - Clone List Header
  28. JQuery for Everyone: $.grep and calcHTML Revisited
  29. JQuery for Everyone: Evolution of the Preview
  30. JQuery for Everyone: Create a Client-Side Object Model
  31. JQuery for Everyone: Print (Any) Web Part(s) Plugin
  32. JQuery for Everyone: Minimal AOP and Elegant Modularity
  33. JQuery for Everyone: Cookies and Plugins
  34. JQuery for Everyone: Live Events vs. AOP
  35. JQuery for Everyone: Live Preview Pane
  36. JQuery for Everyone: Pre-populate Form Fields
  37. JQuery for Everyone: Get XML List Data with OWSSVR.DLL (RPC)
  38. Use Firebug in IE
  39. JQuery for Everyone: Extending OWS API for Calculated Columns
  40. JQuery for Everyone: Accordion Left-nav with Cookies Speed Test
  41. JQuery for Everyone: Email a List of People with OWS
  42. JQuery for Everyone: Faster than Document.Ready
  43. jQuery for Everyone: Collapse or Prepopulate Form Fields
  44. jQuery for Everyone: Hourly Summary Web Part
  45. jQuery for Everyone: "Read More..." On a Blog Site
  46. jQuery for Everyone: Slick Speed Test
  47. jQuery for Everyone: The SharePoint Game Changer
  48. JQuery For Everyone: Live LoadTip
 

Please Join the Discussion

One Response to “JQuery for Everyone: Cookies and Plugins”

Trackbacks

Check out what others are saying about this post...
  1. SharePoint Daily for April 9, 2009…

    Top News Stories Bring On The Open Source Alternatives To SharePoint (Redmond Developer News) It seems…




Notify me of comments to this article:


Speak and you will be heard.

We check comments hourly.
If you want a pic to show with your comment, go get a gravatar!