March 22, 2011

Using the Source Property

For each of the properties in your template you can set a source for it, this isn’t always used but can improve user experience drastically when done throughout a site. The source field comes in to play whenever you are using any of the following fields: Droplink, Droplist, Droptree, File, Grouped Droplink, Grouped Droplist, Image, Multilist, Treelist, Rich text field and a number of others.

There are various ways of setting these up to achieve different results – but in general you are using the source to limit the set of items that can be used, and this requirement can also help you determine what kind of field to use. For example, if you have a Set of items all split down into sub folders and want the content editor to make use of the tree, you could use a TreeList or Drop Tree, but if you just want a set of items without the opportunity to see where those items are – multilists or droplinks are the way to go. For Images you’re generally just specifying where to look for and put the images within the media library, and for Rich text fields the source determines the type of editor to use (if not the default).

There are a number of options for setting the source property but not all can work with every field.

Setting the Root Node: To do this you just give the full path to the item you want to use as the ‘root’. This works with just about every field that pulls options and you can easily grab the path from the content pane when you select your desired item(looking at the Item Path). Ie: if you have a treelist and you only want to show the categories item and its children, you’d put in the path to that item: /sitecore/content/Data/Categories

Sitecore Query: This applies to a smaller set of fields (the List Fields), but gives a lot of power and is what I’ll mainly be going over. The fields you can use this with are: Checklist, Droplink, Droplist, Grouped Droplist, Grouped Droplink, or Multilist. You can also use the fast query: this has some limitations over just using sitecore query but gives benefits of better performance and using less memory.

Treelists are also a little special and can use parameters(I think some other fields will work with this as well, but I most often end up using the query on other items so I don’t have a ton of experience with this), you can specify the root item, what templates/items to display or ignore and which they can select, for example:

DataSource=/Sitecore/Content/Home/Root/Node&IncludeTemplatesForSelection=desiredTemplate1,desiredTemplate2&ExcludeTemplatesForDisplay=secretFolder&ExcludeItemsForDisplay=secretItem&AllowMultipleSelection=true

The above sets the root node to /Sitecore/Content/Home/Root/Node and allows the user to select items using desiredTemplate1 or desiredTemplate2, it also excludes secretFolder and secretItem from showing up in the list as well as allowing the user to choose more than one of the same item.

More on Sitecore Query

Using the query option over simply setting a root node improves the experience for your clients as well as helps to keep your data accurate. If you don’t want them to be able to pick a certain template or value or need to select something dependent on a specific axes – using sitecore query will make it possible.

In the source field, your queries need to begin with query: followed by your query. I’m going to go over a few examples I’ve found useful, but for a more detailed explanation of using Sitecore Query take a look at the Data Definition Reference, there is a Sitecore Query section that explains all the details!

So, a few useful tidbits:

