@Shazwazza

Shannon Deminick's blog all about web development

Umbraco Jupiter Plugins - Part 1

April 29, 2011 11:55

This is the first blog post in a series of posts relating to building plugins for Umbraco v5 (Jupiter)

Disclaimer

This post is about developing for Umbraco v5 (Jupiter) which at the time of this post is still under development. The technical details described below may change by the time Umbraco Jupiter is released. If you have feedback on the technical implementation details, please comment below.

What is a plugin

Since Umbraco Jupiter has been built from the ground up, we first need to define some v5 terminology:

  • Plugin = A single functional component that extends Umbraco such as a Tree, an Editor, a Menu Item, etc…
  • Package = A group of Plugins installed into Umbraco via the ~/Plugins/Packages/[Package Name] folder

The Umbraco v5 back-office has been architected to run entirely on Plugins, in fact the core trees, editors, etc… that are shipped with Umbraco are Plugins in v5.

Types of plugins

The list of Plugin types will most likely increase from the time of this blog post to when Jupiter is launched but as it stands now here are the types of Plugins supported in v5:

  • Property Editors
    • This term is new to v5. In v4.x there was no differentiation between a Data Type and it’s underlying ‘Data Type’ editor. In v5 we’ve made a clear distinction between a ‘Data Type’ (as seen in the Data Type tree and used as properties for Document Types) and the underlying editor and pre-value editor that it exposes.  An example of a Property Editor would be uComponents’ Multi-Node Tree Picker. An example of a Data Type would be when an Umbraco administrator creates a new Data Type node in the Data Type tree and assigns the Multi-Node Tree Picker as it’s Property Editor.
    • So uComponents Team, this is where you need to focus your efforts for version 5!
  • Menu Items
    • Context menu items such as Create, Publish, Audit Trail, etc… are all plugins.
    • See this post in regards to creating menu items in v5, though there have been some new features added since that article was created which I’ll detail in coming posts in this series.
  • Editors
    • Editor plugins are all of the interactions performed in the right hand editor panel and in modal dialogs in the back-office.
    • For example, the Content Editor core plugin in v5 manages the rendering for all views such as editing content, sorting, copying, and moving nodes, and nearly all of the other views that the context menu actions render.
    • Editors are comprised mostly of MVC Controllers, Views, JavaScript & CSS.
  • Trees
    • All trees are plugins, for example, the Content tree, Media tree, Document Type tree are all different plugins.
    • Trees are actually MVC controllers.
    • Tree nodes use Menu Items to render Editors
  •  Presentation Addins (Yet to be officially named)
    • Another type of plugin are Controllers that are installed via packages that interact with the presentation layer, an example of this might be the Controller Action that accepts the post values from a Contour form.

Whats next?

In the coming blog posts I’ll talk about

  • how plugins are installed and loaded
  • how the Umbraco routing system works with all of these controllers
  • how and where the Views are stored that the plugins reference
  • how to create all of the different types of plugins

Code Garden 2011

I’ll be doing a talk on Plugins for Umbraco Jupiter at Code Garden 2011 this year which will go in to a lot more detail than these blog posts. If you are attending Code Garden already, then hopefully this series will give you a head start on Umbraco v5. If you haven’t got your tickets to Code Garden yet, what are you waiting for?! We have so much information to share with you :)

uComponents 2.0 beta out soon

November 17, 2010 20:04

