<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom"><title type="text">Blog posts by Marcus Lindblom</title><link href="http://world.optimizely.com" /><updated>2015-04-08T20:34:47.0000000Z</updated><id>https://world.optimizely.com/blogs/Marcus-Lindblom/</id> <generator uri="http://world.optimizely.com" version="2.0">Optimizely World</generator> <entry><title>Render ContentArea items with, ehm... spacing</title><link href="http://www.kloojed.com/render-contentarea-items-with-ehm-spacing/" /><id>&lt;p&gt;This is an old issue from when I started working with EPiServer CMS 7 but I thought I would share it anyway.&lt;/p&gt;

&lt;p&gt;So, why do I want to the content area items with some space between them? Let&#39;s say that you have three teasers on a page and they should have equal space between them, one possible solution is to use &lt;code&gt;text-align:justify;&lt;/code&gt; on the surrounding element and use a pseudo element &lt;code&gt;:after&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://www.kloojed.com/content/images/2015/04/mockup-1.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;If you use &lt;code&gt;Html.PropertyFor&lt;/code&gt; to render the &lt;code&gt;ContentArea&lt;/code&gt; there will be no spacing between the elements in the &lt;code&gt;HTML&lt;/code&gt; and in most major browsers the &lt;code&gt;CSS&lt;/code&gt; approach I mentioned earlier will not work if there are no spaces between the &lt;code&gt;HTML&lt;/code&gt; tags.&lt;/p&gt;

&lt;p&gt;So, the approach I used was to create a new &lt;code&gt;ContentAreaRenderer&lt;/code&gt; and tell the IoC container to use the new renderer.&lt;/p&gt;

&lt;p&gt;The code I used looks similiar to this:&lt;/p&gt;

&lt;script src=&quot;https://gist.github.com/marcuslindblom/7cedd63ba6a33a6ee82c.js&quot;&gt;&lt;/script&gt;

&lt;p&gt;So, with this new shiny renderer the teasers will look great.&lt;/p&gt;</id><updated>2015-04-08T20:34:47.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>Simplify management of property settings in EPiServer</title><link href="http://www.kloojed.com/simplify-management-of-property-settings-in-episerver/" /><id>&lt;p&gt;&lt;em&gt;Note: This is a translated version of &lt;a href=&quot;https://www.meridium.se/sv/blogg/forenkla-hanteringen-av-egenskapsinstallningar-i-episerver/&quot;&gt;F&#246;renkla hanteringen av egenskapsinst&#228;llningar i EPiServer&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Settings on property level in EPiServer can be very powerful but may be hard to remember to specify on automatic setup and installation.&lt;/p&gt;

&lt;p&gt;In &lt;a href=&quot;http://www.imagevault.se/&quot;&gt;ImageVault&lt;/a&gt; we have that kind of setting on the property type &lt;code&gt;MediaReference&lt;/code&gt;. The goal with this approach is that the size of the area used when the image is cropped should reflect the actual size we want to use on the page in EPiServer. &lt;/p&gt;

&lt;p&gt;At Meridium, we have a &lt;a href=&quot;https://www.meridium.se/sv/vilka-vi-ar/&quot;&gt;workflow&lt;/a&gt; which means that we have several different installations of the same site, some examples are the internal, external testing and production environment. Installation and updates of these environments is almost completely automated. &lt;/p&gt;

&lt;p&gt;The problem we have if we use custom settings is that we have to manually enter the correct settings for each site in each environment, it is easy to forget, but above all a &lt;em&gt;very&lt;/em&gt; tedious and unnecessary task.&lt;/p&gt;

&lt;p&gt;In this blog post I will show an approach to solve this problem and also to share with you some code that makes this possible. &lt;/p&gt;

&lt;p&gt;In our case, the desired scenario is that I as a developer would be able to set the correct height, width and crop mode for an image, or all images in an image list. The settings would automatically be added to the property settings, if I made a change, the settings would be updated with the new values.&lt;/p&gt;

&lt;h2 id=&quot;automateupdateofcustomsettingsonproperties&quot;&gt;Automate update of custom settings on properties&lt;/h2&gt;

&lt;p&gt;This specific problem, I decided to solve by creating a &lt;code&gt;Attribute&lt;/code&gt; which can be used to decorate a &lt;code&gt;MediaReference&lt;/code&gt; or a &lt;code&gt;MediaReferenceList&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;This attribute is very simple and contains only a few properties.&lt;/p&gt;

&lt;script src=&quot;https://gist.github.com/marcuslindblom/df0de697d96a193f2681.js&quot;&gt;&lt;/script&gt;

&lt;p&gt;Below we see how our new attributes can be used on a &lt;code&gt;MediaReference&lt;/code&gt;.&lt;/p&gt;

&lt;script src=&quot;https://gist.github.com/marcuslindblom/4002016b5ea53e502d42.js&quot;&gt;&lt;/script&gt;

&lt;p&gt;The attribute by it self doesn&#39;t make any difference so let&#39;s take a look at how we can use it to add and update a property settings. &lt;/p&gt;

&lt;p&gt;The first thing we want to do is create a module that runs automatically when the website starts without adding any extra configuration, for that we use an &lt;code&gt;IInitializableModule&lt;/code&gt;.&lt;/p&gt;

&lt;script src=&quot;https://gist.github.com/marcuslindblom/b1e1c0caf689613c53ad.js&quot;&gt;&lt;/script&gt;

