Sharepoint 2010 + SPServices + jQuery Mobile

Here we will setup a SharePoint 2010 page that utilizes both jQuery Mobile as well as the jQuery SPServices library. Note: This post was updated Feb 21 to reflect an issue I’ve documented here with IE8.

Create a new page

Create a new blank .aspx page in the “Site Pages” library (using SharePoint Designer 2010). I like to use a new .aspx page like this because I can create a document from scratch, I don’t have to deal with page layouts, master pages, etc. The same principals can be applied elsewhere, but this gives me a clean page to start from (which is way easier to debug).

Setup your html

Note: I’ve created my document using html5 standards (as does jQuery Mobile).

<!DOCTYPE html>
<html>
<head>
<meta name="WebPartPageExpansion" content="full" />
<title>SharePoint, SPServices, and jQuery Mobile!</title>
	<link rel="apple-touch-icon" href="/Style Library/Images/apple-touch-icon.png"/>
	<meta name="viewport" content="user-scalable=yes, width=device-width, initial-scale=1"> 
	<link rel="stylesheet" href="/Style Library/scripts/jquery.mobile-1.0.1/jquery.mobile-1.0.1.min.css" />
	<script src="/Style Library/scripts/jquery-1.6.4.min.js"></script>
	<script src="/Style Library/scripts/jquery.SPServices-0.7.0.min.js"></script>
<script type="text/javascript">
 //we'll put the SPServices functions here
 //note the placement of this script tag BEFORE the jQuery Mobile javascript link
</script>
	<script src="/Style Library/scripts/jquery.mobile-1.0.1/jquery.mobile-1.0.1.min.js"></script>

<!--[if lt IE 9]>
<script src="/Style Library/scripts/html5.js"></script>
<![endif]-->

</head>
<body>
<!--- we'll put the jQuery Mobile and HTML here --->
</body>
</html>

Create jQuery Mobile layout

Now let’s setup our html within the body tag. We’ll use the standard setup you can find in the jQuery Mobile documentation.

<section id="page1" data-role="page">
 <header data-role="header" data-position="fixed">
  <h1>First Page</h1>
 </header>
  <div data-role="content">
   Here's your first name: <span class="first-name" style="font-weight:bold;"></span><br/>
   <a href="#page2">Click here</a> to see your last name
  </div>
</section>

Here’s our first pagelet. It has an ID of “page1″, and a title of “First page”. If you have everything setup right so far, you should see an image like this:

Now let’s setup page 2. You’ll notice above that we’ve used a link tag with a href=”#page2″. jQuery Mobile takes this and navigates us to “page” 2, even though it is simply another section on the same aspx page. Here’s what you’ll have, and the image follows:

<section id="page2" data-role="page">
 <header data-role="header" data-position="fixed">
  <h1>Second Page</h1>
 </header>
  <div data-role="content">
   Here's your last name: <span class="last-name" style="font-weight:bold;"></span><br/>
   <a href="#page1">Go back</a> to see your first name
  </div>
</section>

Create functions

Now that we’ve created our pages, it’s time to create the functions. We’re going to create two functions. One will call the first name of the user, and one will call the last name. Once it gets the first/last name, it appends the value of that variable to the empty ‘span’ tags we created in the step above. This is a basic example, but you’ll get the point at least.

So the first thing we need to do is create the functions on document ready. But note that we won’t CALL the functions just yet.

First function (to get first name of the logged in user):

function getFirstName() {
  firstname = $().SPServices.SPGetCurrentUser({fieldName: "FirstName"})
  $(".first-name").append(firstname);
}	

Second function (to get last name of the logged in user):

function getLastName() {
  lastname = $().SPServices.SPGetCurrentUser({fieldName: "LastName"})
  $(".last-name").append(lastname);
}

Call functions on page change

Right now these two functions are just sitting in the script tag, but we want to call them. You can do one of two things:

  1. call the functions right away
  2. call whenever the new pagelet loads

Because of the functions I am calling in one of my other projects, I’ve decided to call the function each time each pagelet loads. That means that even though jQuery Mobile loads the new pagelet without reloading the url, my data will still load in asynchronously. So when we click on “click here to see your last name”, it will then call the function when that pagelet comes into view.

The other way is fine as well, it just means that while you are using your new web app, the data only loads when the document is ready. This means if data changes while you are navigating, you won’t see the change until you refresh the page.

Note: If you call the functions each time the page is loaded, your script must remain above the jquery mobile js reference (see step 2). This because you need to tweak the DOM before jQuery Mobile applies its classes and functionality to the page.

So onto the code! We’re going to use the jQuery function “on” and pass the event “pagecreate”. Like I mentioned above, this means the function will only run when the page is created (every time).

$("section#page1").live("pagecreate", function(event){
  getFirstName();
});
$("section#page2").live("pagecreate", function(event){
  getLastName();
});

Now you should see the following when you load each page:

Full Code

And for your copying and pasting pleasure, here’s the full code!

