Portal Engine Questions on portal engine and web parts.
Version 7.x > Portal Engine > Adding watermark to an email fiel View modes: 
User avatar
Member
Member
matthew.newby-crl - 7/9/2013 9:22:02 AM
   
Adding watermark to an email fiel
I'd replied to a question about Watermark text and email fields in the Version 6.x Portal Engine forum, but wanted to make sure it got some visibility here in v7.x.

Gitesh asked, "Has anyone found a way to add a watermark on email field?"

Radek responded that Watermarks were intentionally only for TextBox controls, but that they'd consider adding it to Email fields in a future release. He suggested using a TextBox and adding a regular expression to validate it.

I responded with a followup inquiry:
We've been putting a "*" in the TextBox fields to indicate that a value is required, and in our QA testing practically all the testers are noting that the email field is required but not visibly flagged as such. Any progress on adding watermark capabilities to email fields in the Kentico BizForms?

Assuming that this feature is NOT part of the 7.x releases, your suggestion to use a RegEx to validate emails in a TextBox seems to be the only alternative. I'm sure you're aware that building a regular expression to properly validate emails is a non-trivial undertaking. One thread on StackOverflow has 45 different answers to the question of "What's the best regular expression you have or have seen for validating emails?" (http://stackoverflow.com/questions/201323/using-a-regular-expression-to-validate-an-email-address) Couple that with the imminent arrival of some 2000 new top-level domains, and the validity of these answers gets called into question. Bottom line, simple RegEx's will either pass invalid emails or fail valid ones (or both), and even highly complex RegEx's struggle to meet IETF specifications (RFC 822, RFC 5322, etc.) for current TLDs, let alone the freight-train of new ones inbound.

Is there any way to access the built-in Kentico email validation code/function while using the TextBox field type? Alternatively, can you tell us what the internal email validation RegEx is?

Thanks!

-matt

User avatar
Kentico Legend
Kentico Legend
Brenden Kehren - 7/9/2013 12:51:15 PM
   
RE:Adding watermark to an email fiel
I suggest taking a look at the textbox form control and copying that specific functionality over to a cloned version of the e-mail form control. Should take no longer than 30 minutes to complete and can be utilized within your custom tables, doc types, biz forms, etc.

The textbox control is located here: <root>\CMSFormControls\Basic\TextBoxControl.ascx
The e-mail control is located here: <root>\CMSFormControls\Inputs\EmailInput.ascx

If you haven't worked with form controls before within the UI, let me know and I can give you some direction on that as well.

User avatar
Member
Member
matthew.newby-crl - 7/9/2013 2:08:05 PM
   
RE:Adding watermark to an email fiel
Thanks, FroggEye! I'm definitely going to want some pointers as I get into this platform. I've got a pretty extensive background with ColdFusion and Oracle and just jumped over to the Microsoft stack, having had little exposure to it between the old-skool .asp I used back in the 90's and now. A lot has changed in the meantime!

Is "cloning" a simple matter of copying the two source files to new files with a different name, or do I need to invoke some Visual Studio wizardry to get it to work?

User avatar
Kentico Legend
Kentico Legend
Accepted solutionAccepted solution
Brenden Kehren - 7/9/2013 10:21:40 PM
   
RE:Adding watermark to an email fiel
Welcome to ASP.NET! Nothing better in my opinion. Done ColdFusion, PHP, Oracle, etc. and love ASP.NET 100 times more than any of those.

So here are the steps one by one to copy the email form control with watermark text. Check this out for some basics on where to store your custom files.

1). In CMSSiteManager>Development>Form Controls search for "e-mail" (with a dash)
2). Click the arrow to the left of the red X for the E-mail input control and select Clone
3). In the popup window enter the following values:
Display name: E-mail w/watermark
Code name: EmailWithWatermark
4). Check form clone control files
5). Enter the path ~/CMSFormControls/Custom/Inputs/EmailInputWatermark.ascx
6). Click clone.
7). Edit your newly created form control
8). On the properties tab add a new category named Email settings and move it to the top. (added for cosmetic reasons)
9). Add another new category named Watermark and move it to the top. (again cosmetic reasons)
10). Add a new property under the Watermark category called WatermarkText (type=text, size=500, Allow empty value=true, caption=Text, control=Localizable text box) and save
11). Add a new property under the property you just created called WatermarkCssClass (type=text, size=50, allow empty value=true, caption=Css class, control=Text box) and save
12). Open Visual Studio
13). Navigate to the file in step 5 and open the code behind file.
14). Replace all the code behind with code below. Assuming you are following the steps word for word, you shouldn't need to modify anything but if you haven't make sure the class name is the same in the code behind as it is in the .ascx file (in this case CMSFormControls_Custom_Inputs_EmailInputWatermark)
using System;
using System.Web.UI.WebControls;
using System.Collections;
using System.Collections.Generic;