&lt;p&gt;The method &lt;code&gt;Initialize&lt;/code&gt; run as part of EPiServer&#39;s initialization and allows us to run the code to find the page types that have a property and are decorated with our new attribute.&lt;/p&gt;

&lt;script src=&quot;https://gist.github.com/marcuslindblom/5b4bbc62905325f910ff.js&quot;&gt;&lt;/script&gt;

&lt;p&gt;When we found the properties we want to change the settings, it&#39;s easy to pick the right type of setting, update the settings with the new values retrieved from our attributes and then save the new settings.&lt;/p&gt;

&lt;script src=&quot;https://gist.github.com/marcuslindblom/ecb63ffe28b2e3aa3280.js&quot;&gt;&lt;/script&gt;

&lt;p&gt;Error handling has been omitted for the benefit of brevity. &lt;/p&gt;

&lt;h2 id=&quot;otherusecases&quot;&gt;Other use cases&lt;/h2&gt;

&lt;p&gt;This method of adding and updating settings on properties brings many benefits, but above all that we can be sure that the same settings are used consistently in all environments.&lt;/p&gt;

&lt;p&gt;The same technique can also be used for eg specify the style sheet to use for an &lt;code&gt;HTML&lt;/code&gt; editor, or the tools that will be active when we are editing a particular page in EPiServer.&lt;/p&gt;</id><updated>2014-10-22T10:00:00.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>Performance update for the folder browser property</title><link href="http://www.kloojed.com/performance-update-for-the-folder-browser-property/" /><id>&lt;p&gt;The folder browser property is not fully optimized for file areas of larger magnitude.&lt;/p&gt;

&lt;p&gt;By default, all folders in the file area are loaded in the &lt;code&gt;FileSystemDataSource&lt;/code&gt;. To prevent this and make the &lt;code&gt;FileSystemDataSource&lt;/code&gt; fetch only the folders that are actually expanded use the &lt;code&gt;PopulatedOnDemand=&quot;true&quot;&lt;/code&gt; on the &lt;code&gt;asp:TreeNodeBinding&lt;/code&gt; node&lt;/p&gt;</id><updated>2013-02-20T12:00:00.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>Performance update for the folder browser property</title><link href="http://www.kloojed.com/2013/02/performance-update-for-the-folder-browser-property" /><id>The folder browser property is not fully optimized for file areas of larger magnitude.&lt;div class=&quot;feedflare&quot;&gt;
&lt;a href=&quot;http://feeds.feedburner.com/~ff/kloojed?a=HVwKyW4_3iI:0qHkC83dRMA:F7zBnMyn0Lo&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/kloojed?i=HVwKyW4_3iI:0qHkC83dRMA:F7zBnMyn0Lo&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/kloojed?a=HVwKyW4_3iI:0qHkC83dRMA:V_sGLiPBpWU&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/kloojed?i=HVwKyW4_3iI:0qHkC83dRMA:V_sGLiPBpWU&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src=&quot;http://feeds.feedburner.com/~r/kloojed/~4/HVwKyW4_3iI&quot; height=&quot;1&quot; width=&quot;1&quot; /&gt;</id><updated>2013-02-20T09:00:00.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>Install the Folder browser property via NuGet</title><link href="http://www.kloojed.com/2011/07/install-the-folder-browser-property-via-nuget" /><id>Installation of the folder browser property just got a little easier.&lt;div class=&quot;feedflare&quot;&gt;
&lt;a href=&quot;http://feeds.feedburner.com/~ff/kloojed?a=_SnszBMosKw:VkY875IETLs:F7zBnMyn0Lo&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/kloojed?i=_SnszBMosKw:VkY875IETLs:F7zBnMyn0Lo&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/kloojed?a=_SnszBMosKw:VkY875IETLs:V_sGLiPBpWU&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/kloojed?i=_SnszBMosKw:VkY875IETLs:V_sGLiPBpWU&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src=&quot;http://feeds.feedburner.com/~r/kloojed/~4/_SnszBMosKw&quot; height=&quot;1&quot; width=&quot;1&quot; /&gt;</id><updated>2011-07-10T14:30:00.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>Install the Folder browser property via NuGet</title><link href="http://www.kloojed.com/install-the-folder-browser-property-via-nuget/" /><id>&lt;p&gt;Installation of the folder browser property just got a little easier.&lt;/p&gt;

&lt;p&gt;*update folder browser is only available via EPiServer NuGet feed&lt;/p&gt;

&lt;p&gt;I have made a NuGet package of the folder browser property that can be found on the official NuGet package feed but I have also submitted the packaged to the &lt;a href=&quot;http://nuget.episerver.com/&quot;&gt;EPiServer NuGet feed&lt;/a&gt; so I guess the package will be available there as well.&lt;/p&gt;

&lt;p&gt;Just open the the package manager console and write &lt;code&gt;PM&amp;gt; Install-Package Meridium.FolderBrowserProperty&lt;/code&gt; and hit enter and your done!&lt;/p&gt;

&lt;p&gt;You can find information about the custom property on &lt;a href=&quot;https://www.coderesort.com/p/epicode/wiki/FolderBrowserProperty&quot;&gt;epicode&lt;/a&gt; and a previous &lt;a href=&quot;http://www.kloojed.com/2008/08/new-module-at-epicode&quot;&gt;post&lt;/a&gt; here on blog, for NuGet package info and rating please visit &lt;a href=&quot;http://www.nuget.org/List/Packages/Meridium.FolderBrowserProperty&quot;&gt;NuGet&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That&#39;s all for now&lt;/p&gt;</id><updated>2011-07-10T12:00:00.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>Speeding up the FileSystemDataSource in EPiServer</title><link href="http://www.kloojed.com/speeding-up-the-filesystemdatasource-in-episerver/" /><id>&lt;p&gt;For those of you that use my custom property called Folder browser, I have a small performance tips for you.&lt;/p&gt;

