ColdFusion clips for Coda

I have made quite a few Clips in Coda to make development a little speedier. Hopefully you can get some use out of them too.

Coda Clips
Preview of Coda Clips - keep in mind the clips window only shows the first line of each clip.

Download the Clips here:
ColdFusion Coda Clips

CF TinyMCE 090612 – automatically handles multiple instance per page

I updated CF tinyMCE with a small nicety. It now automatically handles multiple instance per page. Previously, it would have to be invoked like so:

<cfoutput>
<tr>
	<td>
		#application.includes.tinymce(
			content=read.en,
			element="en",
			csswidth="444px",
			resizing=true,
			theme='advanced',
			theme_advanced_buttons1 = "bold,italic,underline,|,justifyleft,justifycenter,justifyright,justifyfull,|,formatselect,|,bullist,numlist,|,undo,redo,|,code,cleanup",
			theme_advanced_buttons2 = "",
			theme_advanced_buttons3 = ""

		)#
	</td>
	<td>
		#application.includes.tinymce(
			content=read.es,
			element="es",
			csswidth="444px",
			resizing=true,
			theme='advanced',
			loadbase='0',
			language='es',
			theme_advanced_buttons1 = "bold,italic,underline,|,justifyleft,justifycenter,justifyright,justifyfull,|,formatselect,|,bullist,numlist,|,undo,redo,|,code,cleanup",
			theme_advanced_buttons2 = "",
			theme_advanced_buttons3 = "",
			gecko_spellcheck = "false"
		)#
	</td>
</tr>
</cfoutput>

Notice the ‘loadbase=0’ argument on the second invocation. That told the previous version of CF TinyMCE to not all of TinyMCE again – just load the settings instead.

The new version automatically handles multiple instances and not loading TinyMCE all over again for subsequent invocations on the same page. Therefore, the new syntax example is:

<cfoutput>
<tr>
	<td>
		#application.includes.tinymce(
			VScope=Variables,
			content=read.en,
			element="en",
			csswidth="444px",
			resizing=true,
			theme='advanced',
			theme_advanced_buttons1 = "bold,italic,underline,|,justifyleft,justifycenter,justifyright,justifyfull,|,formatselect,|,bullist,numlist,|,undo,redo,|,code,cleanup",
			theme_advanced_buttons2 = "",
			theme_advanced_buttons3 = ""

		)#
	</td>
	<td>
		#application.includes.tinymce(
			VScope=Variables,
			content=read.es,
			element="es",
			csswidth="444px",
			resizing=true,
			theme='advanced',
			language='es',
			theme_advanced_buttons1 = "bold,italic,underline,|,justifyleft,justifycenter,justifyright,justifyfull,|,formatselect,|,bullist,numlist,|,undo,redo,|,code,cleanup",
			theme_advanced_buttons2 = "",
			theme_advanced_buttons3 = "",
			gecko_spellcheck = "false"
		)#
	</td>
</tr>
</cfoutput>

No more loadbase! The key is the argument “Vscope=Variables”. That lets CF pass the Variables scope back and forth between a page and a function. It is a required argument which I am not happy about. But since it’s value never changes it’s not so bad.

Because of this fundamental change, CF TinyMCE 090612 is not backwards compatible. If anyone knows how to pass the Variables scope back and forth between a page and a function, without an argument like I am here – please let me know!

You can download CF TinyMCE at github: http://github.com/WebVeteran/cf-tinymce/

A better Fix for IE6 and gzip compressed javascripts

In previous posts I found a fix for an intermittent problem with IE6 not loading compressed javascripts. IE was loading the first zero bytes of the gzipped javascripts. But if you copy-paste the url of the javascript it loads fine. And then the pages with those javascripts work just fine from there on. That fix was to exclude IE6 from receiving the compressed version.

Well, this fix is much better. Just add blank Pragma and Cache-control headers. No need to exclude IE6 from receiving the compressed js.

