Archive

Archive for the ‘ColdFusion’ Category

Trimming a decimal with coldfusion & regex

January 12th, 2012

Today I had to import lots of measurements into a mySql table. The columns allow 3 places after the decimal. The data has mixed precision – some values use all 3 places, others use none. To make the output look clean I didn’t want to show all 3 places all the time. So numberFormat() was out. And unlike PHP, coldFusion’s trim() function does not take any parameters (trim trailing zeros and periods). I came up with using two regular expressions to remove any trailing zeros, then the trailing period if any.

Here is some example data:

  • 6.000
  • 0.375
  • 0.500

When using numberFormat(), the output is:

  • 6
  • 0
  • 1

… and numberFormat(val, 0.000) gives:

  • 6.000
  • 0.375
  • 0.500

Blech. So here’s the function that gave exactly what I wanted:

<cffunction name="trimDecimal">
 <cfargument name="value">
 <cfreturn REReplace(REReplace(value, "0+$", "", "ALL"), "\.+$", "")>
</cffunction>

… trimDecimal(val) resulting in…

  • 6
  • 0.375
  • 0.5

Perfect.

ColdFusion , ,

Return a query of all CF Scheduled tasks

September 27th, 2011

I was working on a scheduled task in a shared hosting environment. Which is pretty frustrating when you don’t have access to the CF Administrator.

Googling, I found some functions that would return information about scheduled tasks via coldfusion.server.ServiceFactory. That of course would not work since shared hosting environments have that locked down.

Then I came across an old post by Ben Forte. Instead of ServiceFactory he used an undocumented task called ‘__list’. It almost worked… except that it errored out on some task attributes. I guess a mismatch in versions of CF is to blame.

So I took that undocumented call, then rebuilt the rest entirely. I basically turned the data into tab-separated-values. I haven’t gotten around to learning reFind(), etc yet so please excuse the many replace() functions. It’s very low tech, but it works.

It won’t matter if you expect extra column names than __list gives (those columns in the returned query will be [empty string]s). And it also won’t matter if __list gives more than you’ve expected (those extra columns won’t be in the returned query). In either case, there will be no errors.

<cffunction
	name="getCFScheduledTasks"
	returntype="query"
	output="no"
	hint="Returns a query of CF Scheduled tasks on the server"
>
<!---
Thanks to Ben Forte for posting the undocumented call '__list'
--->
	<cfsavecontent variable='tasks'>
	    <cfschedule action='run' task='__list'>
	</cfsavecontent>

	<!--- TRIM WHITESPACE --->
	<cfset tasks = trim(tasks)>
	<cfset tasks = replace(tasks, chr(10), '', 'all')>

	<!--- REMOVE FIRST AND LAST BRACKETS --->
	<cfset tasks = mid(tasks, 2, len(tasks)-3)>

	<!--- CHANGE THE TASK DELIMETER --->
	<cfset tasks = replace(tasks, '}}},', '}}#chr(10)#', 'all')>

	<!--- CHANGE THE COLUMN DELIMETERS --->
	<cfset tasks = replace(tasks, '={{', chr(9), 'all')>
	<cfset tasks = replace(tasks, '},', '}#chr(9)#', 'all')>

	<!--- REMOVE THE ROW TRAILING BRACKETS --->
	<cfset tasks = replace(tasks&chr(10), '}}#chr(10)#', '}#chr(10)#', 'all')>

	<!--- REMOVE THE COLUMN TRAILING BRACKETS --->
	<cfset tasks = replace(tasks, '}#chr(9)#', chr(9), 'all')>

	<!--- TASK DATA COLUMNS --->
	<cfset columns = 'task,start_date,start_time,last_run,end_time,interval,operation,url,resolveurl,request_time_out,username,password,http_port,path,proxy_server,http_proxy_port,file,disabled,paused,publish'>

	<!--- CREATE A QUERY --->
	<cfset cfScheduledTasks=QueryNew(columns)>

	<!--- LOOP OVER THE ROWS & COLUMNS, ADDING TO THE QUERY --->
	<cfloop list="#tasks#" delimiters="#chr(10)#" index="row">
		<cfset QueryAddRow(cfScheduledTasks)>
		<cfloop list="#columns#" index="column">
			<cfloop list="#row#" delimiters="#chr(9)#" index="data">
				<cfif spanExcluding(data, '=') eq column>
					<cfset QuerySetCell(cfScheduledTasks, column, replace(data, column&'={', ''))>
				</cfif>
			</cfloop>
		</cfloop>
	</cfloop>

	<!--- WWWEEEE! --->
	<cfreturn cfScheduledTasks>
