Create a thumbnail selector for news (5.4 or older)
In the Create a simple image selector (5.4 or older), we saw how to create a simple image selector. Today, we are going to use it to select thumbnails for news items and display them on a page. There are several controls that we need for the purpose.
Walkthrough
You can download the source code for this example from here. Here is a list of what you will need to implement to cover the scenario:
- The control used to select images from the previous post.
- A dialog that displays the control from step 1 and returns the selected image:
- A control used to save the thumbnail URL as a custom field in the news item:
- A control used to display the thumbnail in the public template for news items. This is going to be the same control we create in step 3.
NOTE: All controls that we build in this blog post have a corresponding client component. More information about how to build client components can be found on
MSDN.
A Dialog to Select a Thumbnail
Dialogs have a special role in Sitefinity CMS. They are used everywhere in the backend when editing, creating and selecting items. They provide the infrastructure for opening specialized windows and returning results. How you can use all the goodness that dialogs provide for you is a topic for another post. For our specific purpose, you can think of the dialog as a simple control, which is registered in Sitefinity CMS with a specific URL and opens in a RadWindow.
Our dialog is just a wrapper, that contains the simple image selector we built last week. Here's the template:
<
div
>
<
samples:SimpleImageSelector
ID
=
"imageSelector"
runat
=
"server"
>
</
samples:SimpleImageSelector
>
</
div
>
<
div
class
=
"sfClearer"
>
<
asp:HyperLink
ID
=
"lnkDone"
runat
=
"server"
NavigateUrl
=
"javascript:void(0);"
CssClass
=
"sfLinkBtn sfSave"
>
<
span
class
=
"sfLinkBtnIn"
>Done</
span
>
</
asp:HyperLink
> or
<
asp:HyperLink
ID
=
"lnkCancel"
runat
=
"server"
NavigateUrl
=
"javascript:void(0);"
Text
=
"Cancel"
CssClass
=
"sfCancel"
></
asp:HyperLink
>
</
div
>
There's nothing special in the server-side code of our dialog, so I won't include it here. Just remember that you have to inherit from AjaxDialogBase. All the magic of the dialog happens in two methods of the client component:
_doneLinkClicked:
function
(sender, args) {
var
selectedValue =
this
.get_imageSelector().get_selectedImageUrl();
if
(!selectedValue || selectedValue ===
""
) {
alert(
"No image selected."
);
}
else
{
dialogBase.close(selectedValue);
}
},
_cancelLinkClicked:
function
(sender, args) {
dialogBase.close();
},
This is all that we need to do in our dialog - get the URL of the image from the selector, and return it as a result from the dialog. However, we also need to let Sitefinity CMS know about our dialog. This is done by registering the dialog in our Global.asax file:
protected
void
Application_Start(
object
sender, EventArgs e)
{
Telerik.Sitefinity.Abstractions.Bootstrapper.Initialized +=
new
EventHandler<Telerik.Sitefinity.Data.ExecutedEventArgs>(Bootstrapper_Initialized);
}
protected
void
Bootstrapper_Initialized(
object
sender, Telerik.Sitefinity.Data.ExecutedEventArgs args)
{
Telerik.Sitefinity.Web.UI.Dialogs.RegisterDialog<Telerik.Sitefinity.Samples.SimpleImageSelectorDialog>();
}
A Custom Field Control to Save the Thumbnail URL in the News Item
This is the tricky part, but once you've done it once, it's quite easy. The form through which you edit news items is composed of the so-called field controls. One field control has two main responsibilities - to provide user interface for editing and displaying a single property of a content item. In our case, the content item is a news item, the property is the thumbnail (created as a custom field). Both the TextBox in which you enter the URL, and the thumbnail that you see on the public page are part of the same field control we will create - the former we call Write mode (the user writes the value of the property), the latter Read mode (the value of the property is read and displayed).
Most of the required functionality has already been implemented in a regular text field control. TextField is what lets you edit titles for news items, for example. The different UI in our case is a link that we will display to open the dialog when in write mode (backend), and the image we are going to show when in read mode (frontend). So we inherit TextField, and override what we need to account for the different functionality.
Although the code might look like a lot, most of it is required to hook things up. The most important part that actually does the work is overriding the Value property on the server and on the client:
public
override
object
Value
{
get
{
var val =
string
.Empty;
switch
(
this
.DisplayMode)
{
case
FieldDisplayMode.Read:
val =
this
.ImageControl.ImageUrl;
break
;
case
FieldDisplayMode.Write:
val =
this
.TextBoxControl.Text;
break
;
}
return
val;
}
...
}
Here's the part on the client that grabs the URL from the dialog and populates the TextBox:
_set_readModeValue:
function
(value) {
if
(value === undefined || value ==
null
) {
this
._clearLabel();
}
else
{
if
(
this
._imageControl !=
null
) {
jQuery(
this
._imageControl).attr(
"src"
, value);
}
}
},
...
_windowClosed:
function
(sender, args) {
var
imageUrl = args.get_argument();
if
(imageUrl && imageUrl !==
""
) {
this
.set_value(imageUrl);
}
},
All the rest is getting references to controls in the template, passing values from the server to the client and opening the dialog itself. You can look at the details in the download.
Up to this point, you've created everything Sitefinity CMS needs to select and persist the value of the thumbnail. Now the only thing left is to let it know where to find your controls together with any metadata you may need to pass. For this purpose, it uses control definitions (they define your field control, so Sitefinity CMS knows how to use it). For our purpose, we don't need anything special, so we just inherit from the base definition for TextField. Once this is done, Sitefinity CMS should be able to find you custom field, display it when you edit news items, and show the selected thumbnail in any news item template.
Installation Instructions
- Download the source code for this example and extract it in your project's main folder.
- Open the project in Visual Studio as a web application, and include the files in the project.
- Set the build action of all .js files to "EmbeddedResource"
- Add the following lines to the AssemblyInfo.cs file in SitefinityWebApp:
[assembly: WebResource(
"SitefinityWebApp.ImageSelector.SimpleImageSelector.js"
,
"application/x-javascript"
)]
[assembly: WebResource(
"SitefinityWebApp.ImageSelector.SimpleImageField.js"
,
"application/x-javascript"
)]
[assembly: WebResource(
"SitefinityWebApp.ImageSelector.SimpleImageSelectorDialog.js"
,
"application/x-javascript"
)]
- Compile and run your project.
- Create a custom field in News for the thumbnail and specify a custom widget for entering data. The type of the custom widget should be Telerik.Sitefinity.Samples.SimpleImageField.
- Edit the list template for news and add the control to display the thumbnail:
<
samples:SimpleImageField
runat
=
"server"
DisplayMode
=
"Read"
Value='<%# Eval("Thumbnail")%>' />
Conclusion
This is only scratching the surface of how you can extend Sitefinity CMS. Concepts like Field Controls and Control Definitions allow you to go crazy with your ideas and extend the built-in modules to support custom scenarios.