Add "ImageField" as custom field for Blogs, make it return Guid
OK, so looking for some help from the smart community on this one:
I need to associate an image with a Blog Post. I've added a custom field of name "Image", type "Short Text" and set the custom template as "Telerik.Sitefinity.Web.UI.Fields.ImageField" as per the following post:
http://www.sitefinity.com/devnet/forums/sitefinity-4-x/developing-with-sitefinity/wordpress-to-sitefinity-blog-conversion.aspx
This is working really well, I like the way it works in the backend.
To render this on the Blog Post page, my Widget Template has added the line:
<img src='<%# Eval("Image")%>' />
This also works.
HOWEVER, because this "Telerik.Sitefinity.Web.UI.Fields.ImageField" is returning the image selected and storing the URL as a string in my custom field, I can't access the images alt-text.
I have two options as I see it:
1) Using API, lookup the image by Url/Filepath or similar. Although titles of image should be unique (I think?) this seems hackish and I'm nervous that if someone changes the image URL/Title my link between that image and the blog post might break
2) Much better would be to store the selected images Guid. Then in code-behind I can lookup the image by Guid and access MediaUrl & AlternateText and be happy.
Can anyone offer any insight into how to achieve this please? This is doing my head in and holding up progress on our latest site.
ImageField (selector) can provide the selected GUID to the client.
Accessed from: .get_selectedImageItem().Id
Legend, this is exactly what I need, and seems like it will work really well. I've actually used similar code in my Javascript for a Custom Widget with Designer.
In fact, thinking quickly about this - am I potentially creating a Control that is a complete copy of the ImageField but with a different line or 2 of javascript?
I will second that this needs to be built in. It is already a built in option for items built using the Module Builder.
By the way, I'm tagging along as I have to do the exact same thing here.
Ok, I have a functional module that does this for Image, Document and Videos. It was based off of the SimpleImageField example, but I cleaned it up quite a bit (With a lot of help from the Telerik support staff... thanks again guys). I'd be willing to share if anyone wants to take it and run with it, but I have no intention of maintaining it as a community module... so if anyone wants to take my source and make a generic module for everyone, let me know.
Hi Mike,
I am very happy to hear you have successfully implemented the desired functionality. Thank you very much for actively participating in our community and the willingness to share your project with the rest of the people reading these forums. As a token of appreciation we have updated your Telerik points accordingly.
Regards,
Boyan Barnev
the Telerik team
Hi Michael,
this sounds great, as I have exact the same problem. Would you share your code? :)
Regards,
Michael
Well, I don't have anywhere public to place the ZIP file, and I'm not allowed to attach a ZIP file to this post. That's why I was hoping someone would take this and run with it, create an actual module, etc. All you'd need to do is maybe add some lines to the module file to add these fields to the ShortText field type so you don't have to type in the namespace all the time, etc., if that's possible (Haven't tried yet).
<%@ Control %><%@ Register Assembly="Telerik.Sitefinity" Namespace="Telerik.Sitefinity.Web.UI" TagPrefix="sf" %><sf:ResourceLinks ID="resourcesLinks" runat="server" UseEmbeddedThemes="True" Theme="Default"> <sf:ResourceFile JavaScriptLibrary="JQuery" /> <sf:ResourceFile Name="Telerik.Sitefinity.Resources.Themes.Default.Styles.jQuery.jquery.ui.core.css" Static="True"/> <sf:ResourceFile Name="Telerik.Sitefinity.Resources.Themes.Default.Styles.jQuery.jquery.ui.dialog.css" Static="True"/> <sf:ResourceFile Name="Telerik.Sitefinity.Resources.Themes.Default.Styles.jQuery.jquery.ui.theme.sitefinity.css" Static="True"/> </sf:ResourceLinks><sf:ConditionalTemplateContainer ID="conditionalTemplate" runat="server"> <Templates> <sf:ConditionalTemplate Left="DisplayMode" Operator="Equal" Right="Read" runat="server"> <sf:SitefinityLabel id="titleLabel_read" runat="server" WrapperTagName="div" HideIfNoText="true" CssClass="sfTxtLbl"></sf:SitefinityLabel> <sf:SitefinityLabel id="textLabel_read" runat="server" WrapperTagName="div" HideIfNoText="true" CssClass="sfTxtContent"></sf:SitefinityLabel> <asp:Image ID="image_read" runat="server" /> <sf:SitefinityLabel id="descriptionLabel_read" runat="server" WrapperTagName="p" HideIfNoText="true" CssClass="sfDescription"></sf:SitefinityLabel> <sf:SitefinityLabel ID="exampleLabel_read" runat="server" WrapperTagName="P" HideIfNoText="true" CssClass="sfExample" /> </sf:ConditionalTemplate> <sf:ConditionalTemplate Left="DisplayMode" Operator="Equal" Right="Write" runat="server"> <sf:SitefinityLabel ID="titleLabel_write" runat="server" CssClass="sfTxtLbl" /> <div class="sfPreviewImgFrame"> <asp:Image ID="image_write" runat="server" Width="160" Height="160" /> </div> <sf:EditorContentManagerDialog runat="server" ID="asyncImageSelector" DialogMode="Image" Width="540" HostedInRadWindow="false" BodyCssClass="" /> <asp:LinkButton ID="selectImageButton_write" OnClientClick="return false;" runat="server" CssClass="sfLinkBtn sfChange"> <span class="sfLinkBtnIn"><asp:Literal runat="server" ID="AddImageLiteral" Text="Select..." /></span> </asp:LinkButton> <sf:SitefinityLabel id="descriptionLabel_write" runat="server" WrapperTagName="div" HideIfNoText="true" CssClass="sfDescription" /> <sf:SitefinityLabel id="exampleLabel_write" runat="server" WrapperTagName="div" HideIfNoText="true" CssClass="sfExample" /> </sf:ConditionalTemplate> </Templates></sf:ConditionalTemplateContainer>using System;using System.Collections.Generic;using System.Linq;using System.Web;using System.Web.UI;using System.Web.UI.WebControls;using Telerik.Sitefinity;using Telerik.Sitefinity.Web.UI;using Telerik.Sitefinity.Web.UI.Fields;using Telerik.Sitefinity.Web.UI.Fields.Enums;namespace NSC.Sitefinity.Modules.AssetPickerFields.ImageField /// <summary> /// Sitefinity ImageField class. /// </summary> [FieldDefinitionElement(typeof(ImageFieldDefinitionElement))] public class ImageField : FieldControl #region Constructors /// <summary> /// Initializes a new instance of the <see cref="ImageField" /> class. /// </summary> public ImageField() LayoutTemplatePath = layoutTemplatePath; #endregion #region Properties /// <summary> /// Gets the title control. /// </summary> protected override WebControl TitleControl get return TitleLabel; /// <summary> /// Gets the description control. /// </summary> protected override WebControl DescriptionControl get return DescriptionLabel; /// <summary> /// Gets the example control. /// </summary> protected override WebControl ExampleControl get return ExampleLabel; /// <summary> /// Gets the name of the layout template. /// </summary> protected override string LayoutTemplateName get return null; /// <summary> /// Gets the reference to the label control that represents the title of the field control. /// </summary> /// <remarks> /// This control is mandatory only in write mode. /// </remarks> protected internal virtual Label TitleLabel get return DisplayMode == FieldDisplayMode.Write ? Container.GetControl<Label>("titleLabel_write", true) : Container.GetControl<Label>("titleLabel_read", true); /// <summary> /// Gets the reference to the label control that represents the description of the field control. /// </summary> /// <remarks> /// This control is mandatory only in write mode. /// </remarks> protected internal virtual Label DescriptionLabel get return DisplayMode == FieldDisplayMode.Write ? Container.GetControl<Label>("descriptionLabel_write", true) : Container.GetControl<Label>("descriptionLabel_read", true); /// <summary> /// Gets the reference to the label control that displays the example for this /// field control. /// </summary> /// <remarks> /// This control is mandatory only in the write mode. /// </remarks> protected internal virtual Label ExampleLabel get return DisplayMode == FieldDisplayMode.Write ? Container.GetControl<Label>("exampleLabel_write", true) : Container.GetControl<Label>("exampleLabel_read", true); /// <summary> /// Gets or sets the value. /// </summary> /// <value>The value.</value> public override object Value get return _imageId; set if (value != null) var val = new Guid(value.ToString()); _imageId = val; if (val != Guid.Empty) ReadImage.ImageUrl = App.WorkWith().Image(val).Get().MediaUrl; /// <summary> /// Gets the read image control. /// </summary> protected Image ReadImage get return Container.GetControl<Image>("image_read", false); /// <summary> /// Gets the write image control. /// </summary> protected Image WriteImage get return Container.GetControl<Image>("image_write", false); /// <summary> /// Gets the async image selector. /// </summary> protected EditorContentManagerDialog AsyncImageSelector get return Container.GetControl<EditorContentManagerDialog>("asyncImageSelector", false); /// <summary> /// Gets the select image button control. /// </summary> protected LinkButton SelectImageButton get return Container.GetControl<LinkButton>("selectImageButton_write", false); #endregion #region Methods /// <summary> /// Initializes the controls. /// </summary> /// <param name="container">The container.</param> protected override void InitializeControls(GenericContainer container) TitleLabel.Text = Title; ExampleLabel.Text = Example; DescriptionLabel.Text = Description; if (_imageId != Guid.Empty) ReadImage.ImageUrl = App.WorkWith().Image(_imageId).Get().MediaUrl; /// <summary> /// Gets the script descriptors. /// </summary> /// <returns>List of script descriptors.</returns> public override IEnumerable<ScriptDescriptor> GetScriptDescriptors() var descriptors = new List<ScriptDescriptor>(); var descriptor = base.GetScriptDescriptors().Last() as ScriptControlDescriptor; if (DisplayMode == FieldDisplayMode.Read) descriptor.AddElementProperty("readImage", ReadImage.ClientID); if (DisplayMode == FieldDisplayMode.Write) descriptor.AddComponentProperty("asyncImageSelector", AsyncImageSelector.ClientID); descriptor.AddElementProperty("selectImageButton", SelectImageButton.ClientID); descriptor.AddElementProperty("writeImage", WriteImage.ClientID); descriptor.AddProperty("imageServiceUrl", VirtualPathUtility.ToAbsolute("~/Sitefinity/Services/Content/ImageService.svc/")); descriptors.Add(descriptor); return descriptors.ToArray(); /// <summary> /// Gets the script references. /// </summary> /// <returns>List of script references.</returns> public override IEnumerable<ScriptReference> GetScriptReferences() var scripts = new List<ScriptReference>(base.GetScriptReferences()); scripts.Add(new ScriptReference("Telerik.Sitefinity.Resources.Scripts.jquery-ui-1.8.8.custom.min.js", "Telerik.Sitefinity.Resources")); scripts.Add(new ScriptReference("Telerik.Sitefinity.Resources.Scripts.ajaxupload.js", "Telerik.Sitefinity.Resources")); scripts.Add(new ScriptReference(ScriptReference, typeof(AssetPickerFieldsModule).Namespace)); return scripts; #endregion #region Private members /// <summary> /// Image ID backing field. /// </summary> private Guid _imageId; /// <summary> /// layout template path. /// </summary> public static readonly string layoutTemplatePath = AssetPickerFieldsModule.EmbeddedResourceVirtualPath + typeof(ImageField).Namespace + ".ImageField.ascx"; /// <summary> /// The script reference. /// </summary> public static readonly string ScriptReference = typeof(ImageField).Namespace + ".ImageField.js"; #endregion Type.registerNamespace("NSC.Sitefinity.Modules.AssetPickerFields.ImageField");NSC.Sitefinity.Modules.AssetPickerFields.ImageField.ImageField = function (element) NSC.Sitefinity.Modules.AssetPickerFields.ImageField.ImageField.initializeBase(this, [element]); this._asyncImageSelector = null; this._selectImageButton = null; this._writeImage = null; this._readImage = null; this._imageServiceUrl = null; this._selectImageButtonClickDelegate = null; this._uploadDialog = null;;NSC.Sitefinity.Modules.AssetPickerFields.ImageField.ImageField.prototype = initialize: function () NSC.Sitefinity.Modules.AssetPickerFields.ImageField.ImageField.callBaseMethod(this, "initialize"); this._selectImageButtonClickDelegate = Function.createDelegate(this, this._selectImageButtonClicked); if (this._selectImageButton) $addHandler(this._selectImageButton, "click", this._selectImageButtonClickDelegate); if (this._asyncImageSelector) this._uploadDialog = jQuery(this._asyncImageSelector.get_element()).dialog( autoOpen: false, modal: true, width: 540, height: "auto", closeOnEscape: true, resizable: false, draggable: false, zIndex: 5000, dialogClass: "sfSelectorDialog" ); this._asyncImageSelectorInsertDelegate = Function.createDelegate(this, this._asyncImageSelectorInsertHandler); this._asyncImageSelector.set_customInsertDelegate(this._asyncImageSelectorInsertDelegate); , dispose: function () NSC.Sitefinity.Modules.AssetPickerFields.ImageField.ImageField.callBaseMethod(this, "dispose"); if (this._selectImageButton) $removeHandler(this._selectImageButton, "click", this._selectImageButtonClickDelegate); if (this._selectImageButtonClickDelegate) delete this._selectImageButtonClickDelegate; , /* -------------------- public methods ----------- */ /* -------------------- events -------------------- */ /* -------------------- event handlers ------------ */ _selectImageButtonClicked: function (sender, args) this._uploadDialog.dialog("open"); var scrollTopHtml = jQuery("html").eq(0).scrollTop(); var scrollTopBody = jQuery("body").eq(0).scrollTop(); var scrollTop = ((scrollTopHtml > scrollTopBody) ? scrollTopHtml : scrollTopBody) + 50; jQuery(this._uploadDialog).parent().css( "top": scrollTop ); try this._asyncImageSelector.get_uploaderView().get_altTextField().set_value(""); catch (ex) jQuery(this._asyncImageSelector.get_uploaderView().get_settingsPanel()).hide(); return false; , /* -------------------- private methods ----------- */ _asyncImageSelectorInsertHandler: function (selectedItem) if (selectedItem) this.set_value(selectedItem.Id); this._uploadDialog.dialog("close"); , // Gets the value of the image control. // get_value: function () // debugger; // var value = NSC.Sitefinity.Modules.AssetPickerFields.ImageField.ImageField.callBaseMethod(this, "get_value"); // return value; // , // Sets the value of the image control. set_value: function (value) if (this._displayMode == 0) return; var imageControl = this._writeImage; if (value && value.toString() != "00000000-0000-0000-0000-000000000000") var id = value; var url = this._imageServiceUrl + "live/" + id + "/"; var data = null; $.ajax( url: url, success: function (data) var imageUrl = data["Item"]["MediaUrl"]; if (imageControl) jQuery(imageControl).attr("src", imageUrl); ); else if (imageControl) jQuery(imageControl).attr("src", "data:image/gif;base64,R0lGODlhAQABAIAAAP///////yH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="); NSC.Sitefinity.Modules.AssetPickerFields.ImageField.ImageField.callBaseMethod(this, "set_value", [value]); , /* -------------------- properties ---------------- */ get_asyncImageSelector: function () return this._asyncImageSelector; , set_asyncImageSelector: function (value) this._asyncImageSelector = value; , get_selectImageButton: function () return this._selectImageButton; , set_selectImageButton: function (value) this._selectImageButton = value; , get_writeImage: function () return this._writeImage; , set_writeImage: function (value) this._writeImage = value; , get_readImage: function () return this._readImage; , set_readImage: function (value) this._readImage = value; , get_imageServiceUrl: function () return this._imageServiceUrl; , set_imageServiceUrl: function (value) this._imageServiceUrl = value; ;NSC.Sitefinity.Modules.AssetPickerFields.ImageField.ImageField.registerClass("NSC.Sitefinity.Modules.AssetPickerFields.ImageField.ImageField", Telerik.Sitefinity.Web.UI.Fields.FieldControl);using Telerik.Sitefinity.Configuration;using Telerik.Sitefinity.Web.UI.Fields.Definitions;namespace NSC.Sitefinity.Modules.AssetPickerFields.ImageField public class ImageFieldDefinition : FieldControlDefinition #region Constuctors /// <summary> /// Initializes a new instance of the <see cref="ImageFieldDefinition" /> class. /// </summary> public ImageFieldDefinition() /// <summary> /// Initializes a new instance of the <see cref="ImageFieldDefinition" /> class. /// </summary> /// <param name="configDefinition">The config definition.</param> public ImageFieldDefinition(ConfigElement configDefinition) : base(configDefinition) #endregion using System;using Telerik.Sitefinity.Configuration;using Telerik.Sitefinity.Web.UI;using Telerik.Sitefinity.Web.UI.Fields.Config;namespace NSC.Sitefinity.Modules.AssetPickerFields.ImageField public class ImageFieldDefinitionElement : FieldControlDefinitionElement #region Constructors /// <summary> /// Initializes a new instance of the <see cref="ImageFieldDefinitionElement" /> class. /// </summary> /// <param name="parent">The parent.</param> public ImageFieldDefinitionElement(ConfigElement parent) : base(parent) #endregion #region FieldControlDefinitionElement members public override DefinitionBase GetDefinition() return new ImageFieldDefinition(this); #endregion #region IFieldDefinition members public override Type DefaultFieldType get return typeof(ImageField); #endregion Hello Stephen, this is very interesting. Thanks