</cffunction>

<cfset cfScheduledTasks = getCFScheduledTasks()>
<cfdump var='#cfScheduledTasks#'>

Ben's original code is at: http://www.forta.com/blog/index.cfm/2006/8/28/GetScheduledTasks-Function-Returns-Scheduled-Task-List

ColdFusion , ,

Updated compressed scripty 1.8.3 for LightView, PHP

April 8th, 2010

I ran across a problem with LightView which is stated as requiring Prototype 1.6.1 and Scriptaculous 1.8.2. Yet it was failing even when I had scriptaculous 1.8.3 loaded.

Apparently LightView looks for the loader scriptaculous.js rather than the actual components (effect, builder, etc).

My previous compressed Prototype 1.6.1 and Scriptaculous 1.8.3 did not have the loader/stub scriptaculous.js file. Ideally, that’s never needed as long as you load the other scriptaculous js files.

So here is an updated package. Also in this archive is the PHP version of the ColdFusion file to server the jgz.

The combined file is now 273KB. The load order is as follows:

  • prototype
  • scriptaculous
  • builder
  • effects
  • dragdrop
  • controls
  • slider
  • sound

It includes all comments and credits. I gzipped it down to 62KB.

You’d load it like so:

<script type="text/javascript" charset="ISO-8859-1" src="/includes/js/scriptaculous/scriptaculous.cfm"></script>

Download it: wv-scripty-183.zip

ColdFusion, PHP, Scriptaculous

Speeding up cffm v1.1x

January 7th, 2010

I manage a site with nearly 50GB of small PDFs. Thousands of directories and files. This makes CFFM super duper slow. I know it sounds silly, but when staring at a blank window, 15 seconds feels like 15 minutes. The problem is that with every page load, the entire directory tree below your initial directory is read. Crazy. Here is the fix…

At around line 648 of cffm.cfm, only turn on recursion if this particular action requires it:

<cfset variables.listAllFiles = cffm.directoryList(cffm.includeDir, (isdefined("url.action") and url.action eq 'copymoveForm'))>

… which is, when moving or copying. In my application, speed increased 10x.
And to get a little more speed when listing a directory with images…

At around line 67 of cffm.cfm, turn off image sizes:

<cfinvokeargument name="enableImageDimensionsInDirList" value="true">

ColdFusion , , ,

CFSelect with multiple query columns

December 16th, 2009

CFSelect is nice because it can help you write out some code quicker. Just like the rest of ColdFusion. But I never used it because so many times I needed to display two columns in the <option>, such as “#lastName#, #firstName#”.

While working on a site I fell into the same routine. I start typing out CFSelect then grit my teeth when I get to the Display attribute. Being stubborn about it I stumbled upon a nice MySQL function called CONCAT(). Using that one can merge two columns in the query to be output as a single column name. Like so:

<cfquery name="emps" datasource="#application.datasource#">
SELECT
 id, CONCAT(lastname, ', ', firstname) AS fullName
FROM
 employees
ORDER BY
 lastname, firstname
</cfquery>

Then simply use that column name for the display (or elsewhere needed):

<cfselect name="employeeid" query="emps" selected="" value="id" display="fullName"/>

ColdFusion, MySQL, Web Coding , , , , , , ,

CF TinyMCE 090616 – Vscope no longer required for automatic multiple instance tracking

June 17th, 2009

A big thank to Mr. Camden for giving me a few minutes of his time! With his insight I was able to remove the required Vscope argument. Instead, multiple instances per page are tracked through Request. No more required argument, and it’s backwards compatible again.

Grab the update here: http://github.com/WebVeteran/cf-tinymce/

CF TinyMCE, ColdFusion, TinyMCE , ,

ColdFusion clips for Coda

June 16th, 2009

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

Coda, ColdFusion

CF TinyMCE 090612 – automatically handles multiple instance per page

June 16th, 2009

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/

CF TinyMCE, ColdFusion, TinyMCE , ,

A better Fix for IE6 and gzip compressed javascripts

April 17th, 2009

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>

ColdFusion, JavaScript, Scriptaculous , , ,

Fix for Safari and gzip compressed javascripts

April 2nd, 2009

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.

ColdFusion, JavaScript, Scriptaculous , , , , , , , ,