<!DOCTYPE html>
<html>
<head>
<meta name="WebPartPageExpansion" content="full" />
<title>SharePoint, SPServices, and jQuery Mobile!</title>
	<link rel="apple-touch-icon" href="/Style Library/Images/apple-touch-icon.jpg"/>
	<meta name="viewport" content="user-scalable=yes, width=device-width, initial-scale=1"> 
	<link rel="stylesheet" href="/Style Library/scripts/jquery.mobile-1.0.1/jquery.mobile-1.0.1.min.css" />
	<script src="/Style Library/scripts/jquery-1.6.4.min.js"></script>
	<script src="/Style Library/scripts/jquery.SPServices-0.7.0.min.js"></script>

<!--[if lt IE 9]>
<script src="/Style Library/scripts/html5.js"></script>
<![endif]-->

	<script type="text/javascript">
		$(document).ready(function(){
			
function getFirstName() {
	firstname = $().SPServices.SPGetCurrentUser({fieldName: "FirstName"})
	$(".first-name").append(firstname);
}		
function getLastName() {
	lastname = $().SPServices.SPGetCurrentUser({fieldName: "LastName"})
	$(".last-name").append(lastname);
}
			
$("section#page1").live("pagecreate", function(event){
  getFirstName();
});
$("section#page2").live("pagecreate", function(event){
  getLastName();
});		})
	</script>
	<script src="/Style Library/scripts/jquery.mobile-1.0.1/jquery.mobile-1.0.1.min.js"></script>
</head>
<body>

<section id="page1" data-role="page">
 <header data-role="header" data-position="fixed">
  <h1>First Page</h1>
 </header>
  <div data-role="content">
   Here's your first name: <span class="first-name" style="font-weight:bold;"></span><br/>
   <a href="#page2">Click here</a> to see your last name
  </div>
</section>

<section id="page2" data-role="page">
 <header data-role="header" data-position="fixed">
  <h1>Second Page</h1>
 </header>
  <div data-role="content">
   Here's your last name: <span class="last-name" style="font-weight:bold;"></span><br/>
   <a href="#page1">Go back</a> to see your first name
  </div>
</section>

</body>

</html>

Enjoy!

Ben

jQuery and SharePoint 2010: the Basics

SharePoint out-of-the-box is functional, but fairly lacking when it comes to really wanting to extract and beautify your data. This is where jQuery comes in. It’s light, easy to implement, and actually hooks up with a bunch of SharePoint services when you have the right plugins. Consider this a basic intro to what you can do in jQuery and SharePoint. It’s really the tip of the iceberg, so keep exploring!

Setup jQuery for SharePoint

First things first, let’s make sure we’re properly setup. If you are using SharePoint behind a secure server (as part of an intranet possibly), then you’ll probably want to load up a local copy of the jQuery script instead of grabbing it from jquery.com each time the page loads. So grab the latest build from jquery.com and dump it in “Style Library/scripts/jquery.js”.

Next, go to your master page and put the following script (depending on where your file is) anywhere within the HEAD section:

 <script type="text/javascript" src="/Style Library/scripts/jquery.js"></script>

And that’s it! Now every time a page loads, you’re pulling in all of jQuery’s power. Minified, the file is only about 31kb, so (considering everything else SharePoint is loading) this isn’t that much of a burden. But you can also just load the jQuery script in page layouts, or even within individual pages.

Now that you’ve got jQuery loaded, it might be in your best interest to create another .js file that holds all of your custom scripts. You can choose to do scripts on a per page or page layout basis as well, but this keeps things more organized. So create a “myscripts.js” file in “Style Library/scripts” (the same folder we put jQuery.js in). And don’t forget to reference it in your master page, right under the jquery code. So now the above code is amended to read:

 <script type="text/javascript" src="/Style Library/scripts/jquery.js"></script>
 <script type="text/javascript" src="/Style Library/scripts/myscripts.js"></script>

Now that we’ve got everything loaded, what can we do?

What can you do with jQuery and SharePoint?

Here are just a few things:

Markup your body content and make it interactive

I use this for something like an FAQ section. We’ll put every question in an H4 tag with a class of “question” and every answer in a span with a class of “answer” directly after the h4. That’s all we have to do to our HTML source in the page. Then in our custom scripts file (above) we add the following jQuery code:

$(document).ready(function(){ 
 $("span.answer").slideUp(); // hides all of the answers
 $("h4.question").click(function(){ // when you click an h4
   $(this).next("span.answer").slideToggle('fast') //the answer slides down
 })
});

Keep in mind you may want to add some CSS that make the h4 seem more like a link (cursor:pointer, etc.) so people know they should click.

Make an “instant” search/filter box


Check out this post about how to create this. You can create a filter, and then append it to any list across your site.

Create a slideshow of content from a picture library


I’ve written a separate post with precise instructions about how to do this, but here’s the general idea:

  1. Create a picture library
  2. Make a new page
  3. Put a CQWP in the page, and wrap it in some divs with specific classes
  4. Use the tinycarousel plugin to convert that Content Query WebPart into a slideshow/carousel
  5. Style with CSS

Create tabs (not the jQuery UI kind)

