Wesley Bakker

Interesting things I encounter doing my job...

Sponsors

News

Wesley Bakker
motion10
Rivium Quadrant 151
2909 LC Capelle aan den IJssel
Region of Rotterdam
The Netherlands
Phone: +31 10 2351035

(feel free to chat with me)
 

Add to Technorati Favorites

December 2008 - Posts

Eliminate page flicker in SharePoint

Happy with SharePoint

Sometimes I'm really happy with SharePoint and sometimes I'm not(read previous post). Today I'm happy again. In creating a connected webpart(read previous post) I noticed a very long and irritating page flicker. Normaly I don't really bother and to all those implementing a complete ajax solution just because of a little page flicker: Get a life! So how to solve this page flicker in SharePoint without adding an updatepanel?

IE only

To solve a problem we first need to set it's boundries. And in this case it is bounded to IE. Other browsers resolve the page flicker themselves. So we nee a solution for IE only. Hmm.. wait a second. I solved this issue many times before, without a single line of javascript. The page flicker has always annoyed me on websites that have a dark background color, such as Diveplace. I solved it by simply adding a page transition metatag into the header of my masterpage. This metatag looks like this: <meta http-equiv="Page-Exit" content="blendTrans(Duration=0.0)" />

Additional Page Head

The reason that I'm happy again is that I could create a new SharePoint feature really within minutes and the page flicker is resolved. All you need to do is create a usercontrol that contains this metatag and create a SharePoint feature that adds this UserControl to our AdditionalPageHead delegate control. Just like I showed you before.

So I solved one of the biggest SharePoint issues!!(if i may believe all the folks that implement AJAX on websites because of page flicker only)

Cheers and have fun,

Wes

SharePoint joke of the day

Did you hear that one about the IWebPartTable interface?

Once there was an interface that Microsoft and a lot of MVP's and best practice guys tell you to use for connecting web parts to one another. It was called the IWebPartTable interface. And than one day when somebody actually created a webpart that consumes that specific interface he found out that none of the Microsoft SharePoint 2007 list web parts actualy implement the interface. Woohoo.... this is really funny... use this interface to make shure you CAN'T connect to the built in list view web parts! Great laugh! Best joke ever!

You can find a great tutorial on how to create a useless IWebPartTable connection consumer over here. If you really don't know how to waste your time this is a great read.

(very big sigh)

 

Cheers,

Wes

P.S. If you do like to connect to list view web parts... implement the so called 'obsolete' IListConsumer.

Posted: Dec 22 2008, 01:37 PM by webbes | with 2 comment(s)
Filed under:
SharePoint + jQuery = Stay Here Feature

Fun with jQuery and SharePoint

In my previous post I showd how to create a slideshow in SharePoint with the help of jQuery and the Cycle plugin. Yesterday someone asked me for a feature that takes care of opening all external urls in a new window. That makes sense doesn't it. You do not want visitors to leave your SharePoint site to soon. You want them to Stay Here. And with our jQuery feature in place it's a piece of cake so I decided to create the motion10 Stay Here feature.

The code

All this feature needs is a little javascript. This script must select al hyperlinks on the page that do not have the target attribute set and a different host than the current host. When we have the selected links we need to add the target attribute and that's all. So here's the script.

$(function() {
    $('a').filter(function() {
        return !this.target && this.hostname && this.hostname !== location.hostname;
    }).each(function(){$(this).attr("target", "_blank")});
});

How to create a feature

Actually we would like to have this script in all pages of our sitecollection. Hmmmm.... that sounds familiar doesn't it? Again we can use the Delegate Control to add this script to the head of every page. So the script goes to the layouts directory and we create a User Control that just contains a script reference.

<%@ Control="" Language="C#" ClassName="jQueryStayHereControl" %>

<script type="text/javascript" src="/_layouts/jQuery/Plugins/jquery.stayhere.js"></script>

And just like we did with our Cycle plugin we add this control to our elements collection.

<?xml version="1.0" encoding="utf-8" ?>

