Today I’ll go with the example suggested by Lars. Suppose we’re implementing a new money field type to store both the numeric amount and the currency (229 US Dollars). Both bits of information are stored in a single field using XML, which is a typical approach for Sitecore. I’ll skip the whole implementing a new field type part (no need to repeat SDN); lets say that the Sitecore Client part is already implemented, and editors are able to use the Content Editor to change field value. One problem remains – how to output money values on the website? The field contains XML, so we can’t just do sc:fld(‘money’, .). Different currencies have different signs which can go before or after the amount, which makes non-trivial rendering logic. The typical Sitecore 5 solution would be to implement a new XSL extension method and/or .NET web control. In Sitecore 6, however, you can use the renderField pipeline to make existing rendering methods properly render custom field types. Once again, this is a clean renderField pipeline: <renderField> <processor type="Sitecore.Pipelines.RenderField.GetFieldValue, Sitecore.Kernel"/> <processor type="Sitecore.Pipelines.RenderField.ExpandLinks, Sitecore.Kernel"/> <processor type="Sitecore.Pipelines.RenderField.GetImageFieldValue, Sitecore.Kernel"/> <processor type="Sitecore.Pipelines.RenderField.GetLinkFieldValue, Sitecore.Kernel"/> <processor type="Sitecore.Pipelines.RenderField.GetInternalLinkFieldValue, Sitecore.Kernel"/> <processor type="Sitecore.Pipelines.RenderField.GetMemoFieldValue, Sitecore.Kernel"/> <processor type="Sitecore.Pipelines.RenderField.GetDateFieldValue, Sitecore.Kernel"/> <processor type="Sitecore.Pipelines.RenderField.AddBeforeAndAfterValues, Sitecore.Kernel"/> <processor type="Sitecore.Pipelines.RenderField.RenderWebEditing, Sitecore.Kernel"/> </renderField> Most processors are responsible for rendering specific field types, plus there are some additional processors supporting Sitecore architecture. Following the naming convention, we’ll create a new GetMoneyFieldValue processor and place it after all Get* processors, but before the AddBeforeAndAfterValues: <processor type="Sitecore.Pipelines.RenderField.GetDateFieldValue, Sitecore.Kernel"/> <processor type="Money.GetMoneyFieldValue, Money" /> <processor type="Sitecore.Pipelines.RenderField.AddBeforeAndAfterValues, Sitecore.Kernel"/> The processor responsibility is to render HTML. I’m assuming that money field contains the following XML: <money currency=”USD” amount=”229.99” /> public class GetMoneyFieldValue {
public void Process(RenderFieldArgs args) {
if (args.FieldTypeKey != "money") {
return;
}
var doc = new XmlDocument();
doc.LoadXml(args.FieldValue);
string currency = doc.DocumentElement.GetAttribute("currency");
string amount = doc.DocumentElement.GetAttribute("amount");
string result = string.Empty;
if (currency == "USD") {
result = "$" + amount;
}
else if (currency == "DKK") {
result = amount + " kr.";
}
args.Result.FirstPart = result;
}
}
First, and most importantly, the processor has to check the type of the field being rendered. It’s only supposed to render money fields and ignore everything else. Then we retrieve the field value – notice the FieldValue property. The value is parsed, and depending on the currency we nicely render the monetary amount of either American dollars or Danish kroner. The result is stored in args.Result.FirstPart - money field is not supposed to be able to wrap other values, so nevermind the LastPart.
Why Bother?
Implementing the above processor gives website developers the ability to use standard Sitecore field rendering methods to properly render money fields. Developers can do sc:field(‘money’, .) or use the FieldRenderer class and never have a second thought.
In the last post I’ve mentioned the new ways of rendering fields using .NET code using web controls. Today I’ll focus on them more closely. The purpose for introducing these controls is two-fold: to allow .NET developers enjoy the same simplicity of rendering various Sitecore field types available in the XSL world, and to support the Page Editor. The most notable addition is the Sitecore.Web.UI.WebControls.FieldRenderer web control. This is basically a renderField pipeline wrapped in a web control form. You need to at least specify the field name and the control will do the rest. Optional parameters include the context item, html to render before and after the field and additional parameters. Another useful thing about FieldRenderer is that it’s also registered as a web control rendering in Sitecore, which allows power users to output different field types right from the Page Designer. The same FieldRenderer class also contains a static shortcut render method: Render(Item item, string fieldName [, string parameters]): string. This is the easiest way to render a field – use it when having web control is not desirable, and you’d rather just get result as a string. Along with FieldRenderer we’ve also introduced a number of web controls tailored to render specific field types: Sitecore.Web.UI.WebControls.Date Sitecore.Web.UI.WebControls.Image Sitecore.Web.UI.WebControls.Link Sitecore.Web.UI.WebControls.Text The benefit of these controls is that they provide strongly typed properties, similar to the ones available in their XSL counterparts. For example the Image web control has Alt, MaxHeight and MaxWidth properties. If you want to use these controls but still just get a string as a result, use the Sitecore.Web.HtmlUtil.RenderControl(Control):string convenience method. The most important thing to remember is that if you’re using .NET code to output field values, you have to use one of the above ways to support the Page Editor , because something like Response.Write(item[“FieldName”]) just won’t do it.
Sitecore’s renderField pipeline is a supporting pillar for the Page Editor. The pipeline ties together XSL and .NET field rendering code into one and provides a single place to affect how each field type (rich text, image, link) is rendered on the website. It doesn’t matter if the field is being output using XSL extension methods (sc:field, sc:image), XSL controls (<sc:text />, <sc:image />) or the new family of .NET web controls (Sitecore.Web.UI.WebControls.FieldRenderer, Date, Image, etc) – the renderField pipeline is always the one that provides the actual output. How does this support the Page Editor? Whenever a page is being run in the page editor mode, the renderField pipeline knows that and renders additional html/javascript around each field. How is the pipeline useful to you? The ability to hook into a field rendering process and modify the look of any field on a website is a powerful feature. For example you could completely change the way some or all images are rendered, or merely postprocess the rich text fields, like in the following example. This pipeline would also interest implementers of new field types, because it’s now possible to teach standard output methods to render third party fields types. The code below checks all links rendered as a part of the rich text field and adds the “external” CSS class to all external links. This can be useful to style external links differently, like using different colors or adding an icon next to them. public class MarkExternalLinks {
public void Process(RenderFieldArgs args) {
if (args.FieldTypeKey != "html" && args.FieldTypeKey != "rich text") {
return;
}
if (!args.Result.ToString().ToLower().Contains("<a")) {
return;
}
var firstPart = new HtmlDocument();
firstPart.LoadHtml(args.Result.FirstPart);
MarkLinks(firstPart);
args.Result.FirstPart = firstPart.DocumentNode.OuterHtml;
}
private void MarkLinks(HtmlDocument document) {
var nodes = document.DocumentNode.SelectNodes("//a");
if (nodes == null || nodes.Count == 0) {
return;
}
foreach (var node in nodes) {
if (node.GetAttributeValue("href", string.Empty).Contains("http")) {
var className = node.GetAttributeValue("class", string.Empty);
if (className.Length > 0) {
className += " ";
}
className += "external";
node.SetAttributeValue("class", className);
}
}
}
}
OK, what happens here? First, the check for the field type is performed. This processor is only designed to alter the output of html and rich text fields. If the field contains any links, output is being processed using the Html Agility Pack. The rendered field is stored in args.Result. The reason for having both FirstPart and LastPart is to render fields that can have other content embedded in them, such as general link; rich text fields only have the FirstPart.
Now the processor needs to be placed in web.config. I’m putting it just before the RenderWebEditing processor, so that it doesn’t affect the additional links rendered to support Page Editor. It’s also important that it comes after the GetLinkFieldValue processor:
<renderField> <processor type="Sitecore.Pipelines.RenderField.GetFieldValue, Sitecore.Kernel"/> <processor type="Sitecore.Pipelines.RenderField.ExpandLinks, Sitecore.Kernel"/> <processor type="Sitecore.Pipelines.RenderField.GetImageFieldValue, Sitecore.Kernel"/> <processor type="Sitecore.Pipelines.RenderField.GetLinkFieldValue, Sitecore.Kernel"/> <processor type="Sitecore.Pipelines.RenderField.GetInternalLinkFieldValue, Sitecore.Kernel"/> <processor type="Sitecore.Pipelines.RenderField.GetMemoFieldValue, Sitecore.Kernel"/> <processor type="Sitecore.Pipelines.RenderField.GetDateFieldValue, Sitecore.Kernel"/> <processor type="Sitecore.Pipelines.RenderField.AddBeforeAndAfterValues, Sitecore.Kernel"/> <processor type="Pipelines.MarkExternalLinks, Pipelines" /> <processor type="Sitecore.Pipelines.RenderField.RenderWebEditing, Sitecore.Kernel"/> </renderField>
Once again, here are the different ways of properly rendering a field:
- sc:field XSL extension method, and the family of field type specific methods such as the sc:image, sc:link, sc:date and so on
- XSL controls: <sc:text />, <sc:image />, <sc:date /> and so on
- The Sitecore.Web.UI.WebControls.FieldRenderer web control, and a family of field type specific web controls, such as Sitecore.Web.UI.WebControls.Image, Date, etc [new]
- The Sitecore.Web.UI.WebControls.FieldRenderer.Render() shortcut method. Use it when having the web control is not desirable, and you’d rather just have a string. [new]
It’s important to understand when the renderField pipeline is not used:
- sc:fld XSL extension method returns raw field value, bypassing the pipeline.
- Field values read using the Sitecore API (item[“FieldName”] or item.Fields[“FieldName”].Value) also return raw values.
- Any static html included in the aspx or ascs files is also not processed.
Consequently, these are also the ways of supporting the new Page Editor in Sitecore 6: as long as you output the field using any of the options from the first list so that the renderField is used, you’re automatically getting the full Page Editor support.
In the next post I’ll focus on the new FieldRenderer web control and the family of field controls, added to make rendering fields in .NET to be as easy as using XSL controls.
I’m on vacation in Copenhagen, on 7-10th of September (i.e. next week). I’ll be checking email from time to time: “alexey at this domain dotcom”.
Sitecore comes with some keyboard shortcuts predefined. The purpose of this post is to compile a full list of these shortcuts and for a little extra, show how to define new ones. Global Shortcuts F9 – Publish F2 – Expose (tiles all windows so that you can select the one you need) Ctrl+/ – Focus in the startbar search
Content Editor Shortcuts Tabs (hover over each tab to reveal the shortcut): Alt+H – Home Alt+N – Navigate Alt+R – Review Alt+P – Publish Alt+V – Versions Alt+C – Configure Alt+E – Presentation Alt+S – Security Alt+I - View Some ribbon commands have direct shortcuts. Most important one is Alt+F1, which reveals the shortcuts assigned to ribbon buttons: F2 – Rename F7 – Validation F8 – Edit (Lock / Unlock)
Ctrl+S – Save Ctrl+D – Duplicate
Ctrl+Shift+F – Launch the search application Ctrl+Shift+Home – Move to the Home item Ctrl+Shift+Alt+L – Protect / Unprotect
Ctrl+Shift+Alt+Up – Sort Up Ctrl+Shift+Alt+Down – Sort Down
Assigning New Ribbon Shortcuts Each item representing a ribbon button has a KeyCode field, accepting a shortcut string. How to build this shortcut string? First, you need to know they keycode corresponding to each key. This is the code used by the javascript event model, and here you can find a list of these keycodes. Then, if Shift, Control or Alt buttons are involved in the shortcut, prepend the code with “s”, “c” and “a” respectively. Examples: Ctrl+S is translated into c83 - c for control, 83 for “s”. Ctrl+Shift+Alt+Down is sca40 – s for Shift, c for Control, a for Alt and 40 is the keycode for the down key.
As an exercise, lets assign a shortcut to start the page editor. Page Editor button belongs to the Publish chunk in the Content Editor ribbon. So switch to the core database, and go to the /sitecore/content/Applications/Content Editor/Ribbons/Chunks/Publish/Page Editor. The shortcut I want for the Page Editor is Ctrl+Shift+E. This translates into sc69 shortcut string (s for Shift, c for Control and 69 is the keycode of “e”), so write “sc69” in the KeyCode field.  That’s it. Not only pressing Ctrl+Shift+E will start the page editor from now on, but pressing Alt+F1 will also reveal the shortcut along with the ones that came predefined with Sitecore.
I’m really excited about ubiquity: http://labs.mozilla.com/2008/08/introducing-ubiquity/ is definitely worth a few minutes if you care about where the web is going. I loved Aza Raskin’s Enso launcher and wrote a few commands for Enso 2 prototype but it was too buggy to use. I envy mac users because they have quicksilver. But now Aza, being the head of user experience in Mozilla Labs, has found a perfect place to push his ideas forward: firefox, the best cross-platform browser.
I’m sure some people have noticed that the Sitecore Package Designer contains a “Post Step” field. How can that be used and what for? The Post Step lets you input a method to be run after the package has been installed. To make it work, you need a class that either already exists on the target Sitecore or is in the assembly that is installed with the package. The class should implement Sitecore.Install.Framework.IPostStep interface that has a single RunPostStep(ITaskOutput output, NameValueCollection metaData) method. Your code will run in the “shell” site. What’s more important, it will run in the background thread, so you cannot use the ClientResponse or SheerResponse methods. Instead, the output parameter provides a few basic methods of interaction, such as showing the alert box or a confirm dialog. Below is a trivial example that renames the home item after the package installation: public class Sitecore6Patch2 : IPostStep {
public void Run(ITaskOutput output, NameValueCollection metaData) {
var home = Context.ContentDatabase.GetItem("/sitecore/content/home");
if (home != null) {
home.Name = "Home upgraded";
}
}
}
Note: the above example is for Sitecore 6. In Sitecore 5, your class should have a parameterless RunPostStep method instead, which is also supported in Sitecore 6 for compatibility purposes.
Have you seen or used the Sitecore Poll module? Got any complaints, suggestions or feature requests? Mail ar at sitecore dot net or leave them here in comments. The feedback will be put to good use. Go.
A little known fact is that Sitecore 6 comes with Prototype and Firebug lite preinstalled. Prototype is a mind saving javascript library, and firebug lite is a helpful javascript instrumentation console replacing dozens of alert(“I’m here”) calls. We’d do it for ourselves anyway, but what does it mean for you? Prototype Prototype javascript library is automatically included in Sitecore shell applications – both native, such as Content Editor, and the custom ones. This means you can safely use prototype both in your Sitecore customizations, such as custom fields, and in your own applications. (If you look closely enough, you’ll see that custom FieldTypes I’ve made for Crestone shamelessly use prototype whenever possible). Needless to say that prototype is great and saves a lot of brain cells if you do any javascript at all. Some great alternatives, such as jQuery, do exist – but if you don’t use anything at all, I really wonder why. If you’re new to prototype and javascript frameworks in general – they have very solid documentation at http://prototypejs.org/. Even more, prototype’s cousin – Scriptaculous, a javascript UI controls and effects library is also shipped with Sitecore, but is not included automatically. If you need it, it’s at /sitecore/shell/Controls/Lib/Scriptaculous. Firebug Lite Firebug lite is a cross browser javascript console – the fact that it works in Internet Explorer is of biggest interest to Sitecore developers. I’ve praised it before, but now it’s one key press away in Sitecore shell applications. Press F12 and the firebug lite console will pop up from the top: This means you can use console.log and other instrumentation methods to debug your javascript. Sitecore UI has a lot of IFrames, so pay attention where you click before opening the console – each IFrame is a separate javascript realm, and therefore has its own firebug console. The Website is Safe I’d like to stress again that both Prototype and Firebug lite are only included in the Sitecore shell applications. Technically, if the sitecore.js javascript file is loaded, the prototype and firebug are also inlcuded. We don’t add anything to the frontend sites – it’s your decision.
|