Check out this post on creating tabs using jQuery, but without using the jQuery UI. It’s a bit easier with the UI plugin, but again, the idea is:

  1. Create the tabs in HTML
  2. Create each panel in HTML
  3. Add the jQuery
  4. Style it with CSS

Use SPServices to really hook into SharePoint with jQuery

I’ve started writing what is turning into a small series on using jQuery with SPServices. Some of the things you can do:
Rollup items from multiple lists
Rollup from multiple lists and put the results in a new list
Rollup articles across a site collection

Full-Width Page Layout in Sharepoint 2010

Page Layout without the sidebar (Sharepoint 2010)

In order to create a full-width (whatever the width of your container is) page layout in Sharepoint 2010, you’ll want to disable the sidebar. I find this useful for things like calendars and big lists. Because my design is only 960px wide, I find that by the time you add the sidebar in, you’re left with only around 750px of usable space. For a calendar or a big list, it’s just kind of annoying.

So here’s how it’s done:

Create a new page layout in Sharepoint Designer. Add a new control like this:

<asp:Content ContentPlaceholderID="PlaceHolderLeftNavBar" runat="server" />

By declaring an empty control, we tell Sharepoint to ignore that control and not fill it with anything.

Don’t forget to add a bit of CSS in the header to expand your main body panel to the full width.

Simple as that!

note: use this technique to hide other items on the page layout (top navigation, footer, sky’s the limit)

2-Column Page Layout in Sharepoint 2010

You need a two-column page layout for your Sharepoint project. I’ll show you how to do this with and without the sidebar (quick launch) being active.

Step 1: Create a new page layout
I use Sharepoint Designer for this. I’m not even sure it’s possible using anything else.

Step 2: Setup your basic layout in HTML
You can use tables or divs, but in the spirit of the future, let’s use divs.

<div></div>
<div></div>
<br style="clear:both;" />

Step 3: Fill your divs
Inside these divs you can place webpart zones, page fields, or your own code (maybe a specific header for each column?). Whatever you want to do.

Step 4 (optional): Hide the sidebar/quicklaunch
Declare this control anywhere not the page, but leave it empty so nothing will load into it:

<asp:Content ContentPlaceholderID="PlaceHolderLeftNavBar" runat="server" />

Don’t forget to add a bit of CSS in the header to expand your main body panel to the full width.

Step 5: Style the divs so they appear next to each other.
Using CSS we can make sure those divs appear next to each other.

.col-left,
.col-right {
    width:400px; /*obviously…play with the width to match your setup*/
    float:left;
}

The <br/> tag above should break after the floated elements so everything remains normal in your page layout.

Master Pages vs. Page Layouts in Sharepoint 2010

For those new to Sharepoint, specifically Sharepoint 2010, here is a primer on the difference between page layouts and master pages.

Master Pages
A master page is what I would normally call something like a template. It holds all of Sharepoint’s necessary elements. It creates containers for your information to load into later. It sets the document structure. An analogy would be an empty bookcase. It’s created a bunch of holding places for different elements. You’ll use some of these elements, and Sharepoint will use the rest. So it’s VERY important to not remove elements in this page unless you really know what you’re doing. You might not need the item, but Sharepoint might need it to run the page correctly.

What Master Pages are used for:

  • Calling CSS files
  • Installing javascript & other scripts
  • Tracking codes (I put my Google Analytics code here)
  • Setting top navigation & sidebar functionality
  • Things that occur on EVERY page.

What Master Pages are not used for:

  • Controlling page-level design and structure
  • Webparts and Webpartzones (you can…but I wouldn’t)
  • Anything that DOESN”T occur on EVERY page

Page Layouts
In a page layout, you are essentially telling Sharepoint what it should fill all those empty bookshelves with.You declare a control (a certain shelf), and then tell Sharpeoint what goes inside. You can’t go beyond the reaches of the master pages. Whatever controls are on the master page are the controls you can use in a page layout.

What Page Layouts are used for:

  • Creating the layout of the pages (within the bounds of the master page)
  • Controlling page-level design elements.
  • Including page-level css files to override master page styles
  • Inserting Webparts and Webpartzones
  • Including custom codes (javascript, etc.)
  • Things that occur only on this page layout, not site-wide

What Page Layouts are not used for:

  • Content. This is not the place to write and display content. You’ll create a page to do that. This is merely to provide the placeholders to do that.
  • Applying CSS styles that could be applied at a higher level. You want to keep the management of things like CSS as centralized and high as possible.

A few extra tips:

  • You should never need more than 1 master page (unless for some reason you decide you want a different “admin” and “front-end” master page.
  • Page layouts should be used sparingly. It can get a bit out of control, so consider what you need and make some generic templates using page layouts that will work for many kinds of pages.
  • Don’t put too much extra CSS, javascript, or custom code in page layouts. It can be an enormous task to figure out where a style or a piece of code is coming from if you have master page-level stylesheets, page layout-level stylesheets, and even possibly page-level stylesheets (in a CEWP or something). Try to centralize and simplify.