<cfif cgi.HTTP_ACCEPT_ENCODING contains "gzip">
	<cfheader name="Content-Encoding" value="gzip" >
	<cfheader name="Content-Disposition" value="inline; filename=""protoaculous182min.jgz""">
	<cfheader name="Content-Type" value="application/x-javascript; charset=ISO-8859-1">
	<cfif cgi.HTTP_USER_AGENT contains 'MSIE 6.0; Windows'>
		<cfheader name="Pragma" value="">
		<cfheader name="Cache-control" value="">
	</cfif>
	<cfcontent deletefile="no" file="#expandpath('./protoaculous182min.jgz')#" type="application/x-javascript; charset=ISO-8859-1">
<cfelse>
	<cfheader name="Content-Disposition" value="inline; filename=""protoaculous182min.js""">
	<cfheader name="Content-Type" value="application/x-javascript; charset=ISO-8859-1">
	<cfinclude template="protoaculous182min.js">
</cfif>

Fix for Safari and gzip compressed javascripts

Yesterday I showed how to use cgi.HTTP_USER_AGENT to not push gzipped javascripts to IE6. After fixing that guess who starts choking? IE’s bastard stepchild: Safari. I don’t trust Safari any more than I do IE. Unfortunately my client base uses it all the time: Designers!

After some digging around I learned that you cannot send compressed javascripts to Safari with the extension of “gz”. It must be “jgz”. Steve, you have got to be kidding me.

So here it is fixed… notice the modified filename in the Content-Disposition:

<cfif cgi.HTTP_ACCEPT_ENCODING contains "gzip" and cgi.HTTP_USER_AGENT does not contain 'MSIE 6.0; Windows'>
	<cfheader name="Content-Encoding" value="gzip" >
	<cfheader name="Content-Disposition" value="inline; filename=""protoaculous182min.jgz""">
	<cfheader name="Content-Type" value="application/x-javascript; charset=ISO-8859-1">
	<cfcontent deletefile="no" file="#expandpath('./protoaculous182min.gz')#" type="application/x-javascript; charset=ISO-8859-1">
<cfelse>
	<cfheader name="Content-Disposition" value="inline; filename=""protoaculous182min.js""">
	<cfheader name="Content-Type" value="application/x-javascript; charset=ISO-8859-1">
	<cfinclude template="protoaculous182min.js">
</cfif>

Work flawless in Safari3, IE6, IE7, IE8, and Firefox3.

Fix for IE6 and gzip compressed javascripts

For the past two weeks I’ve been struggling with a website. In particular, IE bugs. Of course.

What I had the most problem with is an intermittent problem with IE6 not loading compressed javascripts. It spews out cryptic javascript errors. The debugger is a joke. If you hit reload, sometimes it works. Sometimes it does not. Then it works fine for quite a while. Then the client emails ‘broken’ messages. Argh what a mess.

It turns out to be a bug in IE that has been around since version 5.5 until version 7. Yes that’s right, 6 years! IE loads the first zero bytes of the gzipped javascripts. But if you copy-paste the url of the javascript it loads fine. And then the pages with those javascripts work just fine from there on (probably cached at that point). Wow. Nice work Redmond!

After figuring this out I quickly made a fix. I’ve been using prototype and scriptaculous compressed for quite some time. Since 99% of my work is on shared hosting I just use ColdFusion to server the gzipped version if the browser allows it (keep in mind this is the old code that can have problems in IE6):

<cfif cgi.HTTP_ACCEPT_ENCODING contains "gzip">
	<cfheader name="Content-Encoding" value="gzip" >
	<cfheader name="Content-Type" value="text/javascript" >
	<cfcontent deletefile="no" file="#expandpath('./protoaculous182min.gz')#" type="text/javascript">
<cfelse>
	<cfinclude template="protoaculous182min.js">
</cfif>

The fix then is to exclude IE6, too, from receiving the compressed version. I also added some other bits to make it nicer and more proper:

<cfif cgi.HTTP_ACCEPT_ENCODING contains "gzip" and cgi.HTTP_USER_AGENT does not contain 'MSIE 6.0; Windows'>
	<cfheader name="Content-Encoding" value="gzip" >
	<cfheader name="Content-Disposition" value="inline; filename=""protoaculous182min.gz""">
	<cfheader name="Content-Type" value="application/x-javascript; charset=ISO-8859-1">
	<cfcontent deletefile="no" file="#expandpath('./protoaculous182min.gz')#" type="application/x-javascript; charset=ISO-8859-1">
<cfelse>
	<cfheader name="Content-Disposition" value="inline; filename=""protoaculous182min.js""">
	<cfheader name="Content-Type" value="application/x-javascript; charset=ISO-8859-1">
	<cfinclude template="protoaculous182min.js">
</cfif>

That seems to work flawless in IE6, IE7, IE8, and Firefox3.

Whew. Hope someone out there finds this helpful!

bd

CFimage vs PhotoShop – reduce image size in multiple passes

I’ve noticed in PhotoShop that it’s best to reduce images in multiple passes. For instance, to make a 100px thumbnail from a 1000px image requires 4 resize actions:

  1. 1000 : 50% = 500
  2. 500 : 50% = 250
  3. 250 : 50% = 125
  4. 125 : 100px = 100px

The smaller image is crisper. Then I wondered if the same would hold true for ColdFusion’s built in CFimage tag. Let’s check it out. In both cases I started with the same image (uncompressed TIF) and output to disk a JPG with quality set to 100%.

You can download the original uncompressed TIF here: grey.tif (12.8MB).

PhotoShop

Using the above steps (but more of them) I brought this 2112px image down to 200px. Interpolation is set to “Bicubic Sharper (best for reduction)”. The output is grey-stepped-ps.jpg (43KB). Then I did a single resize action to create grey-one-ps.jpg (65KB). I found it odd that the output sizes we off by 50%!

ColdFusion

Mimicking the PS work with CFimage is easy. Here I have Interpolation set to the default, “highestQuality’ and antialiasing turned on.

Here is the code I used for the multiple pass version of the resize:

<!--- READ THE TIF --->
<cfimage source="#expandPath('./')#grey.tif" name="myImage">
<cfset ImageSetAntialiasing(myImage,"on")>
<!--- TO 1056 --->
<cfset ImageResize(myImage, "50%", "50%")>
<!--- TO 528 --->
<cfset ImageResize(myImage, "50%", "50%")>
<!--- TO 264 --->
<cfset ImageResize(myImage, "50%", "50%")>
<!--- TO 200 --->
<cfset ImageResize(myImage, "200", "200")>
<!--- WRITE TO DISK --->
<cfimage source="#myImage#" action="write" destination="#expandPath('./')#grey-stepped-cf.jpg" overwrite="yes" quality="1">

The output is grey-stepped-cf.jpg, 43KB. The page took 9.3 seconds.

And here the single pass version:

<!--- READ THE TIF --->
<cfimage source="#expandPath('./')#grey.tif" name="myImage">
<cfset ImageSetAntialiasing(myImage,"on")>
<!--- TO 200 --->
<cfset ImageResize(myImage, "200", "200")>
<!--- WRITE TO DISK --->
<cfimage source="#myImage#" action="write" destination="#expandPath('./')#grey-one-cf.jpg" overwrite="yes" quality="1">

The output is grey-one-cf.jpg, also 43KB. The page took 4.8 seconds.

Outcome

Sure enough, the multiple pass method in PhotoShop yields a nicer image. However, it looks like a single pass resize with CFimage looks better.

Why more CF developers choose FCKeditor, and a TinyMCE CFC

Last week I posted a poll asking CF developers why they preferred FCKeditor over TinyMCE. Here are the results as of 3/2/09.

Quality / reliability 5 (50%)
It’s a simple tag (part of cftextarea) 3 (30%)
Extendability 2 (20%)

Which I have mixed feelings about. The first feeling is, ‘wow only 10 voters’ haha! Then, I thought that its great to use a built in function to get work done fast. That’s kind of what CF is all about. But at the same time I feel it’s more important to deliver to the end client the nicest looking/performing product.

