Sitecore Preview Notifications

Within page editor you can setup custom info bars to feedback more info to your users using page editor notifications. An example of this is:
notification

Custom notifications can be patched into the app via:

Where your custom code implements:

In this example, I based my implementation on Sitecore.Pipelines.GetPageEditorNotifications.GetWorkflowNotification, Sitecore.Kernel

In order to get notifications showing in preview you need to customize things slightly. The toolbar shown in preview and page editor is the WebEditRibbonForm. This is linked into the ui via:
/sitecore/shell/applications/webedit/webeditribbon.aspx
The line that ties the class and the aspx together is:

Using reflector I extracted out the existing implementation of WebEditRibbonForm and extended to work with preview:

An interesting challenge is the need to use reflection to call private static methods on the base class:

The only thing you now need to do is patch in your own custom pipeline:

Find missing Sitecore help text

In Sitecore, field names alone dont always give context to the data that editors are updating. On template fields you can set the Short Description field – this then shows the text next to the field. Some examples are:

It may be a strict requirement that help text is set on all fields, or help text on all fields matches a given pattern. The command and / or query below shows how to find missing Sitecore help text.

In the sitecore command example the code also modifies the help text to set the first letter as a capital if its lower case.

Note, there are constants available for all fields ids. The text value was used to highlight the __. The code forces the language to ‘en’ since all our templates are created in that language.

You then patch this into the application via:

Finally, you need to add a button to core and set its click to be ‘item:validatehelptext’

I thought it would be interesting to try the same thing using Sitecore Rocks Query. There are some really handy blog posts on this – have a look at Sitecore Rocks Query Examples for more info.

I like both these approaches for tracking down missing items – it’s safe to say trawling through fields manually is both time consuming, boring and error prone!

Remove unwanted language versions from Sitecore subtree

This post ties nicely into the idea thats shown in /automatically-set-the-language-of-the-content-editor

If you have a multi site solution, chances are each site has a finite set of languages available to it. In this example we have one language per site ala:

– sitecore
– Content
— English site – field with value for default language set to be ‘en’
— French site – field with value for default language set to be ‘fr-fr’

Its easy to create invalid language content under each site. This not only bloats the amount of data being stored but can also be quite misleading, its easy to edit content on the wrong language.

The code below demonstrates a Sitecore command which allows these invalid items to be purged from the tree.

It assumes the website root item has a template with a known ID (WebsiteTemplate) and on this item there is a shared droplist field: Default Language which has its source set to /sitecore/system/Languages

This is then patched into the Sitecore commands via:

You can then setup a new button in your ribbon by creating a new item in core. In this example, within the versions chunk of the ribbon:
/sitecore/content/Applications/Content Editor/Ribbons/Chunks/Versions/

You need to fill out ‘Click’ to be item:purgeversions and then choose the icon you want.

By overriding the QueryState function the button only shows if:

  • You are below a website root item
  • You are on the valid language set on the website root item <- this is really cool since it means you can only remove invalid language versions

Taking this forwards, if you had multiple languages per site you’d need to update some of the logic to deal with lists of languages rather than 1 language.

Sitecore AddVersion returns null

In a multi-lingual build we’d given the user a new toolbar button to create a copy of the given item in a given language. The logic behind the scenes would create a version of the new item in the destination language, scan the original item and copy all the field values to the destination. It would also then reset things like workflow on the destination item.

As part of this logic we’d call:

but would sometimes find itemTo would be null.

With the help of support, they pointed us towards the <sites> configuration and the following attribute:
filterItems: If true, the site will always show the current version of an item (without publishing) and advised this could be causing the issue. This setting can be manipulated programatically via setting:

So your final code would then be:

Enjoy your new versions!

Sitecore EditFrame buttons disappear

We recently had an odd scenario where Sitecore EditFrame buttons would seemingly disappear randomly. Our edit frame made use of a mixture of Field Editor Buttons (‘/sitecore/templates/System/WebEdit/Field Editor Button’) and Edit Frame Small Buttons (‘/sitecore/templates/System/WebEdit/Edit Frame Small Button’).

We never had problems with the field editor buttons just the edit frame small buttons. On these buttons the clicks are bound to Sitecore commands. Behind the scenes these commands evaluate their querystate to check if they should be visible, disabled or active:

The buttons had a mixture of commands, some custom and some out the box. Examples of the out the box commands were:

Note, to find the code that runs for these commands, have a look in /App_Config/commands.config and search for the specific command name.

After debugging into our custom commands vs the out the box commands we found things like item:movedown has the following checks:

The check that was catching us out was the if (Command.IsLockedByOther(item)) clause.

I’d never have thought to check an item locks as being the cause of EditFrame buttons not showing!!! The more I think about it I can see why the check is there – things like sort order are stored as fields against an item so if they are locked, you shouldn’t be able to edit them. From a UI perspective, it appears edit frame buttons don’t distinguish between CommandState.Disabled and CommandState.Hidden.

Sitecore preview and unauthenticated user

We recently setup some ribbon functionality to add custom popups into buttons in the Sitecore content editor ribbon. The code to launch the popup was via a custom command:

In the popup window we wanted to be diligent and check that only certain users could see the form. This was done via:

The problem we found was sporadically the ‘SitecoreContext.User.IsAdministrator’ check would fail and the popup would be blank.

After a lot of debugging we found the cookies in the HttpRequest object would sometimes be different hence causing the differences in the users attributes. When Sitecore invokes preview mode, it sets the user to be ‘sitecore\anonymous’ via ‘PreviewManager.StoreShellUser(true);’. This is what was catching us out. If the user had been using the cms and then visited preview the popup window would inherit the anonymous user.

