2007 jQuery Form Enhancements; Preserving Site Definition

During a recent discussion with @TashasEv, the topic came up of preserving site definition when rolling out jQuery form enhancements. The preservation of site definitions is something that many people ignore, but in the interest of best practices I figured it was worth a blog post to explain some of the pros and cons, and offer some solutions.

Many of us (myself included) use jQuery to enhance out of the box (OOTB) SharePoint forms. jQuery allows us to make a variety of minor or major changes to the usability and functionality of forms either through straight jQuery or with Marc Anderson's (@sympmarc) popular jQuery Library for SharePoint Web Services (SPServices). Cascading dropdowns, content relevant fields, dynamic changes to styling, and other enhancements can greatly improve the user experience and the data entry side of a form, but can be the achilles heel of your support model if done incorrectly.

In layman's terms, the site definition is the foundation on which all OOTB SharePoint sites, templates, forms and pages are based. Essentially, this allows you to manage assets within the site by managing the site definition. An easy to understand example would be upgrading your SharePoint environment. If a version upgrade or service pack comes along that touches the site definition, all objects using that site definition will be updated accordingly. The issue lies in the fact that when you open your OOTB SharePoint form in SharePoint Designer and edit it, you essentially disconnect that form from the site definition. Six months down the road when you upgrade your environment or push that next service pack, your form will now not be updated. Additionally, if you find yourself in a position where you need to consult Microsoft for support, Microsoft can very well point out that you've customized the OOTB code, and refuse your support request.

SharePoint Designer makes it very easy to tell when you have an item that's separated from the site definition, as those files are marked with a blue information icon as seen below: So you may be asking yourself... how can I add jQuery to my forms if I can't edit the code directly. Well, there's a couple different approaches:

  1. Create a new form: One method is to create a new copy of the form. You're still going to disconnect the form from the site definition, but you'll at least preserve the default OOTB form's association with the site definition. To do this, load the OOTB form (ie: NewForm.aspx) and highlight and copy all of the code. Next, create a new .aspx page within the same folder and paste all of the code in. You can now make the necessary changes to this custom file, and save it as a different filename (ie: NewFormCustom.aspx). You can then right-click on your list in SharePoint Designer, select "Properties", and go to the "Supporting Files" tab. Here you can select your custom form using the browse button, which tells SharePoint to use your custom form rather than the default OOTB form from here on out. This method allows you to preserve the OOTB form without compromising it, and still allows you to directly edit the source of your custom form.
  2. Use a Content Editor Web Part (CEWP): Generally speaking I prefer to add my jQuery and Javascript at the code level (also Marc's recommendation on the SPServices documentation), but in the case of a form you do have the ability to add a CEWP to a form. To add a CEWP to a form, navigate to the form in your web browser (ie: NewForm.aspx) and append ?PageView=Shared&ToolPaneView=2 to the end of the URL (ie: NewForm.aspx?PageView=Shared&ToolPaneView=2). This will display the page in edit view (the equivalent of clicking "Edit Page" in the Site Actions menu of a web part page), allowing you to insert a CEWP to contain your code. This is also a useful technique should you have multiple forms requiring the same customization. In an enterprise environment, you may have multiple forms on multiple sites or lists that the same jQuery enhancement code applies to. You can save that code in a file, and point all of your CEWPs to that file, allowing centralized management of that script. The additional plus to this method, is that if you're on a Tier1 system or other access restrictions prevent you from using SharePoint Designer, this method will still work as all of your changes are done within the browser.

SharePoint Permissions Based Content

One of the challenges I always seemed to face with SharePoint was limiting content displayed based on a users access level. Marc Anderson's (@sympmarc) SPServices library solves some of those hurdles if you're using jQuery elsewhere, as you can call the SharePoint permissions web services to determine if a user is in a specific group, then use jQuery to write content. But what if you're not using jQuery anywhere else, is it worth adding the jQuery library and the related web service calls to check permissions? Are you looking at hiding web parts by permissions, or changing site controls?

I recently discovered the PermissionsString attribute, which compares the user's credentials against the defined permission string. We can then use this logic to display content relevant to the user's permissions. This is a great alternative to calling a web service if you're not already using the jQuery library elsewhere, or if you want to make site wide access based adjustments to the SharePoint UI. As an example, we can hide the "View all site content" link from anyone except for site admins.


<Sharepoint:SPSecurityTrimmedControl runat="server" PermissionsString="ViewFormPages">
<div class="ms-quicklaunchheader"><SharePoint:SPLinkButton id="idNavLinkViewAll" runat="server" NavigateUrl="~site/_layouts/viewlsts.aspx" Text="<%$Resources:wss,quiklnch_allcontent%>" AccessKey="<%$Resources:wss,quiklnch_allcontent_AK%>"/></div>


<Sharepoint:SPSecurityTrimmedControl runat="server" PermissionsString="ManageWeb">
<div class="ms-quicklaunchheader"><SharePoint:SPLinkButton id="idNavLinkViewAll" runat="server" NavigateUrl="~site/_layouts/viewlsts.aspx" Text="<%$Resources:wss,quiklnch_allcontent%>" AccessKey="<%$Resources:wss,quiklnch_allcontent_AK%>"/></div>

We can take this a step further, and specify multiple permission string values separated by a comma, which will do an "or" comparison and return the content if the user has any of the defined strings. For those of you working with the web service option which uses enumerated values of the permission strings, I've included a cross reference chart below.

List Permissions
ManageLists 2048
CancelCheckout 256
AddListItems 2
EditListItems 4
DeleteListItems 8
ViewListItems 1
ApproveItems 16
OpenItems 32
ViewVersions 64
DeleteVersions 128
CreateAlerts 549755813888
ViewFormPages 4096
Site Permissions
ManagePermissions 33554432
ViewUsageData 2097152
ManageSubwebs 8388608
ManageWeb 1073741824
AddAndCustomizePages 262144
ApplyThemeAndBorder 524288
ApplyStyleSheets 1048576
CreateGroups 16777216
BrowseDirectories 67108864
CreateSSCSite 4194304
ViewPages 131072
EnumeratePermissions 4611686018427387904
BrowseUserInfo 134217728
ManageAlerts 274877906944
UseRemoteAPIs 137438953472
UseClientIntegration 68719476736
Open 65536
EditMyUserInfo 1099511627776
Personal Permissions
ManagePersonalViews 512
AddDelPrivateWebParts 268435456
UpdatePersonalWebParts 536870912