Tuesday, August 30, 2005

Javascript function overriding, Part 4

In this final part of the Javascript function override series, I will give you a coding scenario when the 2 method of function overriding will make a difference to your code and a scenario in which I have use method 2 to extend feature functionality.

If you want to refer back to my previous post, follow these links :
Part 1
Part 2
Part 3

The answer to the first question is very obvious. From the 2 example I have given, if your new override function need to call the orginal function, then you have to use method 2. Otherwise you will end up with a recursive function call if you use method 1.

Here come the second part which is more interesting. Recently I use the second method to extend the functionality and overcome some limitation in Windows Sharepoint Services (WSS).

I am not going to go in great length what is WSS. You can find out more on this product from the Microsoft Sharepoint website. In a glance, WSS provide a website for team and departmental collaboration. In each WSS site, you can create picture library, document library, link list to other website, survey poll and custom list to store some custom information and many more.

For the sake of this discussion, I will only focus on custom list. But the method I describe here is equally
applicable to other lists as well.

In the list view, when you hover over each list item, a context menu will be popup. The context menu consist of menu items which offer you actions that you can perform on the item. Behind the scene, there is a series of Javascript function calls which make all these happen. At one point in the call chain, the client side script framework will call a function named AddListMenuItems(m, ctx) (you can find this function is ows.js). This function is responsible to construct the menu item that is relevant to the list item.

If you look into this function, one of the first thing it does is call another function named Custom_AddListMenuItems(m, ctx). According to the Microsoft documentation, if you want to add your own menu item to the context menu, you should create the function Custom_AddListMenuItems(m, ctx) and add your own code to create the extra menu items in this function. This provide some form of extensibility point.

So far so good, except for 2 thing :
1) Your custom menu items always appear before the default menu items provided by WSS.
2) You always have to work on the Custom_AddListMenuItems(m, ctx) function to add your own menu items. Imagine a situation where multiple developers each is dealing with a different set of requirements and they each need to add their own custom menu item. Then it become difficult and messy to maintain the function because it is work by multiple developers and the single function might contain many complex logic to construct the menu item.

Using the javascript capability I demonstrated in method 2 of my example, I come out with a way to insert menu item at the back of the default menu items and allow the creation of each menu item to be encapsulate into different functions.

The idea and steps is pretty simple:
1) I create an array which is use to store the custom function.
2) When the page is loaded, I add the original AddListMenuItems() to the array.
3) Each time a new menu item need to be added, the menu item creation code can be put into a different function, and this function is added into the array.
4) I override the AddListMenuItems function to do something different. My version of the function will loop through the array and call each function in the array to contruct the menu item they are responsible for.


Here are the javascript code that does the logic:
<script language="javascript">

var AddListMenuItemsFuncList;
AddListMenuItemsFuncList = new Array();

AddListMenuItemsFuncList[AddListMenuItemsFuncList.length] = AddListMenuItems;

AddListMenuItems = function(m, ctx)
{
for(ctr=0; ctr < AddListMenuItemsFuncList.length; ctr++)
{
AddListMenuItemsFuncList[ctr](m, ctx);
}
}


function MyMenuItemFunction1(m, ctx)
{

var strDisplayText = "Custom Action 1";
var strAction;
var strImagePath = "";

strAction = "alert('Custom Action 1 " + itemTable.ItemId + "')";

// Add menu item
CAMOpt(m, strDisplayText, strAction, strImagePath);

// add a separator to the menu
CAMSep(m);
}

function MyMenuItemFunction2(m, ctx)
{

var strDisplayText = "Custom Action 2";
var strAction;
var strImagePath = "";

strAction = "alert('Custom Action 2 " + itemTable.ItemId + "')";

// Add menu item
CAMOpt(m, strDisplayText, strAction, strImagePath);

// add a separator to the menu
CAMSep(m);
}


function insertFunctionAt(arr, idx, newFunc)
{
for(ctr=arr.length-1; ctr >=idx; ctr--)
{
arr[ctr+1] = arr[ctr];
}

arr[idx] = newFunc;
return arr;
}

function addFunctionToMenu(funcPointer)
{
AddListMenuItemsFuncList[AddListMenuItemsFuncList.length] = funcPointer;
}

// Add this custom menu item to the back of the default menu items.
addFunctionToMenu(MyMenuItemFunction1);


// Add this custom menu item before the default menu items.
insertFunctionAt(AddListMenuItemsFuncList, 0, MyMenuItemFunction2);

</script>


To see this code in action, add a Content Editor Web Part(CEWP) to your custom list's view page. You can show the Web Part Tool Pane by adding ?ToolPaneView=2 to the end of the URL(This is an unsupported method). Then open the Source Editor, paste the above code into the Source Editor and click OK to save. Now refresh the view page. If you hover over the list item, you will see the new custom menu item in the context menu.

One Last Word


Although the function override capability in Javascript is powerful, it work like a double sided sword. If you don't use it with careful thought, you can be killed for the same reason.

Using it to extend the custom menu items in WSS provide you with greater flexibility, but we are also making an assumption on the behavior of the AddListMenuItems function. Microsoft does not guarantee that this function will not change in future release or Service Pack. If it does, then your code might just break.

To put it in simple words, I think this technique work fine, except that it is an unsupported method, and use it with care.

Labels:

0 Comments:

Post a Comment

<< Home