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.

  1. Display a list that provides links to the five most recently edited pages. This feature will be handy if you are working frequently with a few web pages for a period of time.
  2. Clone a page that you are viewing by creating a new one in the current sub site, and then send an email with a link to this newly created page to someone else.

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:

  1. write some code for the customized actions,
  2. modify the Page Editing Toolbar XML file, and then
  3. deploy the solution on the WFE server.

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 ConsoleActionConsoleAction 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:

  1. Using Sharepoint Designer, check out the CustomEditingMenu.xml file under the master page gallery:   _Catalogs\masterpage\Editing Menu
  2. Then, modify the custom XML file with the following changes:
  • Add some references to the top of the file so that the new actions from the assemblies can be referenced. Make sure you use the right PublicKeyToken key and the namespace so that the references are clear.

<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>

  • Add two new entries: one of them is a new menu item under the Page menu. In order to do this, I have to delete the original page menu, and then add a new one.

<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.  

  • Green section: the new page menu's new ID - MyPageSubMenu
  • Yellow section: Added a new entry for the Clone And Assign menu item.

<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.

  • After that, another entry is added to the XML file for a brand new menu called "Recently Edited", shown below. The sequence attribute controls the relative location of the added menu. The last menu from the default toolbar is Tools, and it has a sequence number of 300. So, any number larger than 300 will put it after the Tools menu. Make sure you have an unique ID specified for this new entry.

<ConsoleNode Sequence="500" DisplayText="Recently Edited" UseResourceFile="false" NodeClass="custom:RecentlyEditedItemsNode" NavigateUrl="javascript:" UserRights="EmptyMask" ID="sa2RecentEdits2TP"/>

  • Save the xml file with SharePoint Designer and check it in. Approve it if you want everyone to see it. The complete content of the XML file after these changes can be found in the following attachment D.

Deployment:  to deploy the custom actions, one must do the following:

  1. Copy the newly created DLL file to the WFE and add it to the assembly (GAC).
  2. Copy the CloneAssignDialog.aspx file to the file path: D:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\LAYOUTS.
  3. You may have to reset IIS for the new menu items to show up properly although I did not have to.

Notes:

  • The recently edited menu does not show up until you have edited a page after you have installed the newly added menu.
  • The clone and assign action will not send out an email until you have configured MOSS to send email. If you have not configured the email delivery in MOSS, it will still create a new page with the cloned content and it will warn you that it failed to send email. The email that will be sent looks like this:

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.