Block Special Characters from a Text Box Form Input

We want to keep users from entering special characters into our textbox input on or form. Ideally we want to not allow those characters to be entered at all, as opposed to let them enter the characters, check to see if they did, and then alerting them. Too much work, simply keep them from entering special characters from the beginning. For this we'll use JavaScript's onKeyPress event, which looks like this:

view plain print about
1<input type="text" onkeypress="myFunction()">

We'll construct a function that will check for special characters. And, well, here it is:

view plain print about
1function isAlphaNum(event) {
2 var regex = new RegExp("^[a-zA-Z0-9\\s]+$");
3 //alert(event + ' - ' + regex);
4 var key = String.fromCharCode(!event.charCode ? event.which : event.charCode);
5 if (!regex.test(key)) {
6 event.preventDefault();
7 return false;
8 }
9}

A quick walk through of the code.... the function is called "isAlphaNum()". The regex we are checking against is "^[a-zA-Z0-9]+$", which checks for numbers and upper and lowercase letters. I wanted allow spaces too, so I added the "\\s" to make it "^[a-zA-Z0-9\\s]+$". The commented alert is for testing. The function checks to see if the keypress does NOT match the expression and returns false. It does nothing if it passes the regex test.

My final HTML form text box looks like:

view plain print about
1<input type="text" onkeypress="isAlphaNum(event);">

Try it out! You will be unable to type in a character other than a number, letter or space.

jQuery Functions Based on datepicker Selection

The request is to have a form field display and be required if the datepicker selected date is within 2 weeks of the current date. If the date is later than 2 weeks, hide the form field and make it not required.

In this case, the date field is prepopulated with an outputted ColdFusion variable which is the date two weeks days from today. If the user selects the date field, datepicker displays allowing the user to change the date. If the newly selected date is less than two weeks from today's date, then display the other field and make that form field required. The default (because of the prepopulated date) is to not display the extra form field and not make it required.

Hopefully the code is documented well enough to make sense.

view plain print about
1//use datepicker to select date
2jQuery("##storeDate").datepicker();
3    
4//if the date is changed anytime, run the comparison function     
5jQuery("##storeDate").change(function() {
6    doDateCompare();
7});
8    
9//initially run the comparison function upon opening document     
10doDateCompare();
11    
12// the date comparison function tasks that need to be run
13function doDateCompare() {
14          
15    //create the comparison date object and set for today
16    var objdate = new Date();
17    
18    // get the date initial or selected from the datepicker form field
19             var objformdate = jQuery("##storeDate").datepicker("getDate");    
20             
21             //compare the dates but add 2 weeks to todays date first
22    if (objformdate < objdate.setDate(objdate.getDate() + 14)){
23            
24        //selected date is less than 2 weeks away
25        
26        //show the extra form field table row    
27     jQuery("##storeDateRow").show();
28    
29     //make the extra form field is now required
30     jQuery("##metaData").attr("required", "required");
31    }
32    else {
33        
34        //selected date is more than 2 weeks out
35        
36        //hide the extra form field row
37     jQuery("##storeDateRow").hide();
38    
39     //remove required attribute from extra form field so we can submit form
40     jQuery("##metaData").attr("required", "");
41    }
42};

Here is the table row that will hide and show. Also the metadata field that picks up the required attribute, losing the required attribute when the date selected is over 2 weeks out.

view plain print about
1<tr id="storeDateRow">
2    <td>
3    Expense Num:<br>
4    <span class="formRequired">(required if date < 2 weeks)</span>
5    </td>
6    <td>
7     <input type="text" name="metaData" id="metaData" value="">
8    </td>
9</tr>

Remove Last Character of String createobject("java", "java.lang.StringBuffer").init()

Manipulating strings which are Java objects created in ColdFusion is a lot different that using standard CF functions. Once the Java object is created, Java methods must be used to manipulate the object.

How do I remove the last character of a Java object string created using the StringBuffer class?

view plain print about
1<cfset myString = createobject("java", "java.lang.StringBuffer").init() />

Here is a listing of the methods that can be used:

http://docs.oracle.com/javase/7/docs/api/java/lang/StringBuffer.html

The most common method seen used in CF is the append() method.

view plain print about
1<cfset myString.append("more string text" & thisVariable & " to " & thatVariable & "!")/>

