Few months ago I prepared ContentArea property with image thumbnails and image preview support. The new EPiServer has Content References list property which already implements thumbnails for list items. In Content references list with preview property I tried to extend standard editor and add support for image preview as well.
Client editor
The multipleReferencesWithPreview.js widget extends built-in EPiServer ContentReferenceListEditor editor. Standard editor use ContentReferenceList widget, which use “List” and “Formatter” mixins. So probably it could be possible to prepare a custom item formatter and use it to show tooltip. I decided to use different solution to minimize the amount of code.
The List mixin has insertRow method used every time new element is added. I tried to call the original method and then add my custom code. To achieve this I used dojo aspect functionality. Using this module we can attach custom code to existing methods. Module provides three methods:
- before – the code will be executed before original method.
- after – the code will be executed after original method.
- around – the code will be executed in place of original method.
I used “around” method, because I needed access to input parameters, but also I wanted to change the return value. The widget source code is below:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
define([ "dojo/_base/declare", "dojo/_base/lang", "dojo/query", "dojo/on", "dojo/dom", "dojo/aspect", "dijit/popup", "dijit/TooltipDialog", "epi-cms/contentediting/editors/ContentReferenceListEditor" ], function( declare, lang, query, on, dom, aspect, popup, TooltipDialog, ContentReferenceListEditor ) { return declare("alloy.editors.multipleReferencesWithPreview", [ContentReferenceListEditor], { buildRendering: function () { this.inherited(arguments); var _this = this; aspect.around(this.list._list, "insertRow", function(originalInsertRow) { return function (object, parent, beforeNode, i, option) { var row = originalInsertRow.apply(this, arguments); var node = query("div.epi-mo--img", row); lang.hitch(_this, _this._createTooltip(row, node, object.previewUrl)); return row; } }); }, _createTooltip: function (node, imgNode, previewUrl) { this.own(node.imageTooltip = new TooltipDialog({ connectId: [node.id], content: "<img src='" + previewUrl + "' style='max-height: 250px;max-width: 400px;'/>", onMouseLeave: function () { popup.close(node.imageTooltip); } })); on(imgNode, 'mouseleave', function () { popup.close(node.imageTooltip); }); on(imgNode, 'click', function () { popup.open({ popup: node.imageTooltip, around: dom.byId(node.id), orient: ["after-centered"] }); }); } }); }); |
Server code
I also created EditorDescriptor responsible for setting new widget class.
1 2 3 4 5 6 7 8 9 10 |
[EditorDescriptorRegistration(TargetType = typeof(IList<ContentReference>), UIHint = UiHint)] public class MultipleReferencesEditorWithPreviewDescriptor : ContentReferenceListEditorDescriptor { public const string UiHint = "multiple-references-with-preview"; public MultipleReferencesEditorWithPreviewDescriptor(IEnumerable<IContentRepositoryDescriptor> contentRepositoryDescriptors, IContentLoader contentLoader): base(contentRepositoryDescriptors, contentLoader) { this.ClientEditingClass = "alloy.editors.multipleReferencesWithPreview"; } } |
To make it work I’ve added “multiple-references-with-preview” on page model:
1 2 3 4 5 6 7 |
[SiteContentType(GUID = "263B8330-791D-4A5E-BAE4-E7B59F93D3FB")] public class ArticleWithSlider: ArticlePage { [UIHint(MultipleReferencesEditorWithPreviewDescriptor.UiHint)] [Display(GroupName = SystemTabNames.Content, Name = "Carousel", Order = 100)] public virtual IList<ContentReference> ContentReferencesCollection { get; set; } } |
The snippet is available on Gist