Telerik

Sitefinity Blog

Extend RadEditor dialogs to add captions for images

This post is inspired by a customer request to provide functionality for adding captions to images inserted through the RadEditor when creating/editing content items. In order to achieve this we will need to work with the external templates for Sitefinity controls. We have to map all templates for controls in which we want this option. Before proceeding with this post, please take a look at the following KB article if you are unsure how to work with external templates: How to map a view to an external template, in Sitefinity 3.6 or later?

 

Now lets take the Generic Content control template (~/Sitefinity/Admin/ControlTemplates/Generic_Content/GenericContentDesigner.ascx) and map it in the controls config xml file, then restart the website:

<?xml version="1.0" encoding="utf-8"?> 
<controlsConfig> 
  <viewMap> 
       <viewSettings hostType="Telerik.Cms.Engine.WebControls.Design.GenericContentDesigner" layoutTemplatePath="~/Sitefinity/Admin/ControlTemplates/Generic_Content/GenericContentDesigner.ascx" /> 
  </viewMap> 
</controlsConfig> 

 

We would also need to provide a path for external dialogs for the RadEditor. Create a folder ~/Sitefinity/Admin/ControlTemplates/CustomEditorDialogs and set the RadEditor ExternalDialogsPath property:

<telerik:RadEditor  
    runat="server"  
    ID="textEditor" 
    ... 
    ExternalDialogsPath="~/Sitefinity/Admin/ControlTemplates/CustomEditorDialogs"

The next step is to provide an external layout template for the ImageEditorDialog control. To do this open ~/Sitefinity/UserControls/Dialogs/ImageEditorDialog.aspx and modify the markup of the ImageEditorDialog:

<lib:ImageEditorDialog runat="server" DisplayMode="Images"  
        ControlTemplatePath="~/Sitefinity/Admin/ControlTemplates/Libraries/Dialogs/ImageEditorDialog.ascx"/> 

Now we need to add a text box to input image caption text and modify the JavaScript in the layout template to return both the image and caption text. Open ~/Sitefinity/Admin/ControlTemplates/Libraries/Dialogs/ImageEditorDialog.ascx and edit the markup like this:

<div class="uploadedImageData">      
                <li>            
                    <asp:Label ID="Label2" runat="server" Text="<%$Resources:AlternativeText %>" AssociatedControlID="altTxt"></asp:Label> 
                    <asp:TextBox runat="server" ID="altTxt"></asp:TextBox> 
                    <class="example"><asp:Literal ID="Literal7" runat="server" Text='<%$Resources:AlternativeExample %>'></asp:Literal></p
                    <class="example"><asp:Literal ID="Literal8" runat="server" Text='<%$Resources:AlternativeDesc %>'></asp:Literal></p
                </li> 
                <li> 
                    <asp:Label ID="captionLabel" runat="server" text="Caption" AssociatedControlID="captionTxt"></asp:Label> 
                    <asp:TextBox runat="server" ID="captionTxt"></asp:TextBox>                 
                </li> 
            </div> 

Then modify the JavaScript function which returns the selected image, this function is called insertLink():

<script type="text/javascript"
    var currentElement = document.createElement("img"); 
    //create div element 
    var divElement = document.createElement("div")
        ... 
    function insertLink() //fires when the Insert Link button is clicked 
    { 
        var closeArgument = currentElement; 
        //create new div element 
        var div = divElement; 
        var captionTxt = document.getElementById('<%=captionTxt.ClientID %>'); 
        selValue = document.getElementById('<%= selectedValueField.ClientID %>'); 
        editHolder = document.getElementById('<%= editHolder.ClientID %>'); 
        var uplImg = document.getElementById('<%= uploadedImage.ClientID %>'); 
        if (editHolder.style.display == 'none') { 
            if (selectedItem) 
                closeArgument.alt = selectedItem.altText; 
            else 
                closeArgument.alt = ''
            closeArgument.src = selValue.value; 
        } 
        else { 
            var altTextTxt = document.getElementById('<%= altTxt.ClientID %>'); 
            closeArgument.src = selValue.value; 
            if (altTextTxt) 
                closeArgument.alt = altTextTxt.value; 
        } 
 
        if (selValue.value.indexOf("~/") == 0) { 
            closeArgument.setAttribute("sfref", selValue.value); 
        } else if (selectedItem != undefined && selectedItem.unresolved) { 
            closeArgument.setAttribute("sfref", selectedItem.unresolved); 
        } else if (uplImg != undefined && uplImg.attributes["sfref"] != undefined) { 
            closeArgument.setAttribute("sfref", uplImg.attributes["sfref"].value);           
            var imgSrc = uplImg.src; 
            if(imgSrc.indexOf("?") < 0){ 
                closeArgument.src = imgSrc; 
            } 
            else 
                closeArgument.src = imgSrc.slice(0, imgSrc.indexOf("?")); 
        } else { 
            closeArgument.removeAttribute("sfref"); 
 
        } 
        //add image to div 
        div.appendChild(closeArgument); 
        //optional assign class name to containing div 
        div.className = "ImageBox"
        var caption = document.createTextNode(captionTxt.value); 
        var span = document.createElement("span"); 
        //optional assing class name to span containing caption text 
        span.className = "CaptionText"
        //adds the text from textbox to the containing span 
        span.appendChild(caption); 
        var br = document.createElement("br"); 
        div.appendChild(br); 
        //add span to the containing div 
        div.appendChild(span); 
        if(getRadWindow()){ 
            var radWindow = getRadWindow(); 
        //return the div as return argument of the radWindow 
        radWindow.argument = div; 
        radWindow.close(div); //use the close function of the getRadWindow to close the dialog and pass the arguments from the dialog to the callback function on the main page. 
    } 
    } 