Now, I don’t have anything against FCKeditor. But I really like TinyMCE. If you followed me on Twitter or this blog you’d know that. So what I’m prepared to do is give away a really great ColdFusion Function that makes rendering a TinyMCE instance a snap:

<cfoutput>
	<tr>
		<td>
			#application.includes.tinymce(
				content='',
				element="en",
				csswidth="444px",
				resizing=true,
				theme='advanced',
				theme_advanced_buttons1 = "bold,italic,underline,|,formatselect,|,bullist,numlist,|,undo,redo,|,code,cleanup",
				theme_advanced_buttons2 = "",
				theme_advanced_buttons3 = ""
			)#
		</td>
		<td>
			#application.includes.tinymce(
				content='',
				element="es",
				csswidth="444px",
				resizing=true,
				theme='advanced',
				loadbase='0',
				language='es',
				theme_advanced_buttons1 = "bold,italic,underline,|,formatselect,|,bullist,numlist,|,undo,redo,|,code,cleanup",
				theme_advanced_buttons2 = "",
				theme_advanced_buttons3 = ""
			)#
		</td>
	</tr>
</cfoutput>

Which renders as:

<tr>
		<td>

		<textarea name='en' id='en' style='width:444px; height:350px; visibility:hidden;'></textarea>

			<script type="text/javascript" src="/includes/js/tiny_mce/tiny_mce_gzip.js"></script>
			<script language="javascript" type="text/javascript">
				tinyMCE_GZ.init({
					plugins : 'autosave,spellchecker,style,layer,table,save,advhr,advimage,advlink,emotions,insertdatetime,preview,media,searchreplace,print,paste,directionality,fullscreen,noneditable,visualchars,nonbreaking,xhtmlxtras',
					themes : 'advanced',
					languages : 'en,es',
					disk_cache : true,
					debug : false,
					suffix : ''
				});
			</script>

		<script language="javascript" type="text/javascript">
			var configArrayen = [{
				mode : 'exact',
				element : "en",
				theme : 'advanced',
				plugins : 'autosave,spellchecker,style,layer,table,save,advhr,advimage,advlink,emotions,insertdatetime,preview,media,searchreplace,print,paste,directionality,fullscreen,noneditable,visualchars,nonbreaking,xhtmlxtras',
				theme_advanced_disable : 'hr',
				theme_advanced_buttons1 : "bold,italic,underline,|,formatselect,|,bullist,numlist,|,undo,redo,|,code,cleanup",
				theme_advanced_buttons2 : "",
				theme_advanced_buttons3 : "",
				content_css : '/static/css/main.css',
				theme_advanced_styles : "",
				paste_auto_cleanup_on_paste : true,
				paste_convert_pageheaders_to_strong : false,
				paste_strip_class_attributes : 'all',
				paste_remove_spans : false,
				paste_remove_styles : false,
				force_br_newlines : true,
				force_p_newlines : false,
				relative_urls : false,
				gecko_spellcheck : true,
				convert_urls : true,
				theme_advanced_resizing_use_cookie : true,
				theme_advanced_resizing : true,
				theme_advanced_resize_horizontal : false,
				theme_advanced_toolbar_location : 'top',
				theme_advanced_toolbar_align : 'left',
				theme_advanced_statusbar_location : 'bottom',
				extended_valid_elements : 'br,a[name|href|target|title|onclick|class],img[class|src|border=0|alt|title|hspace|vspace|width|height|align|onmouseover|onmouseout|name|style],hr[class|width|size|noshade],font[face|size|color|style],span[class|align|style]',
				language : 'en',
				forced_root_block : '',
				theme_advanced_toolbar_location : "bottom",
				theme_advanced_toolbar_align : "center",
				theme_advanced_statusbar_location : 'none',
				entity_encoding : "raw"
			}];
			Event.observe(window,'load', function(){
				tinyMCE.settings = configArrayen[0];
				tinyMCE.execCommand('mceAddControl', false, 'en');
			});
		</script>

		</td>
		<td>

		<textarea name='es' id='es' style='width:444px; height:350px; visibility:hidden;'></textarea>

		<script language="javascript" type="text/javascript">
			var configArrayes = [{
				mode : 'exact',
				element : "es",
				theme : 'advanced',
				plugins : 'autosave,spellchecker,style,layer,table,save,advhr,advimage,advlink,emotions,insertdatetime,preview,media,searchreplace,print,paste,directionality,fullscreen,noneditable,visualchars,nonbreaking,xhtmlxtras',
				theme_advanced_disable : 'hr',
				theme_advanced_buttons1 : "bold,italic,underline,|,formatselect,|,bullist,numlist,|,undo,redo,|,code,cleanup",
				theme_advanced_buttons2 : "",
				theme_advanced_buttons3 : "",
				content_css : '/static/css/main.css',
				theme_advanced_styles : "",
				paste_auto_cleanup_on_paste : true,
				paste_convert_pageheaders_to_strong : false,
				paste_strip_class_attributes : 'all',
				paste_remove_spans : false,
				paste_remove_styles : false,
				force_br_newlines : true,
				force_p_newlines : false,
				relative_urls : false,
				gecko_spellcheck : true,
				convert_urls : true,
				theme_advanced_resizing_use_cookie : true,
				theme_advanced_resizing : true,
				theme_advanced_resize_horizontal : false,
				theme_advanced_toolbar_location : 'top',
				theme_advanced_toolbar_align : 'left',
				theme_advanced_statusbar_location : 'bottom',
				extended_valid_elements : 'br,a[name|href|target|title|onclick|class],img[class|src|border=0|alt|title|hspace|vspace|width|height|align|onmouseover|onmouseout|name|style],hr[class|width|size|noshade],font[face|size|color|style],span[class|align|style]',
				language : 'es',
				forced_root_block : '',
				theme_advanced_toolbar_location : "bottom",
				theme_advanced_toolbar_align : "center",
				theme_advanced_statusbar_location : 'none',
				entity_encoding : "raw"
			}];
			Event.observe(window,'load', function(){
				tinyMCE.settings = configArrayes[0];
				tinyMCE.execCommand('mceAddControl', false, 'es');
			});
		</script>

		</td>