using AjaxControlToolkit;

using CMS.CMSHelper;
using CMS.FormControls;
using CMS.FormEngine;
using CMS.GlobalHelper;
using CMS.PortalControls;
using CMS.SettingsProvider;
using CMS.ExtendedControls;


public partial class CMSFormControls_Custom_Inputs_EmailInputWatermark : FormEngineUserControl
{
#region "Constants"

protected const int AUTOPOSTBACK_TIMEOUT = 700;

#endregion

#region "Properties"

#region "Watermark properties"

/// <summary>
/// The text to show when the control has no value.
/// </summary>
public string WatermarkText
{
get
{
return ValidationHelper.GetString(GetValue("WatermarkText"), null);
}
set
{
SetValue("WatermarkText", value);
}
}


/// <summary>
/// The CSS class to apply to the TextBox when it has no value (e.g. the watermark text is shown).
/// </summary>
public string WatermarkCssClass
{
get
{
return ValidationHelper.GetString(GetValue("WatermarkCssClass"), "WatermarkText");
}
set
{
SetValue("WatermarkCssClass", value);
}
}

#endregion

/// <summary>
/// Gets or sets the enabled state of the control.
/// </summary>
public override bool Enabled
{
get
{
return base.Enabled;
}
set
{
base.Enabled = value;
txtEmailInput.Enabled = value;
}
}


/// <summary>
/// Gets or sets field value.
/// </summary>
public override object Value
{
get
{
return txtEmailInput.Text.Trim();
}
set
{
txtEmailInput.Text = (string)value;
}
}


/// <summary>
/// Gets ClientID of the textbox with emailinput.
/// </summary>
public override string ValueElementID
{
get
{
return txtEmailInput.ClientID;
}
}


private bool mAllowMultipleAddresses = false;

/// <summary>
/// Gets or sets if multiple e-mail addresses can be entered.
/// </summary>
public bool AllowMultipleAddresses
{
get
{
return mAllowMultipleAddresses;
}
set
{
mAllowMultipleAddresses = value;
}
}


/// <summary>
/// Gets or sets string that should be used to delimit multiple addresses (default separator is semicolon - ;).
/// </summary>
public string EmailSeparator
{
get;
set;
}

#endregion


#region "Methods"

/// <summary>
/// Registers script for layout.
/// </summary>
private void RegisterScript()
{
string postbackScript = @"
jQuery(function() {{
jQuery('.apbtbox')
.data('timeout', null)
.keyup(function(){
clearTimeout(jQuery(this).data('timeout'));
jQuery(this).data('timeout', setTimeout(function(){ " + ControlsHelper.GetPostBackEventReference(this, null) + @" }, " + AUTOPOSTBACK_TIMEOUT + @"));
});
}})";
ScriptHelper.RegisterJQuery(Page);
ScriptHelper.RegisterClientScriptBlock(Page, typeof(string), "autopostedbacktbox", ScriptHelper.GetScript(postbackScript));
}

/// <summary>
/// Page load.
/// </summary>
protected void Page_Load(object sender, EventArgs e)
{
// Set control style and css class
if (!string.IsNullOrEmpty(ControlStyle))
{
txtEmailInput.Attributes.Add("style", ControlStyle);
}
if (!string.IsNullOrEmpty(CssClass))
{
txtEmailInput.CssClass = CssClass;
CssClass = null;
}

// Set additional properties
AllowMultipleAddresses = ValidationHelper.GetBoolean(GetValue("allowmultipleaddresses"), AllowMultipleAddresses);
EmailSeparator = ValidationHelper.GetString(GetValue("emailseparator"), EmailSeparator);
}

protected override void OnPreRender(EventArgs e)
{
base.OnPreRender(e);
if (HasDependingFields)
{
txtEmailInput.AddCssClass("apbtbox");
RegisterScript();
}

#region "Watermark extender"

// Watermark extender
// Disable watermark extender for nonempty fields (issue with value which is same as the watermark text)
string resolvedWatermarkText = CMSContext.CurrentResolver.ResolveMacros(WatermarkText);
if (!String.IsNullOrEmpty(WatermarkText) && !String.IsNullOrEmpty(resolvedWatermarkText) && !CMSString.Equals(txtEmailInput.Text, WatermarkText))
{
// Create extender
TextBoxWatermarkExtender exWatermark = new TextBoxWatermarkExtender();
exWatermark.ID = "exWatermark";
exWatermark.TargetControlID = txtEmailInput.ID;
exWatermark.EnableViewState = false;
Controls.Add(exWatermark);

// Initialize extender
exWatermark.WatermarkText = resolvedWatermarkText;
exWatermark.WatermarkCssClass = txtEmailInput.CssClass + " " + ValidationHelper.GetString(GetValue("WatermarkCssClass"), WatermarkCssClass);
}

#endregion
}

/// <summary>
/// Returns true if user control is valid.
/// </summary>
public override bool IsValid()
{
if (string.IsNullOrEmpty(txtEmailInput.Text.Trim()))
{
return true;
}

// Check if valid e-mail addresses were entered
bool validEmails = (AllowMultipleAddresses ? ValidationHelper.AreEmails(txtEmailInput.Text.Trim(), EmailSeparator) : ValidationHelper.IsEmail(txtEmailInput.Text.Trim()));
if (validEmails)
{
if (FieldInfo != null)
{
// Check regular expresion
if (!string.IsNullOrEmpty(FieldInfo.RegularExpression))
{
if (new Validator().IsRegularExp(txtEmailInput.Text.Trim(), FieldInfo.RegularExpression, "error").Result == "error")
{
ValidationError = FieldInfo.ValidationErrorMessage;
return false;
}
}

// Check min lenght
if ((FieldInfo.MinStringLength > 0) && (txtEmailInput.Text.Trim().Length < FieldInfo.MinStringLength))
{
ValidationError = FieldInfo.ValidationErrorMessage;
return false;
}

// Check max lenght
if ((FieldInfo.MaxStringLength > 0) && (txtEmailInput.Text.Length > FieldInfo.MaxStringLength))
{
ValidationError = FieldInfo.ValidationErrorMessage;
return false;
}
}

return true;
}
else
{
ValidationError = GetString("EmailInput.ValidationError");
return false;
}
}

#endregion
}

