A few weeks ago I saw an interesting post on Dzone about what you shouldn't do in Python. (See the article here.) This got me thinking about what features/types of code/practices should be avoided in ColdFusion.
Some are obvious - for example, not using deprecated code. Did you know that CFML Reference guide contains a list of deprecated code for both tags and functions? Also listed are obsolete tags and functions. These functions/tags won't work at all in ColdFusion 8.
But what else would you add to this list? I do not want to turn this entry into a "bash CF" entry (obviously, I love ColdFusion!). If you don't like a feature, I don't want to hear about it as we all have features we don't like. But what things would you caution developers against? Or at least warn them? What tags/functions throw a red flag in your mind when you see the code.
I'll go first, and these are in no particular order, and I won't even pretend to say I haven't done this in the past.
- CFFILE - Before ColdFusion 8, the only way to read a file in was to read in the entire file. (Unless you used Java.) Any use of CFFILE to read a file where the file is dynamic should have some kind of sanity check to ensure you aren't reading in a two gig file. I'd extend this warning to anything that works on the file system. Will your code work if you leave Windows and go to a Linux system? Will your code handle missing files, paths, etc?
- Not using the Database: If you ever see logic being done on query data (like adding, averaging, hiding rows based on some logic), you need to immediately check and see if that work can be done in the database instead.
- From the Python article above, I'll ditto the recommendation to not leave gobs of commented out code in files. No decent developer should be without source control. There is no excuse. Period. (Will there be a day when bloggers can stop saying this?)
- Building UDFs for functions that already exist in ColdFusion. Ok, so I'm probably the only one affected by this - but I tend to see submissions to CFLib that mimic things already built into CF. I see it from time to time on cf-talk as well. If you don't have time to read the entire docs - at least skim the reference manual and ensure you know what each tag and function basically does.
- Misuse or unsafe use of CFTHREAD - I have a post on this coming up later this week - but CFTHREAD is a powerful and dangerous tool. Be sure, for example, that you don't blindly ignore errors in the thread.
- Bad error handling - Again a bit related to the Python article - but do not use try/catch to hide errors that should actually be exposed. I've actually seen entire pages written in try/catch. Scary.
- Caching as a bandaid. There are some cool ways to cache in ColdFusion. (See this article.) But caching should not be used to cover up bad code.
Thoughts?
Archived Comments
CfDocument - while this can be great for small un-strict projects, trying to do something like checks or invoices printing on an overlay is enough to make you pull your hair out. Some of the strange padding / page break issues can cause you to loose sleep. I switched to Java's iText and I haven't looked back.
Just subscribing to comments...
I think the database one is a really important one. I know I'm guilty of it, and have seen a lot of us doing similar things. Breaking down what could be 1 query into looping with a query each iteration, or double loops with queries to do things the database was meant to do!
What the cf community needs is na sql version of the Camden-Sharp connection. :P
CFFORM and built in CFFORM validation.
YUCK
Gus - I want to make a rule, if I may, for these comments. You have to explain why. Not in super detail as it is just a comment, but you can't just say X is yuck.
I'm embarassed to even post this, but I'm currently trudging through a half-dozen legacy files with this very problem:
putting cflocations in act and mod files.
Marc - and this is bad why?
Again - I don't want this to be a simple list of bad things. I want _reasons_ behind things as well. Please. :)
Using cfdirectory can be deathly when you need file listings on really large directories. Don't ever just use a plain cfdirectory tag, either use the underlying java libraries or the undocumented "listinfo" attribute.
listinfo is documented.
As for your tip - interesting. Doesn't the OS put a limit on the total # of files in the folder?
While I have seen people load up files that are too big - I've rarely seen the issue you describe. Have you seen it often?
Ray,
I have inherited a site with over 20,000 images in a single folder. You and I both know it *shouldn't* happen, but unfortunately it does =(
Ah okay, I see that listinfo is documented in CF8 now...it wasn't in CF7 even though it did work in that version as well. So I guess my comment doesn't exactly apply now! Good to know that's been addressed.
And yes, I commonly see users just upload all the images for a site to a single directory. On an ecommerce site, this is often many thousands of images.
Mary: <cfdirectory> is _a lot_ faster in ColdFusion 8 and has a ton of options that can enhance performance.
Ok, I've been looking into using source code control, but I never get around to doing it. I've got a lot of stuff on my plate, but, I've been burned by losing some work before and source control would have saved my ass. I guess I could make this my weekend project to get up to speed on using source control.
Are there any tutorials you know of aimed at the CF developer on setting up something such as subversion on a local machine at least, or maybe a dedicated server for a small team?
CoolJJ
Bundled Verity search engine has caused me several gray hairs in the past, at least for following issues
- indexing doesn't neccessarily support latest version of documents and used to break if something unsupported was provided. I had most issues with relatively recent PDF files and ended up writing code to determine PDF version and skip unsupported ones.
- there is limit how many hits it will return, I hit that around 8000 documents but it seems to depend on data itself.
This should be expected but it's not properly documented as far as I know.
- indexing large amount of documents needs to be done in batches. I ended up doing 1.000 for each run. This requires some custom code.
- I don't think I ever got it to work with non-english documents but in all honesty I haven't tried that since 2000.
Verity is nice to have but if you need something that would be called "enterprise level" look for some other solutions. Most of them are 50k€+ unfortunately.
@Tero - the bundled Verity engine was updated in a major way for MX7. It is drastically different. (And the docs do talk about the document limit.)
@CoolJJ - Google for the Acme Guide. It is a darn good guide that covers the entire dev setup. CF+Web Server+DB+Source Control.
@All - again folks I kind of want to focus on things that you think should not be done - as opposed to features you think need improvement. For example:
Don't select * from a db (good)
cfquery should do XX (bad)
You shouldn't neglect setting addtoken="no" in the <cflocation> tag if you don't need the urltoken appended to the URLs.
It just results in unnecessary querystring variables being passed around and makes it confusing when trying to determine if the site is using cookies or querystring variables to pass the token info.
How about doing something like resizing an image with cfimage every time a page is displayed versus doing a single resize when it's uploaded? May seem obvious to a lot of us, but I guarantee you people will do this. ;-)
The other thing that comes to mind for me (and again, I don't know how much this may have been improved on CF8) is use of QoQ with larger recordsets. It's such a powerful tool it can be easy to overuse it, and it simply can't handle some of the heavy lifting the actual database engine can. Like cfthread, you have to know when and where to use it effectively.
I agree, there are probably a lot of things that should *not* be done in ColdFusion. I should probably learn another language at least as well as a I know SQL and CF. Because "when the only tool you have is a hammer, you tend to see the problem as a nail"
What language should a well-versed CF'er learn? Perl?
I'm looking forward to more about threads.
@Mary Jo - If you don't mind, I'll riff on your comment about image resizing, and say that (and this applies to any language) - dont do N times what you can do 1 time.
Using cflocation altogether.
Yes, it's my pet hate, but by default, cflocation produces a "302 *temporarily* moved" header.
So don't use it if your database query returned no records:
e.g. for product.cfm?id=1234
<cfquery name="variables.blah">
select blah from blah where id=<queryparam "#url.id#" />
</cfquery>
<cfif not variables.blah.recordcount>
<cflocation url="index.cfm" addtoken="false" />
<cfelse>
Do something
</cfif>
This is bad - if you can't find blah.id in your database, you should serve a 404, or handle it some other way.
And, if you used to run a website (say, "ray.camdenfamily.com") and you moved it elsewhere (for example, "www.coldfusionjedi.com"), use a "301 moved permanently" - that way google will transfer all that inbound love you got on the old domain to your new one. *grin*
And if you run a feed aggregator website (say "fullasagoog.com"), don't use cflocation 302 redirects as you end up ranking better than the final article you're pointing to...
Um, you do know that cflocation lets you set a status code, right?
You can do cflocation url="foo" statuscode="301"
In CF7?
And in CF8, is the default still a 302 ?
CF8, yep. I would assume the default is 302 still.
@Ray - Yup, that will work for a lot of things, probably a lot of the stuff newbies tend to do. The "not using the database" is the one I often see with inexperienced developers. I still remember the time I found code in a legacy application that did a "SELECT * FROM Table" and then did a cfloop over it to find a specific record....rather than just using a WHERE clause in the query. Still makes me shudder...
I'll just add two things that aren't so much "don't do them in CF" as they are "don't do them in languages not designed for them, and CF isn't designed for them"
1) Crunching lots of large numbers. I've tried to do this in CF and, while it eventually gets there, it's slow. If you know something like C or Haskell, offload the task into an external, preferably compiled, function. Obviously better in MX6/7/8 that it was in 5, and your value of "lots" and "large" may vary.
2) The same thing, except with text processing. CF can handle quite a bit, but when I need to analyze multimegabyte text files, it is not my language of choice. Perl or Python both do the job (typically) better and faster (IMHO).
Pardon, Ray. here's why the cflocations are bad in act and mod files: I was reworking some old code today, trying like hell to use existing code where applicable via good old cfincludes. but in about 80% of the cases, I had to do more work than I wanted to because the existing act files relocated me to places I didn't want to go.
Now, these act files *could* still be used for a little while, so modifying them wasn't ideal. So I was stuck with choosing copy/paste just for the purpose of deleting a cflocation, or adding cfif code around the existing cflocation stuff, which is a total hack.
so in essence its immediate negative effect is that it eliminated the possibility for reuse.
that, and act files are supposed to do just that: act. do something. insert something. delete something. but don't take me anywhere i don't want to go.
use a "cfquery" udf in cfscript instead of <cfquery> just so it acts like php. I have inherited an app that does this extensively and there is no way (that I know of) that allows you to use cfqueryparam in cfscript or protect the sql statements from sql injection.
I'll go back to Gus' comment about using the built-in form validation and go ahead and give the reasoning as to why it should be avoided, although I want to expand on the comment slightly and say that you shouldn't use the automatic *server-side* validation. If you plan to write your own server-side validation but also want some client-side stuff, the cfform JavaScript is acceptable (but I personally prefer using Dreamweaver CS3's Spry form validation stuff as it provides for a nicer end-user experience.)
First, CF still uses single quotes in the generated hidden fields, meaning that the error message cannot contain apostrophes (so you can't say, "You must provide the customer's last name"). Related to that is the fact that the generated hidden fields aren't closed and thus result in invalid XHTML. Neither of these issues have ever been considered as a high enough priority to get fixed, but they severely limit the usefulness of the validation.
Second and much more importantly, the fact that the server-side validation relies on the presence of hidden fields at all is a huge problem and should be a deal-breaker to anyone who is serious about form validation. It is ridiculously easy to get the form to submit without those hidden fields, at which point you have no validation at all. The simplest method is to download and install the Tamper Data extension for Firefox (or something similar). The only slightly more difficult method is to simply create your own HTML file that submits to the same action page, and simply excludes the hidden fields.
The first most important rule in form validation is that you should never trust any data coming from the browser, and yet the cfform validation relies on exactly that and should thus make anyone's list of things you shouldn't do in CF.
I would also like to add a caveat to your statement about not using deprecated features. I think it's as important to be aware of, and make sure you use, any new features in CF that will make your life easier. (Which is the whole point of using CF, right?) Take logging in users - I still seee applications that are being written today that manually handle logging users in and tracking them on the site, rather than using the cflogin framework. The same would apply, on a much bigger scale, to all of the many developers who continue to shy away from CFCs imply because they don't want to take the time to learn them.
As we deal with spatial data (i.e. maps of Antarctica and its surrounds), we often like to produce light-weight maps of results along with a coastline or bathymetry. This means using external products like Geoserver or ITT's IDL to render data in various projections which CF knows nothing about. The problem is each mapping tool requires its own data access and query scripts that have to be kept in logical sync with anything we do in CF.
I remember a rumor going around not too long ago that cfswitch is a lot slower than a string of cfelseif's. Anyone know if this is (still) true?
@ben
I'm pretty sure that was never true. In CF5, I seem to remember the opposite being true, but since 6 I don't think there has been a measurable difference
I'll play Devil's Advocate here - is worrying about the speed of cfswitch versus cfif something a developer should worry about?
@Ray,
In my opinion a developer should always be concerned about the speed of what he is developing. He/she should always be thinking about how to do things better/faster. Create a stored procedure to aggregate data on the database instead of doing it in CF for example.
So to answer your question yes we should be worried about a cfswitch vs cfif/elseif and here is why.
A cfswitch will find the matching cfcase and jump to and execute that case, while a cfif/elseif will evaluate until it finds a matching one or drop out to the last cfelse.
Not only is a cfswitch faster its also easier to read and maintain.
I think you may have misunderstood me. Obviously speed is important. But do you not write code using cfswitch because cfif is faster, even though cfswitch may be more readable? (Or vice versa.)
My point is - you can and should worry about speed at a level where you have control over it. But when it comes down to timing and comparing individual CF functions/tags, I think it is a mistake, especially when from version to version it may change. Many tags/funcs were sped up in CF8.
i can't see, at least in what I am doing, where using cfif vs. cfswitch makes any difference performance-wise. I think they both have their places for different processes.
I am one of those people that has never embraced the cflogin framework. am I a terrible person for that?
I have continued to use cfswitch blocks where it's convenient for me, but I still had this nagging uncertainty. Thanks for your thoughts. I feel a little better, in fact I might take a break and go have a milkshake to celebrate.
"I've actually seen entire pages written in try/catch. Scary."
Not sure what you mean by this statement. Can you please explain further?
Try/Catch is intended to wrap code that may throw an exception and that you have no control over. It is not meant to hide all exceptions over an entire page. So for example - imagine i have a datasource that points to a DB that - for whatever reasons - is sometimes offline. I have no control over that - so using try/catch around the query makes sense.
Now imagine I want to output X. X may not exist. Should I try/catch that? No - I can use isDefined instead.
@Doug S. - I think he was meaning both the potential overhead of weapping an entire page in a block as well as the possiblilty of opening up vulnerabilities by having the entire page in a catch.
@Rob - I've been told a lot by people to never use cfform or the built in form validation for a variety of reasons. I've often found them to be somewhat outdated, but not completely invalid. I never knew the things you pointed out on the single quotes, thanks!
Since no one tossed this one out there. Avoid having an entire function that is an if statement.
e.g.
<cffunction ...>
<cfif isSomethingTrue>
lots of logic here
<cfreturn whatever />
<cfelse>
<cfreturn false />
</cfif>
</cffunction>
This can be a lot easier to read by doing something like:
<cffunction ...>
<cfif not isSomethingTrue>
<cfreturn false />
</cfif>
.... do rest of your processing
<cfreturn whatever />
</cffunction>
@Ray,
Thanks for clarifying. As I said your comment struck me as a little odd...and now I know why... I misunderstood what you meant :)
As I mentioned in my post we need to use the right tool for the job and at the same time produce efficient and maintainable code.
I do, however, tend to worry about the speed of certain tags or functions (take iif for instance) and try to avoid using them unless necessary, it won't stop me from using it , but it will make me think twice before I do.
@Gary - Actually it's debatable if cfswitch is faster. If you are using a string to evaluate, it may be slower. See this article for reference:
http://www.webapper.net/ind...
Hi all. Here is a short list off the top of my head. Probably none of these are absolutes, but I have run across them all.
Using a CFloop to loop over query content and place cfoutput tags just outside the loop when the content of the loop needs to go to the browser.
Using cfoutput to loop over content that is not going to a browser.
Using the pound symbols around variable assignments. (<cfset foo = #var.otherfoo#>)
Extensive use of isdefined. Define it with a cfparam and set with some value-even-- an empty string.
Write a log entry(to a file) for every navigation link clicked.
Avoid looping over queries -- if you can. Find someone to write a better query. (Sometimes you are working with someone else's database and you can't avoid it)
Expect Verity to return results as fast as Google.
Allocate in MX7, more than 512Mb of RAM for each instance of CF in Enterprise. There is a physical limit the JVM can handle for each instance of CF (a good reason to upgrade to 8)
Index large Verity collections in the middle of the day. If you have a busy site, you want your resources to serving pages.
Cache your components (in an application variable) without designing some way to clear out and reinstate those variables on demand. (At some point you will make changes to the web app and be in a bit of debugging hell)
Reset your application variables without first notifying all current users of your app of the possible disruption.
Avoid doing the database work in CF. Send the data to a stored procedure and let the database do all of the heavy lifting.
Avoid extensive use of web services for your servers' apps to communicate with each other in a web farm. The delay for execution is unbearable.(although I don't know of a good way around this.)
1: Don't have CF do what your database should be doing. Do your best to limit database calls. Write stored procedures to combine multiple calls or to do data manipulation logic. Databases are designed to process data so let them do it.
2: Logically break up your code. Don't put all 500 files for your site in a single directory. This just makes it harder to develop and maintain. Use sub directories and split the code up.
3: Don't do something just cause you can. By this I mean, don't write some overly complex code or have this one off procedure in a part of a site just because CF could do it. Every site does not need to be a showcase for all the glory that is CF. Know when to say enough is enough.
--Dave
How about this one?
I have learned extremely painful lessons to not use flash forms when form items are being dynamically generated from user input or database values. The code that works delightfully for the handful of fields that are generated during testing (oh silly short-sighted developer!) may quickly outgrow the flash form size limit and leave you with no alternative but to completely rewrite the code for an html-version of the form.
Obviously, the easy answer is to use Flex. Wish I had known my action scripting a bit better about 9 months ago...
@Andy,
-- Write a log entry(to a file) for every navigation link clicked.
Sometimes this is a neccessary evil to track users from a legal perspective. Its application-centric, but I've worked on one where its a security as well as legal requirement. Theres even been lawsuits where this information came into play (I was told anyhow!).
-- There is a physical limit the JVM can handle for each instance of CF (a good reason to upgrade to 8)
I believe this is based on memory allocation. For example on a 32bit OS you can't have a contiguous memory block of over 1.8GB I believe. I'd assume in theory you cannot set this in the CF Admin to over 1.8GB without your CF not restarting or acting weird.
@Andy - I'm curious about your statement to avoid overusing isdefined, and instead using cfparam. Is there a significant performance difference there? I mean, is <cfparam name="form.foo" default=""> then <cfif form.foo is ""> really better than <cfif not isdefined("form.foo")>?
Not trying to play devil's advocate or anything here, by the way - I'm genuinely curious.
Oh, and one more "shouldn't do" that I see a lot from beginners - having essentially static content get generated from a DB by CF, such as navigation bars. Yes, there are plenty of aps where the navigation really is changing constantly and needs to be dynamic, but I've seen lots of examples of nav that rarely if ever changes that is still generated by CF, instead of being plain old HTML. The same would apply to using date functions to output the copyright year - something that needs to be changed exactly once per year (and yeah, I have seen it done).
@Rob---
You make a good point about the footer date. The only way this would be necessary is if one had a ton of pages that one did not wish to update once per year. However, if this was the case, I would question why one would not simply use an include with a hard-coded date for the footer.
Whilst I agree with Rob H's comments about the server-side validation being deficient in CFFORM, I'd disagree with any recommendations to avoid the client-side validation these days. CFFORM has grown up a lot in the last couple of revisions and yet people still have a knee jerk reaction against it, based on how terrible it used to be.
Particularly in CF8 with all the AJAX-y goodness, data binding and so on, it makes a *lot* of sense to use CFFORM.
I guess a "rule" here is: be prepared to revisit your beliefs each time a new version of CF comes out - maybe something that was bad before just became really good?
So much to address....
First, I agree with Sean about CFFORM validations...when using Ajax forms I'm starting to get back to using the built in validations a bit (hey, you're in a cfform anyways...and as he said they're not _that_ bad).
Second... I have no problem whatsoever with using year(now()) to output a copyright date in a footer (or anywhere)... If your app needs the extra .000000001ms saved by hardcoding this - and your time is so cheap that you don't mind wasting 5 minutes every year changing this (oh - what if it's not in your hands anymore...) then by all means hardcode the date. Sorry for being brutally honest...
Thirdly... Just my opinion here, but I can't remember the last time I used isDefined. It's just not in my toolbox anymore. To me it's almost like var scoping in a cfc...if I'm creating a variable somewhere in my page I immediately hop to the top of the page and param it. Also - boo on using <cfif form.foo is "" /> -- use len() - and don't do <cfif len(form.foo) is 0> -- why take the extra step? CF will evaluate to boolean so <cfif len(form.foo)> is all you need (same goes with recordCount, etc).
Thats all for now...
@Rob
My remark about isDefined stems from a blog comment made by Ben Forta a long time ago. His point had to do with overhead. Personally, it's not a bad idea to declare what gets used in your template at the top anyway.
-A-
@todd, totally agree on your second point and the first half of your third point.
Totally disagree on using <cfif not len(form.foo)> rather than the much more explicit <cfif form.foo is ""> or <cfif trim(form.foo) is ""> - part of the issue here is that <cfif len(form.foo)> just doesn't read as language: "if the length of the form field foo..." If the length what? And of course it's not len() which is a negative condition instead of is "" which is a positive condition. This is basic readability. Compare with "if the trimmed value of the form field foo is the empty string" which is what <cfif trim(form.foo)> says.
isDefined is old school, and I never use it any more.
For what its worth, I usually go this route:
<cfif structKeyExists(form, "foo") AND len(trim(form.foo)) neq 0>
do really cool stuff
</cfif>
Its much more readable to me, and the 2nd part wont ever execute if the field does not exist. Safe and to the point.
I agree 100% on using the database where possible! Have learned the hard way myself ;-)
Off the top of my head I would add...
1. Using TABs to indent code and/or leaving unnecessary spaces within your files slows down the page rendering significantly. I suggest using minimal spaces and returns in your code and would put more emphasis on code performance than code-readability. I have seen significant performance gains by striping all unnecessary whitespace characters from CF files and although this is a generic issue not solely related to CF it has proved time and again to be a good place to start when optimising page-load performance.
2. Wrapping entire pages of HTML display code in CFOUTPUT when there are only a couple of variables to output in the middle of the code! Using CFOUTPUT just around the variable is my preferred method where possible.
3. Using CFOUTPUT around code which has nothing to output! hahahaha... I have seen this TOO many times from in-experienced developers.
4. Relying on the timeout setting in CFADMIN to stop long requests from processing. This can lead to dropped connections and page timeouts on busy servers/apps. My preferred approach is to have the tieout really low in my development environment and use debugging to highlight code which requires longer to process. I then use the CFSETTING tag on these particular templates to specify a longer timeout value. On live servers I have the CFADMIN timeout set to 45 secs.
5. Not scoping variables... for the love of God scope your variables... always!
6. Using stupid un-descriptive names for database tables, database fields, variables, etc. If you have a table for employees call it "employees" not "EMP"... if it has a field for FirstName call it FirstName not "FN"... unless of course you really want to frustrate the hell out of the poor sod who is trying to understand your app!
PS. love your stuff Ray!
I disagree with stripping out the white space. I think whatever you gain in page download will be dwarfed by what you lose in code productivity.
I'm also a bit lose on my cfoutput. I won't do an entire page, but to me, this is more readable:
<cfoutput>
some text, a #var#, some more text
</cfoutput>
Then this:
some text, a <cfoutput>#var#</cfoutput>, some more text
The first option lets me see the text clearer. And anyway - CF just igores anything not in #s anyway.
As for table names - remember some DBs prevent you from using nice long names. I think it's Oracle that has some crazy rules for names. I always laugh - you pay a fortune for a DB that has insane rules for names. ;)
In regards to whitespace, I should have said "excessive" TABs, whitespace and multiple concurrent carrige returns. For example I would replace 3x line breaks with a single line break, which still allows you to scan the code easily ;-) and always use spaces as opposed to TABS for code indentation.
I disagree on the performance aspect as I have honestly seen significant improvements, especially when replacing TAB-indented code blocks with spaces.
I agree with your comment regarding CFOUTPUT and adopt the same methodology myself.
It's interesting to weigh the performance benefits against the development productivity benefits. I'd like to hear others feelings about which should take precedence. Personally I put the emphasis on performance because a poorly performing application is destined to be unused, unwanted and ultimately dumped, therefore negating the requirement for further development at all ;-)
#1 annoyance with code I've worked with: bad/inconsistent abbreviations...
I used to abbreviate alot - then realized how stinking confusing it gets to be.
Hypothetical example: columns mgrName and areaMngrName in the same table.
So now you're in your CFC thinking "gee, how did I abbreviate that column again?" and you're jumping back to the DB to check. Then you're calling your CFC on another page and outputting a query and you're thinking again "gee, what was that column called again?". This issue is compounded in this example because it used different abbreviations for the same word (mgr and mngr for manager). So I look it up the first time and assume the second instance uses the same abbreviation and now I'm looking it up _again_.
All avoidable by simply not abbreviating. (Disclaimer: unless the abbreviation is commonly accepted and not easily confused - such as ID). Just my opinion, but I rarely abbreviate anymore. The time it costs me to type out 'managerName' is less then it takes me to go look it up...
OH...and I really gotta see proof of the 'significant improvements' from removing TABs.
I agree with Sean about CFFORM validations.
Can any of you tell me (because I am so new to CF the wrapper the software came is is still in my hand) what limites there are on CFFORMs and Checkboxes???
Reason I ask is I have built a site with 40 pages and one is now nearly 3000 lines of code and it was working fine until I added a tooltip which was coded correctly but seemed to be the straw that broke the camels back and now the page will load but the form which houses all the fields and main part of the page is blank. Of course I undid the last tooltip and re-put but the same is happening.
I 100% haven't got duplicate names or src that doesn't exist or such like...it was working fine, i put an extra tool tip and now its broken.
I also had a similar issue with check boxes on a tab navigator in that it seems the limit is 20 check boxes...add a 21st and the page says nope, not loading anymore....
I really tried to google this for some time before posting this here...
ALL help understanding limits in CF8 would be greatly received