</tr>

There’s a lot of good stuff going on in there. Lazy loading, multiple instances per page, good defaults, language support, etc etc. Here is a sample including multilingual spellchecking:

tinymce_cfc

TinyMCE CF GZip – now officially part of tinyMCE

I am very pleased to announce that my ColdFusion based compressor for TinyMCE has been adopted by Moxiecode’s for their official CF compressor.

Coldfusion Gzip Compressor 2.1.0 released

This version of the Coldfusion Gzip compressor is a complete rewrite that doesn’t require any jar file to be installed in the lib directory. The previous versions was basically written in Java and the cfm file only called the logic in this Java file. This was a major problem when the compressor was to be used on shared hosting servers since users can’t install these .jar files by themselves.

The rewrite of this compressor was done by Jules Gravinese. He will be the new maintainer for the Coldfusion compressor. So this release is also an introduction to a new team member.

We are trying to move TinyMCE from being a tightly maintained Moxiecode project to more of a community project. We recently added a new team page to the site that lists the members that are the core part of the TinyMCE community.

This is great news for shared hosting. Now you can run TinyMCE, compressed, without installing a jar file.

Many thanks to Artur Kordowski for his gzip work in Zip CFC.

You can look forward to tweaks and improvements over time!

Poll for ColdFusion Developers: why FCKeditor?

Last week I posted a poll asking CF developers which RTE they like to deploy and use themselves. Here are the results as of 2/24 midnight.

Deploy FCKeditor, use FCKeditor 13 (48.15%)

Deploy tinyMCE, use tinyMCE 12 (44.44%)

Deploy FCKeditor, use tinyMCE 2 (7.41% )

Delpoy tinyMCE, use FCKeditor 0 (0%)

Until today, FCK was more than a few votes ahead. I wondered why. And I found it odd that some deployed FCK but would rather use Tiny. So here is a new poll based on those results.

For those of you ColdFusion developers who prefer to deploy FCKeditor: why? Feel free to add more comments below.