<Elements xmlns="http://schemas.microsoft.com/sharepoint/">

  <Control

  Id="AdditionalPageHead"

  ControlSrc="~/_controltemplates/jQuery/Plugins/jQueryStayHereControl.ascx"

  Sequence="1" />

</Elements>

We must not forget our jQuery dependency though. So in our feature.xml we add an Activation Dependency and that's all.

<?xml version="1.0" encoding="utf-8"?>

<Feature  Id="853d13a2-3bbf-411e-b8a5-ef0a30d4636f"

          Title="motion10 jQuery Stay Here Plugin"

          Description="If you enable this feature all external links on your site will be opened in a new window."

          Version="12.0.0.0"

          Hidden="FALSE"

          Scope="Site"

          DefaultResourceFile="core"

          Creator="Wesley Bakker"

          ImageUrl="motion10/FeaturesIcon.png"

          ImageUrlAltText="http://www.motion10.com"

          xmlns="http://schemas.microsoft.com/sharepoint/">

  <ActivationDependencies>

    <ActivationDependency FeatureId="f805f632-a321-435c-9d13-025454e3fd5a"/>

  </ActivationDependencies>

  <ElementManifests>

    <ElementManifest Location="elements.xml"/>   

  </ElementManifests>

</Feature>

By activating the feature the user control is added to the head of our page which loads the script which in turn makes all of our links to external websites open in a new window.

Please do feel free to download the motion10 SharePoint Solution Pack. It contains all of the source and an installation folder. Oh... and you might find some extra features in there. I'll try to add a new feature every two weeks and update the package. So if you do have some good ideas for features just leave me a comment or drop me an email and we'll se what I can do. I hope my next feature will enable Google Analytics on your site. Busy with that one because I need to add an application page to enable you to configure your Google user account id.

Cheers,

Wes

Posted: Dec 18 2008, 11:00 AM by webbes | with 4 comment(s)
Filed under: ,
SharePoint Slideshow Web Part

Slideshow for SharePoint

In two previous posts I demonstrated how you could use wrappers for list items in order to enable strongly typed access to list item properties. Very nice but I can imagine you guys and girls would like to see a real life example of it's usage. And I guess it would be very nice if I could come up with something that we can actually use in our project today. So I decided to create a slideshow web part. With the help of: jQuery, the jQuery Cycle plugin and a PictureWrapper I created a very basic slideshow. It's not completely finished, but I'll leave the addition of some extra options as practice for you guys. If you're not interested in my writing you can download the complete source and the Windows SharePoint Solution Package at the end of this article. It has been created with the help of WSP Builder. The must have tool for all SharePoint developers.

Screenshot

PictureWrapper

To get me started I first had to create a wrapper arround picture items. This wrapper is responsible for returning pictures from a PictureLibrary. To make shure we have all our needed fields I filter on contentTypeId and I make sure the ViewFields contains al the nececary field refrences. If you read the previous articles about wrapping list items this is all straight forward.

internal sealed class PictureWrapper

{

    private static readonly string contentTypedId = "0x010102";

 

    private SPListItem listItem;

    internal PictureWrapper(SPListItem listItem)

    {

        if (listItem == null)

        {

            throw new ArgumentNullException("listItem");

        }

 

        this.listItem = listItem;

    }

 

    internal static string ContentTypeId

    {

        get

        {

            return contentTypedId;

        }

    }

 

    internal string NameOrTitle

    {

        get

        {

            return listItem.GetValue<string>("NameOrTitle", string.Empty);

        }

    }

 

    internal string Url

    {

        get

        {

            return listItem.GetValue<string>("Url", string.Empty);

        }

    }

 

    internal string ThumbnailUrl

    {

        get

        {

            return listItem.GetValue<string>("EncodedAbsThumbnailUrl", string.Empty);

        }

    }

 

    internal string WebImgUrl

    {

        get

        {

            return listItem.GetValue<string>("EncodedAbsWebImgUrl", string.Empty);

        }

    }

 

    internal static IEnumerable<PictureWrapper> GetItems(string listUrl, string viewName)

