In MOSS 2007, there is a Page Editing Toolbar that allows a user to edit a web page from a web browser (see picture below). Out of the box, this toolbar already provides a rich set of features for editing and publishing web pages in a publishing site. However, you may or may not know that this toolbar can also be extended to surface customized actions tailored for your environment. So, Sterling Crockett and I (Kai Lee) from the ECM team put together this blog, and show you the toolbar customization by building a couple of handy features.
These are the new features that we want to add to the toolbar.
Before you continue reading the rest of this blog, you may want to check out this article that shows you how to extend the Page Editing Toolbar for some background about adding custom actions.
http://msdn2.microsoft.com/en-us/library/aa674506.aspx
To add these two features, we basically have to do 3 things:
Here are the major changes involved, and I will try to explain the key points below. The complete code change is given as attachments to the blog.
Custom code Changes: Sterling created the code change, and compiled them into a strong named assembly (DLL file). The complete code listing can be found at the end of this blog (Attachments).
Two classes are created for the two new features: CloneAndAssignAction and RecentlyEditedItemsNode. The CloneAndAssignAction is a class derived from a class called ConsoleAction. ConsoleAction is a class provided by MOSS for you to create new menu items. This item can invoke a specific customized action like we do here.
The class has a number of methods that can be overridden so that the default behavior can be customized. For example, Sterling has overridden the AuthoringStates method to enable the menu item for clicking only when a user is viewing, not editing, a publishing page.
public override AuthoringStates RequiredStates
{
get
return AuthoringStates.IsDocLibListItemTrue |
AuthoringStates.InWebPartDesignModeFalse |
AuthoringStates.IsPublishingPageTrue |
AuthoringStates.SaveConflictExistsFalse;
}
Note that the complete list of possible RequiredStates can be found at http://msdn2.microsoft.com/en-us/library/microsoft.sharepoint.publishing.webcontrols.authoringstates.aspx . Only when all states are true will the action be shown.
A lot of the behavior can be specified not only in code, but can also be specified in the XML configuration file the toolbar uses. I will show you later in this blog.
The main functionality is provided in the method: RaisePostBackEvent. This method basically does all the heavy lifting required at the time the action is clicked.
public override void RaisePostBackEvent(string eventArgument)
The method first reads the page name and email address entered by the user via a pop-up dialog. Then, it creates a new page using the same page layout as the source page in the same sub site. It finds all the fields and web parts on the page, and copies the content into the newly created page. At the end, it sends email to the specified address. The complete markup of the ASPX file for the pop-up dialog can be found in Attachment C: Custom Dialog
To provide the second feature of recently edited page, Sterling wrote another class called: RecentlyEditedItemsNode. The compete code listing can be found in attachment B. This class is derived from the ConsoleNode class and not from the ConsoleAction class because we want this feature to be presented as a top level menu with children, not just a single menu item. The main methods are InitNode and EnsureChildNodes.
InitNode will be run on every page load, when the object is created, so we use this method to determine whether the current page is in edit mode. If so, we add the current URL to the internally maintained list of recently edited pages. EnsureChildNodes is executed at the time the set of child nodes is requested, and will construct the correct list of links which are to be displayed to the user, based on the most recently edited pages.
The two classes are complied into a single strong named assembly called RecentlyEditedItemsAction. After this, we are now ready to add these new menu and menu item to the Page Editing Toolbar via an XML file.
XML file: The Page Editing Toolbar configures itself based on an XML file. The toolbar reads the default XML file shipped with MOSS, and then it reads a custom XML file that you can modify. Your modification made to this custom file specifies the incremental changes made to the toolbar; therefore, your modification is always relative to the default one. You can get an idea what this default file looks like by reading the default XML file in this file path:
D:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\LAYOUTS\EditingMenu\EditingMenu.xml
Where D is the drive you have installed MOSS.
Note: don't modify the default XML directly on the file system because you would lose compatibility to future releases of MOSS. Instead, I will show you the proper way of doing this here.
First, let me show you the end result of the extended toolbar. Two changes are added to the default toolbar:
Here are the steps involved to change the custom XML file:
<references>
<reference TagPrefix="cms" assembly="Microsoft.SharePoint.Publishing, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" namespace="Microsoft.SharePoint.Publishing.WebControls.EditingMenuActions" />
<reference TagPrefix="custom" assembly="RecentlyEditedItemsAction, Version=1.0.0.0, Culture=neutral, PublicKeyToken=d3bfa9e538ba8cdc" namespace="SamplePublishingActions" />
</references>
<ConsoleNode ConfigMenu="Delete" ChangedNodeID="saPageSubMenu" />
The attribute ConfigMenu is set to "Delete" (case sensitive) so that the original page menu is removed first.
Then, a new modified menu with the additional menu item is added.
<ConsoleNode Sequence="100" NavigateUrl="javascript:" AccessKey="G" DisplayText="cms,console_pagesubmenu"
ImageUrl="/_layouts/images/saveitem.gif" UseResourceFile="true" UserRights="EmptyMask" ID="MyPageSubMenu">
<ConsoleNode Action="custom:CloneAndAssignAction" DisplayText="Clone And Assign..." UseResourceFile="false" ID="saCloneAndAssign" />
<ConsoleNode Action="cms:SavePublishingPageAction" DisplayText="cms,console_savechanges" ImageUrl="/_layouts/images/saveitem.gif" UseResourceFile="true" ID="saSaveChanges"/>
<ConsoleNode Action="cms:SwitchToPublishedModeAction" DisplayText="cms,console_reviewmode" ImageUrl="/_layouts/images/saveitem.gif" UseResourceFile="true" ID="saReviewMode"/>
......
</ConsoleNode>
By the way, I mention above that we can specify some menu item behavior in the xml file instead of doing that in the code. You may have noticed a few attributes such as UserRights, you can add a mask here to enable the menu item only when a user has certain permissions. This allows you to trim the menu items when the user does not have the right to perform certain operations. This is particularly useful if you only want to add a URL to the menu item, and not a customized action. In that case, you don't really need to write any code, but can simply make all the changes in the XML file.
<ConsoleNode Sequence="500" DisplayText="Recently Edited" UseResourceFile="false" NodeClass="custom:RecentlyEditedItemsNode" NavigateUrl="javascript:" UserRights="EmptyMask" ID="sa2RecentEdits2TP"/>
Deployment: to deploy the custom actions, one must do the following:
Notes:
A new page, kaitest2.aspx, has been created by Kai Lee and assigned to you. You can view this page at http://server/Pages/kaitest2.aspx.
We hope you find the above useful. Let us know if you have any comments and questions.