While working on a responsive testimonials application for a client, I was looking for an alternative editor control that would allow visitors to enter their testimonials. I determined that the XMod Pro "TextArea" control was not adequate because it doesn't allow line breaks and paragraph breaks. I could use the "HtmlInput" control, which utilizes the DNN CKEditor but, even in its basic configuration it still had too many bells and whistles for my purpose.
EXPERIENCE LEVEL - INTERMEDIATE
DESIGN CRITERIA
- The editor control must integrate with the XMod Pro "TextArea" control.
- Make it easy for the visitor to enter a testimonial and allow the user to express themselves by adding bold and italic features.
- Include line breaks and paragraph breaks.
- Include spell check.
- The ability to validate the control on form submission.
- Allow an administrator to edit the testimonial and access the source code.
Since I had experience in my WordPress projects with the TinyMCE editor, I decided to give it a try.
INTRODUCING THE TINYMCE EDITOR
What is TinyMCE Editor?
TinyMCE (Tiny Moxiecode Content Editor) is a platform-independent, web-based JavaScript HTML WYSIWYG editor control, released as open-source software under the LGPL by Ephox. It has the ability to convert HTML textarea fields or other HTML elements to editor instances.
REQUIREMENTS
- DNN 7+
- XMod Pro v4+
- jQuery
- Bootstrap v3+
INSTALLATION
It is always good practice to backup your DNN website before adding new modules or code.
I will assume you know how to add a XMod Pro FormView module to a DNN page and create a custom form. Below are snippets of the code you will need for this lesson.
Step 1: Add a XMod Pro <ScriptBlock> to your AddForm tab.
<AddForm Clientname="Testimonial">
<ScriptBlock ScriptId="CustomCSS" BlockType="HeadScript" RegisterOnce="true">
<style type="text/css">
.validate-error {
color: red;
}
.required-field {
border-left: 1px solid red;
}
.post-testimonial-form {
max-width: 800px;
margin: 40px auto;
}
.post-testimonial-form label small {
font-weight: normal;
border-left: 1px solid;
padding-left: 5px;
}
.post-testimonial-form .checkbox {
padding-left: 25px;
}
</style>
<script src="//cdn.tinymce.com/4/tinymce.min.js"></script>
</ScriptBlock>
Step 2: I created a simple database table for testing.
USE [YourDatabaseName]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[CT_Testimonial_Demo](
[TID] [int] IDENTITY(1,1) NOT NULL,
[Quote] [nvarchar](max) NOT NULL,
[Author] [nvarchar](50) NOT NULL,
CONSTRAINT [PK_CT_Testimonial_Demo] PRIMARY KEY CLUSTERED
(
[TID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
Step 3: Add a <SubmitCommand>, form fields, <ValidationSummary> and an <AddButton> to your AddForm.
<SubmitCommand CommandText="INSERT INTO CT_Testimonial_Demo
(
[Quote]
,[Author]
)
VALUES
(
@Quote
,@Author
)" />
<div class="post-testimonial-form">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">
What Would You Like to Say?
</h3>
</div>
<div class="panel-body">
<div class="form-group">
<Label For="Testimonial_Quote">
Quote
<small>
The main quote for your testimonial (max 250 characters).
</small>
</Label>
<TextArea Id="Testimonial_Quote" CssClass="form-control tinymce" Height="200" Nullable="true" DataField="Quote" DataType="string" MaxLength="250" />
<Validate Target="Testimonial_Quote" CssClass="validate-error" Type="required" Text="* Required" Message="Quote is required." />
</div>
<div class="form-group">
<Label For="Testimonial_Author">
Author
<small>
Your name.
</small>
</Label>
<TextBox Id="Testimonial_Author" CssClass="form-control required-field" Nullable="true" MaxLength="50" DataField="Author" DataType="string" HtmlEncode="true" />
<Validate Target="Testimonial_Author" CssClass="validate-error" Type="required" Text="* Required" Message="Author is required." />
</div>
<ValidationSummary CssClass="col-sm-offset-2 col-sm-10 alert alert-info" Id="vsCT_Testimonial" />
<AddButton CssClass="btn btn-primary" Text="Post Testimonial" />
<CancelButton CssClass="btn btn-default" Text="Cancel" />
</div>
Step 4: I added a jQueryReady tag to the form and added the TinyMCE initialization code.
<jQueryReady>
tinymce.init({
selector: '.tinymce',
statusbar: false,
menubar: false,
valid_elements: "p,br,b,i,strong,em",
toolbar: "bold italic",
browser_spellcheck: true,
</jQueryReady>
</AddForm>
THE OH OH MOMENT
During testing I soon realized there were issues. The client validation on the "Quote" Textarea was not triggering and TinyMCE editor was not passing the values to the control for submission.
TinyMCE Form Submission
- When a textarea is replaced by TinyMCE, it's actually hidden and TinyMCE editor (an iframe) is displayed instead.
- However, it's this textarea's contents which is sent when the form is submitted. Consequently its contents has to be updated before the form submission.
THE FIX
You can configure TinyMCE as follows to keep the values of hidden textareas in sync as changes are made via TinyMCE editors:
<AddButton CssClass="btn btn-primary" Text="Post Testimonial" OnClientClick="tinyMCE.triggerSave();" />
<CancelButton CssClass="btn btn-default" Text="Cancel" />
</div>
<jQueryReady>
tinymce.init({
selector: '.tinymce',
statusbar: false,
menubar: false,
valid_elements: "p,br,b,i,strong,em",
toolbar: "bold italic",
browser_spellcheck: true,
setup : function(ed) {
ed.on('change', function(e) {
// This will print out all your content in the tinyMce box
console.log('the content '+ed.getContent());
// Your text from the tinyMce box will now be passed to your text area ...
$(".tinymce").text(ed.getContent());
}); //end setup
}
});
</jQueryReady>
Now I had a working solution that met my design criteria of presenting the user with a simple toolbar allowing them to use browser spell check, bold and italic functionality, The TextArea allows line breaks and paragraph breaks. Client side validation is working.
But, what about allowing an administrator to edit the testimonial and access the source code?
That is simple. When you create your edit form, make the following changes to TinyMCE initialization:
<UpdateButton CssClass="btn btn-primary" Text="Save Changes" OnClientClick="tinyMCE.triggerSave();" />
<jQueryReady>
tinymce.init({
selector: '.tinymce',
statusbar: false,
menubar: false,
plugins: 'code', // note the comma at the end of the line!
valid_elements: "p,br,b,i,strong,em",
toolbar: "code bold italic",
browser_spellcheck: true,
setup : function(ed) {
ed.on('change', function(e) {
// This will print out all your content in the tinyMce box
console.log('the content '+ed.getContent());
// Your text from the tinyMce box will now be passed to your text area ...
$(".tinymce").text(ed.getContent());
}); //end setup
}
});
</jQueryReady>
By adding the code plugin and adjusting your toolbar setup to include code (toolbar: "code bold italic") to the toolbar TinyMCE creates a modal source code viewer. Sweet!
Grab the full source code below and if you have any questions or suggestions you know where they go.
Have Fun!
Buck Anderson
CodeTrader.com
<AddForm Clientname="Testimonial">
<ScriptBlock ScriptId="CustomCSS" BlockType="HeadScript" RegisterOnce="true">
<style type="text/css">
.validate-error {
color: red;
}
.required-field {
border-left: 1px solid red;
}
.post-testimonial-form {
max-width: 800px;
margin: 40px auto;
}
.post-testimonial-form label small {
font-weight: normal;
border-left: 1px solid;
padding-left: 5px;
}
.post-testimonial-form .checkbox {
padding-left: 25px;
}
</style>
<script src="//cdn.tinymce.com/4/tinymce.min.js"></script>
</ScriptBlock>
<SubmitCommand CommandText="INSERT INTO CT_Testimonial_Demo
(
[Quote]
,[Author]
)
VALUES
(
@Quote
,@Author
)" />
<div class="post-testimonial-form">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">
What Would You Like to Say?
</h3>
</div>
<div class="panel-body">
<div class="form-group">
<Label For="Testimonial_Quote">
Quote
<small>
The main quote for your testimonial (max 250 characters).
</small>
</Label>
<TextArea Id="Testimonial_Quote" CssClass="form-control tinymce" Height="200" Nullable="true" DataField="Quote" DataType="string" MaxLength="250" />
<Validate Target="Testimonial_Quote" CssClass="validate-error" Type="required" Text="* Required" Message="Quote is required." />
</div>
<div class="form-group">
<Label For="Testimonial_Author">
Author
<small>
Your name.
</small>
</Label>
<TextBox Id="Testimonial_Author" CssClass="form-control required-field" Nullable="true" MaxLength="50" DataField="Author" DataType="string" HtmlEncode="true" />
<Validate Target="Testimonial_Author" CssClass="validate-error" Type="required" Text="* Required" Message="Author is required." />
</div>
<ValidationSummary CssClass="col-sm-offset-2 col-sm-10 alert alert-info" Id="vsCT_Testimonial" />
<AddButton CssClass="btn btn-primary" Text="Post Testimonial" OnClientClick="tinyMCE.triggerSave();" />
<CancelButton CssClass="btn btn-default" Text="Cancel" />
</div>
<jQueryReady>
tinymce.init({
selector: '.tinymce',
statusbar: false,
menubar: false,
valid_elements: "p,br,b,i,strong,em",
toolbar: "bold italic",
browser_spellcheck: true,
setup : function(ed) {
ed.on('change', function(e) {
// This will print out all your content in the tinyMce box
console.log('the content '+ed.getContent());
// Your text from the tinyMce box will now be passed to your text area ...
$(".tinymce").text(ed.getContent());
}); //end setup
}
});
</jQueryReady>
</AddForm>
<AddSuccessTemplate>
<ItemTemplate>
<xmod:ScriptBlock ScriptId="SuccessCSS" BlockType="HeadScript" RegisterOnce="true">
<style type="text/css">
.success-message {
max-width: 800px;
margin: auto;
margin-top: 25px;
}
.btn:visited, .btn:focus {
color: #000;
}
</style>
</xmod:ScriptBlock>
<div class="alert alert-success success-message">
<h1>
Success!
</h1>
<p>
Thank you for your testimonial.
</p>
</div>
</ItemTemplate>
</AddSuccessTemplate>