    {

        if (string.IsNullOrEmpty(listUrl))

        {

            throw new ArgumentNullException("listUrl");

        }

 

        SPList itemsList = CycleHelper.GetListByUrl(listUrl);

        SPView itemsView = null;

 

        if (!string.IsNullOrEmpty(viewName))

        {

            itemsView = itemsList.Views[viewName];

        }

 

        if (itemsView == null)

        {

            itemsView = itemsList.DefaultView;

        }

 

        SPQuery query = new SPQuery(itemsView);

        query.Query = string.Format(CultureInfo.InvariantCulture,

                                    "<Where><BeginsWith><FieldRef Name='ContentTypeId'/><Value Type='Text'>{0}</Value></BeginsWith></Where>",

                                    ContentTypeId);

 

        query.ViewFields = "<FieldRef Name='NameOrTitle'/><FieldRef Name='Url'/><FieldRef Name='EncodedAbsThumbnailUrl'/><FieldRef Name='EncodedAbsWebImgUrl'/>";

 

 

        SPListItemCollection items = itemsList.GetItems(query);

 

        foreach (SPListItem item in items)

        {

            yield return new PictureWrapper(item);

        }

    }

}

Using the PictureWrapper

Since we have a PictureWrapper we can access our properties strongly typed. Which is what we'll do in our PictureCycle web part. The web part generates an unordered list with which the Cycle plugin can create a slideshow. Access to our properties is really as simple as this.

foreach (PictureWrapper wrapper in pictureListItems) {

    HtmlGenericControl li = new HtmlGenericControl("li");

    HtmlImage img = new HtmlImage();

    img.Alt = wrapper.NameOrTitle;

    img.Attributes.Add("title", img.Alt);

 

    img.Src = (Size == DisplaySize.WebImage) ? wrapper.WebImgUrl : wrapper.ThumbnailUrl;

 

    li.Controls.Add(img);

    _container.Controls.Add(li);

}

jQuery and the Cycle plugin

Our PictureCycle web part uses both jQuery and the Cycle plugin and it took me a while to figure out a decent way of implementing both in our solution. I do not want every control to register jQuery or the plugins. So I decided to create two seperate features for taking care of that. I took the great example of mister Tielens and enhanced it a little bit by adding the Sequence attribute to the Control Element like so:

<?xml version="1.0" encoding="utf-8" ?>

<Elements xmlns="http://schemas.microsoft.com/sharepoint/">

  <Control

    Id="AdditionalPageHead"

    ControlSrc="~/_controltemplates/jQuery/jQuery126Control.ascx"

    Sequence="0"/>

</Elements>

With the Sequence attribute we ensure ourselves that the jQuery script is being added to the header before our plugins which get a Sequence of anything greater than 0

Another thing we need to do is make sure that we activate our features in the correct order. This can be done very simple by adding feature activation dependencies. The Cycle plugin depends on jQuery so we add the FeatureId of our jQuery feature as an activation dependency to our Cycle plugin feature like so:

<?xml version="1.0" encoding="utf-8"?>

<Feature  Id="9da8615f-49d1-4d14-b3d3-35f6e45ec16b"

          Title="motion10 jQuery Cycle Plugin"

          Description="This feature adds the jQuery Cycle Plugin to your site."

          Version="12.0.0.0"

          Hidden="FALSE"

          Scope="Site"

          DefaultResourceFile="core"

          Creator="Wesley Bakker"

          ImageUrl="motion10/FeaturesIcon.png"

          ImageUrlAltText="http://www.motion10.com"

          xmlns="http://schemas.microsoft.com/sharepoint/">

  <ActivationDependencies>

    <ActivationDependency FeatureId="f805f632-a321-435c-9d13-025454e3fd5a"/>

  </ActivationDependencies>

  <ElementManifests>

    <ElementManifest Location="elements.xml"/>

  </ElementManifests>

</Feature>

A lot more...

Of course there is a lot more in the download. We need some javascript to enable the creation of slideshows in one simple line. We need some styling as well. Both the script and the styling are added as embedded resources. Just as an example on how you could accomplish something like that.

So far for now. Please leave comments if you like it or when you see room for improvement.

Cheers,

Wes

More Posts