demonstrates some string concatenation. Notice that there is an exclamation point (!) added to the end.

So the boss says, "No more exclamation points!!! Just at the end, you can use them in the middle of strings, like when I call you a @&!!*#% you worthless @#$%#!!"

So, before you start looking for another job (who could work for someone who talks to you like that?), we will remove the exclamation point at the end. The obvious way to do this would be just remove the concatenated

view plain print about
1& "!"

But the point of this lesson is to remove it using a Java StringBuffer method.

We could use deleteCharAt(), that's a StringBuffer method, but how do we find what the index of the exclamation point is?. It's at the end of a varying length string, changing every time the function is called and new variables are introduced.

This is where another StringBuffer method, length() comes to play

view plain print about
1<cfset myString.deleteCharAt(myString.length()-1) />

Starting from the inside, we find the myString length, subtract one and delete the character in that position.

This is a simple example but it is just for demonstration. On this post you can see how it came in really handy.

Invalid JSON property [object Error] found when trying to apply resultTemplate or paging.summaryTemp

Invalid JSON property [object Error] found when trying to apply resultTemplate or paging.summaryTemplate. Please check your spelling and try again. Error: Unable to get value of the property 'name': object is null or undefined

Error with jQuery, combobox, flexbox in IE7 and IE8. Runs fine on IE9, Chrome, and Firefox.

Solution:
My combobox jQuery was dynamically generated using ColdFusion code concatenating JavaScript strings while looping data. I found some bad logic that was erroneously adding an extraneous trailing comma to my dropdown array.

Read more here....

Debugging CF and JavaScript, flexbox combobox jQuery

Invalid JSON property [object Error] found when trying to apply resultTemplate or paging.summaryTemplate. Please check your spelling and try again. Error: Unable to get value of the property 'name': object is null or undefined

Getting errors when using flexbox combobox on IE7 and IE8. The code runs on IE9, Chrome, and all Firefox.

Using ColdFusion to generate JavaScript can sure lead to complications when trying to debug. It's complicated trying to write the CFML to generate the code, but we do it to make our lives easier!

This post is more about the process of debugging than writing or even the actual solution. First I will list efforts that proved worthless. I'll bet you tried at least one of these before finding this post.

  1. Searching for "resultTemplate" and/or "summaryTemplate"
  2. Editing jquery.flexbox.js. I actually put in "alert"s to step debug – waste of time.
  3. Edited the generating CF code to add spaces in the resultant JS.
  4. Did a LOT of Googling. This only helped if you found this article, which wasn't here when I went through the process!
So what worked? or how do we find the cause?

The first objective is to narrow down the area which is causing the problem. Because it was clicking in the combobox throwing the error, that sure helped. Next is to look at the JavaScript generated for the combobox. Here's what I had.

view plain print about
1<scr!pt type="text/javascript">var values_6789 = {};values_6789.results = [{id: "View The Collection", name: "View The Collection"},{id: "View The Trunk Show Collection", name: "View The Trunk Show Collection"},{id: "Personal Appearance", name: "Personal Appearance"},];values_6789.total = values_6789.results.length;$(document).ready(function () {$("#misc2").flexbox(values_6789, {autoCompleteFirstMatch: false, selectBehavior: true, paging: false, width: 180, noResultsText: "" });});</script>

Looking through this code, something very small is out of place, a comma.

view plain print about
1......name: "Personal Appearance"},];values_6789.total =......

The comma just before the closing bracket, "]".

Here's the code that builds that part of the JavaScript

view plain print about
1<cfloop query="arguments.qProductAddorValues">
2 <cfif arguments.qProductAddorValues.productAddorID eq arguments.productAddorID>
3 <!--- write element for the JSON object --->
4 <cfset fldString.append('{id: "#arguments.qProductAddorValues.value#", name: "#arguments.qProductAddorValues.name#"} ' )>
5 <cfif arguments.qProductAddorValues.currentrow neq arguments.qProductAddorValues.recordcount>
6 <cfset fldString.append(',')>
7 </cfif>
8 <cfif (len(arguments.fldval) and not cbBoxFldValAdded)>
9 <!--- this string is used for initialization of the control --->
10 <cfset defaultSelection = ',initialValue: "#arguments.fldval#"'>
11 <cfif arguments.qProductAddorValues.currentrow neq arguments.qProductAddorValues.recordcount>
12 <cfset fldString.append(',')>
13 </cfif>
14 <cfset cbBoxFldValAdded = 1>
15 <cfelse>
16 <cfif (arguments.qProductAddorValues.default eq 1 and not cbBoxFldValAdded)>
17 <cfset defaultSelection = ',initialValue: "#arguments.qProductAddorValues.value#"'>
18 </cfif>
19 </cfif>
20 </cfif>
21</cfloop>

