Skip to main content
Logo of TeamLink

Blog

Go Search
Blog
Website
  

This is the blog site of TeamLink.be.
This blog contains experiences and tutorials around SharePoint. WSS and MOSS
ECB menu on whatever field you want

Today I had a this request to show the ECB menu on the Title field instead of the Name field.

This was one of those requests I couldn't decline as it's in fact a very usefull feature.

So I looked at the OOTB functionality and I couldn't find a way to do it with OOTB functionality. Before I dug into the problem I asked my collegue and he thought it wasn't possible, then I stubled on http://community.zevenseas.com/Blogs/Robin/archive/2008/11/09/quicktask-webpart.aspx (Read this blog, the guy deserves to be MVP). I asked the guy in question and he wasn't sure it was possible aswell.

I couldn't live with that awnser, so I tried finding a work-around and now I have one.

I must warn you, it's not advised to change SharePoint files, but this technique can be used for custom document libraries.

So lets start:

1. Modify schema.xml

Open your schema.xml of the default Document library (C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\FEATURES\DocumentLibrary\DocLib)

2. Locate List/MetaData/Fields

When found enter this custom Field, like this
image

     <!-- Customization This field is needed to display our customization -->

      <Field ID="{9d30f126-ba48-446b-b8f9-83745f322ebe}" ReadOnly="TRUE" Type="Computed" Name="LinkFilenameNoMenu2" DisplayName="Naam" DisplayNameSrcField="FileLeafRef" Filterable="FALSE" AuthoringInfo="(gekoppeld aan document)" SourceID="http://schemas.microsoft.com/sharepoint/v3" StaticName="LinkFilenameNoMenu" FromBaseType="TRUE">

    <FieldRefs>

      <FieldRef Name="FileLeafRef"/>

      <FieldRef Name="FSObjType"/>

      <FieldRef Name="Created_x0020_Date"/>

      <FieldRef Name="FileRef"/>

      <FieldRef Name="File_x0020_Type"/>

      <FieldRef Name="ContentTypeId"/>

      <FieldRef Name="PermMask"/>

      <FieldRef Name="CheckoutUser"/>

      <FieldRef Name="IsCheckedoutToLocal"/>

    </FieldRefs>

    <DisplayPattern>

      <IfEqual>

        <Expr1>

          <LookupColumn Name="FSObjType"/>

        </Expr1>

        <Expr2>1</Expr2>

        <Then>

          <FieldSwitch>

            <Expr>

              <GetVar Name="RecursiveView"/>

            </Expr>

            <Case Value="1">

              <LookupColumn Name="FileLeafRef" HTMLEncode="TRUE"/>

            </Case>

            <Default>

              <SetVar Name="UnencodedFilterLink">

                <SetVar Name="RootFolder">

                  <HTML>/</HTML>

                  <LookupColumn Name="FileRef"/>

                </SetVar>

                <SetVar Name="FolderCTID">

                  <FieldSwitch>

                    <Expr>

                      <ListProperty Select="EnableContentTypes"/>

                    </Expr>

                    <Case Value="1">

                      <Column Name="ContentTypeId"/>

                    </Case>

                  </FieldSwitch>

                </SetVar>

                <FilterLink Default="" Paged="FALSE"/>

              </SetVar>

              <HTML><![CDATA[<A onfocus="OnLink(this)" HREF="]]></HTML>

              <GetVar Name="UnencodedFilterLink" HTMLEncode="TRUE"/>

              <HTML><![CDATA[" onclick="javascript:EnterFolder(']]></HTML>

              <ScriptQuote NotAddingQuote="TRUE">

                <GetVar Name="UnencodedFilterLink"/>

              </ScriptQuote>

              <HTML><![CDATA[');return false;">]]></HTML>

              <!-- Changed this to Title instead of the FileLeafRef (url) -->

              <Field Name="Title"/>

              <!-- End Customization -->

              <IfEqual>

                <Expr1>

                  <GetVar Name="ShowAccessibleIcon"/>

                </Expr1>

                <Expr2>1</Expr2>

                <Then>

                  <HTML><![CDATA[<img src="/_layouts/images/blank.gif" class="ms-hidden" border=0 width=1 height=1 alt="]]></HTML>

                  <HTML>Druk op SHIFT+ENTER om het menu te openen (nieuw venster)</HTML>

                  <HTML><![CDATA[">]]></HTML>

                </Then>

              </IfEqual>

              <HTML><![CDATA[</A>]]></HTML>

            </Default>

          </FieldSwitch>

        </Then>

        <Else>

          <HTML><![CDATA[<A onfocus="OnLink(this)" HREF="]]></HTML>

          <Field Name="ServerUrl" URLEncodeAsURL="TRUE"/>

          <HTML><![CDATA[" onclick="return DispEx(this,event,']]></HTML>

          <ScriptQuote NotAddingQuote="TRUE">

            <ServerProperty Select="HtmlTransform"/>

          </ScriptQuote>

          <HTML><![CDATA[',']]></HTML>

          <ScriptQuote NotAddingQuote="TRUE">

            <ServerProperty Select="HtmlTrAcceptType">

              <Column Name="File_x0020_Type"/>

            </ServerProperty>

          </ScriptQuote>

          <HTML><![CDATA[',']]></HTML>

          <ScriptQuote NotAddingQuote="TRUE">

            <ServerProperty Select="HtmlTrHandleUrl">

              <Column Name="File_x0020_Type"/>

            </ServerProperty>

          </ScriptQuote>

          <HTML><![CDATA[',']]></HTML>

          <ScriptQuote NotAddingQuote="TRUE">

            <ServerProperty Select="HtmlTrProgId">

              <Column Name="File_x0020_Type"/>

            </ServerProperty>

          </ScriptQuote>

          <HTML><![CDATA[',']]></HTML>

          <ScriptQuote NotAddingQuote="TRUE">

            <ListProperty Select="DefaultItemOpen"/>

          </ScriptQuote>

          <HTML><![CDATA[',']]></HTML>

          <ScriptQuote NotAddingQuote="TRUE">

            <MapToControl>

              <Column Name="HTML_x0020_File_x0020_Type"/>

              <HTML>|</HTML>

              <Column Name="File_x0020_Type"/>

            </MapToControl>

          </ScriptQuote>

          <HTML><![CDATA[',']]></HTML>

          <ScriptQuote NotAddingQuote="TRUE">

            <Column Name="HTML_x0020_File_x0020_Type"/>

          </ScriptQuote>

          <HTML><![CDATA[',']]></HTML>

          <ScriptQuote NotAddingQuote="TRUE">

            <ServerProperty Select="GetServerFileRedirect">

              <Field Name="ServerUrl"/>

              <HTML>|</HTML>

              <Column Name="HTML_x0020_File_x0020_Type"/>

            </ServerProperty>

          </ScriptQuote>

          <HTML><![CDATA[',']]></HTML>

          <ScriptQuote NotAddingQuote="TRUE">

            <Column Name="CheckoutUser"/>

          </ScriptQuote>

          <HTML><![CDATA[',']]></HTML>

          <ScriptQuote NotAddingQuote="TRUE">

            <UserID AllowAnonymous="TRUE"/>

          </ScriptQuote>

          <HTML><![CDATA[',']]></HTML>

          <ScriptQuote NotAddingQuote="TRUE">

            <ListProperty Select="ForceCheckout"/>

          </ScriptQuote>

          <HTML><![CDATA[',']]></HTML>

          <ScriptQuote NotAddingQuote="TRUE">

            <Field Name="IsCheckedoutToLocal"/>

          </ScriptQuote>

          <HTML><![CDATA[',']]></HTML>

          <ScriptQuote NotAddingQuote="TRUE">

            <Field Name="PermMask"/>

          </ScriptQuote>

          <HTML><![CDATA[')">]]></HTML>

          <UrlBaseName HTMLEncode="TRUE">

            <!-- Changed this to Title instead of the FileLeafRef (url) -->

            <Field Name="Title"/>

            <!-- End Customization -->

          </UrlBaseName>

          <IfEqual>

            <Expr1>

              <GetVar Name="ShowAccessibleIcon"/>

            </Expr1>

            <Expr2>1</Expr2>

            <Then>

              <HTML><![CDATA[<img src="/_layouts/images/blank.gif" class="ms-hidden" border=0 width=1 height=1 alt="]]></HTML>

              <HTML>Druk op SHIFT+ENTER om het menu te openen (nieuw venster)</HTML>

              <HTML><![CDATA[">]]></HTML>

            </Then>

          </IfEqual>

          <HTML><![CDATA[</A>]]></HTML>

          <IfNew Name="Created_x0020_Date">

            <HTML><![CDATA[<IMG SRC="/_layouts/1043/images/new.gif" alt="]]></HTML>

            <HTML>Nieuw</HTML>

            <HTML><![CDATA[">]]></HTML>

          </IfNew>

        </Else>

      </IfEqual>

    </DisplayPattern>

  </Field>

      <!-- Customization -->

3. Locate Views/View base=1/ViewBody

Then search for

<Field />

Modify it to this:

image

            <!-- Customization -->

            <!-- I changed the logic

                 If the fieldsname equals Title render the ECB around it

                 else show the field (this will call the caml of the field itself)

             -->

            <FieldSwitch>

              <Expr>

                <Property Select="Name" />

              </Expr>

              <Case Value="Title">

                <!-- My Customization -->

                <Field Name="_EditMenuTableStart"/><!-- Makes the start of the ECB table -->

                <Field Name="LinkFilenameNoMenu2"/><!-- Displays a link with the Title as display -->

                <Field Name="_EditMenuTableEnd"/><!-- Makes the end of the ECB table -->

                <!-- Customization -->

              </Case>

              <Default>

                <!-- Default Field rendering -->

                <Field />

              </Default>

            </FieldSwitch>

4. Perform an IISReset

5. Et voila, this is the result

image

Records Center bug for long filenames

When you try to send documents to the records center that have a filename of 122 to 128 characters, then the records center throws exceptions.

After reflectoring the code I have found out that there's a bug in the check on the filename length. When the length of the file name with a unique extension added is longer than 128, then there's a miswritten substring executed. Instead of taking 128 and detract the extension it's reversed. So there's always a negative length in the substring.

This is written on the place where they create a new filename with the extension at the method Microsoft.Office.RecordsManagement.RecordsRepository.HoldingZone.StrMakeName in the Microsoft.Office.Policy dll.

Solution: make sure that the filename length is less than 122 before it's send to the records center or develop a custom router where you check the filename yourself.

Custom Fields with Custom Controls with Custom Properties

A lot of Custom in the title, but that's also the main purpose of this blog.

Let me begin with an explaination of what I mean with:

  • Custom Fields: Your own type of Column to be used in the lists. Examples are Telephone number (with multiple parts) or in my case a MultipleFileSelector
  • Custom Controls: Your custom type will mostlikely need a custom way of representing itself. Examples are multiple textboxes for the Telephone number or in my case a Javascript Popup to select your file and add it to a list.
  • Custom Properties: Your own properties that customize your own field.

It is that latest that forms the most problems and I'll post the solution for it in here.

The problem is that there just aint no information about how to make your own properties for your own fields. And the explenation there is, will only help you out a bit.

We want to get this, a drop down for the options.

image

It starts by defining the fields in your own custom fldtypes_blabla.xml file.

 

  <FieldType>

    <Field Name="TypeName">MultipleFileSelector</Field>

    <Field Name="ParentType">MultiColumn</Field>

    <Field Name="SQLType">nvarchar</Field>

    <Field Name="TypeDisplayName">Multiple File Selector Field</Field>

    <Field Name="TypeShortDescription">Multiple File Selector Field</Field>

    <Field Name="UserCreatable">TRUE</Field>

    <Field Name="ShowInListCreate">TRUE</Field>

    <Field Name="ShowInSurveyCreate">TRUE</Field>

    <Field Name="ShowInDocumentLibraryCreate">TRUE</Field>

    <Field Name="ShowInColumnTemplateCreate">TRUE</Field>

    <Field Name="Sortable">TRUE</Field>

    <Field Name="Filterable">TRUE</Field>

    <Field Name="AllowBaseTypeRendering">TRUE</Field>

    <Field Name="FieldTypeClass">xxxxx.xxxx.xxxx.MultipleFileSelector.MultipleFileSelectorField, xxxxx.xxxx.xxxx, Version=1.0.0.0, Culture=neutral, PublicKeyToken=xxxxxx</Field>

    <PropertySchema>

      <Fields>

        <Field Name="AllowedFileTypes" DisplayName="Allowed File types" Type="Choice">

          <Default>Email Types</Default>

          <CHOICES>

            <CHOICE>Office Types</CHOICE>

            <CHOICE>Email Types</CHOICE>

          </CHOICES>

        </Field>

      </Fields>

    </PropertySchema>

    <RenderPattern Name="DisplayPattern">

      <Switch>

        <Expr>

          <Column HTMLEncode="TRUE" />

        </Expr>

        <Case Value=""></Case>

        <Default>

          <HTML>

            <![CDATA[<SCRIPT type="text/javascript" language="JavaScript">var strHost = "]]>

          </HTML>

          <HttpHost URLEncodeAsURL="TRUE" />

          <HTML>

            <![CDATA[";var strOfUrls = "]]>

          </HTML>

          <Column HTMLEncode="TRUE" />

          <HTML>

            <![CDATA[";var arrOfUrls = strOfUrls.split(";#");var iLength = arrOfUrls.length;for(i=0;i < iLength;i++){if(arrOfUrls[i] != ""){var strFullUrl = strHost + arrOfUrls[i];var strHtml = strFullUrl.link(strFullUrl);if(i > "1"){strHtml = "<br/>" + strHtml};document.write(strHtml);}}</SCRIPT> ]]>

          </HTML>

        </Default>

      </Switch>

    </RenderPattern>

  </FieldType>

 

You need to add a PropertySchema to your field. This element has fields as childs and here you can add your Choices.

 

The next part is reading the selected value from within your field:

 

        /// <summary>

        /// This will allow you to define which types are possible

        /// </summary>

        public string AllowedFileTypes

        {

            get

            {

                return this.GetProperty("AllowedFileTypes");

            }

        }

 

And the last part is setting a default value in the schema.xml for your own Custom Lists like this:

<Field ID="{9422FF9B-123B-436b-8C1D-C6B953C4BA45}" SourceID="http://schemas.microsoft.com/sharepoint/v3" Type="MultipleFileSelector" Name="SupportingDocuments" StaticName="SupportingDocuments" DisplayName="Supporting Documents" Group="Custom" Hidden="FALSE" ReadOnly="FALSE" Required="FALSE" RowOrdinal="0" AllowedFileTypes="Office Types" />

 

If you combine this all you can get really handy fields like this:

image

This is a field that lets you select multiple files to add to your item. It uses ajax to fasten things up. It also uses the UrlAssetSelector to help you chose the files.

 

Small note: You always need to make a DisplayPattern in CAML or else your Field won't show up.

Customizing Menu's in SharePoint

In this blog I'll rant about how and what menu's you can change in SharePoint. The core of this article will be about adding items to the NewMenu.

Okay, so now you know what this article is about, let me make 2 things clear.

There is a difference in Menu's.

First you have the Left Menu called Quick Launch and the Top Menu called Top Navigation. The second kind of Menus are the following: SiteActions, Menu Toolbars, Personal Actions, Edit Control Blocks, ...

To manipulate the first set, you have different ways:

  1. Add links in your custom schema.xml. This will make sure that every site you create has the same links.
  2. Add NavigationNodes to QuickLaunch and TopNavigation collections in the SPWeb object of your site. This is a way to programatically change your menus. You'll find a lot of this on the web.
  3. Make your own SiteMapProvider and change the datasource of those ASP Menu's. I'm really fond of this way, because then I have absolute control about who sees what and I can do a lot more than what SharePoint offers you OOB. If you need more info about this, I can give you some ;)

To manipulate the second set, you have 2 options and they both require CustomAction features:

  1. Use the CustomAction with the UrlAction child element. This lets you define one link to a custom application page, url, ... . The key is that you have 1 element per custom action. There are also a lot of articles about this, so I'll skip this aswell.
  2. Use the CustomAction with ControlClass attribute. This lets you create a custom WebControl that will enable you to control whatever you want. This is what I want !!!!

Now we have more or less all the possibilities summed, I shall now focus on the latter way to have my Menu's behave how I want.

Before I move on I need to give you the following links:

http://msdn.microsoft.com/en-us/library/ms460194.aspx
http://msdn.microsoft.com/en-us/library/bb802730.aspx
http://johnholliday.net/resources/customactions.html

They are great resources about where you can put your links and what the GroupId & Locations are.

Okay now we're ready to start.

I mentioned you can do whatever you want with the ControlClass way, but to give you an Idea these are the things I do:

  • Hide Menus dynamically. Okay you can do a lot with Permissions, but sometimes it's just not that easily.
  • Add SubMenus dynamically. This is what I'll show you.

First you need to understand how the Feature System works.

It all starts with some user control who has a child repeater control who gets dynamically filled with ToolBarButtons, these ToolBarButtons get filled with MenuTemplates, which can be SubMenuTemplates and MenuItemTemplates.

SubMenuTemplates can hold SubMenuTemplates and MenuItemTemplates.

MenuItemTemplates are clickable and perform some action.

When you use the CustomAction feature with the ControlClass, your control gets wrapped around a FeatureMenuTemplate, which is a different kind of MenuTemplate.

So your Location field determines which user control will load your feature and the GroupId where your feature will get loaded.

To filter your can use RegistrationType and RegistrationId attributes. This lets you define on what kind of element your feature will work on.

Back to the ToolBarButtons, those are inherited to form special buttons, examples are NewMenu and ActionsMenu. By inheriting the ToolBarButton they can add special functionality to it. For example the NewMenu behaves very differently with a Survey list. It also fucks up your CustomAction, but I'll explain it in a moment.

Okay, now you should have an idea about how your control fits the puzzle.

So what do we need ?
A feature.xml
A elements.xml
A custom dll with your custom webcontrol.

Because we want our menu to be shown at the NewMenu we have another file aswell, my FixupJavaScript.js.

For those who have written CustomActions with custom WebControls, there is nothing new. Except when they tried to add it to the NewMenu, they should have noticed that nothing gets rendered. I have a solution for this. And for those who saw there control, but it was flickery, I also have a solution. Basicly I can do this:

image

So here's my code:

Feature.xml:
<?xml version="1.0" encoding="utf-8" ?>
<Feature Id="{DF5009DE-15B7-4397-9933-995727F3E276}"
         Title="New Template Selector"
         Description="Helps chosing templates from the New Document link"
         Version="1.0.0.0"
         Scope="Web"
         Hidden="FALSE"
         xmlns="
http://schemas.microsoft.com/sharepoint/" >
  <ElementManifests>
      <ElementManifest Location="elements.xml" />
  </ElementManifests>
</Feature>

elements.xml:

<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <CustomAction
    Id="CustomActionNewTemplateSelector"
    RequireSiteAdministrator="FALSE"
    GroupId="NewMenu"
    Location="Microsoft.SharePoint.StandardMenu"
    ControlAssembly="MyDLL"
    ControlClass="MyDLL.CustomTemplateSelector"
    Sequence="10"
    RegistrationType="List"
    RegistrationId="101"
    Title="New Template"
    Description="Use this menu to select a template"
    >
  </CustomAction>
   <!--RegistrationID 101 = Document Library -->
</Elements>

CustomTemplateSelector.cs:

/*
* This control dynamically loads the document templates for the different business units
* There are some extra's added to make it function under the NewMenu
*          - Override of the Render method that explicitly calls the RenderChildren function
*          - Addition of a Fixup Script to fix some javascript in the Core.Js
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.UI.WebControls;
using Microsoft.SharePoint.WebControls;
using Microsoft.SharePoint;
using System.Web.UI;
using Microsoft.SharePoint.Utilities;
using System.Web.UI.HtmlControls;

namespace xxxxx.xxxxxx.Controls
{
    /// <summary>
    /// This class will generate a dynamic Menu, which will allow us to select from the different templates
    /// </summary>
    public class CustomTemplateSelector: WebControl
    {
        #region Control Events
        protected override void OnLoad(EventArgs e)
        {
            // Ensure the control is build
            this.EnsureChildControls();
            base.OnLoad(e);
        }

        protected override void CreateChildControls()
        {
            // Register the improved javascript
            RegisterFixupScript();
            StringBuilder jsText = null;

            // Here is where all the action is.
            // Define the menu under which all the templates will hang
            SubMenuTemplate firstLevelMenuTemplate = new SubMenuTemplate();
            firstLevelMenuTemplate.ID = "CustomActionNewTemplateSelector";
            firstLevelMenuTemplate.Description = "Use this menu to select a template";
            firstLevelMenuTemplate.Text = "New Template";
            firstLevelMenuTemplate.Sequence = 10;
            //firstLevelMenuTemplate.MenuGroupId = 1000;

            // Add Child Menus
            for (int i = 0; i < 3; i++)
            {
                // Fill in your menuItemTemplate Properties
                SubMenuTemplate secondLevelMenuTemplate = new SubMenuTemplate();
                secondLevelMenuTemplate.ID = "menuItem" + i;
                secondLevelMenuTemplate.Text = "Title " + i;
                secondLevelMenuTemplate.Description = "Description " + i;
                secondLevelMenuTemplate.Sequence = i;
                //secondLevelMenuTemplate.MenuGroupId = 1000 + i;

                for (int j = 0; j < 2; j++)
                {
                    // Fill in the necessary properties
                    string strPathTemplate = "http:\u002f\u002flocalhost:33033\u002fShared Documents\u002fForms\u002ftemplate.doc";
                    string strSaveLocation = getSaveLocation();

                    // Build your javascript
                    // This Javascript will open your local application with the correct template
                    jsText = new StringBuilder();
                    jsText.AppendLine(@"createNewDocumentWithProgID('");
                    jsText.AppendLine(strPathTemplate);
                    jsText.AppendLine(@"','");
                    jsText.AppendLine(strSaveLocation);
                    jsText.AppendLine(@"','SharePoint.OpenDocuments', false)");

                    // Fill in your menuItemTemplate Properties
                    MenuItemTemplate thirdLevelItemTemplate = new MenuItemTemplate();
                    thirdLevelItemTemplate.ID = "menuItem" + j + i;
                    thirdLevelItemTemplate.Text = "Title " + j + i;
                    thirdLevelItemTemplate.Description = "Description " + i;
                    thirdLevelItemTemplate.Sequence = i * 10 + j;
                    thirdLevelItemTemplate.ClientOnClickScript = jsText.ToString();
                    thirdLevelItemTemplate.UseShortId = true;
                    //thirdLevelItemTemplate.MenuGroupId = 1000 + i * 10;

                    // Add it to the parent level
                    secondLevelMenuTemplate.Controls.Add(thirdLevelItemTemplate);
                }

                // Add the subMenuItem to your Menu
                firstLevelMenuTemplate.Controls.Add(secondLevelMenuTemplate);
            }

            // Return your menu
            this.Controls.Add(firstLevelMenuTemplate);
        }

        /// <summary>
        /// We need to override this, or else there will be a SPAN object around our <IE:MENUITEM> objects
        /// This SPAN object makes it impossible for the javascript in the core.js to build your menu
        /// </summary>
        /// <param name="output">The HTML Writer</param>
        protected override void Render(System.Web.UI.HtmlTextWriter output)
        {
            RenderChildren(output);
        }

        #endregion

        #region Private helper methods
        /// <summary>
        /// This method registers a deffered javascript that will override a core.js function
        /// </summary>
        private void RegisterFixupScript()
        {
            ((HtmlHead)Page.Header).Controls.Add(new LiteralControl("<script type='text/javascript' src='/_layouts/1033/FixUp.js' defer></script>"));
        }

        /// <summary>
        /// This methods finds out what the save location is of the document
        /// </summary>
        /// <returns>A absolute URL</returns>
        private string getSaveLocation()
        {
            string strSaveLocation;

            string strSiteUrl = SPContext.Current.Web.Url;

            // Check if you are in a Sub Folder
            if (HttpContext.Current.Request.QueryString["RootFolder"] == null)
            {
                // If not, add the RootFolder (= your list itself) it to your URL
                strSaveLocation = strSiteUrl + SPContext.Current.List.RootFolder.ServerRelativeUrl;
            }
            else
            {
                // If so, use the path in the RootFolder parameter
                strSaveLocation = strSiteUrl + HttpContext.Current.Request.QueryString["RootFolder"];
            }

            return strSaveLocation;
        }

        #endregion
    }
}

// If you want to hide whole menu's, add this code to the page_load event
// To Hide the menu button, use this code
// ((ToolBarMenuButton)((TemplateContainer)((FeatureMenuTemplate)this.Parent).Parent).Parent).Visible = false;

FixUp.js (place this in your layouts folder)

function MenuHtcInternal_Show(oMaster, oParent, y, fFlipTop)
{
    var oPopup=oMaster._arrPopup[oMaster._nLevel];   
    var nIndex;                           
    var fTopLevel;                           
    var oInnerDiv;
    if (!oMaster._oContents) PrepContents(oMaster);
    if (!oMaster._oContents || IsOpen(oMaster)) return;
    if (!oPopup && !oMaster._oRoot)
        {
        oMaster._nLevel=0;
        oMaster._oRoot=oMaster._oContents;
        }
    fTopLevel=oMaster._nLevel==0;
    fFlipTop=fFlipTop && fTopLevel;
    if (!oPopup)
    {
        oMaster._arrPopup[oMaster._nLevel]=document.createElement("DIV");
        oPopup=oMaster._arrPopup[oMaster._nLevel];
        oPopup.isMenu=true;
        oPopup.master=oMaster;
        oPopup.level=oMaster._nLevel;
        oInnerDiv=document.createElement("DIV");
        var oTable=document.createElement("table");
        var oTBody=document.createElement("tbody");
        oInnerDiv.isInner=true;
        oPopup.style.position="absolute";
        oInnerDiv.style.overflow="visible";
        oTable.appendChild(oTBody);
        oInnerDiv.appendChild(oTable);
        oPopup.appendChild(oInnerDiv);
        if (oMaster._fIsRtL)
            oPopup.setAttribute("dir", "rtl");
        else
            oPopup.setAttribute("dir", "ltr");
        document.body.appendChild(oPopup);
        FixUpMenuStructure(oMaster);
        var id=0;
        var childNodeLength=oMaster._oRoot.childNodes.length;
        for (nIndex=0; nIndex < childNodeLength; nIndex++)
        {
            var oNode=oMaster._oRoot.childNodes[nIndex];
            if (oNode.nodeType !=1)
                continue;
            if (!FIsIType(oNode, "label"))
            {
                var oItem=CreateMenuItem(oMaster, oNode, MakeID(oMaster, oMaster._nLevel, id));
                if (oItem) oTBody.appendChild(oItem);
                id++;
            }
        }
        oPopup.className="ms-MenuUIPopupBody";
        oTable.className=oMaster._wzMenuStyle;
        oTable.cellSpacing=0;
        oTable.cellPadding=0;
        oPopup.oncontextmenu=kfnDisableEvent;
        oPopup.ondragstart=kfnDisableEvent;
        oPopup.onselectstart=kfnDisableEvent;
        if (oParent._onmouseover==null)
            oParent._onmouseover=oParent.onmouseover;
        if (oParent._onmouseout==null)
            oParent._onmouseout=oParent.onmouseout;
        if (oParent._onmousedown==null)
            oParent._onmousedown=oParent.onmousedown;
        if (oParent._onclick==null)
            oParent._onclick=oParent.onclick;
        if (browseris.nav)
        {
            oPopup.onkeypress=function(e) {return false; };
            oPopup.onkeyup=function(e) {return false; };
            oPopup.onkeydown=function(e) {PopupKeyDown(e); return false; };
            oPopup.onmousedown=function(e) {TrapMenuClick(e); return false; };
            oPopup.onmouseover=function(e) {PopupMouseOver(e); return false; };
            oPopup.onmouseout=function(e) {PopupMouseLeave(e); return false; };
            oPopup.onclick=function(e) {PopupMouseClick(e); TrapMenuClick(e); return false; };
            oParent.onmouseover=function (e) {PopupMouseOverParent(e); return false; };
            oParent.onmouseout=function(e) {PopupMouseLeaveParent(e); return false; };
            oParent.onmousedown=function(e) {TrapMenuClick(e); return false; };
            oParent.onclick=function(e) {TrapMenuClick(e); return false; };
            oParent.oncontextmenu=function(e) {TrapMenuClick(e); return false; };
        }
        else
        {
            oPopup.onkeydown=new Function("PopupKeyDown(event); return false;");
            oPopup.onmousedown=new Function("TrapMenuClick(event); return false;");
            oPopup.onmouseover=new Function("PopupMouseOver(event); return false;");
            oPopup.onmouseout=new Function("PopupMouseLeave(event); return false;");
            oPopup.onclick=new Function("PopupMouseClick(event); TrapMenuClick(event); return false;");
            //oParent.onmouseover=new Function("PopupMouseOverParent(event); return false;");
            //oParent.onmouseout=new Function("PopupMouseLeaveParent(event); return false;");
            oParent.onmousedown=new Function("TrapMenuClick(event); return false;");
            oParent.onclick=new Function("TrapMenuClick(event); return false;");
            //oParent.oncontextmenu=new Function("TrapMenuClick(event); return false;");
        }
        if (fTopLevel)
        {
            var wzOnUnload=oMaster.getAttribute("onunloadtext");
            if (wzOnUnload) oPopup.onunload=new Function(wzOnUnload);
        }
    }
    else
    {
        var oOld=oMaster._arrSelected[oMaster._nLevel];
        if (oOld) UnselectItem(oOld);
    }
    oMaster._arrSelected[oMaster._nLevel]=null;
    var oBackFrame;
    if (browseris.ie)
    {
        var originalScrollLeft=document.body.scrollLeft;
        oBackFrame=document.createElement("iframe");
        AssureId(oBackFrame);
        oBackFrame.src="/_layouts/blank.htm";
        oBackFrame.style.position="absolute";
        oBackFrame.style.display="none";
        oBackFrame.scrolling="no";
        oBackFrame.frameBorder="0";
        document.body.appendChild(oBackFrame);
        oPopup.style.zIndex=103;
        oPopup._backgroundFrameId=oBackFrame.id;
        if (originalScrollLeft !=document.body.scrollLeft)
        {
            document.body.scrollLeft=originalScrollLeft;
        }
    }
    SetMenuPosition(oMaster, oParent, oPopup, oInnerDiv, fFlipTop, fTopLevel);
    if (browseris.ie)
    {
        SetBackFrameSize(null, oPopup);
        oPopup.onresize=new Function("SetBackFrameSize(event, null);");
        oBackFrame.style.display="block";
        oBackFrame.style.zIndex=101;
    }
}

There's more to be said.

Your Menu gets rendered by JavaScript, this javascript is located in the Core.Js. There are some problems with it, namely it doesn't really behave good when hovering on top of your custom menu.

You cannot insert basic javascript blocks to override this functionality, because the Core.Js gets loaded after your page has loaded. They've done this by adding the defer keyword to the script tag. That's why we need to this aswell, so our function gets loaded after the one in the core.js and thus override it.

I couldn't do this with Page.ClientScript. ... methods, because none has the option to add the defer keyword.

 

Have fun with it. If you do have problems with it, post a comment or mail us.

 

Pascal Van Vlaenderen
TeamLink Consultant

The Power of Data View Web Part

In my search to a nice Picture Web Part I came across some things.

2 free Flash Web Parts that SlideShow pictures from a Picture Library. Here are the links:
http://www.flexnetconsult.co.uk/WebParts/WebParts.htm

The downside of these Web Parts is that's it SlideShow WebParts, not really useful as Picture Viewer. But hey it's free, so you might want to test it J

The opposite of Flash is ofcourse SilverLight.

There is a nice free SilverLight project on codeplex called Slide.Show
http://www.codeplex.com/SlideShow

Very handsome and customizable SilverLight project, but … no SharePoint integration. I could have used my Web Part to host it, but no.

Second SilverLight option SilverLight Photoviewer. A photoviewer with the functionality you need. Except, it's in beta fase and doesn't run now J. It does however have SharePoint integration.
http://www.codeplex.com/bjspv

There was some a mention of using the Data View Web Part instead of a hosting Web Part. See: http://www.wssdemo.com/Blog/archive/2008/01/05/sharepoint-picture-library-silverlight-demo-working-again.aspx
Not my taste and I don't know enough SilverLight to adjust it.

All this made me come to the following solution.

A Data View Web Part to show and browse your pictures. How do you start ?

  1. Open SharePoint Designer and add a test page
  2. Add a Data View Web Part to it
  3. Select your Picture Library in the Data Source Panel
  4. Show Data
  5. Drag and drop the fields you need. One is enough to get started
  6. Now SharePoint Designer makes all the XSLT you need for the library

From here on I'll show you some tricks about how to get some decent stuff

If you want a some function you don't know how to start, first look at the common tasks:
Right click and go to the arrow

Paging is one of those things that require a lot of functions
This option shows all your items in sets of 6 and adds a footer containing the navigation you need

At the Layout tab you can define most of the basic layouts. Use this before you fine tune your XSLT

General shows some more functions

Select one field of a row and right click: Format as.
This lets you change the variable to images, links, textboxes,. …

Conditional Formatting can be used to hide, highlight, … stuff.
Right Click on the row



Code view lets us then "generate" what we want see the if block

Editing Formula gives us the possibility to change the results. Very handy as you'll see later.

Formula Screen

Openign the Formula screen from within code view. Inside a XSLT tag enter a space

If you use fields elsewhere like in my example, be sure not to forget {} or else the value won't be substituted.

Now you know the basics and can start editing in code view. I made 2 XSLT views with a little of JavaScript and some CSS and got this.

The most importing part is this line:
<a href="{@FileRef}" onmouseover="changePicture('{@FileRef}');"><img height="110" border="0" src="{concat('/', substring-before(substring-after(@FileRef, '/'),'/'), '/_t/', substring-after(substring-after(concat(translate(@FileRef,'.','_'),'.jpg'), '/'), '/'))}"></img></a>

I had to change the link a bit so I could use thumbnails which are located in another folder. /Pictures/_t/filename_extention.jpg

Result:

XSLT used for it:
<xsl:stylesheet xmlns:x="http://www.w3.org/2001/XMLSchema" xmlns:d="http://schemas.microsoft.com/sharepoint/dsp" version="1.0" exclude-result-prefixes="xsl msxsl ddwrt" xmlns:ddwrt="http://schemas.microsoft.com/WebParts/v2/DataView/runtime" xmlns:asp="http://schemas.microsoft.com/ASPNET/20" xmlns:__designer="http://schemas.microsoft.com/WebParts/v2/DataView/designer" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:SharePoint="Microsoft.SharePoint.WebControls" xmlns:ddwrt2="urn:frontpage:internal">    

    <xsl:output method="html" indent="no"/>

    <xsl:decimal-format NaN=""/>

    <xsl:param name="dvt_apos">'</xsl:param>

    <xsl:param name="dvt_firstrow">1</xsl:param>

    <xsl:param name="dvt_nextpagedata" />

    <xsl:variable name="dvt_1_automode">0</xsl:variable>    

    

    <!-- Here Starts the XSLT Render Process -->

    <xsl:template match="/" xmlns:x="http://www.w3.org/2001/XMLSchema" xmlns:d="http://schemas.microsoft.com/sharepoint/dsp" xmlns:asp="http://schemas.microsoft.com/ASPNET/20" xmlns:__designer="http://schemas.microsoft.com/WebParts/v2/DataView/designer" xmlns:SharePoint="Microsoft.SharePoint.WebControls">

        <!-- Add the javascript to change the picture -->

        <SCRIPT LANGUAGE="javascript">

            function changePicture(picture)

            {

                document.getElementById("imgPhoto").src = picture;

                document.getElementById("divPhoto").style.display = 'inline';

            }    

        </SCRIPT>

        <!-- Add the CSS for the Thumbnail row and the Picture Holder -->

        <style type="text/css">

            /* Class for the Photo Div */

            .photoClass

            {

                border: 1px solid #000000;

                background-color: #FFFFFF;

                width: 590px;

                padding: 10px;

                display: none;

            }

            /* Position the Thumbnail row*/

            #motioncontainer {

                /*margin:0 auto; Uncomment this line if you wish to center the gallery on page */

                width: 100%; /* Set to gallery width, in px or percentage */;

                height: 160px;

                vertical-align: middle;

                margin-bottom: 20px;

            }

            /* Add a small invisible box around the thumbnail */

            #motioncontainer a img {

                border: 1px solid white;

                vertical-align: middle;

            }

            

            /* Add a small gray rectangle around the thumbnail on hover */

            #motioncontainer a:hover img {

                border: 1px dashed #000000; /* Set image border hover color */

            }

        </style> <table width="100%">

            <tr>

                <td align="center">

                    <div id="motioncontainer" style="position:relative; overflow:hidden; margin-bottom:5px">

                        <div id="motiongallery" style="position:absolute;left:0;top:0;white-space: nowrap; vertical-align: middle; margin-bottom:20px;">

                            <nobr id="trueContainer">

                                <!-- Call the looping process -->

                                <xsl:call-template name="dvt_1"/>

                            </nobr>

                        </div>

                    </div>

                </td>

            </tr>

            <tr>

                <td align="center" valign="top">

                    <div id="divPhoto" class="photoClass">

                        <img id="imgPhoto" width="600"/>

                    </div>

                </td>

            </tr>    

        </table>

    </xsl:template>

    <!-- Here ends the XSLT Render Process -->

    <!-- The XSLT Body -->

    <xsl:template name="dvt_1">

    <!-- Here Starts the XSLT Render Process -->

        <xsl:variable name="dvt_StyleName">2ColFrm</xsl:variable>

        <xsl:variable name="Rows" select="/dsQueryResponse/Rows/Row" />

        <xsl:variable name="dvt_RowCount" select="count($Rows)" />

        <xsl:variable name="RowLimit" select="5" />

        <xsl:variable name="FirstRow" select="$dvt_firstrow" />

        <xsl:variable name="LastRow" select="$FirstRow + $dvt_RowCount - 1" />

        <xsl:variable name="IsEmpty" select="$dvt_RowCount = 0 or $RowLimit = 0" />

        

        <!-- Call the Header Template -->

        <xsl:call-template name="dvt_1.commandheader">

            <xsl:with-param name="FirstRow" select="$FirstRow" />

            <xsl:with-param name="LastRow" select="$LastRow" />

            <xsl:with-param name="RowLimit" select="$RowLimit" />

            <xsl:with-param name="dvt_RowCount" select="$dvt_RowCount" />

            <xsl:with-param name="RealLastRow" select="number(ddwrt:NameChanged('',-100))" />

        </xsl:call-template>

 

        <!-- Call the Body (the rows which are pictures here) Template -->

        <xsl:call-template name="dvt_1.body">

            <xsl:with-param name="Rows" select="$Rows" />

            <xsl:with-param name="FirstRow" select="1" />

            <xsl:with-param name="LastRow" select="$LastRow - $FirstRow + 1" />

        </xsl:call-template>

    </xsl:template>

    <!-- End of render process Template -->

    

    <!-- Here starts the Body Template -->

    <xsl:template name="dvt_1.body">

        <xsl:param name="Rows" />

        <xsl:param name="FirstRow" />

        <xsl:param name="LastRow" />

        <!-- Call the RowView Template for each Row (Picture) -->

        <xsl:for-each select="$Rows">

            <xsl:variable name="dvt_KeepItemsTogether" select="false()" />

            <xsl:variable name="dvt_HideGroupDetail" select="false()" />

            <xsl:if test="(position() &gt;= $FirstRow and position() &lt;= $LastRow) or $dvt_KeepItemsTogether">

                <xsl:if test="not($dvt_HideGroupDetail)" ddwrt:cf_ignore="1">

                    <xsl:call-template name="dvt_1.rowview" />

                </xsl:if>

            </xsl:if>

        </xsl:for-each>

    </xsl:template>

    <!-- Here ends the Body Template -->

    <!-- Here starts the RowView Template -->

    <xsl:template name="dvt_1.rowview">

        <!-- A Link is build per picture containing the thumbnail as link -->

        <a href="{@FileRef}" onmouseover="changePicture('{@FileRef}');"><img border="0" height="90" src="{concat('/', substring-before(substring-after(@FileRef, '/'),'/'), '/_t/', substring-after(substring-after(concat(translate(@FileRef,'.','_'),'.jpg'), '/'), '/'))}"></img></a>

                <xsl:if test="$dvt_1_automode = '1'" ddwrt:cf_ignore="1">

                            <span ddwrt:amkeyfield="" ddwrt:amkeyvalue="''" ddwrt:ammode="view" />

                </xsl:if>

    </xsl:template>    

    <!-- Here ends the RowView Template -->

    

    <!-- Here starts the Command Header Template -->

    <xsl:template name="dvt_1.commandheader">

        <xsl:param name="FirstRow" />

        <xsl:param name="LastRow" />

        <xsl:param name="RowLimit" />

        <xsl:param name="dvt_RowCount" />

        <xsl:param name="RealLastRow" />

        <table cellspacing="0" cellpadding="4" border="0" width="100%">

            <tr>

                <!-- If there is paging needed add it -->

                <xsl:if test="$FirstRow &gt; 1 or $dvt_nextpagedata">

                    <xsl:call-template name="dvt_1.navigation">

                        <xsl:with-param name="FirstRow" select="$FirstRow" />

                        <xsl:with-param name="LastRow" select="$LastRow" />

                        <xsl:with-param name="RowLimit" select="$RowLimit" />

                        <xsl:with-param name="dvt_RowCount" select="$dvt_RowCount" />

                        <xsl:with-param name="RealLastRow" select="$RealLastRow" />

                    </xsl:call-template>

                </xsl:if>

            </tr>

        </table>

    </xsl:template>

    <!-- Here ends the Command Header Template -->

    

    <!-- Here starts the Paging Template -->

    <xsl:template name="dvt_1.navigation">

        <xsl:param name="FirstRow" />

        <xsl:param name="LastRow" />

        <xsl:param name="RowLimit" />

        <xsl:param name="dvt_RowCount" />

        <xsl:param name="RealLastRow" />

        <xsl:variable name="PrevRow">

            <xsl:choose>

                <xsl:when test="$FirstRow - $RowLimit &lt; 1">1</xsl:when>

                <xsl:otherwise>

                    <xsl:value-of select="$FirstRow - $RowLimit" />

                </xsl:otherwise>

            </xsl:choose>

        </xsl:variable>

        <xsl:variable name="LastRowValue">

            <xsl:choose>

                <xsl:when test="$LastRow &gt; $RealLastRow">

                    <xsl:value-of select="$LastRow"></xsl:value-of>

                </xsl:when>

                <xsl:otherwise>

                    <xsl:value-of select="$RealLastRow"></xsl:value-of>

                </xsl:otherwise>

            </xsl:choose>

        </xsl:variable>

        <xsl:variable name="NextRow">

            <xsl:value-of select="$LastRowValue + 1"></xsl:value-of>

        </xsl:variable>

        <td nowrap="" class="ms-paging" align="center">

        <span style= "margin-right:5px">Count : <xsl:value-of select="count(/dsQueryResponse/Rows/Row)" /></span>

            <xsl:if test="$dvt_firstrow &gt; 1" ddwrt:cf_ignore="1">

                <a>

                <xsl:attribute name="href">javascript: <xsl:value-of select="ddwrt:GenFireServerEvent('dvt_firstrow={1};dvt_startposition={}')" />;</xsl:attribute>

                Start</a>

                <xsl:text disable-output-escaping="yes" ddwrt:nbsp-preserve="yes">&amp;nbsp;</xsl:text>

                <a>

                <xsl:attribute name="href">javascript: history.back();</xsl:attribute>

                <img src="/_layouts/images/prev.gif" border="0" alt="Previous" />

                </a>

                <xsl:text disable-output-escaping="yes" ddwrt:nbsp-preserve="yes">&amp;nbsp;</xsl:text>

            </xsl:if>

            <xsl:value-of select="$FirstRow" />

             - <xsl:value-of select="$LastRowValue" />

            <xsl:text xmlns:ddwrt="http://schemas.microsoft.com/WebParts/v2/DataView/runtime" ddwrt:nbsp-preserve="yes" disable-output-escaping="yes">&amp;nbsp;</xsl:text>

            <xsl:if test="$LastRowValue &lt; $dvt_RowCount or string-length($dvt_nextpagedata)!=0" ddwrt:cf_ignore="1">

                <a>

                <xsl:attribute name="href">javascript: <xsl:value-of select="ddwrt:GenFireServerEvent(concat('dvt_firstrow={',$NextRow,'};dvt_startposition={',$dvt_nextpagedata,'}'))" />;</xsl:attribute>

                <img src="/_layouts/images/next.gif" border="0" alt="Next" />

                </a>

            </xsl:if>

        </td>

    </xsl:template>

    <!-- Here ends the Paging Template -->

    </xsl:stylesheet>    

Changing the look and feel:

  1. Edit Page
  2. Modify Shared Web Part
  3. XSL Editor
  4. Paste your new

Second layout:

The XSLT:

<xsl:stylesheet xmlns:x="http://www.w3.org/2001/XMLSchema" xmlns:d="http://schemas.microsoft.com/sharepoint/dsp" version="1.0" exclude-result-prefixes="xsl msxsl ddwrt" xmlns:ddwrt="http://schemas.microsoft.com/WebParts/v2/DataView/runtime" xmlns:asp="http://schemas.microsoft.com/ASPNET/20" xmlns:__designer="http://schemas.microsoft.com/WebParts/v2/DataView/designer" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:SharePoint="Microsoft.SharePoint.WebControls" xmlns:ddwrt2="urn:frontpage:internal">    

    <xsl:output method="html" indent="no"/>

    <xsl:decimal-format NaN=""/>

    <xsl:param name="dvt_apos">'</xsl:param>

    <xsl:param name="dvt_firstrow">1</xsl:param>

    <xsl:param name="dvt_nextpagedata" />

    <xsl:variable name="dvt_1_automode">0</xsl:variable>    

    

    <!-- Here Starts the XSLT Render Process -->

    <xsl:template match="/" xmlns:x="http://www.w3.org/2001/XMLSchema" xmlns:d="http://schemas.microsoft.com/sharepoint/dsp" xmlns:asp="http://schemas.microsoft.com/ASPNET/20" xmlns:__designer="http://schemas.microsoft.com/WebParts/v2/DataView/designer" xmlns:SharePoint="Microsoft.SharePoint.WebControls">

        <!-- Add the javascript to change the picture -->

        <SCRIPT LANGUAGE="javascript">

            function changePicture(picture)

            {

                document.getElementById("imgPhoto").src = picture;

                document.getElementById("divPhoto").style.display = 'inline';

            }    

        </SCRIPT>

        <!-- Add the CSS for the Thumbnail row and the Picture Holder -->

        <style type="text/css">

            /* Class for the Photo Div */

            .photoClass

            {

                border: 1px solid #000000;

                background-color: #FFFFFF;

                height: 480px;

                padding: 10px;

                display: none;

            }

            /* Position the Thumbnail row*/

            #motioncontainer {

                /*margin:0 auto; Uncomment this line if you wish to center the gallery on page */

                height: auto; /* Set to gallery width, in px or percentage */;

                width: 145px;

                vertical-align: middle;

                margin-bottom: 20px;

            }

            /* Add a small invisible box around the thumbnail */

            #motioncontainer a img {

                border: 1px solid white;

                vertical-align: middle;

            }

            

            /* Add a small gray rectangle around the thumbnail on hover */

            #motioncontainer a:hover img {

                border: 1px dashed #000000; /* Set image border hover color */

            }

        </style> <table width="100%">

            <tr>

                <td align="center" width="150" valign="top">

                    <div id="motioncontainer" style="position:relative; margin-bottom:5px">

                        <div id="motiongallery" style="position:absolute;left:0;top:0;white-space: nowrap; vertical-align: middle; margin-bottom:20px;">

                            <nobr id="trueContainer">

                                <!-- Call the looping process -->

                                <xsl:call-template name="dvt_1"/>

                            </nobr>

                        </div>

                    </div>

                </td>

                <td align="center" valign="top" height="500">

                    <div id="divPhoto" class="photoClass">

                        <img id="imgPhoto" height="480"/>

                    </div>

                </td>

            </tr>    

        </table>

    </xsl:template>

    <!-- Here ends the XSLT Render Process -->

    <!-- The XSLT Body -->

    <xsl:template name="dvt_1">

    <!-- Here Starts the XSLT Render Process -->

        <xsl:variable name="dvt_StyleName">2ColFrm</xsl:variable>

        <xsl:variable name="Rows" select="/dsQueryResponse/Rows/Row" />

        <xsl:variable name="dvt_RowCount" select="count($Rows)" />

        <xsl:variable name="RowLimit" select="4" />

        

        <xsl:variable name="FirstRow" select="$dvt_firstrow" />

        <xsl:variable name="LastRow" select="$FirstRow + $dvt_RowCount - 1" />

        <xsl:variable name="IsEmpty" select="$dvt_RowCount = 0 or $RowLimit = 0" />

        

        <!-- Call the Header Template -->

        <xsl:call-template name="dvt_1.commandheader">

            <xsl:with-param name="FirstRow" select="$FirstRow" />

            <xsl:with-param name="LastRow" select="$LastRow" />

            <xsl:with-param name="RowLimit" select="$RowLimit" />

            <xsl:with-param name="dvt_RowCount" select="$dvt_RowCount" />

            <xsl:with-param name="RealLastRow" select="number(ddwrt:NameChanged('',-100))" />

        </xsl:call-template>

 

        <!-- Call the Body (the rows which are pictures here) Template -->

        <xsl:call-template name="dvt_1.body">

            <xsl:with-param name="Rows" select="$Rows" />

            <xsl:with-param name="FirstRow" select="1" />

            <xsl:with-param name="LastRow" select="$LastRow - $FirstRow + 1" />

        </xsl:call-template>

    </xsl:template>

    <!-- End of render process Template -->

    

    <!-- Here starts the Body Template -->

    <xsl:template name="dvt_1.body">

        <xsl:param name="Rows" />

        <xsl:param name="FirstRow" />

        <xsl:param name="LastRow" />

        <!-- Call the RowView Template for each Row (Picture) -->

        <xsl:for-each select="$Rows">

            <xsl:variable name="dvt_KeepItemsTogether" select="false()" />

            <xsl:variable name="dvt_HideGroupDetail" select="false()" />

            <xsl:if test="(position() &gt;= $FirstRow and position() &lt;= $LastRow) or $dvt_KeepItemsTogether">

                <xsl:if test="not($dvt_HideGroupDetail)" ddwrt:cf_ignore="1">

                    <xsl:call-template name="dvt_1.rowview" />

                </xsl:if>

            </xsl:if>

        </xsl:for-each>

    </xsl:template>

    <!-- Here ends the Body Template -->

    <!-- Here starts the RowView Template -->

    <xsl:template name="dvt_1.rowview">

        <!-- A Link is build per picture containing the thumbnail as link -->

        <a href="{@FileRef}" onmouseover="changePicture('{@FileRef}');"><img height="110" border="0" src="{concat('/', substring-before(substring-after(@FileRef, '/'),'/'), '/_t/', substring-after(substring-after(concat(translate(@FileRef,'.','_'),'.jpg'), '/'), '/'))}"></img></a>

        <br />

                <xsl:if test="$dvt_1_automode = '1'" ddwrt:cf_ignore="1">

                            <span ddwrt:amkeyfield="" ddwrt:amkeyvalue="''" ddwrt:ammode="view" />

                </xsl:if>

    </xsl:template>    

    <!-- Here ends the RowView Template -->

    

    <!-- Here starts the Command Header Template -->

    <xsl:template name="dvt_1.commandheader">

        <xsl:param name="FirstRow" />

        <xsl:param name="LastRow" />

        <xsl:param name="RowLimit" />

        <xsl:param name="dvt_RowCount" />

        <xsl:param name="RealLastRow" />

        <table cellspacing="0" cellpadding="4" border="0" width="100%">

            <tr>

                <!-- If there is paging needed add it -->

                <xsl:if test="$FirstRow &gt; 1 or $dvt_nextpagedata">

                    <xsl:call-template name="dvt_1.navigation">

                        <xsl:with-param name="FirstRow" select="$FirstRow" />

                        <xsl:with-param name="LastRow" select="$LastRow" />

                        <xsl:with-param name="RowLimit" select="$RowLimit" />

                        <xsl:with-param name="dvt_RowCount" select="$dvt_RowCount" />

                        <xsl:with-param name="RealLastRow" select="$RealLastRow" />

                    </xsl:call-template>

                </xsl:if>

            </tr>

        </table>

    </xsl:template>

    <!-- Here ends the Command Header Template -->

    

    <!-- Here starts the Paging Template -->

    <xsl:template name="dvt_1.navigation">

        <xsl:param name="FirstRow" />

        <xsl:param name="LastRow" />

        <xsl:param name="RowLimit" />

        <xsl:param name="dvt_RowCount" />

        <xsl:param name="RealLastRow" />

        <xsl:variable name="PrevRow">

            <xsl:choose>

                <xsl:when test="$FirstRow - $RowLimit &lt; 1">1</xsl:when>

                <xsl:otherwise>

                    <xsl:value-of select="$FirstRow - $RowLimit" />

                </xsl:otherwise>

            </xsl:choose>

        </xsl:variable>

        <xsl:variable name="LastRowValue">

            <xsl:choose>

                <xsl:when test="$LastRow &gt; $RealLastRow">

                    <xsl:value-of select="$LastRow"></xsl:value-of>

                </xsl:when>

                <xsl:otherwise>

                    <xsl:value-of select="$RealLastRow"></xsl:value-of>

                </xsl:otherwise>

            </xsl:choose>

        </xsl:variable>

        <xsl:variable name="NextRow">

            <xsl:value-of select="$LastRowValue + 1"></xsl:value-of>

        </xsl:variable>

        <td nowrap="" class="ms-paging" align="center">

        <span style= "margin-right:5px">Count : <xsl:value-of select="count(/dsQueryResponse/Rows/Row)" /></span>

            <xsl:if test="$dvt_firstrow &gt; 1" ddwrt:cf_ignore="1">

                <a>

                <xsl:attribute name="href">javascript: <xsl:value-of select="ddwrt:GenFireServerEvent('dvt_firstrow={1};dvt_startposition={}')" />;</xsl:attribute>

                Start</a>

                <xsl:text disable-output-escaping="yes" ddwrt:nbsp-preserve="yes">&amp;nbsp;</xsl:text>

                <a>

                <xsl:attribute name="href">javascript: history.back();</xsl:attribute>

                <img src="/_layouts/images/prev.gif" border="0" alt="Previous" />

                </a>

                <xsl:text disable-output-escaping="yes" ddwrt:nbsp-preserve="yes">&amp;nbsp;</xsl:text>

            </xsl:if>

            <xsl:value-of select="$FirstRow" />

             - <xsl:value-of select="$LastRowValue" />

            <xsl:text xmlns:ddwrt="http://schemas.microsoft.com/WebParts/v2/DataView/runtime" ddwrt:nbsp-preserve="yes" disable-output-escaping="yes">&amp;nbsp;</xsl:text>

            <xsl:if test="$LastRowValue &lt; $dvt_RowCount or string-length($dvt_nextpagedata)!=0" ddwrt:cf_ignore="1">

                <a>

                <xsl:attribute name="href">javascript: <xsl:value-of select="ddwrt:GenFireServerEvent(concat('dvt_firstrow={',$NextRow,'};dvt_startposition={',$dvt_nextpagedata,'}'))" />;</xsl:attribute>

                <img src="/_layouts/images/next.gif" border="0" alt="Next" />

                </a>

            </xsl:if>

        </td>

    </xsl:template>

    <!-- Here ends the Paging Template --></xsl:stylesheet>    

 

I hope you see how fast (if you are good at CSS / Javascript) you can write nice pages.

Btw: this is security trimmed J

Welcome to the TeamLink Blog

We hope we can give you a lot of intresting posts and most of all valuable information about SharePoint.

This blog will focus mainly on SharePoint content, but it will also cover the borders and overlaps with other Products.

Thanks for reading this.

TeamLink

TeamLink Share Point
SharePoint
ShaerPoint
Microsoft Office Server
Micrsooft Office Server
Microsoft Office Servre
Search Server
Search Server Express
Search Server Expres
TeamLink.be SharePointer
Moss
Moss 2007
WSS
Windows SharePoint Services

 ‭(Hidden)‬ Admin Links