&lt;p&gt;I created a small &lt;a href=&quot;http://www.kloojed.com/2008/08/new-module-at-epicode&quot;&gt;plug in&lt;/a&gt; for &lt;a href=&quot;http://www.episerver.com/&quot;&gt;EPiServer&lt;/a&gt; quite a while ago that adds functionality for selecting a folder in EPiServers file system. The plugin utilises the built in &lt;code&gt;FileSystemDataSource&lt;/code&gt; for fetching folders and files. In my case I just want to fetch the folders and not the files, this can easily be done by adding the &lt;code&gt;HideFilesFromList&lt;/code&gt; attribute to the FileSystemDataSource control in the &lt;code&gt;FolderBrowserDialog.aspx&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This may not be an issue for you but I have a client that loooves page folders and this small improvement made the tree load alot faster.&lt;/p&gt;</id><updated>2011-01-11T12:00:00.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>Extend SiteValidator with custom rules</title><link href="http://www.kloojed.com/extend-sitevalidator-with-custom-rules/" /><id>&lt;p&gt;&lt;a href=&quot;http://www.meridium.se/en/products/sitevalidator/overview/&quot;&gt;SiteValidator&lt;/a&gt; has an API that enables partners and customers to add additional tests to the product. To create and add a new test you should start with creating a new class, the class should implement a specific interface and report errors of the correct type. The interfaces and the error class that should be used can be found in the assembly named Meridium.Web.Accessibility.&lt;/p&gt;

&lt;p&gt;When our new test reports an error it should create a new object of the type &lt;code&gt;ExternalValidationError&lt;/code&gt;. It is important that new tests is using this class for error reporting, there are others but those are meant for use internally in SiteValidator.&lt;/p&gt;

&lt;p&gt;There are two interfaces that you can choose from when you implement a test class, &lt;code&gt;IGeneralValidationRule&lt;/code&gt; and &lt;code&gt;IXPathValidationRule&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;igeneralvalidationrule&quot;&gt;IGeneralValidationRule&lt;/h2&gt;