15). Your form control is complete now.
16). Test it out by going to a document type and adding a new field and selecting your newly created form control and adding a new doc type to your content tree.

There you have it email form control with watermark.

User avatar
Member
Member
matthew.newby-crl - 7/10/2013 4:43:14 PM
   
RE:Adding watermark to an email fiel
FroggEye, you rock! If I'm understanding this all correctly though, the Code Name in step 3, the file name in step 5, and the last part of the Class name in step 14 all need to match, right? The one in step 3 above is EmailWithWatermark, while the other ones are EmailInputWatermark. Once I set all three of mine to the same thing (the step 3 value) it started working!

So, once we've QA tested this on our dev instance, is the process for rolling this out to the production servers any shorter than repeating the above steps on each instance? Or can I export the form control from CMSSiteManager, and on the production box, click the New Form Control button and point it at the export file. Does the export contain the codebehind bits as well, or will they need to be copied over separately?

User avatar
Kentico Legend
Kentico Legend
Brenden Kehren - 7/10/2013 6:27:07 PM
   
RE:Adding watermark to an email fiel
matthew.newby-crl wrote: If I'm understanding this all correctly though, the Code Name in step 3, the file name in step 5, and the last part of the Class name in step 14 all need to match, right? The one in step 3 above is EmailWithWatermark, while the other ones are EmailInputWatermark. Once I set all three of mine to the same thing (the step 3 value) it started working!
No the code name in the UI can be whatever you want it to be. That's how you reference the control from within the API. The File name in step 5 can also be whatever you want it to be. The important parts are in the .ascx file and the .ascx.cs files make sure the Inherits and the public partial class names are the same
<%@ Control Language="C#" AutoEventWireup="true" Inherits="CMSFormControls_Custom_Inputs_EmailInputWatermark" CodeFile="~/CMSFormControls/Custom/Inputs/EmailInputWatermark.ascx.cs" %>
public partial class CMSFormControls_Custom_Inputs_EmailInputWatermark : FormEngineUserControl...

matthew.newby-crl wrote:
So, once we've QA tested this on our dev instance, is the process for rolling this out to the production servers any shorter than repeating the above steps on each instance? Or can I export the form control from CMSSiteManager
Yes you can export/import it without a problem. In CMSSiteManager>Development>Form Controls find the newly created control and click the down arrow next to the delete icon and select Export. When it finished exporting save it to a place on your local computer. Go to your production server and in CMSSiteManager>Sites click the Import button and upload the file then select it and click next. On the next screen ensure the Import files checkbox is checked and leave all the other defaults and click next. Should work like a charm.

User avatar
Member
Member
jefferey.berger-ottawa - 7/18/2013 11:41:52 AM
   
RE:Adding watermark to an email fiel
Hi FroggEye,
First, thanks for a great post!
Second, can I assume that you could follow similar steps to add a watermark to other field types as well? For example a drop-down field?
Thanks!

User avatar
Kentico Legend
Kentico Legend
Brenden Kehren - 7/18/2013 8:50:58 PM
   
RE:Adding watermark to an email fiel
Never done a dropdown but should be very similar. There are some things that would be very nice to have consistent. For instance, all form controls have a watermark property. Or all repeater webparts, no matter what, have a header, footer, item, alt item, selected item and separator transformation.

I've created a library of my own web parts that are simple enhancements to what one webpart has that the others that are similar don't.