A jQuery Primer for SharePoint: Selectors, Attributes, and Traversing – Oh My!

This entry is part 2 of 4 in the series A jQuery Primer for SharePoint

Welcome back to “a jQuery Primer for SharePoint” here on SharePoint Magazine. It’s time to take a closer look at some examples of using jQuery to locate the correct elements in an HTML page.

So what can you do with jQuery in a SharePoint context? I touched upon some of the general things that you can do in my last article, but in this one I thought I’d start to go through the main categories of functionality jQuery gives you, explain what they are, and give you some simple examples to show why they can be useful.

The jQuery site breaks jQuery’s functionality into some really nice buckets:

  • jQuery Core
  • Selectors
  • Attributes
  • Traversing
  • Manipulation
  • CSS
  • Events
  • Effects
  • Ajax
  • Utilities
  • jQuery UI

I find that this breakdown makes it relatively straightforward to think about jQuery, though it may seem a bit mystical to you until you can internalize the groupings.

In this article, we will look at three of the first four of these, selectors, attributes, and traversing. The jQuery Core is sort of an anachronism, harking back to the time when it was a separate component. Generally speaking, you don’t need to think about the jQuery Core, as it is what gives you the jQuery and $ capabilities.

Selectors

I think that about half the battle with learning jQuery is getting the idea behind selectors.

Here’s how I think about it: everything in the Document Object Model (DOM) that is sent from the server to the browser is data. The DOM happens to be a type of data called HTML, which is a special flavor of XML.

If you’re starting from scratch, HTML looks something like this:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Untitled 1</title>
</head>
<body>
  <div id="helloDiv">
    Hello, world!
  </div>
</body>
</html>

This is the simplest HTML page you can create in SharePoint Designer 2007 by choosing File / New / HTML with the exception that I’ve added one div element with the “Hello, world!” text into the body section. It’s such a simple page that you may not even see any value in it, but bear with me as we move forward, using this page as the basis for the examples.

A very simple selector for this page would look like this:

$("#helloDiv")

This selector will return an object which represents the div surrounding the “Hello, world!” text.