&lt;p&gt;This interface should you choose if you want create a test based on the page as raw text. The interface contains one method and one property:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;List Validate(string html, string inputNamespace); Dictionary Settings { get; set; } 
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;When it is time to evaluate the rule for a given page, then this method will be called with the entire html source code as a parameter and the namespace of the page (if it is a valid XHTML page, this is likely &lt;a href=&quot;http://www.w3.org/1999/xhtml&quot;&gt;http://www.w3.org/1999/xhtml&lt;/a&gt;). The property will contain the keys that have been set for the rule in the web.config.&lt;/p&gt;

&lt;p&gt;The method should return a list populated with &lt;code&gt;ExternalValidationError&lt;/code&gt; objects containing the errors detected. If no error is found, the method may either return null or an empty list.&lt;/p&gt;

&lt;h2 id=&quot;ixpathvalidationrule&quot;&gt;IXPathValidationRule&lt;/h2&gt;

&lt;p&gt;This interface should you choose if you want create a test based on the page as an XPathDocument. You will receive an already created &lt;code&gt;XPathDocument&lt;/code&gt; that can be shared between several different tests, thus saving performance. The interface contains one method and one property:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;List Validate(XPathDocument document, System.Xml.XmlNamespaceManager ns); Dictionary Settings { get; set; }
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In this case the method will be called with the parameter set to a document &lt;code&gt;XPathDocument&lt;/code&gt; created from the whole page source.&lt;/p&gt;

&lt;p&gt;So let&#39;s create a simple test to ensure that we did not use any inline css in our templates. (note that this is a demo and the code is untested and may contain errors)&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public class InlineCssRule: IXPathValidationRule
{
    public Dictionary Settings { get; set; }
    public List Validate(XPathDocument document, XmlNamespaceManager ns)
    {
        var result = new List();
        var navigator = document.CreateNavigator();
        var iterator = XPathCache.Select(&quot;//*[@style]&quot;, navigator);
        if (iterator.Count &amp;amp;gt; 0)
        {
            var error = new ExternalValidationError
            {
                ExternalErrorName = &quot;Inline-CSS&quot;,
                ExternalErrorDescription = string.Format(&quot;The document uses the {0} style-attributes. Use external style sheets or style elements instead.&quot;, iterator.Count),
                ExternalErrorTypeId = 10001
             };
            result.Add(error);
           }
        return result;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;ExternalErrorTypeId property is used to identify a particular type of error. For example, all errors of type &quot;inline-CSS&quot; has the same error type id. It is important that every error type has a unique id. It must also be greater than 10 000 (the first numbers are reserved for internal use).&lt;/p&gt;

&lt;p&gt;Complile your code and register the new test in web.config inside the rule node of the SiteValidator configuration section and you are good to go.&lt;/p&gt;

&lt;p&gt;For &lt;a href=&quot;http://www.meridium.se/&quot;&gt;Meridium&lt;/a&gt; partners &lt;a href=&quot;http://www.meridium.se/en/products/sitevalidator/overview/&quot;&gt;SiteValidator&lt;/a&gt; is free to use when developing a new website for a customer so feel free to &lt;a href=&quot;http://www.meridium.se/en/products/sitevalidator/files-documents/&quot;&gt;download a copy&lt;/a&gt; and take it for a test run.&lt;/p&gt;</id><updated>2010-05-10T12:00:00.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>Folder Browser Property now available for EPiServer CMS 6</title><link href="http://www.kloojed.com/2010/05/folder-browser-property-now-available-for-episerver-cms-6" /><id>Folder browser property is a very useful plugin for EPiServer CMS and is now available for version 6 of the CMS.&lt;div class=&quot;feedflare&quot;&gt;
&lt;a href=&quot;http://feeds.feedburner.com/~ff/kloojed?a=r0F8TiESjtI:OWad7hDTc3Q:F7zBnMyn0Lo&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/kloojed?i=r0F8TiESjtI:OWad7hDTc3Q:F7zBnMyn0Lo&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/kloojed?a=r0F8TiESjtI:OWad7hDTc3Q:V_sGLiPBpWU&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/kloojed?i=r0F8TiESjtI:OWad7hDTc3Q:V_sGLiPBpWU&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src=&quot;http://feeds.feedburner.com/~r/kloojed/~4/r0F8TiESjtI&quot; height=&quot;1&quot; width=&quot;1&quot; /&gt;</id><updated>2010-05-04T22:13:00.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>Folder Browser Property now available for EPiServer CMS 6</title><link href="http://www.kloojed.com/folder-browser-property-now-available-for-episerver-cms-6/" /><id>&lt;p&gt;Folder browser property is a very useful plugin for EPiServer CMS and is now available for version 6 of the CMS.&lt;/p&gt;

&lt;p&gt;The very useful &lt;a href=&quot;http://www.kloojed.com/2008/08/new-module-at-epicode&quot;&gt;folder browser plugin&lt;/a&gt; is now available for EPiServer 6 and can be downloaded from &lt;a href=&quot;https://www.coderesort.com/p/epicode/wiki/FolderBrowserProperty&quot;&gt;EPiCode&lt;/a&gt;. Many thanks to &lt;a href=&quot;http://www.frederikvig.com/&quot;&gt;Frederik Vig.&lt;/a&gt;&lt;/p&gt;</id><updated>2010-05-04T12:00:00.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>Improve performance by adding expire headers on images supplied by ImageVault</title><link href="http://www.kloojed.com/improve-performance-by-adding-expire-headers-on-images-supplied-by-imagevault/" /><id>&lt;p&gt;Because all images in ImageVault is served with an http handler it&#39;s not possible to configure expire headers the normal way by configuring the cache control for static content.&lt;/p&gt;

&lt;p&gt;With this post I intend to show how easy it is to boost your performance by adding expire headers and make all images stored in ImageVault cacheable. Open up web.config and navigate the configuration section for ImageVault and add &lt;strong&gt;ImagesExpiresInMinutes&lt;/strong&gt;, the value must be just over three days to be considered as a far future date so the minimum value is 4321 minutes.&lt;/p&gt;

&lt;p&gt;One small drawback when expire headers is added to ImageVault images is that the function to replace the original does not work because the images are cached by the client and path is the same even though you changed the image, the image will thus be replaced when the cache is released and the client requests the image again. According to me the advantages outweigh the disadvantages, but you certainly should notify the editors about this change.&lt;/p&gt;</id><updated>2010-04-11T12:00:00.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>Hidden gems in ImageVault</title><link href="http://www.kloojed.com/hidden-gems-in-imagevault/" /><id>&lt;p&gt;It&#39;s been quite a while since my last post but now I would like to share some small but useful tips regarding ImageVault.&lt;/p&gt;

&lt;p&gt;When you have installed ImageVault you can see two new editor plugins on each and every &lt;code&gt;HTML&lt;/code&gt; string property. Because the lack of possibility to disable a custom editor plugin in EPiServer the ImageVault team has created a solution for those who want to disable these tools.&lt;/p&gt;

&lt;p&gt;So how do you do it? It&#39;s quite simple, if your &lt;code&gt;XHTML&lt;/code&gt; property is named MainBody you should create a new property of any type e.g. String (&amp;lt;= 255) and name it &lt;code&gt;MainBodyHideMeridiumLinkEditor&lt;/code&gt; to hide the link editor or &lt;code&gt;MainBodyHideImageVault&lt;/code&gt; to hide ImageVault. I&#39;m quite sure some of you guys/girls out there has created cleaner solution for this kind of problem but this works out of the box.&lt;/p&gt;

&lt;p&gt;Let me know what you think or if you have a better solution that you would like to share.&lt;/p&gt;</id><updated>2010-02-17T12:00:00.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>Measuring text readability in EPiServer</title><link href="http://www.kloojed.com/measuring-text-readability-in-episerver/" /><id>&lt;p&gt;Increase your web sites accessibility by measuring text readability.&lt;/p&gt;

&lt;p&gt;When working with a web sites accessibility content is very often overlooked. Even if your web site fullfills all W3C recommendations it will still be inaccessible if your content is difficult to understand.&lt;/p&gt;

&lt;p&gt;With this in mind I have made a &lt;a href=&quot;http://code.google.com/p/lixr/&quot;&gt;tool&lt;/a&gt; that can help you to measure your texts readability. The plugin uses a technique called &lt;a href=&quot;http://sv.wikipedia.org/wiki/LIX&quot;&gt;LIX&lt;/a&gt; which is appliable on Swedish and Danish texts only. A readability index score is not an exact science but can be used to make sense of how easy or difficult a text is to read.&lt;/p&gt;

&lt;p&gt;To test the tool just download &lt;a href=&quot;http://lixr.googlecode.com/files/Lixr.epimodule&quot;&gt;Lixr.epimodule&lt;/a&gt; and use EPiServer Deployment Center to install the module from a compressed file. When the installation is done navigate to a page with an XHTML editor, select some text and use the context menu with the option &quot;L&#228;sbarhetsindex...&quot;. A longer text provides a more accurate measurement.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://www.kloojed.com/upload/lixr/1.png&quot; alt=&quot;episerver context menu&quot; /&gt;&lt;/p&gt;

&lt;p&gt;This is how the results look like:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://www.kloojed.com/upload/lixr/2.png&quot; alt=&quot;Lixr results&quot; /&gt;&lt;/p&gt;

&lt;p&gt;That&#39;s about it, feel free to drop a comment.&lt;/p&gt;</id><updated>2009-05-22T12:00:00.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>Say goodbye to Widows and Orphans</title><link href="http://www.kloojed.com/say-goodbye-to-widows-and-orphans/" /><id>&lt;p&gt;In typesetting, a widow is the final word of a paragraph or heading if it falls down on the next line. This is an example of bad typhography and should be corrected if possible.&lt;/p&gt;

&lt;p&gt;Our goal with the new property is basically to put a non-breaking space between the last two words in all headings, thus in effect gluing them together and forcing them onto the next line.&lt;/p&gt;

&lt;p&gt;Create a new class that inherits from EPiServer.Web.WebControls.Property and add the code below.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public class Hn : Property
   {
    public string Heading
    {
        get
           {
            return (string)(ViewState[&quot;Heading&quot;] ?? &quot;h1&quot;);
          }
        set
        {
            ViewState[&quot;Heading&quot;] = value;
          }
     }
    protected override void Render(HtmlTextWriter output)
    {
        if (InnerProperty != null)
        {
            EnsurePropertyControlsCreated();
            if (InnerProperty.Value != null)
            {
                output.WriteBeginTag(Heading);
                if (InnerProperty is EPiServer.Core.PropertyString)
                {
                    string value = InnerProperty.ToWebString().Trim();
                    string[] fragments = InnerProperty.ToWebString().Split(new[] { &#39; &#39; }, StringSplitOptions.RemoveEmptyEntries);
                    if (fragments.Length &amp;amp;gt; 2)
                    {
                        value = string.Empty;
                        for (int i = 0; i &amp;amp;lt; fragments.Length; i++)
                        {
                            if (i == fragments.Length - 2)
                            {
                                value += fragments[i] + &quot;&amp;amp;nbsp;&quot;;
                            }    
                            else
                            {
                                value += fragments[i] + &quot; &quot;;
                              }
                          }
                        output.Write(value.Trim());
                    }
                    else
                    {
                        base.RenderChildren(output);
                     }
                    output.WriteEndTag(Heading);
                 }
                else if (string.IsNullOrEmpty(PropertyName.Trim()))
                {
                    output.WriteLine(&quot;[Error: PropertyName is not set.]&quot;);
                   }
                else if (((PageBase)Page).CurrentPage == null)
                   {
                    if (DisplayMissingMessage) output.WriteLine(&quot;[Error: Property is contained in a page/control/template that does not have a current page.]&quot;);
                 }
                else if (((PageBase)Page).CurrentPage.Property[PropertyName] == null)
                {
                    if (DisplayMissingMessage) { output.WriteLine(&quot;[Error: No property \&quot;{0}\&quot;.]&quot;, PropertyName);
                }
            }
            else output.WriteLine(&quot;[Error: Unknown error.]&quot;);
        }
    }
} 
&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;To use the control you need to have a separate string property on your template like this:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://www.kloojed.com/upload/widows/add_prop.png&quot; alt=&quot;New property on template&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Next, add the new control to a page and enjoy your shiny new headings without any widows.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;Kloojed:Hn runat=&quot;server&quot; PropertyName=&quot;Heading&quot; /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;</id><updated>2009-01-16T12:00:00.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>Enhance ImageVault with jQuery</title><link href="http://www.kloojed.com/enhance-imagevault-with-jquery/" /><id>&lt;p&gt;In the spirit of Microsoft&#39;s official embrace of jQuery, I&#39;d like to show you an example of how you can add jQuery functionality to ImageVault.&lt;/p&gt;

&lt;p&gt;jQuery is a powerfull JavaScript library that can help you with e. g. animations and Ajax interactions. The prefered way of loading jQuery is to use &lt;code&gt;google.load()&lt;/code&gt;, Google provides the most popular, open source JavaScript libraries through the &lt;a href=&quot;http://en.wikipedia.org/wiki/Ajax_(programming)&quot;&gt;AJAX&lt;/a&gt; Libraries API. To load jQuery just add the following section to your head section.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;script type=&quot;text/javascript src=&quot;http://www.google.com/jsapi&quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script type=&quot;text/javascript&quot;&amp;gt;
    google.load(&quot;jquery&quot;, &quot;1.2.6&quot;)
 &amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;For more information about &lt;code&gt;google.load()&lt;/code&gt; please visit &lt;a href=&quot;http://code.google.com/intl/sv-SE/apis/ajaxlibs/documentation/index.html&quot;&gt;Google AJAX APIs.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next i&#39;m going to show you how easy it can be to create an autocomplete searchbox that searches through ImageVault and all of it&#39;s contents. For this to work we will add a ready to use plugin for jQuery called &lt;a href=&quot;http://bassistance.de/jquery-plugins/jquery-plugin-autocomplete/&quot;&gt;Autocomplete&lt;/a&gt;. So just download the [script (&lt;a href=&quot;http://jquery.bassistance.de/autocomplete/jquery.autocomplete.zip&quot;&gt;http://jquery.bassistance.de/autocomplete/jquery.autocomplete.zip&lt;/a&gt;) and include the path in your head section of your document. We should end up with something like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;script type=&quot;text/javascript src=&quot;http://www.google.com/jsapi&quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script type=&quot;text/javascript&quot;&amp;gt;
    google.load(&quot;jquery&quot;, &quot;1.2.6&quot;);
&amp;lt;/script&amp;gt;
&amp;lt;script type=&quot;text/javascript&quot; src=&quot;/js/jquery.autocomplete.min.js&quot;&amp;gt;&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Next it&#39;s time to create the handler responsible for delivering the images based on our query and for this my choice is a generic handler, so let&#39;s add a new generic handler to our project.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public class AutoComplete : IHttpHandler {
    public void ProcessRequest(HttpContext context)
    {
        if (context.Request.QueryString[&quot;q&quot;] != null)
        {
            IVFileDataCollection hits = IVDataFactory.FindFilesWithCriteria(1, context.Request.QueryString[&quot;q&quot;], null, IVSearchConditions.StartsWith, null, true);
            IVUrlBuilder urlBuilder = new IVUrlBuilder();
            foreach (IVFileData hit in hits)
            {
                urlBuilder.Id = hit.Id;
                urlBuilder.Width = 46;
                urlBuilder.Height = 46;
                context.Response.Write(urlBuilder + &quot;|&quot; + hit.FileName + Environment.NewLine);
              }
         }
        context.Response.End();
     }
    public bool IsReusable
    {
        get {
            return false;
          }
      }
  } 
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;... and there we have a very simple ImageVault search handler, the first paramter to the &lt;code&gt;FindFilesWithCriteria&lt;/code&gt; method is the id of the album you want to search in and this should ofcourse be configured from e. g. the page template.&lt;/p&gt;

&lt;p&gt;The handler above is invoked by some JavaScript, so let&#39;s add a new script file and write some jQuery.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$(document).ready(function() {
    $(&quot;#ctl00_QuickSearch_SearchText&quot;).autocomplete(&quot; /AutoComplete.ashx &quot;, {
        delay: 5,
        minChars: 1,
        matchSubset: 1,
        matchContains: 1,
        max: 6,
        autofill: true,
        scroll: false,
        formatItem: function(data, i, n, value) {
            return &quot;![+data[1]+](+value+)&quot;;
          },
        formatResult: function(data, value) {
            return data[1];
          }
      });
 });
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;As you can see above I have hijacked the quicksearch field on a standard EPiServer CMS 5 demo site, you probably want to change this but for now this is all about proof of concept.&lt;/p&gt;

&lt;p&gt;Next, add the newly created file to your head section and it should look something like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;script type=&quot;text/javascript src=&quot;http://www.google.com/jsapi&quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script type=&quot;text/javascript&quot;&amp;gt;
    google.load(&quot;jquery&quot;, &quot;1.2.6&quot;);
   &amp;lt;/script&amp;gt;
&amp;lt;script type=&quot;text/javascript&quot; src=&quot;/js/jquery.autocomplete.min.js&quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script type=&quot;text/javascript&quot; src=&quot;/js/demo.autocomplete.js&quot;&amp;gt;&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;When you have saved all your files you should be able the have a test run so fire up the demo site and start typing in the quicksearch field, if you have the required access to ImageVault you should see some images. When your done testing you could add some clean &lt;abbr title=&quot;Cascading Style Sheets&quot;&gt;css to give this proof of concept thingy a nice look and feel &lt;/abbr&gt;&lt;/p&gt;

&lt;p&gt;Hope you like this article and feel free to drop a comment or contact me if you have some ImageVault questions.&lt;/p&gt;</id><updated>2008-12-12T12:00:00.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>Simple breadcrumb using the PageSiteMapProvider</title><link href="http://www.kloojed.com/simple-breadcrumb-using-the-pagesitemapprovider/" /><id>&lt;p&gt;A pretty common thing to implement on a web site is a breadcrumb and with EPiServers &lt;code&gt;PageSiteMapProvider&lt;/code&gt; it&#39;s an easy task.&lt;/p&gt;

&lt;p&gt;In this tutorial I assume you have a clean install of EPiServer CMS 5.&lt;/p&gt;

&lt;p&gt;The first thing we need to do is enable the PageSiteMapProvider in our &lt;code&gt;web.config&lt;/code&gt; by adding the following:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;siteMap defaultProvider=&quot;PageSiteMap&quot;&amp;gt;
    &amp;lt;providers&amp;gt;
        &amp;lt;add name=&quot;PageSiteMap&quot; type=&quot;EPiServer.PageSiteMapProvider, EPiServer&quot; /&amp;gt;
    &amp;lt;/providers&amp;amp;gt&amp;gt;
&amp;lt;/siteMap&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If we were lazy we could use the the &lt;code&gt;asp:SiteMapPath&lt;/code&gt; and call it a day and the result would be OK but i&#39;m a fan of clean HTML and therefore I decide we make a custom control that renders exactly what we want.&lt;/p&gt;

&lt;p&gt;So let&#39;s start by creating a new class named e. g. Path.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public class Path : Control
{
    protected override void CreateChildControls()
    {
        if (SiteMap.CurrentNode == null) return;    
            PrependText(SiteMap.CurrentNode);
            PageSiteMapNode parent = SiteMap.CurrentNode.ParentNode as PageSiteMapNode;
            while (parent != null &amp;amp;&amp;amp; parent != SiteMap.RootNode &amp;amp;&amp;amp; parent.CurrentPage.PageLink != PageReference.RootPage)
            {
                Controls.AddAt(0, new LiteralControl(&quot; / &quot;));
                PrependAnchor(parent);
                parent = parent.ParentNode as PageSiteMapNode;
            }
            base.CreateChildControls();
         }
        public virtual void PrependText(SiteMapNode node)
        {
            Controls.AddAt(0, new LiteralControl(HttpUtility.HtmlEncode(node.Title)));
          }
        public virtual void PrependAnchor(SiteMapNode node)
        {
            HtmlAnchor anchor = new HtmlAnchor
            {
                HRef = node.Url,
                InnerText = node.Title
              };
            Controls.AddAt(0, anchor);
        }
   }
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;For my simple example i&#39;m quite satisfied and ready to test my new breadcrumb control. To do that we just need to add our newly created Path to our page like this.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;Kloojed:Path runat=&quot;server&quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We should now have a clean breadcrumb with no extra markup generated from the included &lt;code&gt;PageSiteMapProvider&lt;/code&gt;.&lt;/p&gt;</id><updated>2008-12-04T12:00:00.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>Create standards compliant links with EPiServer property</title><link href="http://www.kloojed.com/create-standards-compliant-links-with-episerver-property/" /><id>&lt;p&gt;If you are using a strict doctype when developing an EPiServer site which you always should do, then you probably are aware of the validation errors caused by the target attribute on the anchor tag that appears when you are using an EPiServer property if the target is set on the specific page.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public class PropertyPageReferenceCtrl : PropertyPageReferenceControl
{
    public override void CreateDefaultControls()
    {
        if (PageReference.IsValue(PageLink))
        {
            HyperLink target = new HyperLink();
            target.Text = &quot;Link&quot;;
            target.NavigateUrl = &quot;#&quot;;
            IPageSource parent = Parent as IPageSource;
            if (parent != null)
            {
                PageData page = parent.GetPage(PageLink);
                target.Text = HttpUtility.HtmlEncode((string)page[&quot;PageName&quot;]);
                target.NavigateUrl = page.LinkURL;
                if (page[&quot;PageTargetFrame&quot;] != null)
                {
                    string targetName = ((PropertyFrame)page.Property[&quot;PageTargetFrame&quot;]).FrameName;
                    if (targetName == &quot;_blank&quot;)
                    {
                        UrlBuilder url = new UrlBuilder(page.LinkURL);
                        Global.UrlRewriteProvider.ConvertToExternal(url, null, System.Text.Encoding.Default);
                        target.Attributes.Add(&quot;onclick&quot;, &quot;window.open(&#39;&quot; + url.Uri + &quot;&#39;); return false;&quot;);
                      }
                  }
                if (target.NavigateUrl == &quot;#&quot;)
                {
                    target.Attributes.Add(&quot;onclick&quot;, &quot;return false;&quot;);
                    target.Style.Add(&quot;cursor&quot;, &quot;default&quot;);
                  }
             }
            CopyWebAttributes(target);
            Controls.Add(target);
           }
       }
   }
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We inherit from PropertyPageReferenceControl and change the rendering in the CreateDefaultControls method. In this case the code looks exactly like the original property but with the modifications we wanted if the PageTargetFrame is set to _blank.&lt;/p&gt;

&lt;p&gt;Now we need to register our class to handle the rendering for all PropertyPageReference properties on our site. This can be done in your &lt;code&gt;global.asax.cs&lt;/code&gt; file in the &lt;code&gt;Application_Start&lt;/code&gt; method like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;protected void Application_Start(Object sender, EventArgs e)
{
    PropertyControlClassFactory.Instance.RegisterClass( typeof( PropertyPageReference ), typeof( PropertyPageReferenceCtrl ));
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;There you have it! Your done and ready to create x/html valid links with the EPiServer property.&lt;/p&gt;</id><updated>2008-08-28T12:00:00.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>New module at epicode</title><link href="http://www.kloojed.com/new-module-at-epicode/" /><id>&lt;p&gt;Have you ever wanted to provide your customers with an easy way of choosing a directory in the unified file system? I have created a custom property that allows you to do exactly that.&lt;/p&gt;

&lt;p&gt;The Folder Browser is a custom property with a popup dialog that lets the editor browse in all EPiServer file systems available on the site.&lt;/p&gt;

&lt;p&gt;The module is a part of the open source community for EPiServer modules called EPiCode. In order to download and browse the source code you need to register and apply for membership at &lt;a href=&quot;https://www.coderesort.com/p/epicode/wiki/FolderBrowserProperty&quot;&gt;EPiCode&lt;/a&gt;.&lt;/p&gt;</id><updated>2008-08-01T12:00:00.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>Browse ImageVault with PicLens</title><link href="http://www.kloojed.com/browse-imagevault-with-piclens/" /><id>&lt;p&gt;PicLens is a very useful addon for your browser that lets you browse images and other media in a 3D view. I have created a simple example on how you can enable PicLens on your EPiServer site running ImageVault.&lt;/p&gt;

&lt;p&gt;The following walkthrough shows you how to enable PicLens on any website using ImageVault.This tutorial shows the basics of creating a Media RSS and it will expose all images from ImageVault. In part 2 of this article you will be able to download a template with a little more functionality. If you don&#39;t have PicLens installed in your browser please visit &lt;a href=&quot;http://www.cooliris.com/&quot;&gt;http://www.cooliris.com/&lt;/a&gt; to install.&lt;/p&gt;

&lt;p&gt;To create the media RSS you need to create a generic handler. The media RSS is a standard for syndicating multimedia files (audio, video, image) in RSS feeds. So lets create a new generic handler and add the methods and properties we need.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public class PicLensHandler : IHttpHandler
{
    public void ProcessRequest(HttpContext context) { }
    private void WriteEntry(XmlTextWriter xtw, IVFileData item) { }
    public bool IsReusable { get { return true; } }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now its time to enable processing of the HTTP web request by overriding the ProcessRequest method. This is where we create the basic media rss structure needed for PicLens to work.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public class PicLensHandler : IHttpHandler
{
    public void ProcessRequest(HttpContext context)
    {
        int id = Convert.ToInt32(context.Request[&quot;album&quot;]);
        context.Response.ContentType = &quot;text/xml&quot;;
        XmlTextWriter xtw = new XmlTextWriter(context.Response.Output);
        xtw.Formatting = Formatting.Indented; xtw.WriteStartDocument();
        xtw.WriteStartElement(&quot;rss&quot;);
        xtw.WriteAttributeString(&quot;version&quot;, &quot;2&quot;);
        xtw.WriteAttributeString(&quot;xmlns&quot;, &quot;media&quot;, null, &quot;http://search.yahoo.com/mrss&quot;);
        xtw.WriteStartElement(&quot;channel&quot;);
        foreach (IVFileData fileData in IVDataFactory.GetFiles(IVDataFactory.RootAlbumId,true))
        {
            WriteEntry(xtw,fileData);
           }
        xtw.WriteEndElement();
        xtw.WriteEndElement();
        xtw.WriteEndDocument();
    }
    private void WriteEntry(XmlTextWriter xtw, IVFileData item) { }
    public bool IsReusable {
    get
    {
        return true;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;To complete the media rss we need to provide some code to our WriteEntry &lt;br /&gt;
method. This method creates an item entry with three different ImageVault &lt;br /&gt;
handler links to different image sizes (weburl, thumbnailurl and largeurl).&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public class PicLensHandler : IHttpHandler
{
    public void ProcessRequest(HttpContext context)
    {
        int id = Convert.ToInt32(context.Request[&quot;album&quot;]);
        context.Response.ContentType = &quot;text/xml&quot;;
        XmlTextWriter xtw = new XmlTextWriter(context.Response.Output);
        xtw.Formatting = Formatting.Indented; xtw.WriteStartDocument();
        xtw.WriteStartElement(&quot;rss&quot;);
        xtw.WriteAttributeString(&quot;version&quot;, &quot;2&quot;);
        xtw.WriteAttributeString(&quot;xmlns&quot;, &quot;media&quot;, null, &quot;http://search.yahoo.com/mrss&quot;);
        xtw.WriteStartElement(&quot;channel&quot;);
        foreach (IVFileData fileData in IVDataFactory.GetFiles(IVDataFactory.RootAlbumId,true))
        {
            WriteEntry(xtw,fileData);
        }
        xtw.WriteEndElement();
        xtw.WriteEndElement();
        xtw.WriteEndDocument();
     }
    private void WriteEntry(XmlTextWriter xtw, IVFileData item)
    {
        xtw.WriteStartElement(&quot;item&quot;);
        xtw.WriteElementString(&quot;title&quot;, item.Title);
        xtw.WriteElementString(&quot;link&quot;, new IVUrlBuilder
            {
                Id = item.Id,
                Width = 500,
                Height = 500
             }.ToString();
         xtw.WriteStartElement(&quot;media:thumbnail&quot;);
        xtw.WriteAttributeString(&quot;url&quot;, new IVUrlBuilder
            {
                Id = item.Id,
                Width = 300,
                Height = 300
            }.ToString();
        xtw.WriteEndElement();
        xtw.WriteStartElement(&quot;media:content&quot;);
        xtw.WriteAttributeString(&quot;url&quot;, new IVUrlBuilder
            {
                Id = item.Id,
                Width = 1024,
                Height = 1024
            }.ToString();
         xtw.WriteEndElement();
        xtw.WriteEndElement();
    }
    public bool IsReusable
    {
        get 
        {
            return true;
        }
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now your done and we can add the handler to your head section in your &lt;abbr title=&quot;Extensible HyperText Markup Language&quot;&gt;x/html&lt;/abbr&gt; document like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&quot;alternate&quot; type=&quot;application/rss+xml&quot; title=&quot;Kloojed - ImageVault image stream&quot; href=&quot;/PicLensHandler.ashx&quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Visit your page and enjoy your ImageVault images in PicLens. Hope you enjoyed this article and feel free to drop a comment below.&lt;/p&gt;</id><updated>2008-07-25T12:00:00.0000000Z</updated><summary type="html">Blog post</summary></entry></feed>