The platform allows developers to extend the content editor to provide for richer content.
Why Extend the Content Editor?
The content editor allows the input of html, images and video, however other types of content cannot be entered or would be difficult to enter or validate for end users. The platform provided extensions to the content editor are good use cases for what extending the content editor can provide.
Source Code with Syntax Highlighting
Source code can be entered into the editor without an extension, but without an extension each user is responsible for providing the styling for the source code they enter. By adding a source code extension to the editor, we can simplify the input required by the end user and provide a consistent output for code samples with syntax highlighting.
Polls
A Polls extension is also provided with the platform. Without this extension Polls could not be entered using the editor. The Polling extension is able to provide an interface to allow poll entry, rendered those polls and store the data custom set of database tables.
Creating an Extension
The platform provides two ways to extend the editor: Scripted Embeddables , which are created within Embeddable Studio using scripting, and the IEmbeddableContentFragmentType plugin type, which enables plugins to extend the editor using compiled code distributed as a plugin. The platform includes both scripted- and plugin-based embeddables.
This example will create a new plugin-based embeddable that displays a box inside the content. The background color of the box will be configurable when inserting the content. We'll that implements the IEmbeddableContentFragmentType plugin type:
using System;
using System.Collections.Generic;
using Telligent.Evolution.Extensibility.EmbeddableContent.Version2;
using Telligent.Evolution.Extensibility.Version1;
using Telligent.Evolution.Extensibility.Configuration.Version1;
namespace Samples
{
public class SampleEmbeddable : IEmbeddableContentFragmentType, ITranslatablePlugin, IPlugin
{
readonly Guid _fragmentTypeId = new Guid("6c33babb0c0e45e8b691294b8b6569e5");
ITranslatablePluginController _translation;
#region IPlugin
public string Name
{
get { return "Sample Embeddable"; }
}
public string Description
{
get { return "Displays a box with configurable height."; }
}
public void Initialize()
{
}
#endregion
#region IEmbeddableContentFragmentType
public string ContentFragmentName
{
get { return _translation.GetLanguageResourceValue("fragment_name"); }
}
public string ContentFragmentDescription
{
get { return _translation.GetLanguageResourceValue("fragment_description"); }
}
public Guid EmbeddedContentFragmentTypeId
{
get { return _fragmentTypeId; }
}
public bool CanEmbed(Guid contentTypeId, int userId)
{
return true;
}
public PropertyGroup[] EmbedConfiguration
{
get
{
var group = new PropertyGroup
{
Id = "options",
LabelResourceName = "configuration_group",
OrderNumber = 1
};
group.Properties.Add(new Property
{
Id = "color",
LabelResourceName = "configuration_color",
DataType = "Color",
OrderNumber = 1,
DefaultValue = ""
});
return new PropertyGroup[] { group };
}
}
public void AddUpdateContentFragments(Guid contentId, Guid contentTypeId, IEnumerable<IEmbeddableContentFragment> embeddedFragments)
{
}
public string PreviewImageUrl
{
get { return null; }
}
public string Render(IEmbeddableContentFragment embeddedFragment, string target)
{
var color = embeddedFragment.GetString("color");
if (String.IsNullOrEmpty(color))
return String.Empty;
return String.Format("<div style='height: 300px; width: 300px; background-color: {0};'> </div>", color);
}
public EmbeddableContentFragmentValidationState Validate(IEmbeddableContentFragment embeddedFragment)
{
var color = embeddedFragment.GetString("color");
if (string.IsNullOrEmpty(color))
return new EmbeddableContentFragmentValidationState(false) { Message = _translation.GetLanguageResourceValue("configuration_colorinvalid") };
return new EmbeddableContentFragmentValidationState(true);
}
#endregion
#region ITranslatablePlugin Members
public Translation[] DefaultTranslations
{
get
{
var translation = new Translation("en-us");
translation.Set("fragment_name", "Embeddable Box");
translation.Set("fragment_description", "Displays a box with configurable height.");
translation.Set("configuration_group", "Options");
translation.Set("configuration_color", "Background Color");
translation.Set("configuration_colorinvalid", "A Background Color must be provided.");
return new Translation[] { translation };
}
}
public void SetController(ITranslatablePluginController controller)
{
_translation = controller;
}
#endregion
}
}
To implement IEmbeddableContentFragmentType, we need to provide a unique id (EmbeddedContentFragmentTypeId), name (ContentFragmentName) and description (ContentFragmentDescription) for our content fragment type. In this example, we use the ITranslatablePlugin plugin type to provide translations for the name and description.
We can limit the types the content that this embeddable can be embedded within. In the example we allow all types, so we will just return true in CanEmbed(). If we wanted to limit our new type to only be allowed in blog posts, we could return true only when the contentTypeId parameter matches the blog post content type id.
The EmbedConfiguration property is used to define the configuration options presented when creating or editing this embeddable within the editor. In this case, we will allow the user to choose the background color of the embedded box, so we define a single property with the DataType of Color.
The Validate() method is provided to verify that the data entered by the end user is correct. A translated error may be returned to the end user to assist in correcting any invalid data.
The AddUpdateContentFragments() method is called whenever embedded content is added or updated. This can be used to create, update and delete database records for the embeds. This example does not need to use this method, so we leave it blank.
The PreviewImageUrl will be displayed as an icon in the editor menu and in the editor to represent the embedded content. For this example, we can just leave this blank and allow the platform to provide an image.
The Render() method is called when the embedded content is being output. A target parameter is also provided, this can be useful if you want to display different output for different targets. The example reads the color parameter we defined in the configuration metadata. If the color has been set, we will render a div with a fixed height and width and the selected background color.
Once the and enabled in the community, when creating a post you will see the option to "Insert Embeddable Box"
Select that option and you will be able to configure the background color
After submitting this form, the editor will display the embeddable content using the PreviewImageUrl provided in the code (which wasn't set). After creating the post, you should see the box rendered with the chosen background color.