If you’re familiar with Cascading Style Sheets (CSS), then you’ll know that the pound sign (#) means “something with this id”. So what we are doing in the selector is saying: find me something that has an id equal to “helloDiv”. Ids are simply a way to attach a name to an HTML element so that you can refer to it more easily. Generally, in well-formed HTML, ids are unique within the DOM.

Here’s a real example from a WSS 3.0 page. This is the part at the top of the Quick Launch where you see the “View All Site Content” link.

<DIV class="ms-quicklaunchheader">
<A accessKey=3 id=ctl00_PlaceHolderLeftNavBar_idNavLinkViewAll href="/_layouts/viewlsts.aspx">
View All Site Content
</A>
</DIV>

If we wanted to select the outer div above, we could do this:

$("div.ms-quicklaunchheader")

Now, we’d need to be careful about this because of one of the really cool things about jQuery: it will select ALL the elements that match the selector in the DOM. So if there were more than one div with its class set to ms-quicklaunchheader, then we’d end up with those objects as well. Although this truly is One Very Cool Thing, it’s something you need to think about in your selectors.

In this case, there is exactly one (1) div with the ms-quicklaunchheader class in any SharePoint page, at least as SharePoint renders them out of the box.

Since there is only one div with the class ms-quicklaunchheader, it probably would have made more sense for Microsoft to have given the div a unique id. This sort of thing is one of the reasons that Web developers complain about SharePoint’s markup all the time. It sometimes doesn’t follow best practices – heck, it often doesn’t follow best practices – which makes so-called “front end developer”‘s jobs harder.

Here is another example:

var thisNavLinkViewAll = $("#ctl00_PlaceHolderLeftNavBar_idNavLinkViewAll");

The variable thisNavLinkViewAll now contains an object reference to the anchor tag. Note that I used the ugly id which SharePoint assigned to the anchor tag in my selector.

As you may know, SharePoint is built on top of ASP.NET, and ASP.NET is rife with really long and ugly ids, often containing long GUIDS, strings built of of the names of components and controls, and the like.

But wait, jQuery has capabilities to help with those silly, long ids (which are actually necessary, by the way, but still ugly). Looking at the id above, we can see that it ends in “NavLinkViewAll”. It turns out that is in fact unique in the DOM. So we can take advantage of a nice jQuery trick:

var thisNavLinkViewAll = $("a[id$='NavLinkViewAll']");

This different notation means: find me an anchor tag which has an id which ends with ‘NavLinkViewAll’. Nice, eh?

There are a bunch of other notation options which you can use in your selectors based on the start of something [^=], whether it contains something [*=], and so on.

As I said, this is half the battle: finding what you want to work with in the DOM. Especially when you are working with SharePoint-generated pages, where you may not have a lot of control over what is rendered to the browser, you need to figure out something to select to get started.

I think of the initial selector as a sort of “anchor” which allows me to move forward. If we can’t reliably find our place in the DOM, then we can’t reliably manipulate anything down the line.

Attributes

Attributes are characteristics of HTML elements, such as the href attribute of an <a> element or the src attribute of an <img> element.

In the first example above, the only attribute that the div has is the id. That’s not very exciting, so let’s add something else. I’m going to use just the div element from the example above going forward so that I don’t clutter up the page too much.

  <div id="helloDiv" class="ms-bold" >
    Hello, world!
  </div>

I’ve added a class attribute to the div. A class refers to a named section in the CSS which describes how the element ought to be formatted.

In this case, I’ve borrowed a class that Microsoft put into SharePoint’s core.css (but not core4.css in SharePoint 2010, for some reason) called ms-bold. All that class does is add

font-weight: bold;

to the formatting of the element to which it is applied. The net effect is that you get bold text.

Well, that’s all well and good, but so what? Well, we can find and set attributes on elements by using jQuery.

$("#helloDiv").attr("class");

This returns the string “ms-bold”. We might use this to find out what the currently applied style is for the “helloDiv” element. We can also set attributes like this:

$("#helloDiv").attr("class", "ms-hidden");

There are special jQuery functions to work with classes (which are part of CSS – wait for it!) but we can also make changes this way. In the example above, I’m changing the class from ms-bold to ms-hidden. The effect of this is to “hide” the element in the DOM because the ms-hidden class which Microsoft put into SharePoint’s CSS sets

display: none;

From the user’s perspective, the div just disappeared! Bang, we just did something which has an impact on what the user sees on the page.

Let’s go back to our “View All Site Content” link again. Note that the anchor tag (the “<a>”) has an attribute called accessKey, set to the value of 3.

<DIV class="ms-quicklaunchheader">
  <A accessKey=3 id=ctl00_PlaceHolderLeftNavBar_idNavLinkViewAll href="/_layouts/viewlsts.aspx">
    View All Site Content
  </A>
</DIV>

The accessKey is for setting up keyboard shortcuts to HTML items in a page, which is very useful for people with disabilities.

We can grab the value like this:

var thisAccessKey = $("a[id$='NavLinkViewAll']").attr("accessKey");

Now the variable thisAccessKey is set to the value 3.

We can also set the accessKey:

$("a[id$='NavLinkViewAll']").attr("accessKey", 5);

Now the accessKey is set to 5.

Traversing

We know that we need to find a good “anchor” in the DOM from which to operate. What if we want to work with something which SharePoint generates that isn’t tidily packaged up with an id or class? This is where traversing comes in. We can locate something which we do know how to find and traverse up, down, or over in the DOM tree to find what we really need.

The simple “Hello world!” example from earlier in this article has about outlived its usefulness, so let’s look at the “View All Site Content” link again.

<DIV class="ms-quicklaunchheader">
  <A accessKey=3 id=ctl00_PlaceHolderLeftNavBar_idNavLinkViewAll href="/_layouts/viewlsts.aspx">
    View All Site Content
  </A>
</DIV>
$("a[id$='NavLinkViewAll']").parent();

would give us the div which surrounds the anchor tag.

XML, and therefore HTML, has a concept of parents and children, just like databases and your own family. Everything comes from somewhere. The parent of the anchor tag here is the div. This means that the anchor tag is enclosed by the div.

We also can do something more like the reverse: select the parent and then traverse to the child:

$("div.ms-quicklaunchheader").find("a")

This will select the div and then find all of the “a” tags within it. We know that there is only one in this case.

Traversing is incredibly important in working with SharePoint pages. When we want to work with the SharePoint out of the box forms, for example, many of the control elements don’t have ids or classes which we can use in our selectors.

The next example is from SPServices. Here, I’m trying to find the left and right boxes for a multi-select lookup column like the one you see in the image.

A jQuery Primer for SharePoint - Selectors, Attributes, and Traversing- Oh My! - Figure 2

The jQuery code is a little messy, but take a look:

var possibleValues = $("select[ID$='SelectCandidate'][Title^='" + opt.multiSelectColumn + " ']");
var selectedValues = possibleValues.closest("span").find("select[ID$='SelectResult'][Title^='" + opt.multiSelectColumn + " ']");

Because it’s the “easiest” thing to find, first I use a selector to get a reference to the “SelectCandidate” select element which is inside the left hand list in the image below.

Note that I’m using a pretty complicated selector to be absolutely certain that I’m ending up with the correct left hand list; there could be multiple multi-select lookup columns in the form.

Once I have that reference tucked away into the possibleValues variable, I go looking for the right side list. I traverse from the possibleValues element “up” to the closest span (.closest(“foo”) means traverse up the tree until you get to the first foo element) and then find the select for the right side box.

Again, I’m using a complicated selector to be sure I have the right thing. It’s always better to be more specific if you can, especially when you don’t have full control over the DOM, like when you are working with SharePoint!

Summary

I can see that you’re eyes are glazing over a little at this point, so I think I’ll call it a day for this article. We’ve looked at how you can find things in the DOM with selectors; check the attributes of things; and traverse up, down, and across the DOM tree. The examples are simple, but hopefully they are enough to get you interested in digging into these ideas a bit more.

These capabilities alone should show you the power of jQuery. Sure, you might say that you can do all these things with straight JavaScript, and you’d be right. However, you’d be writing a *lot* more code, which would increase the development, testing and maintenance costs for your solutions.

A take away assignment for you is to go off and do a little research on CSS concepts if you aren’t familiar with them. So much of what you are used to seeing on the “modern Web” is driven by smart use of CSS that if you choose to ignore CSS, you’re doing the old “cutting off your nose to spite your face” thing.

If you’ve gotten this far in the article and you think “Well, this doesn’t look like any fun AT ALL. I’m going back to my .NET work.”, then maybe that’s not such a bad thing. It’s better to stick with what you know and not move forward, right? I will make you a wager that if you learn these concepts, even if you never write a single line of jQuery yourself, you’ll become a better all around .NET programmer, too.

In the next articles, I’ll take you through some more of the jQuery capabilities that can kick things up yet another notch.

Series NavigationA jQuery Primer for SharePointA jQuery Primer for SharePoint: Manipulation and CSS
Twitter Digg Delicious Stumbleupon Technorati Facebook Email

No comments yet... Be the first to leave a reply!

Leave a Reply

Before you post, please prove you are sentient.

What is 2 times 5?