Why is that extra comma there? There's a checking for the end...

view plain print about
1<cfif arguments.qProductAddorValues.currentrow neq arguments.qProductAddorValues.recordcount>
2 <cfset fldString.append(',')>
3</cfif>

The logic is probably bad. To prove it we have to output the 2 variables in the test. We have to output them and NOT break jQuery so the page will render AND still display the variable output.

This is done by commenting out the variable output with JavaScript syntax, /* stuff */. First, I create a string with the 2 test variables and concatenate them together with opening and closing JS comments.

view plain print about
1<cfset JSStringTest = "/* " & arguments.qProductAddorValues.currentrow & " = " & arguments.qProductAddorValues.recordcount & " */" />

Then I stick output of the string into the generated JS string where I think it will be innocuous. Outside of the array but inside the single quote.

view plain print about
1<cfset fldString.append('{id: "#arguments.qProductAddorValues.value#", name: "#arguments.qProductAddorValues.name#"} #JSStringTest#' )>

Here is the resultant JavaScript output:

view plain print about
1<scr!pt type="text/javascript">var values_6789 = {};values_6789.results = [{id: "View The Collection", name: "View The Collection"} /* 2 = 63 */,{id: "View The Trunk Show Collection", name: "View The Trunk Show Collection"} /* 3 = 63 */,{id: "Personal Appearance", name: "Personal Appearance"} /* 4 = 63 */,];values_6789.total = values_6789.results.length;$(document).ready(function () {$("#misc2").flexbox(values_6789, {autoCompleteFirstMatch: false, selectBehavior: true, paging: false, width: 180, noResultsText: "" });});</script>

You can see that the commented /* 4 = 63 */ for the final entry is obviously false. Thus proving the test is bad.

From here I have 2 options

  1. Find an accurate test.
  2. Just remove the last comma.

In this instance there really wasn't a valid test that could be easily and accurately generated. Information was being pulled from too many different places. I decided to just add the trailing comma after every iteration and remove it from end of the string after the loop is completed, but before we appended more JavaScript.

This turned out to not be easy either. If you recall, the string, fldString was appending JavaScript using:

view plain print about
1fldString.append()

This was because fldString is not really a string but a Java object created with:

view plain print about
1fldString = createobject("java", "java.lang.StringBuffer").init()

using CF's create Java object and Java's StringBuffer class. So the "fldString.append()" is a StringBuffer method.

What other StringBuffer method can I use to trim off the pesky trailing comma? We could use deleteCharAt() but how to find what the index is of the comma. It's at the end of a variable length string, changing every time the function is called. Well we just find the length of the string using another StringBuffer method, length(). Can't get much simpler than that! So here is how that code looks:

view plain print about
1<!--- remove trailing comma which is always added above ~ line 156, using Java StringBuffer class --->
2<cfset fldString.deleteCharAt(fldString.length()-1) />

Starting from the inside, we find the fldString length, subtract one and delete the character in that position.

So here's the final bit of completed code:

view plain print about
1<cfloop query="arguments.qProductAddorValues">
2 <cfif arguments.qProductAddorValues.productAddorID eq arguments.productAddorID>
3 <!--- write element for the JSON object --->
4 <cfset fldString.append('{id: "#arguments.qProductAddorValues.value#", name: "#arguments.qProductAddorValues.name#"},' )>
5 <cfif (len(arguments.fldval) and not cbBoxFldValAdded)>
6 <!--- this string is used for initialization of the control --->
7 <cfset defaultSelection = ',initialValue: "#arguments.fldval#"'>
8 <cfset cbBoxFldValAdded = 1>
9 <cfelse>
10 <cfif (arguments.qProductAddorValues.default eq 1 and not cbBoxFldValAdded)>
11 <cfset defaultSelection = ',initialValue: "#arguments.qProductAddorValues.value#"'>
12 </cfif>
13 </cfif>
14 </cfif>
15</cfloop>
16<!--- remove trailing comma which is always added above ~ line 156, using Java StringBuffer class --->
17<cfset fldString.deleteCharAt(fldString.length()-1) />

