Tuesday, December 29, 2009

Custom upload page in Layouts for document library and it's Navigation from upload menu in the Toolbar. Bend it !! Custom upload menu for the document library.

You just dont want to use the OOB upload.aspx in the "Layouts" to upload the documents in to the document library and you have created your custom upload.aspx (with all your requirements) based on the look and feel of OOB upload.aspx. Now your custom upload.aspx page is available in the "Layouts", But................................................. You started wondering that how to integrate the Navigation to the New custom upload.aspx page from the "Upload Menu" in the document library toolbar. You might have created the customupload.aspx and placed in the "Layouts" but clicking on the upload single or multiple document in the Upload menu will navigate you to "Upload.aspx" and not to the "Customupload.aspx"...
Thinking again............ Oh got it !!! Yes, I can add a new menu item through "customaction" feature and can navigate to the "CustomUpload.aspx" page to upload the documents. Think again ...... Yes, You can do it !! But what about the existing OOB menu item which navigates you to the OOB "upload.aspx" page. Still thinking ........ Hurray !!! Through "HideCustomAction" i will hide the existing OOB menu item in the upload menu which navigates to the OOB upload.aspx page.
Let me interrupt here !! As long the "CustomAction" feature is considered, you can add a new item under the "UploadMenu". But hiding the existing OOB menu item is not possible through the "HideCustomAction" feature. The "HideCustomAction" feature can hide the item which has been rendered through the CustomAction feature framework such as Site Action, Site Setting.... etc. Even you cannot hide the item from the "ECB" menu through HideCustomAction but can add a new menu item in the ECB menu through custom action. Because the ECB menu is rendered by the JavaScript from Core.js file. Likewise the "Upload menu" is rendered through a class library as a web control from the Microsoft.SharePoint.dll
So "HideCustomAction" feature can be used only to hide the item which are rendered through the custom action feature.
Following are some truth about the document library (as well "Lists") toolbar and the way to render the custom control in the toolbar :
1.    The toolbar of the document library consists of New Menu, Upload menu, Actions Menu and Settings Menu. These menus are rendered by the sharepoint dll and not by any JavaScript.

2.    To customize the Upload Menu, Create a class which inherits from the Microsoft.Sharepoint.WebControls.UploadMenu class and Override the “SetmenuItemProperties” method to navigate to the custom upload page. In this method it has been hard coded to navigate to the OOB upload.aspx.

3. The code snippet and the sample project has been attached in this post.

4.  Compile the class library and place the DLL in the GAC.

5.    The Rending Template for the document library is in the defaulttemplates.ascx control under 12/Template/Control template. The rendering template ID is “DocumentLibraryViewToolbar”. This template renders the New menu, Upload menu, Actions menu and Settings menu in the toolbar. The template looks like follows :


 


6.    Modifying the OOB files are not supported so copy the defaulttemplates.ascx and save it with a custom name under 12/Template/Control Template.

7.    Modify the “DocumentLibraryViewToolbar” in the custom ascx such that to render your custom upload menu from the class library you created. (Note : You need to add your assembly reference and register the tag prefix in the Custom ascx control. The sample customdefaulttemplates.ascx control is attached in this post)

8. The following are the snippet from the custom ascx control :

Along with the other existing tag prefixes need to add the tag prefix for your custom upload menu control dll

<% @Register TagPrefix="MyUpload" Assembly ="customupload, Version=1.0.0.0, Culture=neutral, PublicKeyToken=be322df48bc9f56c" Namespace="customupload" %>

 
 


9.    Next step is to render the custom rendering template to the document library so that the custom upload menu will be rendered in the toolbar. For this the "ToolbarTemplate" property of the View should be changed in the schema.xml file of teh document library definition. As modifying the OOB files are not supported, Copy the “DocumentLibrary” folder from 12/Template/Features and paste in the same place as “CustomDocumentLibrary”.

10.    Change the feature ID of the “CustomDocumentLibrary”

11.    Open the schema.xml file of custom document library and add the “ToolbarTemplate=CustomDocumentLibraryViewToolbar” attribute to the “View BaseID=1”. The sample custom document library definition with schema.xml changes is attached in this post.

12.    Install the feature and activate it.

13.    Create a document library using the custom document library definition and you can test that the custom upload menu has been added to the document library toolbar.

14. Now clicking on the upload document will navigate you to the custom upload.aspx page


                                                       HAPPY CUSTOMIZING

Wednesday, December 23, 2009

Closures and executing JavaScript on page load

 coppy right from: http://www.sitepoint.com/blogs/2004/05/26/closures-and-executing-javascript-on-page-load/
Over on my other blog I’ve just published a new technique for executing a piece of JavaScript once a page has finished loading. Here’s the code:

1function addLoadEvent(func) { 
2  var oldonload = window.onload; 
3  if (typeof window.onload != 'function') { 
4    window.onload = func; 
5  } else { 
6    window.onload = function() { 
7      oldonload(); 
8      func(); 
9    } 
10  } 
11
12 
13addLoadEvent(nameOfSomeFunctionToRunOnPageLoad); 
14addLoadEvent(function() { 
15  /* more code to run on page load */  
16}); 

view plain | print

function addLoadEvent(func) {
  var oldonload = window.onload;
  if (typeof window.onload != 'function') {
    window.onload = func;
  } else {
    window.onload = function() {
      oldonload();
      func();
    }
  }
}

addLoadEvent(nameOfSomeFunctionToRunOnPageLoad);
addLoadEvent(function() {
  /* more code to run on page load */ 
});


A closure consists of a function along with the lexical environment (the set of available variables) in which it was defined. This is a remarkably powerful concept, and one commonly seen in functional programming languages such as JavaScript. Here’s a simple example of closures in action:

1function createAdder(x) { 
2  return function(y) { 
3    return y + x; 
4  } 
5
6 
7addThree = createAdder(3); 
8addFour = createAdder(4); 
9 
10document.write('10 + 3 is ' + addThree(10) + ''); 
11document.write('10 + 4 is ' + addFour(10)); 

view plain | print

function createAdder(x) {
  return function(y) {
    return y + x;
  }
}

addThree = createAdder(3);
addFour = createAdder(4);

document.write('10 + 3 is ' + addThree(10) + '
');
document.write('10 + 4 is ' + addFour(10));
createAdder(x) is a function that returns a function. In JavaScript, functions are first-class objects: they can be passed to other functions as arguments and returned from functions as well. In this case, the function returned is itself a function that takes an argument and adds something to it.

Here’s the magic: the function returned by createAdder() is a closure. It “remembers” the environment in which it was created. If you pass createAdder the integer 3, you get back a function that will add 3 to its argument. If you pass 4, you get back a function that adds 4. The addThree and addFour functions in the above example are created in this way.
Let’s take another look at the addLoadEvent function. It takes as its argument a callback function which you wish to be executed once the page has loaded. There follow two cases: in the first case, window.onload does not already have a function assigned to it, so the function simply assigns the callback to window.onload. The second case is where the closure comes in: window.onload has already had something assigned to it. This previously assigned function is first saved in a variable called oldonload. Then a brand new function is created which first executes oldonload, then executes the new callback function. This new function is assigned to window.onload. Thanks to the magical property of closures, it will “remember” what the initial onload function was. Further more, you can call the addLoadEvent function multiple times with different arguments and it will build up a chain of functions, making sure that everything will be executed when the page loads no matter how many callbacks you have added.
Closures are a very powerful language feature but can take some getting used to. This article on Wikipedia provides more in-depth coverage.