Sunday, January 15, 2006
« Welcome | Main | Running both versions of ASP.NET with WS... »

One Click Minimize/Restore for WebParts

One anoyance I have with WebPart pages that have a lot of WebParts is the need to click the WebPart menu to select Minimize or Restore when you want a little more screen real estate or you need to expand a previously minimized WebPart.

To solve this niggle I've developed a simple WebPart that using client side Javascript that traps the double click on a WebPart title and toggles the state of the WebPart. It integrates with the SharePoint client side object model so any changes are saved to the site and persists across sessions.

Unzip the DoubleClick WebPart Minimize/Restore DWP file to a directory of your choice

Browse to the SharePoint WebPart page - Click the 'Modify My Page' - 'Add Web Parts' - 'Import menu' option

Click the Browse button and select the DWP file.

Click the upload button - once uploaded you can drag the WebPart to anywhere on the page.

 


Here's a little more detail of the SharePoint client side scripting.

First I needed to get a list of WebParts on a page. Thats easy - every WebPart page that holds WebParts has a global object WPSC that is initialized like this WPSC.Init(document). The object WPSC is defined in IE55up.js/IE50.js/NonIe.js depending on browser. This is the Web Part Page Services Component which handles the client side WebPart infrastructure, it provides services such as loading/saving properties and handles page events see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/spptsdk/html/wpscaOverview_SV01098760.asp  for more details.

OnPage javascript adds every WebPart on the page to its WebPartPage.Parts collection e.g.

WPSC.WebPartPage.Parts.Register('WPQ1','8db7d8d8-b1e0-4e9d-84ff-0b266b8c0beb',document.all.item('WebPartWPQ1'))

To get a list of all the WebParts on the Page you can do this

for(var i=0; i< WPSC.WebPartPage.Parts.Count;i++)
  {
    wp=WPSC.WebPartPage.Parts.Item(i);
}

What we really need is the WebPartQualifierproperty of the WebPart which is the unique ID for each WebPart on the Page, various parts of the WebPart are then suffixed with this identifier e.g WebPartTitleWPQ2 for the title div and WebPartWPQ2 for the actual serverside rendered HTML div container.

So to hook the DblClick event we can modify the inner loop like so

    wpq=WPSC.WebPartPage.Parts.Item(i).WebPartQualifier;
    var oTitle=document.getElementById('WebPartTitle' + wpq);
  
    if (oTitle)
    { 
       oTitle.attachEvent('ondblclick',MinRestoreWP);
    }

Here we're setting the double click event to fire the MinRestoreWP function. this is defined as

function MinRestoreWP()
{
var WPQId, WPObject;
var titleid,  WPQPos;

// Clear the selection the double click produces
document.selection.empty();
window.event.cancelBubble = true;
window.event.returnValue = false;

titleid=window.event.srcElement.parentNode.id;
WPQPos=titleid.lastIndexOf("WPQ");
if (WPQPos>0)
{
   WPQId='WebPart' + titleid.substring(WPQPos, titleid.length);
   WPObject=document.getElementById(WPQId);
   // call the MSO api to do the work
   if (WPObject) MSOLayout_MinimizeRestore(WPObject);
}
 
return false;
}

Here we get the WebPart to collapse or expand by going to the parent element of the Title bar which holds the WebPart title id which we can parse to get the WPQ id. This allows us to get the WebPart object we need.

The expand collapse is handled by a SharePoint function MSOLayout_MinimizeRestore which simply takes a WebPart object and does the hard work of hidding or showing the webpart by changing the WebPart.style.display CSS property. It also logs the change so the property is saved back to the WebPartPages webservice and is remembered if you close the browser and revisit the page.

DoubleClickWebPartMinimizeRestore.zip (1.35 KB)
Thursday, March 30, 2006 5:14:09 PM (GMT Standard Time, UTC+00:00)
I was wondering about the persistance of the FrameState property of the webpart. I've made a custom webpart that uses a custom container overriding the Render() method instead of the RenderWebPart() method. This makes it look really good due to being able to completely customize the look of the webpart. But with that it looses some funtionality. I can replace all the needed funtionality of the webpart such as minimizing, restoring, and opening the menu and toolpane. Easy stuff. But what I haven't been able to do was keep the FrameState to perssist between user sesssions, either using your code or the built in sharepoint function. There is something in the RenderWebPart() method that looks at these changes or looks at the saved properties.

Do you happen to know what code I need in order to keep that funtionality? Otherwise the minimize changed don't save between sessions. Plz email me. Thanks.
Sunday, April 02, 2006 5:33:25 PM (GMT Standard Time, UTC+00:00)
Mike,

As far as I can see RenderWebPart simply delegates to the RenderChildren method on Control. The Render method does do some checking for FrameState but it doesn't write to it.
I doubt the render methods change the properties, that's easily tracked, just profile SQL and you'll see a call to proc_UpdateWebPart when properties are changed. If that call is not made no properties have been changed and persisted.

Have you tried using the toolpane to set and view the properties?
Are you changing the properties in shared or user mode?

Colin
colin
Monday, April 10, 2006 7:45:13 PM (GMT Standard Time, UTC+00:00)
If comments are still open, what I am trying to do is to get on page load or page refresh an event to fire so that it changes the frametype property of the webpart from Minimized to Normal.

I see your code as very good starting point for this. But however I am unale to get past the fact that I only want the webparts that are minimized to be restored. Any clues??? Appreciate your help!!!
Niks
Wednesday, April 12, 2006 10:41:45 AM (GMT Standard Time, UTC+00:00)
Niks,

Once you have the WebPart body div i.e. the div with the id of say WebPartWPQ7
this line in my code: WPObject=document.getElementById(WPQId);
to see if its minimized check the WPObject.style.display property.
If its 'none' then it's minimized.

Colin
colin
Tuesday, June 06, 2006 1:49:08 PM (GMT Standard Time, UTC+00:00)
Well I used the Render() method for the webpart which means I have to completely use my own HTML code for the container. Which is exactly what I want. I basically render a div tag that holds all the content conditionally depending on the framestate property. works like a charm.

I've got another question though. The only examples of WPSC being used is to minimize and restore webparts. This content isn't unique to this blog.... but have you worked on saving and retrieving webpart properties through WPSC?
Wednesday, June 07, 2006 7:06:02 PM (GMT Standard Time, UTC+00:00)
Mike,

I've not used the WebPart properties of the WPSC object but it should be fairly easy. Check the IE55UP.JS file for the details. Its cool code as using SOAP and AJAX is how SharePoint calls the webservices. The interesting code starts at

function PartDef(WebPartQualifier, StorageKey, DOMObject)
{
....

It calls the SaveWebPart and GetWebPart methods at '/_vti_bin/WebPartPages.asmx'.
The properties XML is the same format you'd find in a DWP file.

This hangs off the WPSC object as WebPartPage.Parts where Parts is a PartDef object.
You could probably use the existing routines if your only interested in IE support or check my other blog entries on Cross-Browser AJAX to call the webservices directly.



colin
Comments are closed.