1

We would like to add custom property when we click on General link from Experience Editor.

enter image description here

Would like to add custom property below "Alternate Text" and append custom property values in URL.

1

For adding a custom attribute to the media link you can follow the approach in this blog post https://sitecorejunkie.com/2015/10/10/add-a-custom-attribute-to-the-general-link-field-in-sitecore/, which describes the exact steps required for adding it for internal link and general links.

Based on your printscreen, if you would like to customize the media link dialog you have to change the custom form class and the dialog.

For the Sheer UI Custom form class you would need to look at the class Sitecore.Shell.Applications.Dialogs.MediaLink.MediaLinkForm from the dll Sitecore.Client.dll and have your custom one based on this. You would need to customize the Sheer UI dialog based on the \sitecore\shell\Applications\Dialogs\MediaLink\MediaLink.xml file instead.

4
  • I have added MediaLink.XML for creating new property and changed code Sitecore.Shell.Applications.Dialogs.MediaLink.MediaLinkForm. However, it is showing perfactly in Content Editor but in Experience Editor newly added property value is showing "display:none" in HTML. – User7864 Feb 23 at 15:23
  • From what I can see in experience editor when clicking Edit Link button for example, /sitecore/shell/Applications/Dialogs/GeneralLink/GeneralLink.xml is loaded – Cristi Vulturar Feb 23 at 15:56
  • If /sitecore/shell/Applications/Dialogs/GeneralLink/GeneralLink.xml this file is loaded then do we need to change in GeneralLink.xml or its Form class? – User7864 Feb 23 at 16:02
  • I think you have to change both if you want to render the custom property in the html markup. It really depends on the requirements as there are other approaches to extending the general link, for example byteium.com/2020/03/extend-general-link-field-in-sitecore – Cristi Vulturar Feb 23 at 16:28
1

1- Edit the file "...\sitecore\shell\Applications\Dialogs\MediaLink\MediaLink.xml"

2- Right below "alternate text", add:

<Literal Text="My text:" GridPanel.NoWrap="true"/>
          <Edit ID="MyText" Width="100%"/>
          

3- Comment out the line:

<CodeBeside Type="Sitecore.Shell.Applications.Dialogs.MediaLink.MediaLinkForm,Sitecore.Client"/>

and add

<CodeBeside Type="yournamespace.yourform,[yourassembly]"/>

4- Write your own class replacing the following, this time writing your property "MyText" and build your assembly (that you added above) and interpret it accordingly:

using System;
using System.Collections.Specialized;
using System.Web.UI.WebControls;```

namespace Sitecore.Shell.Applications.Dialogs.MediaLink
{
    /// <summary>
    /// Link of type media.
    /// </summary>
    public class MediaLinkForm : LinkForm
    {
        /// <summary>
        /// The anchor.
        /// </summary>
        protected Edit Anchor;

        /// <summary>
        /// The class.
        /// </summary>
        protected Edit Class;

        /// <summary>
        /// The custom label.
        /// </summary>
        protected Panel CustomLabel;

        /// <summary>
        /// The custom target.
        /// </summary>
        protected Edit CustomTarget;

        /// <summary>
        /// The media link data context.
        /// </summary>
        protected DataContext MediaLinkDataContext;

        /// <summary>
        /// The media link treeview.
        /// </summary>
        protected TreeviewEx MediaLinkTreeview;

        /// <summary>
        /// The preview.
        /// </summary>
        protected Border Preview;

        /// <summary>
        /// The target.
        /// </summary>
        protected Combobox Target;

        /// <summary>
        /// The text.
        /// </summary>
        protected Edit Text;

        /// <summary>
        /// The title.
        /// </summary>
        protected Edit Title;

        /// <summary> The upload button </summary>
        protected Button Upload;

        public MediaLinkForm()
        {
        }

        /// <summary>
        /// Handles the message.
        /// </summary>
        /// <param name="message">
        /// The message.
        /// </param>
        public override void HandleMessage(Message message)
        {
            Assert.ArgumentNotNull(message, "message");
            Item item = null;
            if (message.Arguments.Count > 0 && ID.IsID(message.Arguments["id"]))
            {
                IDataView dataView = this.MediaLinkTreeview.GetDataView();
                if (dataView != null)
                {
                    item = dataView.GetItem(message.Arguments["id"]);
                }
            }
            if (item == null)
            {
                item = this.MediaLinkTreeview.GetSelectionItem();
            }
            Dispatcher.Dispatch(message, item);
            base.HandleMessage(message);
        }

        /// <summary>
        /// Called when the listbox has changed.
        /// </summary>
        protected void OnListboxChanged()
        {
            if (this.Target.Value == "Custom")
            {
                this.CustomTarget.Disabled = false;
                this.CustomLabel.Disabled = false;
                return;
            }
            this.CustomTarget.Value = string.Empty;
            this.CustomTarget.Disabled = true;
            this.CustomLabel.Disabled = true;
        }

        /// <summary>
        /// Raises the load event.
        /// </summary>
        /// <param name="e">
        /// The <see cref="T:System.EventArgs" /> instance containing the event data.
        /// </param>
        /// <remarks>
        /// This method notifies the server control that it should perform actions common to each HTTP
        /// request for the page it is associated with, such as setting up a database query. At this
        /// stage in the page lifecycle, server controls in the hierarchy are created and initialized,
        /// view state is restored, and form controls reflect client-side data. Use the IsPostBack
        /// property to determine whether the page is being loaded in response to a client postback,
        /// or if it is being loaded and accessed for the first time.
        /// </remarks>
        protected override void OnLoad(EventArgs e)
        {
            string path;
            Assert.ArgumentNotNull(e, "e");
            base.OnLoad(e);
            if (Context.ClientPage.IsEvent)
            {
                return;
            }
            this.MediaLinkDataContext.GetFromQueryString();
            string item = base.LinkAttributes["target"];
            string empty = string.Empty;
            string linkTargetValue = LinkForm.GetLinkTargetValue(item);
            if (linkTargetValue == "Custom")
            {
                empty = item;
                this.CustomTarget.Disabled = false;
                this.CustomLabel.Disabled = false;
            }
            this.Text.Value = base.LinkAttributes["text"];
            this.Target.Value = linkTargetValue;
            this.CustomTarget.Value = empty;
            this.Class.Value = base.LinkAttributes["class"];
            this.Title.Value = base.LinkAttributes["title"];
            if (base.LinkType != "media")
            {
                path = "/sitecore/media library";
            }
            else
            {
                string str = base.LinkAttributes["id"];
                if (string.IsNullOrEmpty(str) || !ID.IsID(str))
                {
                    path = "/sitecore/media library";
                }
                else
                {
                    Item item1 = Client.ContentDatabase.GetItem(new ID(str));
                    if (item1 == null || !(item1.ID != ItemIDs.MediaLibraryRoot))
                    {
                        path = "/sitecore/media library";
                    }
                    else
                    {
                        path = item1.Paths.Path;
                        if (path.StartsWith("/sitecore/media library", StringComparison.InvariantCulture))
                        {
                            path = path.Substring("/sitecore/media library".Length);
                        }
                        if (this.MediaLinkTreeview.GetDataView() == null)
                        {
                            return;
                        }
                        if (item1.Parent != null)
                        {
                            this.MediaLinkDataContext.SetFolder(item1.Uri);
                        }
                    }
                }
            }
            this.MediaLinkDataContext.AddSelected(new DataUri(path));
            this.MediaLinkDataContext.Root = "/sitecore/media library";
            this.UpdatePreview(this.MediaLinkDataContext.GetFolder());
            this.Upload.ToolTip = Translate.Text("Upload a new media file to the Media Library");
        }

        /// <summary>
        /// Called when the new has folder.
        /// </summary>
        /// <param name="message">
        /// The message.
        /// </param>
        [HandleMessage("medialink:newfolder")]
        protected void OnNewFolder(Message message)
        {
            Assert.ArgumentNotNull(message, "message");
            Item folder = this.MediaLinkDataContext.GetFolder();
            if (folder != null)
            {
                Items.NewFolder(folder);
            }
        }

        /// <summary>
        /// Handles a click on the OK button.
        /// </summary>
        /// <param name="sender">
        /// </param>
        /// <param name="args">
        /// </param>
        /// <remarks>
        /// When the user clicks OK, the dialog is closed by calling
        /// the <see cref="M:Sitecore.Web.UI.Sheer.ClientResponse.CloseWindow">CloseWindow</see> method.
        /// </remarks>
        protected override void OnOK(object sender, EventArgs args)
        {
            Assert.ArgumentNotNull(sender, "sender");
            Assert.ArgumentNotNull(args, "args");
            Item selectionItem = this.MediaLinkTreeview.GetSelectionItem();
            if (selectionItem == null)
            {
                Context.ClientPage.ClientResponse.Alert("Select a media item.");
                return;
            }
            string mediaPath = selectionItem.Paths.MediaPath;
            string linkTargetAttributeFromValue = LinkForm.GetLinkTargetAttributeFromValue(this.Target.Value, this.CustomTarget.Value);
            Packet packet = new Packet("link", Array.Empty<string>());
            LinkForm.SetAttribute(packet, "text", this.Text);
            LinkForm.SetAttribute(packet, "linktype", "media");
            LinkForm.SetAttribute(packet, "title", this.Title);
            LinkForm.SetAttribute(packet, "class", this.Class);
            LinkForm.SetAttribute(packet, "target", linkTargetAttributeFromValue);
            LinkForm.SetAttribute(packet, "id", selectionItem.ID.ToString());
            SheerResponse.SetDialogValue(packet.OuterXml);
            base.OnOK(sender, args);
        }

        /// <summary>
        /// Called when this instance has open.
        /// </summary>
        protected void OnOpen()
        {
            Item selectionItem = this.MediaLinkTreeview.GetSelectionItem();
            if (selectionItem != null && selectionItem.HasChildren)
            {
                this.MediaLinkDataContext.SetFolder(selectionItem.Uri);
            }
        }

        /// <summary>
        /// Selects the tree node.
        /// </summary>
        protected void SelectTreeNode()
        {
            Item selectionItem = this.MediaLinkTreeview.GetSelectionItem();
            if (selectionItem == null)
            {
                return;
            }
            this.UpdatePreview(selectionItem);
        }

        /// <summary>
        /// Updates the preview.
        /// </summary>
        /// <param name="item">
        /// The item.
        /// </param>
        private void UpdatePreview(Item item)
        {
            Assert.ArgumentNotNull(item, "item");
            MediaUrlBuilderOptions thumbnailOptions = MediaUrlBuilderOptions.GetThumbnailOptions(item);
            thumbnailOptions.UseDefaultIcon = new bool?(true);
            thumbnailOptions.Width = new int?(96);
            thumbnailOptions.Height = new int?(96);
            thumbnailOptions.Language = item.Language;
            thumbnailOptions.AllowStretch = new bool?(false);
            string mediaUrl = MediaManager.GetMediaUrl(item, thumbnailOptions);
            this.Preview.InnerHtml = string.Concat("<img src=\"", mediaUrl, "\" width=\"96\" height=\"96\" border=\"0\" alt=\"\" />");
        }

        /// <summary>
        /// Uploads the image.
        /// </summary>
        protected void UploadImage()
        {
            Item selectionItem = this.MediaLinkTreeview.GetSelectionItem();
            if (selectionItem != null)
            {
                if (!selectionItem.Access.CanCreate())
                {
                    SheerResponse.Alert("You do not have permission to create a new item here.", Array.Empty<string>());
                    return;
                }
                Context.ClientPage.SendMessage(this, "media:upload(edit=1,load=1)");
            }
        }
    }
}

          
3
  • need to add property when we click from Experience Editor. – User7864 Feb 24 at 6:08
  • 1
    For experience editor, the xml file will be "...\sitecore\shell\Override\Applications\Dialogs\GeneralLink\GeneralLink.xml" and following is what you need to replace with yours: <CodeBeside Type="Sitecore.XA.Foundation.Multisite.Controls.GeneralLinkForm, Sitecore.XA.Foundation.Multisite"/> – Debabrata Biswas Feb 24 at 11:00
  • yes , I have tried this path \sitecore\shell\Override\Applications\Dialogs\GeneralLink\GeneralLink.xml and it is loading instead of /sitecore/shell/Applications/Dialogs/GeneralLink/GeneralLink.xml – User7864 Feb 24 at 11:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.