I am migrating data from DOS dBASE IV to MySQL and I am building an input form using ColdFusion 11. My problem is, as an example, I have a field called 'size' and in it a value of " 2" X 2" X 1/4" X 10' LONG ".
Just one of thousands, so please don't advise me to replace the inch and feet marks with txt.
First I provide a form for selecting fields from the table to display, then provide a form to apply filters and search criteria to the selected fields, then query to get my results.
Because I have a dynamic list of fields I loop over a list of them. I then replace the ' and then the " so the field value will display in the html input form property.
Everything works except when there is both a ' and a " in the value. Then the JavaScript onBlur function returns an error "Uncaught SyntaxError: missing ) after argument list"
<!---Coldfusion code --->
<cfloop list="#fcolumnlist#" index="c"> <!---Loop over list of fields selected--->
<td>
<cfset thisfield = '#Evaluate('t.#c#')#'> <---Determine the value of the field--->
<cfset thisfield = Replace(thisfield, '"', "&##34;", "ALL")> <--- replace ' --->
<cfset thisfield = Replace(thisfield, "'", "&##39;", "ALL")> <--- replace " --->
<input type="text" id="#c##t.id#" name="#c#" value='#thisfield#'
onfocus="adjWidth(this);" onblur='ck_chg(this, "#thisfield#" )' >
</td>
</cfloop>
My JavaScript functions:
function adjWidth(el) {
el.style.width =((el.value.length + 10) * 8) + 'px';
}
function ck_chg(el, v) {
if ( el.value!=v )
{
el.style.backgroundColor='#05AD05';
el.style.color='#FFFFFF';
} else {
el.style.backgroundColor='';
el.style.color='#000000';
}
}
The html source looks like this and displays correctly in the form. BTW: my form can return 1 to over 5,000 records.
<input type="text" id="SIZE3137" name="SIZE" value='2" X 2" X 1/4" X 10' LONG' onfocus="adjWidth(this);" onblur='ck_chg(this, "2" X 2" X 1/4" X 10' LONG" )' >
I have tried almost every possible combination of replacing the inch and feet marks but nothing has worked. I have tried just using textarea which displays easier but I could not get the style and the JavaScript to function like I want. BTW; the function adjWidth()
is because of the unknown widths of the unknown columns, it works, ugly but it works.
How can I improve or at least make this work?
The issue is that after the HTML has been parsed, and the HTML entities have been resolved, the JavaScript engine will have to deal with parsing the code. This onblur
code will now look like this:
ck_chg(this, "2" X 2" X 1/4" X 10' LONG" )
...and there we see the problem: the string literal is closed immediately after the first "2", and the rest becomes a syntax error.
One quick workaround is to rely on the value
attribute that already has the desired string value. So the onblur
could be set like this:
<input type="text" id="#c##t.id#" name="#c#" value='#thisfield#'
onfocus="adjWidth(this);"
onblur='ck_chg(this, this.getAttribute("value") )' >
Another possibility is to escape the double quotes that appear inside the JavaScript string literal (again), but then with JS escapes, i.e. with a backslash. So:
<cfset thisfield = Replace(thisfield, '"', "&##34;", "ALL")> <--- replace ' --->
<!--- add this variant: the quote is also escaped for JS --->
<cfset thisfield2 = Replace(thisfield, '"', "\\&##34;", "ALL")>
<cfset thisfield = Replace(thisfield, "'", "&##39;", "ALL")> <--- replace " --->
<input type="text" id="#c##t.id#" name="#c#" value='#thisfield#'
onfocus="adjWidth(this);" onblur='ck_chg(this, "#thisfield2#" )' >
Please also consider using EncodeForHTMLAttribute
for escaping HTML instead of doing it "manually" with Replace
calls.
And finally, this kind of string manipulation makes code hard to maintain. Although it would be a non-trivial effort, consider moving all that JavaScript code away from HTML attributes, and instead attach event handlers via JavaScript code that resides in <script>
tags. This is considered better practice, and results in less character escaping head aches.