Bam! The JSON error is gone in IE7 and IE8 and the code still runs perfectly in all other browsers. This is a long story with a few important pieces. I'll break out the useful tidbits and post those in separate blog entries so that others may find specific answers without having to read this saga.

Debugging ColdFusion Generated JavaScript Trick

With JavaScript that is generated with ColdFusion, debugging can be very difficult. One can do step debugging by adding JS alerts each step and output the variables passed as far as the alert. But this becomes more difficult the more one relies on dynamically generated (ColdFusion) JavaScript and jQuery.

One easy trick is to output the testing variables in commented JavaScript. We have to output them and NOT break jQuery so the page will render AND still display the variable output.

This is done by commenting out the variable output with JavaScript syntax, "/* JavaScript comment */".

First, I create a string with the variables for which I am testing and concatenate them together with opening and closing JS comments.

view plain print about
1<cfset JSStringTest = "/* " & variables.thisTestValue & " = " & variables.thatTestValue & " */" />

Then I stick output of the string into the generated JS string where I think it will be innocuous.

This is really handy in loops, where you may be outputing variables based on tests, for example, using

See more here....

JQuery Prefix Textbox with Specific Number

jQuery Masked Input prefixing a form field text box with a specific character set.

A form requiring a project code, which was numeric, needed to have the project code prefixed with 1000 and be 10 digits long. An example of a properly formatted project code is "1000123456". How to do this with jQuery?

Use Josh Bush's Masked Input Plugin for jQuery to start. Make sure you have jquery.js (latest version) in your .

(Please note that the "invalidTag" referenced below is actually "script". CFFormProtect is changing this for my own good and your confusion.)

view plain print about
1<invalidTag src="jquery.js" type="text/javascript"></script>
2<invalidTag src="jquery.maskedinput.js" type="text/javascript"></script>

Using Mask Definitions
My form field text box had the name and id of "projectCode" My first attempt using regex resulted in failure. It looked like this:

view plain print about
1<invalidTag language="javascript">
2 $(document).ready(function () {
3     $.mask.definitions['~']=' \b[1][0]{3}\b ';
4     $("##projectCode").mask('~999999');
5 });
6</script>
FAIL!

I'm using ColdFusion, hence the escaped double pound signs (##).

Next try

view plain print about
1<invalidTag language="javascript">
2 $(document).ready(function () {
3     $.mask.definitions['~']='\b[1][0][0][0]\b';
4     $("##projectCode").mask('~999999');
5 });
6</script>
FAIL!

which lead to:

view plain print about
1<invalidTag language="javascript">
2 $(document).ready(function () {
3     $.mask.definitions['~']='\b[1][0][0][0]\b';
4     $("##projectCode").mask('~~~~999999');
5 });
6</script>
This allowed me to input "1000" into the correct fields but I could also input "1111" and "0000" or any binary combination of 1s and 0s.

Multiple Mask Definitions
So I used multiple mask definitions to successfully accomplish what I needed.

view plain print about
1<invalidTag language="javascript">
2 $(document).ready(function () {
3     $.mask.definitions['~']='[1]';
4     $.mask.definitions['^']='[0]';     
5     $("##projectCode").mask('~^^^999999');
6 });
7</script>
SUCCESS!

So a little explanation may help. The mask definition for requires that the tilde (~) field will only accept the digit 1. The carat (^) field will only accept 0. So the mask '~^^^' will only accept '1000'.

The great thing is that we are not just restricted to numbers, as in this case. You could restrict by specific letters or characters too. Simply adjust the mask definition.

From the user's point of view, the only issue could be that the user could hack away at the keyboard not understanding why they could not put in the numbers they wanted. A little instruction in the label solved that issue. "Please prefix the Project Code with '1000'".

jQuery flexbox IE8 invalid JSON property