Once we found the solution it was a very easy change to integrate (the WebEdit command -> Run(ClientPipelineArgs args) gave us the answer).

During our command before we open the popup we simply needed to add:

Paste into Sitecore Rich Text Editor from word and remove styling

If you want to change the behavior of when you past content into the Sitecore Rich Text Editor, you can change the settings used by the Telerik control.

This is embedded into the application via:

/sitecore/shell/Controls/Rich Text Editor/EditorPage.aspx

Then the attribute that causes the change in behavior is:

<telerik:RadEditor ID=”Editor” Runat=”server”

StripFormattingOnPaste=”All,ConvertWordLists”

To see all options for the enumeration, have a look at http://demos.telerik.com/aspnet-ajax/editor/examples/cleaningwordformatting/defaultcs.aspx

Content driven classes in the sitecore rich text editor

Here’s a quick tip related to the rich text editor in Sitecore. In 6.4 the telerik rad control was added, via specific style sheets you can expose css classes for the content editor to use.

Mark Stiles has blogged about this here.

These approaches works fine but what if you want the styles to be dynamic ie a content editor can add and remove them?

The solution

  1. You setup some items in your tree which represent CSS classes (name and required styles).
  2. You then create an httpHandler which sets its content type to be CSS.
  3. In your handler you expose all the CSS styles from the tree and render to the output (you may need to explicitly select which db to use in the handler since the requests may not run through all the sitecore pipelines). If needs be you could stream through the styles from the physical existing web stylesheet as well.
  4. You then point the WebStylesheet setting at your new handler.

Remember, you need to include the CSS link tag in your layout which points to your handler otherwise the classes won’t exist in the front end.

Tables in Sitecore Page Editor

We had an interesting challenge recently which involved generating email markup via the page editor. Most html emails are build up from tables – in this situation we needed to generate several rows of content such that we were adding multiple sublayouts each representing a row:

  • Sublayout in placeholder ‘body’: <tr><td>New row content</td></tr>
  • Sublayout in placeholder ‘body’: <tr><td>Next new row content</td></tr>
  • Sublayout in placeholder ‘body’: <tr><td>etc</td></tr>

In normal usage of the Page Editor you would be adding div’s to build up your html – unfortunately emails rely on a parent or several nested parent <table> tags.

When adding new sublayouts to the page the page editor didnt recognize where the table cells and rows would live (note the position of Add to here):

If this was done via divs you would expect to see something like:

One of the strict requirements of the work was the output markup matched existing templates exactly – the original templates had been rigorously tested in email clients. Because of this we really wanted to write the markup into our layouts and sublayouts so it matched the original html (albeit broken into placeholders and components).

After testing at cell and row level we found rewriting tags when in page editor mode helped the page editor respect the page layout much better.

The solution we arrived at was to tap in at page level and rewrite the whole markup in page editor. One of the assemblies that ships with Sitecore is the HtmlAgilityPack – its great for parsing and manipulating html.

There are 2 steps required:

  1. Tap into the page render
  2. Rewrite the content

First, lets rewrite the content:

Then tie into the layout’s render:

What I like about this approach:

  • You only need to make the change once rather than per tag
  • The markup you write into the layouts and sublayouts is the original

What I don’t like about this approach:

  • Adding the style tags doesn’t check for existence – you could end up with duplicate tags if the original style attribute contains the new value. This would be easy to resolve by parsing the existing value in the AddStyle method

Hide fields on specific Sitecore Items

There are certain scenarios when working with Sitecore when you need to hide fields on specific Sitecore items in the content editor. Its worth noting the solution shown below actually hides things rather than correcting the template hierarchy. For certain scenarios this may be a quicker solution which doesn’t require editing any of the existing content of the Sitecore tree.

The two key aspects are:

  • Configuring the rules for hiding and showing fields
  • Applying the rules to the ui via the getContentEditorFields pipeline

As per normal, Sitecore makes this easy once you know which pipelines to tap into. During the lifecycle of an item in the content editor several pipelines run – the difference here is some are from Sitecore.Client rather than the kernel. In the example shown below the bulk of the code is around querying xml (config) for the rules. This could come from any datastore.

The rules I adopted were pretty simple and based around the following idea. Either you always want to show or always want to hide the field. You would then want to decide the opposite case eg when to show the field based on a set of rules – here it uses the context item as the starting point for each rule.

An example rule then becomes: Always hide the logo field unless you are below the navigation node.

Why do this – surely this points at a problem with my template hierachy? Yes it does. However the amount of regression testing involved with changing base templates of a large tree could be high. Certain assertions in code may apply rules based on templateId so changing base templates isnt a feasible option. It may be down the line you do want the logo field on certain items elsewhere in the tree as well – to bring that into play would mean simply config changes.

First you need the code:

This is then patched into the config via:

What I like about this approach:

  • Additional field rules can be added without any code changes – its all config (as long as the rules you need eg unlessIsDescendentOf exist)
  • The patch:attribute on the include file allows swapping out the existing type attribute
  • Its very easy to bolt in new IFilterRules

What I don’t like about this approach:

  • I’ve subclassed the dtos and interfaces for eg IFilterRule – the rational here was these are only ever going to needed by the FieldFilter class (and it kept the amount of code blocks in the blog post down :S)
  • More complex combinations of IFilterRules eg combining and/or logic doesn’t work yet
  • It loads the config for every field – some simple caching would get around this
  • Big or naive filter rules could really slow down the content editor