As the inline comments say you can assign CSS class names to the image containing div and the span containing the caption text. Then add rules in your themes to style the caption. See attached image for the result of our customizations.

Insert image with caption

 

Once we are done with customizations for inserting captions we also have to modify the dialog which is used for setting image properties. This is the reason why we mapped a path for external dialogs for the RadEditor. In the file attachment you will find the external dialog we are editing (~/Sitefinity/Admin/ControlTemplates/CustomEditorDialogs/SetImageProperties.ascx). Open this file and first edit the markup to add a text box for the image caption:

                <tr> 
                    <td class="reLabelCell" style="width: 120px;"
                        <label class="reDialogLabel" for="CaptionTxt"
                            <span style="text-align: right;"
                                Caption 
                            </span> 
                        </label> 
                    </td> 
                    <td class="reControlCell"
                        <input type="text" id="CaptionTxt" style="width: 165px;" /> 
                    </td> 
                </tr> 

Then we need to add some JavaScript to first load the already inserted caption text. Add this to the loadImageProperties function:

loadImageProperties: function(originalImage) { 
        ... 
        this._imageAlt.value = this._getAttribute(currentImage, "alt"); 
        this._imageLongDecs.value = this._getAttribute(currentImage, "longDesc"); 
        this._imageAlignment.setTagName("IMG"); 
        //populate the Caption textbox 
        $get('CaptionTxt').value = originalImage.parentElement.lastChild.innerText; 
        ... 

Then we need to save the caption text once the OK button has been clicked. Modify the getModifiedImage function:

getModifiedImage: function() { 
        ... 
        this._setAttribute(resultImage, "alt"this._imageAlt.value); 
        this._setAttribute(resultImage, "longDesc"this._imageLongDecs.value); 
        //set the new value of the caption text 
        this._originalImage.parentElement.lastChild.innerText = $get('CaptionTxt').value; 
        ... 

 

Now the dialog for setting image properties will look like this:

Set image properties dialog

 

You can download the sample markup and JavaScript code from this link: CustomEditorDialogs

 

More information on working with external dialogs for the RadEditor can be found here: RadEditor ExternalDialogsPath property.

Tags: external templates RadEditor Code samples content items Generic Content

By Radoslav Georgiev on 13 Jan 2010 in Tip of the Week All Blog Posts

  • Facebook
  • DZone It!
  • Digg It!
  • StumbleUpon
  • Technorati
  • Del.icio.us
  • NewsVine
  • Reddit
  • Blinklist
  • Furl it!

10  comments

  • KingKong
    14 Jan 2010
    I followed the post and this works like a charm
  • not easy to map a view to an external template, in Sitefinity 3.6. Pls update more info on this subject. Regards.
    chase personal loans
  • CandiceMc
    04 Aug 2010
    It's no that easy to make it true, because there so many people will think two times on it. personal loans
  • swimming pool pumps
    06 Aug 2010
    This site is good and creative. I have got a lot of information through this.
    swimming pool pumps
  • backpacks
    08 Aug 2010
    wow complete tutorial thanks sharing with us <a href="http://www.buywholesalesource.com/wholesale-travel-bags/">backpacks</a>
  • boomschors
    19 Aug 2010
    Nice to create and know how to work with external templates. Actually, your given article is quite interesting and it gave me very reliable and useful information.I like to read such valuable articles as it increase my knowledge in creating folder.
    Regards, boomschors
  • Viking refrigerator repair
    20 Aug 2010
    A similar precaution is needed if you choose to override OnLoad. Always call base.OnLoad, otherwise the Load event won't get called. As a tip, if Visual Studio can't render the new control, clean the solution and rebuild it again. If it still does not work, you might have to manually purge the bin folders, and check what objects you initialize at Design time.
    <a href="http://www.vikinglosangeles.com">Viking refrigerator repair</a>
  • Viking refrigerator repair
    20 Aug 2010
    A similar precaution is needed if you choose to override OnLoad. Always call base.OnLoad, otherwise the Load event won't get called. As a tip, if Visual Studio can't render the new control, clean the solution and rebuild it again. If it still does not work, you might have to manually purge the bin folders, and check what objects you initialize at Design time.
    Viking refrigerator repair
  • Buso Russel
    26 Aug 2010
    Images are the best media to increase the quality of a post. You have explained it well.
    SEO
  • Lakeside Home Search
    02 Sep 2010
    wow complete tutorial thanks sharing with us
    Lakeside Home Search
Add Comment
  1. Formatting options
       
      
     
     
       
Subscribe to blog feed

Categories

Powered by Sitefinity ASP.NET CMS

Contact Us | Site Feedback | Terms of Use | Privacy Policy
Copyright © 2002-2010 Telerik. All rights reserved.