* grabs all the children of a node: query:/sitecore/content/home/dessert/*  <--  the * grabs every child and / followed by text denotes the exact item name you’re looking at. So you could also mix this up a bit and return query:/sitecore/home/*/pie/* <-- this will grab all the items that have a parent pie from any item under home with the pie grandchild.

. references the context item, this can be handy if you need to find the ancestors, children or anything along the axes (if you need just the parent, use: .. ): query:./pies/* <-- if we were the dessert item, this would grab all the grandchildren with the parent pie.

// is the descendant axis – this should be used Very sparingly but can be done the following way: query:/sitecore/content/home//pie/* <-- this grabs all the items with a parent pie under home. So that would include, home/pie/*, home/anything/pie/* and so on. The fear with using this is that you’re going to return the whole tree or a whole section which might have thousands of items, so when considering using the descendant axis or any query, be mindful of the result set you will get.

@ denotes a field, and @@ denotes an xml attribute for the item, you’ll probably be using mainly @@templatename or @@templateid.

For example: query:/sitecore/content/home/dessert/*[@pastry=’1’] <-- this grabs all the items under desserts which have the checkbox ‘pastry’ checked (so it might return pies).

Sitecore query also supports the xpath axes, allowing you to use things like ancestor-or-self, following and preceeding (siblings) and so on:

query:./ancestor-or-self::*[@@templatename='Site']/Data/Touts/*

For a more practical example in a multisite solution, the above takes the current item, finds an ancestor or itself that represents the top ‘site’ item and then find the Data folder and then grabs all the children of the Touts folder.

Logical operators can be used to combine options as well, so we could look for query:./*[@@templatename='template1' or @@templatename='template2'] or something more like query:./pies/*|./cakes/* <-- this would give both children of pies and cakes instead of choosing one or the other.

There are also functions you can use (here’s a link with a listing of a number of useful functions), primarily I end up using: position(), last(), and contains()

To use them, you’d do something like query:./*[position()=1] <-- grabs the first item

query:./*[position()=last()] <-- grabs the last item

query:./*[contains(@ingredients,’apple’)] <-- grabs the items with ‘apple’ in their ingredients field, this could also be written as: query:./*[@ingredients = '%apple%']

To test out any query, you can always open up the developer center and then open the xpath builder. You do not need query: before your query but you do need to include fast: if you want to use the fast query.

These queries can become pretty complex depending on your needs, but that initial work can leave content editors with a very easy to use and understand set of items and fields. Leave a comment if you know of any good query examples or are wondering how to form a query to meet your needs (I’ll try to help)!

March 7, 2011

Getting Started with Breadcrumbs

Breadcrumbs have been covered by just about everyone so there are lots of examples that all seem to do things a Little differently. With that in mind I’m going to keep this short with my example and two other examples I’ve found that might also meet your needs and cover the basics for just about every xslt breadcrumb example you’ll find.

The general idea: you’re at item c, in your tree the path is something like:  /sitecore/content/a/b/c and you want to display a pretty html list for a » b » c anywhere on your site.  You’ll always be dealing with the ancestors of your current item so you’ll be making use of $sc_currentitem/ancestor-or-self::… somewhere.

You’ll need to go through each ancestor item and display it, probably checking to see if you’re at the last item so you don’t display a ‘»’ after the final item. You also need to make sure to not display unwanted ancestors in your breadcrumb, being /sitecore and /content in our case.

So onto the examples!

First is the Sitecore breadcrumb xslt example: http://sdn.sitecore.net/Articles/XSL/Breadcrumb%20Example.aspx
  You will need a login to sdn to view this, but the magic is that it does a for-each across ancestor-or-self::item and then has an if statement to make sure that position()> 2 (this avoids the sitecore/content portion) and avoiding folders and there is the requisite check for position()!=last() so that we do not have the extra » after c.

Next up is Brian Pedreson’s breadcrumb example http://briancaos.wordpress.com/2009/02/09/breadcrumb-in-sitecore/
Similar to the above, however in this case he only selected items which had the appropriate template and a check to make sure the items should be in the navigation at all:
select="$sc_currentitem/ancestor-or-self::item[sc:IsItemOfType('mypages',.) and sc:fld('ShowInMenu',.)='1']"

I am certain there are many many more breadcrumb examples, but these were the first I was able to find easily to share.

Finally, my contribution to the breadcrumb party:

  <xsl:template match="*" mode="main">
<
div>
<
ul class="breadcrumb">
<
xsl:variable name="ancestors" select="$sc_currentitem/ancestor-or-self::item[ancestor-or-self::item/@template='home page']" />
<
xsl:for-each select="$ancestors">
<
li>
<
xsl:choose>
<
xsl:when test="position()=last()">
<
sc:text field="Breadcrumb Title" />
</
xsl:when>
<
xsl:otherwise>
<
sc:link>
<
sc:text field="Breadcrumb Title" />
</
sc:link> »
</xsl:otherwise>
</
xsl:choose>
</
li>
</
xsl:for-each>
</
ul>
</
div>
</
xsl:template>

To satisfy the condition of not showing /sitecore or /content, I am only grabbing ancestors (or self) who have the ancestor (or is the item) that has the special template for the Home item. This excludes anything above the home item, but includes the home item too so that it can be listed. And we end up with a » b » c.


Hope this can be helpful if you are getting started with breadcrumbs!

February 24, 2011

Links as Items Redux!

Previously I had posted on how to set up items in your content tree to act as external links to other pages (for use with Navigation mainly – for example if you have a blog elsewhere but still want it listed in the main navigation). However, Ivan Buzyka pointed out some issues with the simple implementation so I added creating a better redirect to my ‘to do’ list for the blog. The time has come!

Let’s pretend we are modifying an existing site, we don’t want to change the navigation so that won’t be covered here – we just want to update our layout to work a little more universally. Our new items need to be able to link to an internal, external or Media item reliably for display in our navigation. Our template will consist of similar things to last time:

Link: General Link

Nav Title: Text -> standard values: $name

In Navigation: Checkbox ->standard values: checked

Create the template, add in standard values for it with the above settings and now we can create our Layout which should be assigned to the standard values of the new template.

In my layout is the following (inside the page load):

String url;
Item extItem = Sitecore.Context.Item;
LinkField extLink = (LinkField)(extItem.Fields["Link"]);
if (extLink != null)
{
if (extLink.IsInternal && extLink.TargetItem != null)
{
url = Sitecore.Links.LinkManager.GetItemUrl(extLink.TargetItem);
}
else if (extLink.IsMediaLink && extLink.TargetItem != null)
{
url = Sitecore.StringUtil.EnsurePrefix('/', Sitecore.Resources.Media.MediaManager.GetMediaUrl(extLink.TargetItem));
}
else
{
url = extLink.Url;
}
}
else
{
Item homeItem = Sitecore.Context.Database.GetItem(Sitecore.Context.Site.StartPath);
url = Sitecore.Links.LinkManager.GetItemUrl(homeItem);
}
if (!String.IsNullOrEmpty(url))
{
Response.Redirect(url);
}

To step through it: we’re setting the default to bring the user back to the home page just in case something goes wrong. From there, we check to see if the Link field exists and what type of link it is.

For an internal link, we grab the url for the item itself, and for the media item, we’re grabbing the url for the Media item to be displayed (or pdf etc.), and if it’s external – we’re just redirecting them to the url they specified.

If we stopped here, everything would be working great as long as the content was entered appropriately, however, that doesn’t always happen and we’d like to avoid this going boom. To do that we can add a simple validator: open up the content tree within Sitecore and then head to your template, expanding out the children and select the Link field item.

Scroll down to Validation in the Data section.

We want to make sure that the Link field is Always one of the following: and Internal link, a Media item, or an external Link. Also, we want it to have Some value.

Within Validation you’ll need to put the actual content you want to validate, and ValidationText is what will appear if that is not met. This will pop up when the user tries to save the item with an improper value.

validation

Shown above is the Validation and our error message: linktype is how we can determine what sort of link it is, and is generated automatically when a user selects their link (unless they are editing raw values). Our validation just makes sure that the linktype text contains one of those three options (internal, media, or external) and as long as one of those match the text in the raw value for the field we have a valid link.

This helps prevent a scenario where the user has used one of the other options for an external link which would stop the page from going anywhere.

You can also add in some of the default validation options – I'd recommend adding the Required field validator as well.

If you have any tips to help improve this further please let me know!

February 18, 2011

Adding your own Icons

I have returned from blogger oblivion – stay tuned for more frequent updates! I’m looking forward to meeting people at Dreamcore this year – I’ll  be sure to update as that is happening.

Back to the topic: adding your own icons! As you may have noticed, items can be configured to have an icon – and Sitecore provides an extensive list of them. But you may want to add your own for whatever reason. To do this you’ll need an image suitable for making into an icon, and the ability to resize this image to the correct sizes (Paint.net, Photoshop, GIMP).logo

For our example we’re making an Arke Icon and we're going to say our largest icon will be 128x128, so we have a transparent png called logo.png to work with: 

The image you want to use should have a transparent background unless you want the icon to be a square, and ideally not overly detailed as it will be very small.

Next, we need to make this image into various sizes, and put logo.png into the appropriately named directories, the structure is as follows (if you have several icons, just do the same thing by putting multiple icons into each size folder):

  • ArkeIcon
    • 16x16
      • logo.png
    • 24x24
      • logo.png
    • 32x32
      • logo.png
    • 48x48
      • logo.png
    • 128x128
      • logo.png

Zip this all up with the same name as the containing folder, so ArkeIcon.zip

Upload this new zip file to /sitecore/shell/Themes/Standard/ and make sure the permissions are correct for your installation (check the other files such as Application.zip for a comparison).

Back within your content editor: each item has an Icon field and you can now enter in your custom icon by entering: ArkeIcon/16x16/logo.png

Once you do this, the new icon will show up in the list of recently used icons as well.

As for adding the new icon set to the list of usable icons – that’s a little more tricky since the list is specified statically (if you know a good way of changing this please share).

You can however modify the existing sets/zips of images, such as the aforementioned application.zip – just add your image to the appropriate directories and you can use it just like all the other icons!