Showing posts with label ColdFusion. Show all posts
Showing posts with label ColdFusion. Show all posts

Thursday, January 22, 2015

Sometimes solution for: Cannot read property "aDataSort" of undefined

At my company, we use DataTables frequently.  (Code available at Datatables.net)

Like my last post, I wanted to put up another post either to help others, or more likely, help myself when I can't solve the answer.

When I'm building out my datatables, I am often converting from an older syntax to the (currently) latest version.   I bang my head on the wall for at least 30 minutes over this error in the Javascript console:

Cannot read property "aDataSort" of undefined

Take this Datatable setup.

In my case, this is my (overly simplified) columnDefs section of my Datatable definition

, 'columnDefs': [
 { 'title':'ID', 'name': 'BatchID', 'data': 'BatchID' }
, { ''title':'Type', 'name': 'Type', 'data': 'Type' }
, { 'title':'Status', 'name': 'Status', 'data': 'Status'

This error is thrown because I'm missing (what should be an obvious addition) below:

var nColNumber = -1;
...
, 'columnDefs': [
  { 'targets': [ ++nColNumber ], 'title':'ID', 'name': 'BatchID', 'data': 'BatchID' }
, { 'targets': [ ++nColNumber ], 'title':'Type', 'name': 'Type', 'data': 'Type' }
, { 'targets': [ ++nColNumber ], 'title':'Status', 'name': 'Status', 'data': 'Status'

When you build your Datatable with a columnDefs configuration option, it's obviously VERY important to tell it the "target" of the definition.   I typically have only an empty <table id="someID"></table> definition in my HTML, then build it completely from Javascript.

I use the ++nColNumber, simply so I can easily move columns around later, and not have to renumber them, and I try to always reference columns by name not position, such as for hiding and showing columns at runtime.

Hope this helps someone solve this issue!

- Will Belden
January 22, 2015

Tuesday, January 13, 2015

Javascript DataTables and TN4 error on Sorting

This is just a quick note for myself.  Perhaps it will help others.  Mind you, I feel like this is a workaround, not an actual solution.

I have an ajax sourced DataTable.  (If you're not familliar with these, see: http://datatables.net.  They really are awesome.)

This particular table is struggling with handling the refresh of the table based on clicking a sortable (orderable) column header.

The TN4 error is reported against columns that have a "render" function associated with them.  Removing the render() function removes the problem, but I need those functions or they wouldn't be there.

Adding a "defaultContent" value to the column definition, however, seems to alleviate the issue.  I think the problem is somehow related to the sorting feature clearing the data, then the render function says "Um, you asked for row.clientName, but....there's no data, so there's certainly no "clientName" in the (missing) data."

I have other tables that do NOT have this issue, but this seems to be a workaround.

Now I can remember next time.

- Will Belden
January 13, 2015

Wednesday, April 16, 2014

IIS 7, Railo and Rewrite Rules (SES)

I recently added the "suggested" SES rewrite rules for my Coldbox app.  I use IIS7 along with Railo Tomcat.  After the rewrite rules were added to my web.config file and uploaded, my Railo admin became (keywords coming:) ugly, unusuable, missing CSS, no style, missing images...just horrible!

You're a developer.  You've been searching for a while.  (Because you didn't find this post sooner.)  You are struggling with getting the Railo Admininistrator screen to look like it ought to.  Everyone says "Oh...sorry, we don't use IIS."  Or those that do say "Oh...sorry, we use Helicon Rewrite engine."  Or even better: "Windows?  Sorry, man..."

I stumbled on a post finally after getting some community attempts at helping, but no real answer.  I don't have the link to the post handy, but at the end of the discussion, the fella said "Okay, well, I'll go back to using Path_Info."   For me, this was for Coldbox and Railo on IIS.  Perhaps you're using CFWheels or another framework where the SES requires rewrite rules.

The rule I had found initially used SCRIPT_NAME.  Not sure if that's an IIS vs. Railo vs. Tomcat problem, but I gave it shot.  It worked!  No more ugly Railo admin screens.  I could actually see what I was doing in there!  (When it doesn't work, and tries to rewrite the Railo links, you might be butchering your error logs for your app, as well as confusing your IIS log files, I'm sure.)

Here's my current rule from my web.config.  (Or you can adapt it for the visual interface in the IIS admin, if you need to.)

<rule name="Application Administration" stopProcessing="true">
<match url="^(.*)$" />
<conditions logicalGrouping="MatchAll">
<add input="{PATH_INFO}" pattern="^/(.*(CFIDE|cfide|CFFormGateway|jrunscripts|railo-context|fckeditor|ckeditor)).*$" ignoreCase="true" />
</conditions>
<action type="None" />
 </rule>

Rules you may have found previously may use SCRIPT_NAME.  Try swapping it out.  Hope you found this and it solved your problem in 5 minutes instead of the week I've been needing an answer.

- Will Belden
April 16, 2014

Monday, April 14, 2014

Coldfusion 8 and Decrypt function

Found an interesting item today in Coldfusion.

Apparently decrypt() in Coldfusion (8, at least) can apparently figure out when you intentionally change an encrypted value and still decrypt it.


Saturday, April 12, 2014

Coldfusion: Easy Timers for your objects

I've been really getting into logging lately.  A good friend of mine, through repeated "Gibbsing", wore me down on it, and I really do like using it.  (We'll talk about unit testing another time.)  It really helps to leave debugging statements in your code, re-enable debugging for that class later and get an insight into what was going on when you haven't looked at the code for a year.

I'm also a big user of Coldbox.  Therefore it is only logical that I also use Logbox, which is heavily modeled on Log4J.  Now, my solution here is really for classes and components (*.cfc files), not so much for *.cfm files.  Though you could easily put this into an application function or anywhere you want that's easy to access.  Would not take much tweaking at all.  In my case, I'm using this in my Service Layer, where 99% of my objects all inherit from a Base.cfc class.  Here are the functions I added to the Base.cfc component.  (I've stripped off some of the hints for clarity here in the post..)

Sorry for the small font, the layout here isn't very conducive.  Just copy to your favorite editor (Sublime?) to view in a larger font.

Coldfusion Code:

<!--- --------------------------------------------------------------------- --->
<!--- Add to your init() or preconstructor:  --->
<!--- --------------------------------------------------------------------- --->
<!--- <cfset variables.stTimers = {} /> --->
<!--- <cfset variables.nTimerTimeoutMS = 600000 > --->
<!--- --------------------------------------------------------------------- --->
<cffunction name="startTimer" access="private" returntype="string" output="false">
<!--- For Railo only, in CF use createUUID --->
<cfset var sHandle = createUniqueID() />

<cfset purgeTimers() />
<cfset variables.stTimers[sHandle] = getTickCount() />
<cfreturn sHandle />
</cffunction>

<!--- --------------------------------------------------------------------- --->
<cffunction name="endTimer" access="private" returntype="numeric" output="false">
<cfargument name="handle" type="string" required="true" />

<cfset local.nTimeInMS = -1 />
<cfif structKeyExists(variables.stTimers, arguments.handle)>
<cfset local.nTimeInMS = getTickCount() - variables.stTimers[arguments.handle] />
<cfset structDelete(variables.stTimers, arguments.handle) />
</cfif>

<cfreturn local.nTimeInMS />
</cffunction>

<!--- --------------------------------------------------------------------- --->
<cffunction name="purgeTimers" access="private" returntype="void" output="false">
<cfloop collection="#variables.stTimers#" index="local.sPurgeHandle">
<cfif getTickCount() - variables.stTimers[local.sPurgeHandle] GT variables.nTimerTimeoutMS>
<cfset structDelete(variables.stTimers, local.sPurgeHandle) />
</cfif>
</cfloop>
</cffunction>

Usage within inherited objects, in this case in conjunction with Logbox debug logging:

<cffunction name="myFuncNeedingTiming">
<!--- 'log' is in my component's 'variables' scope --->
<!--- *Always* wrap debugging code with log.canDebug() --->
<cfif log.canDebug()>
<cfset local.sTimerHandle = startTimer() />
</cfif>

<cfset someOperationThatWillTakeSomeTime() />
<cfset anotherOperationThatWillTakeSomeTime() />

<cfif log.canDebug()>
<!--- Sending the handle back, will kill the timer and return the milliseconds --->
<cfset log.debug('myFuncNeedingTimer complete in #endTimer(local.sTimerHandle)# ms') />
</cfif>
</cffunction>


Fairly easy to implement, should be mighty fast.  In the case of a transient bean inheriting from your Base class, you could modify to add another variables (or override in your BaseBean/BaseEntity class) for whether purging should be performed or not.  (Or create an override function that does nothing.)

Seemed like an idea worth sharing!

- Will Belden
April 12, 2014


Tuesday, August 13, 2013

Coldfusion: Issue with application mappings and expandPath()

This is just a quickie regarding Coldfusion's per-application mappings and what happens when you try to use expandPath() with your mapping.  (Note:  This is under CF9, our company hasn't yet gone to CF10.)

Working in a test file of testSandbox/testFolder/test.cfm, I needed to access a CFC outside my webroot.  I added this to my testProjection/Application.cfc. (Because there's no way to add per-app mappings at runtime (outside of the Application.cfc) that I could find.)
   this.mappings['cfc'] = 'c:\Development\Sandbox\someOtherFolder';

In my testSandbox/testFolder/test.cfm file I had these lines:
  <cfset local.sPath = expandPath('cfc') />
  <cfdirectory action="list" directory="#local.sPath#" name="local.dir" />
  <cfdump var="#local.dir#" />
  <cfdump var="#local.sPath#" />

The query contained no records.  The local.sPath variable showed (an assumed) path of my working directory, with 'cfc' at the end.  I had no testSandbox/testProject/cfc folder!  But I had added a per-app mapping for it!  What gives?!?!

So I looked at our actual code, and noticed that all the mappings had a leading forward slash.  Okay, so I changed the mapping line to:
   this.mappings['/cfc'] = 'c:\Development\Sandbox\someOtherFolder';

...and ran my lines again.  The query was still empty, and the sPath output still showed 'testProject/cfc'!  Next, I edited the .cfm code to also add the leading slash:
  <cfset local.sPath = expandPath('/cfc') />
  <cfdirectory action="list" directory="#local.sPath#" name="local.dir" />
  <cfdump var="#local.dir#" />
  <cfdump var="#local.sPath#" />

NOW I get a list of the files in the actual cfc folder outside my root.   Out of curiosity, I went back and took out the leading slash in the Application.cfc, so back to:
   this.mappings['cfc'] = 'c:\Development\Sandbox\someOtherFolder';

and ran again.  The results were completely different.  This time it pointed to:
   testSandbox/cfc

That sort of makes sense, as it pointed to the [webroot]/cfc and I'm using a leading forward slash, except I kept asking "why isn't the mapping honored?".

Clearly, you have to create the mapping with a leading slash like:
  this.mappings['/cfc'] = ....

....and you have to access it with the leading slash, at least for directory- and file-based operations.  

Running a createObject with just the mapping name (the only way you can):
  <cfset local.marshaller = createObject('component', 'cfc.integrations.Gateway') />

seems to work just fine, whether the Application.cfc this.mappings key has the leading slash or not.  So createObject() seems to treat the value differently than does a file/directory operation.  Again, this is for Coldfusion 9, I haven't tested the behavior on CF10 or Railo yet.

- Will Belden
August 13, 2013

Tuesday, May 19, 2009

Better Javascript in Coldfusion

I gave a presentation today at work on improving your Javascript skills, as it relates to Coldfusion development. While there were a million things I would've like to cover, I only had an hour. Here are some highlights that might be worth passing on:
  • Avoid <cfinput> and <cfform>
    These tools, while helping to make your Coldfusion development faster, really cripple us as coders. I believe that every HTML developer (those who code in PHP, CF, etc.) needs to know Javascript. The js code generated by Coldfusion is very bulky and not necessarily optimized.

  • Avoid using Coldfusion variables in your Javascript code.
    Think it through and parameterize your JS rather than being lazy and including #variable# directly in the code.
    Good and Bad Javascript example

  • Move your Javascript to external files
    By placing your js in an outside file, linked to by your Coldfusion code, you allow the browsers to cache something that doesn't change too often. This results in increased bandwidth savings, better logical separation and enforcement of keeping CF out of JS.

    In addition, if you have access to a "resource service" that you can tell to include a particular js file (as opposed to using the <script> tag) you'll be able to implement a minify/pack/gzip solution as well as a combining technique at a later date. A service like this can prevent multiple script tags for the same file when the HTML is rendered.

  • Think cross-browser, at all times.
    Sure, maybe today your company says "We only support IE". But I can almost guarantee you that tomorrow it will be "We only support IE and Firefox." In one set of code I saw recently, the js would simply reference "myInput.value". Apparently this works in IE, but doesn't work as well in Firefox. If they had done a proper getElementById() or even
    document.myForm.myInput.value there wouldn't have been issues.

  • Get behind jQuery (or some Javascipt abstraction library)
    By using a tool like jQuery for DOM element selection, like $('#myInput'), you enable abstraction of how you get the object. These tools are also optimized differently for different browsers, allowing you to use a single style of object fetching, without writing a lot of "if IE" statements.

  • If you name an object, also give it an ID.

  • Remember, ID's are meant to be unique amongst all elements on a page.

  • If you need to "group" objects, just add a non-styled class element to the objects. Then you can use something like jQuery to get all the elements with that class.

  • Don't use versioning in your file names.
    If you have myCode.1.2.3.js and you reference that in your code, then you have to refactor all your pages that reference that file when you want to upgrade. Just copy that file to myCode.js, then you swap out the files when a newer version comes along with no code changes.

  • Comment, comment, comment!
    Can't stress this enough. Even if you're the only developer on the project and always will be, commenting is still valuable. I can't tell you how many times I've come back to some code, no matter what language I used, and had no immediate recognition of the code I had written or how it worked. Commenting is so important.

  • Try dynamic event binding
    If you have 10 phone fields with onblur="formatPhone(this);", why not add a class to those fields, like class="phone". Then with something like jQuery, you can create an document.ready event that will bind the formatPhone() custom function to all objects of input#phone that it can find. You could save a whole lot of bandwidth on a site that dishes out such a page frequently.

  • Remember, there's always more optimization to be done
    Most developers are receiving a paycheck from a company that has hired them to produce results. Because of this we have to balance speed with quality. Typically, however, a little forethought can go a long way. Rush, rush, rush is never the answer. Spend 3 hours now to do it right versus 1 hour to "bang it out" and you'll be spending that 1 hour now and 5 later trying to refactor it and correct it. (And that's just you....what about other developers on your team that may get saddled with having to fix your poorly thought out code?)
- Will Belden
May 19, 2009
Updated: August 22, 2009

Wednesday, June 18, 2008

Losing my mind with a form...

Yesterday I created a form. I actually had two on the page. One that did a search, and the results allowed for inline editing. After saving the values in the fields that accompanied the search results, I wanted the search to run again, showing the saved values.

Unfortunately, while my save operation worked just fine, the search wouldn't run again. I didn't understand. My form variables existed in the form scope, but they were always blank. I had added the search criteria to hidden variables within the
tag, but they just wouldn't process. I even threw in some onsubmit() javascript testing alerts, which also indicated that the hidden form values were blank. Looking at the source, prior to submit, I could CLEARLY see the values were there. See for yourself:

<form name="saveForm" action="catmappings.cfm" method="post">
  <input type="hidden" name="site" default="#site.siteid#" />
  <input type="hidden" name="action" default="saveEdits" />
  <input type="hidden" name="searchKey" default="#param.searchKey#" />
  <input type="hidden" name="searchGen" default="#param.searchGen#" />
....


It took me twenty minutes to figure out the problem. I had copied and edited these from commands. Instead of value="#whatever#", the all have default="#whatever#". So you get the fields in the form scope, but, well..no values.

Maybe this post will save someone 5-10 minutes of their life. Clearly, I'm never getting those 20 minutes back for mine!

- Will Belden
June 18, 2008

Tuesday, March 25, 2008

Eclipse and getting .htm and .html files to open in CFEclipse...

I've been working lately with a lot of HTML files that primary templates, read in by ColdFusion and Java for processing. I love CFEclipse, with it's great color coding making my files easier to read and scan.

However, with my current "company-provided" Eclipse setup, .htm* files opened in the regular text editor. I finally figured out how to change it, instead of right clicking on each file in the navigator and selecting "Open With...CFML Editor".

Select the Window menu, then choose Preferences. Under General, Editors select File Associations. Then, scroll down in the list to .htm and .html. Click on the first, ".htm". In the bottom section, called "Associated Editors", depending on your configuration, you might see multiple options. These, apparently, are the choices you have when you right click the specific file. But highlight "CFML Editor", then click the "Default" button to the right. Do this again for .html in the top list, and you'll be set!

- Will Belden
Tuesday, April 25, 2008

Thursday, March 20, 2008

ColdBox Framework, Filename Incorrect error I keep getting...

If you're using the [awesome] Coldbox framework from Luis Majano, you might have run into this error more than once, but can never remember why it happens, even though you've solved it forty million times already.

Application Execution Exception
Error Type: java.io.IOException : [N/A]
Error Messages: The filename, directory name, or volume label syntax is incorrect
ID: CFINCLUDE
Line: 107
Template: C:\[your root]\html\coldbox\system\plugins\renderer.cfc


Well, here's what it is, so you can quit banging your head. You've set the view in your handler, but you included the .cfm at the end, like thus:
<cfset Event.setView("tester/testDumper.cfm") />

Since I've already hit this error many times, and cannot seem to learn from my mistakes, I'm hoping like crazy that actually blogging about it might help me remember for next time!

- Will Belden
Thursday, March 20, 2008

Saturday, September 02, 2006

ColdFusion ColdSpring - Evaluate variables in ColdSpring.xml


As part of my new implementation of ModelGlue:Unity, I found that I have to place the values of different things in many different places. In this situation, that was the applications datasource name, user ID and password. I dislike having more than one or two places to have to place values, in the event they need to change. (A good security policy for databases is to change those passwords every so often.)

In my ColdSpring's XML config file, I had attempted to place the following:

<bean id="oDatabase" class="com.oDatabase" >
<constructor-arg name="dbDatasource">
<value>#APPLICATION.dbName#</value>
</constructor-arg>
<constructor-arg name="dbUser">
<value>#APPLICATION.dbUser#</value>
</constructor-arg>
<constructor-arg name="dbPass">
<value>#APPLICATION.dbPass#</value>
</constructor-arg>
</bean>

However, this only resulted in a query error along the lines of a datasource not being found with a name of "#APPLICATION.dbName#".

Perhaps my solution to my need is not the best way, since I modified ColdSpring files directly. Perhaps there is even another way, but a couple hours of searching did not reveal the answer to me. I thought "there has to be a way to tell CS to evaluate the XML value entry instead of just seeing it as a literal string."

I opened DefaultXMLBeanFactory.cfc in the /coldspring/beans/ directory and modified the "constructBean" function. There are two places you'll find this line, one in a regular bean function setup, I believe, and the other specifically for init() functions.

<cfinvokeargument name="#argDefs[arg].getArgumentName()#" value="#argDefs[arg].getValue()#"/>

I replaced that line with this block:

<cfset VARIABLES.csTempEval = argDefs[arg].getValue() />
<cfif FindNoCase("~~~", VARIABLES.csTempEval) GT 0>
<cfset VARIABLES.csTempEval = mid(VARIABLES.csTempEval, 4, 999999) />
<cfset VARIABLES.csTempEval = Evaluate(VARIABLES.csTempEval) />
</cfif>
<cfinvokeargument name="#argDefs[arg].getArgumentName()#" value="#VARIABLES.csTempEval#"/>

In my ColdSpring XML config file, I changed the section above to look like this:

<bean id="oDatabase" class="com.oDatabase" >
<constructor-arg name="dbDatasource">
<value>~~~#APPLICATION.dbName#</value>
</constructor-arg>
<constructor-arg name="dbUser">
<value>
~~~#APPLICATION.dbUser#</value>
</constructor-arg>
<constructor-arg name="dbPass">
<value>
~~~#APPLICATION.dbPass#</value>
</constructor-arg>

</bean>

Voila! Now my ColdSpring dynamically evaluates APPLICATION.dbName instead of trying to use it as a literal. It will only do this is the tag has the three tildes (~~~) at the front. Obviously, you can modify it to do it with any character combination you find more appealing. I would avoid anything too crazy, or anything you might actually want as a true value down the road. I considered having the changes look for anything beginning and ending with "#" characters but that would eliminate the ability for more complex combinations, if needed, such as "myTest_v#APPLICATION.version#" where it evaluates to "myTest_v01" or similar.

If anyone out there knows of a more ColdSpring acceptable way (that I was unable to find), please let me know. Of course, I made a backup of the original CFC in the event that someone brings it to my attention!

Will Belden,
September 9, 2006