It’s been a while since I’ve had the time to write a blog post and this is far overdue. We very quietly released uComponents v2.0 Preview on Oct 16th (which you can find here: http://ucomponents.codeplex.com/releases/view/54016 ) and soon we’ll be releasing v2.0 Beta! Since I really don’t have much time to write this post, I’ll keep it very brief. Here’s what you can expect from v2.0:

  • Umbraco ‘Shortcuts’
    • Keyboard navigation in the tree
    • Keyboard navigation between applications
  • Drag/Drop everywhere
    • Ability to drag and drop nodes from the main content tree to media/content pickers, from content trees to Multi-node tree picker, etc.... Pretty much allows you to drag and drop nodes to nearly anywhere where you think it's relavent.
  • New data types:
    • URL Picker
    • Country Picker
    • Text Image (if we can hunt down Dascoba to fix the remaining issues)
  • Plenty more XSLT extensions for your enjoyment
  • Some bugs fixed… turns out there hasn’t been too many since v1.0… that’s great news!!
  • And hopefully i can get to a few of the user’s requests for additions to Multi Node Tree Picker such as XPath selectors from current node, or from entire tree, etc…

Thanks to the uComponents team for all of their hard work and especially to Niels Kühnel for ‘Shortcuts’ and ‘Drag/Drop everywhere' and to James Diacono from TheFARM for the new URL Picker.

We’ll keep everyone informed once the beta is out. It shouldn’t be too much longer and we won’t be keeping this release quiet like the preview!

Injecting JavaScript into other frames

September 9, 2010 20:44

The beautiful part of JavaScript is that it is ridiculously flexible and lets you do things that ‘probably’ shouldn’t be done. Here’s a good example of that.

During uComponents development I stumbled upon a situation where I needed to attach a JavaScript method to the top-level frame from inside of an iframe. Well in fact it turns out this is quite easy, you can do something like this:

window.top.doThis = function() { alert("woot!"); }

However, since we’re attaching the ‘doThis’ method to the main frame from an inner iframe, when the inner iframenavigates to another page, this function will no longer exist on the main frame… So this clearly isn’t going to work if we want to be able to call the ‘doThis’ method from the inner frame no matter when and where it navigates to… Conundrum!

So the next possibility is to try to just inject a script block into the main frame from the iframewhich actually does work in Firefox and Chrome but fails in Internet Explorer and Safari. (This snippet of code requires that you have jQuery loaded in the main frame)

var js = "function doThis() { alert('woot!'); }"; var injectScript = window.top.$('<script>') .attr('type', 'text/javascript') .html(js); window.top.$("head").append(injectScript);

In the above, we’re creating a string function, creating a <script> block with jQuery, appending the string function to the script block and then appending this script block to the <head> element of the main frame. But as i said before, Firefox and Chrome are ok with this but Internet Explorer and Safari will throw JavaScript exceptions such as: Unexpected call to method or property access

Ok, so unless you don’t want to be cross browser, this isn’t going to work. It took me a while to figure out that you can do this, but this does work. Yes it looks pretty dodgy, and it probably is. In reality, attempting to do something like this is pretty dodgy to begin with. So here it is (this works in Internet Explorer 8 (probably earlier ones too), Firefox 3.6 (probably earlier ones too) and Chrome 5 (probably earlier ones too) and i didn’t get around to testing Safari but I am assuming it works):

var iframe = window.top.$("#dummyIFrame"); if (iframe.length == 0) { var html = "<html><head><script type='text/javascript'>" + "this.window.doThis = function() { alert('woot'); };" + "</script></head><body></body></html>"; iframe = window.top.$("<iframe id='dummyIFrame'>") .append(html) .hide() .css("width", "0px") .css("height", "0px"); window.top.$("body").append(iframe); }

So i guess this requires a bit of explanation. All browsers seem to let you create iframes dynamically which also means that you can put whatever content into the iframes while it’s being created, including script blocks. Here’s what we’re doing:

  • checking if our ‘dummy’ iframe already exists (since we don’t want to create multiple dummy iframes since we only need one), if it doesn't:
  • create an html text block including the script that will attach the ‘doThis’ method to the ‘this.window’ object (which for some reason will be referring to the window.top object)
  • next we create an iframe element and append the html text block, and then make sure the iframe is completely hidden
  • finally, we append the iframe to the main window’s body element
window.top.doThis();

Nice! So this pretty much means that you can create code from an inner frame and attach it to a different frame, then have that code run in the context of the main frame with the main frame’s objects and script set.

One last thing that i found out you can do, though i wouldn’t recommend it because i think it might start filling up your memory. But this is also possible:

var html = "<html><head><script type='text/javascript'>" + "this.window.doThis = function() { alert('woot'); };" + "this.window.doThis();" + "</script></head><body></body></html>"; iframe = window.top.$("<iframe id='dummyIFrame'>") .append(html);

All that is happening here is that I’m attaching the ‘doThis’ method to the main frame’s window object, calling it directly after and then creating an iframe in memory with this script block. The funny part is that the method executes straight away and I haven’t attached the iframe to the DOM anywhere!

Multi-node tree picker enhanced!

September 3, 2010 12:19

Thanks to everyone who’s submitted feedback for the Multi-node tree picker (or MNTP as it’s known by the uComponents guys). I’ve pretty much done everything everyone’s asked for except for a couple of things which I’ll do next week. In the meantime, I figured I’d write up another post to show you how far it’s come in just under 1 week. So here’s all of the new features:

New data type options

image

I know I said I wasn’t going to do it for this release but quite a few people commented on having a start node id assigned, so I got it implemented. There will still be issues if you assign a start node id for the picker that a particular user doesn’t have access to. The picker will then display an error message to the user, but this could be confusing to them so keep that in mind. You can now toggle the XSLT match type so that either: no nodes are selectable unless the XPath matches them, or all nodes are selectable unless the XPath matches them. A new feature in the data editor (as seen below) is an informational tooltip for a selected node. These can be turned off if you don’t want your editors seeing them. And lastly, you can choose how you would like to save the data in Umbraco, either as XML or comma separated values.

Data editor enhancements

image

As you can see there’s the new tooltip info display (which can be turned off in the pre-value editor if you don’t want it). Inside the tooltip panel, you can click on the ‘edit’ button to navigate to the editor screen for that selected node. A prompt will be displayed asking you if you are sure you’d like to continue since your current page will not be displayed.

image

And as you can see above,  specifying the start node id is working!

//TODO:

So the last few things to implement are:

  • Visually show in the tree which nodes have already been selected on the right
  • Add property to the data type to specify a minimum number of nodes that must be selected
  • Thumbnail previews when using the Media tree

 

Hopefully we can launch v1.0 soon!!!

Multi-node tree picker in uComponents v1.0 BETA

September 1, 2010 09:46

The uComponents team has been hard at work trying to get this project launched and finally we managed to get a beta out last week. Woot! Hopefully we can get the RTM out within a week or two and get a few of those bugs fixed. The package is listed on Our.Umbraco here, be sure to vote for it if you like it.

The Multi-node tree picker is one of the 17 data types that can be found in uComponents (only 13 are available in the beta). This is essentially a content or media picker that can select multiple nodes that can then be sorted and saved to a document type… it’s also packed full of fun features!

Here’s what it can currently do

image

Drag & drop sortable list

The nodes on the right can easily be sorted by simply dragging and dropping them in the order you’d like them

Tree syncing

When the nodes on the right hand side are clicked, the tree on the left hand side will sync to that node so that your content editors can see where that node originated.

UI indicators

  • Dimmed nodes indicate nodes that cannot be selected based on the XPath filter specified in the pre-value editor for the data type
  • When nodes are clicked and the max node selection limit has been reached, or the node is not a selectable node, the node will quickly blink red

image

Media & content pickers

The data type can be customized to allow a content or media picker. Future version will most likely allow for other types of data.

XPath filter

An XPath fliter to match nodes that will be disabled from being clicked. These nodes will be dimmed (as seen in the first screen shot) when the editor is rendered.

Maximum node selections

A negative –1 value will mean that the editor is able to select an unlimited number of nodes. If a positive number is entered, the content editor will only be able to select the number of nodes defined here. If they attempt to select more than the amount defined, the node will blink red (as seen in the first screen shot).

Here’s what I’d like it to do

Hopefully I can get most of these ideas into the RTM release of uComponents

Thumbnail preview for media selections

When Media is the source of the picker, it would be great to render the thumbnail of the media item (if it’s an image) on the right hand side with a link to view the full image.

UI Indicator for already selected nodes

It would be cool to have a custom background color for nodes in the tree that are already selected on the right hand side

Custom tooltips with detailed information about selected nodes

When an item on the right is hovered over, a custom tooltip (or similar) should be displayed with the item’s path and ID

Limitations

Once of the limitations of this control that a few people have asked for is the ability to select a starting node for the tree. The reason that this isn’t implemented is because this is already implemented in standard tree security. The trees rendered in this control respect the same security principles as the standard content & media trees. It would be slightly confusing to be able to assign a start node ID on a tree twice as in some cases, based on security, a content editor might not see any nodes rendered for a tree. Perhaps this can be implemented in a later release if people really want this functionality but will probably not be included with v1.0.

Currently this data type saves the data as XML into Umbraco. Though this works great for XSLT, there’s issues in Umbraco that don’t return the XML data stored when using Node factory or Linq to Umbraco. In Umbraco version 4.5.2, the Node factory issue is fixed but the Linq to Umbraco issue still remains. Because of this, I will probably add support to the Multi-node tree picker to allow the developer to choose how they would like the data stored; either has comma delimited or XML.

Dynamically registering custom trees without writing to UmbracoAppTree

August 17, 2010 08:41

When creating custom trees in Umbraco, the standard rule of thumb is that you need to register your tree definition into the UmbracoAppTree table so that it shows up in the back-office for a particular application. Well here’s a little secret gem that has been around since version 4 … you don’t actually need to register your trees in the database, you just need to register them in code (however, read the important note at the end of this post!)

In the Umbraco codebase there is a Singleton class called: TreeDefinitionCollection which contains the definitions of all of the trees that are registered in the UmbracoAppTree database table. It just so happens that the TreeDefinitionCollection is a mutable collection, meaning you can dynamically add/remove items from it at runtime. So, here’s how you do it:

Somewhere in your application, you’ll need to add a new tree definition to this collection and you’ll definitely want to do the registration before you want your tree to be rendered, so you’ve got a couple of options here:

  • Global.asax or module
  • In an ApplicationBase class of your own
  • Or, some class, static constructor, etc… that you know will be executed before your tree is rendered

You’ll also need to put a lock on your code, otherwise you might run into concurrency issues. This example registers my custom FilteredContentTree in a static constructor method for my data type. Since this data type is the only object that requires this tree, I know that this code is going to execute before the tree is ever rendered.

public MultiNodeTreePickerDataEditor() { //check if my custom tree is already registered if (TreeDefinitionCollection.Instance .Where(x => x.TreeType == typeof(FilteredContentTree)) .Count() == 0) { lock (m_Locker) { //double check lock.... if (TreeDefinitionCollection.Instance .Where(x => x.TreeType == typeof(FilteredContentTree)) .Count() == 0) { //need to add our tree definitions to the collection. //find the content tree to duplicate var contentTree = TreeDefinitionCollection.Instance .Where(x => x.Tree.Alias == "content").Single(); //create the tree definition with the same details //as the standard content tree, however mark it as 'initialize' = false //which means that it won't be rendered by default in the umbraco //back-office, only when I use the tree control to render it //directly for my data type. var filteredContentTree = new TreeDefinition(typeof(FilteredContentTree), new umbraco.BusinessLogic.ApplicationTree(true, false, 0, contentTree.Tree.ApplicationAlias, "FilteredContentTree", contentTree.Tree.Title, contentTree.Tree.IconClosed, contentTree.Tree.IconOpened, "uComponents.Core", "DataTypes.MultiNodeTreePicker.FilteredContentTree", contentTree.Tree.Action), contentTree.App); //add it to the collection at runtime TreeDefinitionCollection.Instance.Add(filteredContentTree); } } } }

I

think the code/comments are fairly straight forward. As you can see, registering a custom tree into the collection at runtime is very easy! No database work required :)

IMPORTANT NOTE: Though this is nice and easy to do, this does prevent your users from being able to remove trees that they don’t want!! They would only have 2 options at their disposal to remove the tree that they no longer want:

  • Delete the assembly that is registering the tree
  • OR, use their own code to unregister the tree

The example that I’ve used above is for the Multi-node tree picker in uComponents and is used for the data type only (which is why it is registered to not be initialized).

Enjoy!

Multi-node tree picker now supporting filters

August 13, 2010 12:48

This data type is coming quite close to release with full support for XPath filtering.

Here’s some screen shots with an example:

image

So the above basically will make sure that the editor cannot link to faqCategory or faq node types. Here’s the result in the editor:

image

As you can see in the editor these 2 node types are disabled and not clickable…. sweet!

The XPath filter support full xpath against the standard Umbraco XML for an individual node.

How to embed ASMX web services in a DLL

August 13, 2010 00:01

The development of uComponents for Umbraco is still ongoing but is probably close to a v1.0 release. During the development of the Multi-node tree picker data type, I’ve spotted a bug in the Umbraco core in regards to the ASMX web service the existing tree uses to render out it’s initial node. The bug basically won’t allow the tree to render an individual tree, only a full app. Since the Multi-node tree picker requires rendering of an individual tree, i needed to fix this. To do this was a bit of a work around but i had to override the tree’s ASMX web service with my own (I’ll write a post about this one later). It then occurred to me that I’ve never embedded an ASMX web service into a DLL without a physical file and I didn’t want to go updating the web.config with custom handlers, etc… So I came up with a way to embed ASMX web services in your DLL without modifying web.config’s, etc… here’s how:

First, create your web service as a standard class and add all of the functionality that your require your web service to have:

image

In your class library project, create a new text file but give it the extension .asmx:

image

Set the file to be a non compiled file:

image

Create an resource file:

image

Double click on your new RESX file, then drag your ASMX file into the editor to add the file as a property of your RESX file:

image

Double click your ASMX file to edit it and set it to inherit from your custom web service class:

image

Now, we need to register this ASMX web service into the web application that it’s being deployed to. This is easily done by just checking if the ASMX file exists where it needs to be before it needs to be called and if it doesn’t, we just create the file. In the case of uComponents and the multi-node tree picker requires the ASMX web service for the CustomTreeControl, so we’ll do this check in the CustomTreeControl’s static constructor:

public CustomTreeControl() { var filePath = HttpContext.Current .Server.MapPath("~/CustomTreeService.asmx"); //check if it exists if (!File.Exists(filePath)) { //lock the thread lock (m_Locker) { //double check locking.... if (!File.Exists(filePath)) { //now create our new local web service using (var sw = new StreamWriter(File.Create(filePath))) { //write the contents of our embedded resource to the file sw.Write(CustomTreeServiceResource.CustomTreeService); } } } } }

 

That’s it!

And it begins

August 11, 2010 10:22

For the last couple of years I've been blogging on FARMCode.org and today decided that I was going to start up my own blog as well. This doesn't mean that I won't still be blogging on FARMCode, it just means that I have a new place to post up information that may not directly relate to TheFARM.

In the coming weeks I'll start posting up some new content, code snippets, some info on the up and coming Umbraco project we've been working on called uComponents and maybe some portfolio work as well.

Adding embedded resource with ClientDependency

August 3, 2010 22:32
This post was imported from FARMCode.org which has been discontinued. These posts now exist here as an archive. They may contain broken links and images.
The uComponents project for Umbraco is coming along rather nicely! So far there are 13 new data types created and a few extensions, hopefully soon we’ll have a package ready to go. In the meantime, I thought I’d share a nice little code snippet that we’re using this throughout uComponents that allows you to add embedded resources to ClientDependency. It’s pretty easy and works perfectly with Umbraco 4.5 or any other site you have running ClientDependency. This will ensure that embedded resources (JavaScript or CSS) are added to the ClientDependency combined scripts/styles and also compressed and cached.

First, I’ll show you how to register your embedded resources using our extension method class (for a Control object):

this.AddResourceToClientDependency(
    "DataTypesForUmbraco.Controls.Shared.Resources.PrevalueEditor.css", 
    ClientDependency.Core.ClientDependencyType.Css);

The above code assumes:

  • The class that you are consuming the code inherits from System.Web.UI.Control
  • That your embedded resource’s path is: DataTypesForUmbraco.Controls.Shared.Resources.PrevalueEditor.css
  • That your embedded resource is a CSS type

Pretty easy right!! Well, the only thing missing is that you’ll need to add our extension method class to your project which looks like this:

/// 
/// Extension methods for embedded resources
/// 
public static class ResourceExtensions
{

    /// 
    /// Adds an embedded resource to the ClientDependency output by name
    /// 
    /// 
    /// 
    /// 
    public static void AddResourceToClientDependency(this Control ctl, string resourceName, ClientDependencyType type)
    {
        //get the urls for the embedded resources           
        var resourceUrl = ctl.Page.ClientScript.GetWebResourceUrl(ctl.GetType(), resourceName);

        //add the resources to client dependency
        ClientDependencyLoader.Instance.RegisterDependency(resourceUrl, type);
    }

    /// 
    /// Adds an embedded resource to the ClientDependency output by name and priority
    /// 
    /// 
    /// 
    /// 
    public static void AddResourceToClientDependency(this Control ctl, string resourceName, ClientDependencyType type, int priority)
    {
        //get the urls for the embedded resources           
        var resourceUrl = ctl.Page.ClientScript.GetWebResourceUrl(ctl.GetType(), resourceName);

        //add the resources to client dependency
        ClientDependencyLoader.Instance.RegisterDependency(priority, resourceUrl, type);
    }

}

So basically, if you have a Control, you can register your embedded resources in ClientDependency with one line of code… sweeeeet.