Customizing the SharePoint ECB with Javascript, Part 1
Other articles in this series:
- Customizing the SharePoint ECB with Javascript, Part 2
- Customizing the SharePoint ECB with Javascript, Part 3
First of all; what is the ECB in SharePoint? Well ECB stands for Edit Control Block and it is the context menu that is displayed for all items in SharePoint Lists and Document Libraries (and their corresponding web parts). The menu items shown below are the default ones that you get out-of-the-box, in this case in a List.
Probably the most commonly used technique to customize the ECB is by making use of a Feature that contains a CustomAction element, as displayed below:
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
<CustomAction
Id="{B0B5A0CB-7FBE-4dd6-9B2A-2B1E1321B8F9}"
RegistrationType="List"
RegistrationId="101"
Location="EditControlBlock"
Title="Dummy Menu Item">
<UrlAction
Url="/_layouts/dummy.aspx"/>
</CustomAction>
</Elements>
By using the EditControlBlock value for the Location attribute, the Dummy Menu Item is added to the ECB in all the Document Libraries (the RegistrationId attribute value of 101). This technique works of course, but there are some limitations related to it. First of all when a menu item is added to the ECB by using a CustomAction element, the menu item is displayed in all ECB menus; there is no way to make the menu item context sensitive. It could be for example that you only want to show the menu item for some of the documents, not all of them. The out-of-the-box Check In/Out behaviour is a good example of this: Check In is only displayed when the document is in the Checked Out state and visa versa. A second limitation is that using this technique, it’s not possible to create nested menu items, like the out-of-the-box Send To ECB menu item for example. The underlying reason is that unfortunately it is not possible to use the ControlAssembly and ControlClass attributes in the CustomAction element of a feature, when the location is EditControlBlock. When using the ControlAssembly and ControlClass attributes you can basically point to a server control that's responsible for rendering the UI to show as the Custom Action in the ECB. More information and an example can be found in one of my previous posts Creating Hierarchical Menus with a Custom Action. But once again, this will not work in the ECB!
Luckily there is another technique to customize the ECB that solves these issues, this technique is using Javascript. The key functionality to build custom ECB menu items is pretty easy since SharePoint already contains some wrapper Javascript functions to do this. In the core.js file (which can be found in C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\LAYOUTS\1033) you can find the methods AddListMenuItems and AddDocLibMenuItems. These methods are called by SharePoint when an ECB should be built for a List item or Document. Although technically it is possible to modify those functions directly in the core.js, it is not supported. There is a much nicer mechanism available to accomplish this! The first lines of code you can find in the AddListMenuItems function look like this (the AddDocLibMenuItems function contains similar code):
if (typeof(Custom_AddListMenuItems) !="undefined")
{
if (Custom_AddListMenuItems(m, ctx))
return;
}
Basically the Javascript function verifies if there is a function known called Custom_AddListMenuItems, if so this function is called. The return value of this function (true or false) determines if the rest of the AddListMenuItems function is executed; thus if the default menu items are added or not. Out-of-the-box there is no function called Custom_AddListMenuItems, the goal is that you build on yourself. Once again you can define this function directly in the core.js file, but this is unsupported. The nice thing is that this function can be defined in other .js files or even directly in SharePoint pages. Before we do that, let’s find out the code to implement a custom Custom_AddListMenuItems function:
function Custom_AddListMenuItems(m, ctx) {
CAMOpt(m, "Dummy link", "alert('Hello World!');", "/_layouts/images/LWV16.GIF");
CAMSep(m);
}
The first line calls the CAMOpt function (which is available in the core.js as well) to create a new menu item. As you can verify in the core.js, the CAMOpt function can have seven parameters (the first three are required):
- a reference to an ECB, typically passed by the caller of Custom_AddListMenuItems
- the text to display
- the Javascript function to execute, in this sample a basic Hello World dialog is shown
- the URL of an icon for the menu item
- the HTML alt attribute value of the icon
- the HTML description attribute value of the icon
On the second line the CAMSep function is called which renders a separator (a thin line).
The easiest way to test this code is to navigate to a SharePoint list, for example a Task list (e.g. http://yoursite/Lists/Tasks/AllItems.aspx). In the Site Actions menu of that page choose Edit Page. Notice that this page is having one Web Part Zone called Main, which already displays one web part. Add a new Content Editor web part to the Main zone; and choose Modify Shared Web Part from the Edit menu of the newly added web part (top right). In the properties task pane of the web part, click on the Source Editor button and copy/paste the entire AddListMenuItems function. When the page is reloaded, the result should look like this:
When the new Dummy link menu item is clicked; a simple dialog box will be shown.
This is the first part of a series of posts which will show you how to customize the Edit Control Block by using Javascript. In the next post I’ll show you how you can create nested (or hierarchical) menu’s in the ECB.
Update: I added a few lines which explicitly specify that the ControlClass and ControlAssembly attributes will not work in the ECB. Thanks Wouter for mentioning this!