Invalid JSON property TypeError: Unable to get value of the property 'name': object is null or undefined found when trying to apply resultTemplate or paging.sumaryTemplate.

We are using a jQuery flexbox for a dropdown combobox in a form. Clicking on the dropdown combobox field generates the above JavaScript alert ONLY in IE8. In all other browsers the combobox works correctly.

So, in short, the error occurs because of the IE8 parsing engine. Quit looking elsewhere!

Here is the fix, place this in your head:

view plain print about
1< meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7" />

This worked. Newer versions of jQuery are backward compatible so having IE run as IE7 doesn't cause any problems for us in our situation.

Reference: MSDN

Adding JavaScript to the Mura form "thank you" page

If JavaScript needs to be added to the returning Mura "thank you" page after filling out a form, such as Google Conversion code, you need not worry. Here's how you do it.

Create a custom display page and put it in your custom folder: "[siteid]/includes/display_objects/custom/ "

I named my page "dsp_google_code.cfm". "[siteid]/includes/display_objects/custom/dsp_google_code.cfm"

This is all that "dsp_google_code.cfm" contained:

view plain print about
1<invalidTag language="javascript" type="text/javascript">
2alert('Put the Google Code where this message is generated. You will be forwarded to About Us in 10 seconds.');
3setTimeout('getgoing()',10000);
4function getgoing() {
5 top.location="index.cfm/?LinkServID=9F4D0619-110A-FD5C-A8ECA3B68233106D";
6}
7</script>

Then go to the Form section in Mura Admin and edit your form. In the Confirmation Message box, after you return message place this, or something similar:

view plain print about
1[mura]dspInclude('display_objects/custom/dsp_google_code.cfm')[/mura]

My Confirmation box looks just like this:

view plain print about
1<strong>Thank you!</strong><br/><br/>
2
3We have received your request about our software solutions are looking forward to working with you.<br/><br/>
4
5Your browser will now be forwarded to the About Us page so you can read case studies and such to learn more about our software solutions.<br/><br/>
6
7[mura]dspInclude('display_objects/custom/dsp_google_code.cfm')[/mura]

The JavaScript gives you an alert telling you the script actually was run, then forwards to a permanent link.

This experiment was inspired by Stephen Withington's blog post, http://www.stephenwithington.com/blog/index.cfm/2009/10/5/How-to-Send-Confirmation-Emails-to-Form-Submitters-in-Mura-CMS

CoolMenu Script not working

On an older site of mine, www.polygraph.to, I used Cool Menus 3 by Thomas Bratta (bratta.com) from dhtmlcentral.com. That site now redirects to opencube.com to sell you a menu generator. Dhtmlcentral.com is now a German sports blog(?). Whatever.

The reason why the script is not working is because of the browser check function for IE. It works great in FireFox and Chrome, but as usual, IE sucks. All you have to do is add references for IE 8. Or you could just replace the lib_bwcheck() function with this below:

view plain print about
1function lib_bwcheck(){
2
3    this.ver=navigator.appVersion; this.agent=navigator.userAgent
4
5    this.dom=document.getElementById?1:0
6
7    this.ie5=(this.ver.indexOf("MSIE 5")>
-1 && this.dom)?1:0;
8
9    this.ie6=(this.ver.indexOf("MSIE 6")>-1 && this.dom)?1:0;
10
11    this.ie7=(this.ver.indexOf("MSIE 7")>-1 && this.dom)?1:0;
12
13    this.ie7=(this.ver.indexOf("MSIE 8")>-1 && this.dom)?1:0;
14
15    this.ie4=(document.all && !this.dom)?1:0;
16
17    this.ie=this.ie4||this.ie5||this.ie6||this.ie7||this.ie8
18
19    this.mac=this.agent.indexOf("Mac")>-1
20
21    this.opera5=this.agent.indexOf("Opera 5")>-1
22
23    this.ns6=(this.dom && parseInt(this.ver) >= 5) ?1:0;
24
25    this.ns4=(document.layers && !this.dom)?1:0;
26
27    this.bw=(this.ie8 || this.ie7 || this.ie6 || this.ie5 || this.ie4 || this.ns4 || this.ns6 || this.opera5 || this.dom)
28
29    return this
30
31}

BlogCFC was created by Raymond Camden. This blog is running version 5.9.7. Contact Blog Owner