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