• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 910
  • Last Modified:

ColdFusion, Javascript and <cfoutput>

How do you pass the values from a coldfuson query to an external javascript file that is used in a web page?

I tried using <cfoutput> with the #variable# where it was required in the javascript and it didn't work due to being unrecognised by javascript.

I don't want to change the file extension of the js file to cfm.

Thanks in anticipation.
0
Artic
Asked:
Artic
  • 4
  • 3
1 Solution
 
digicidalCommented:
You need to have a local script block that is wrapped in the <cfoutput> tags which will set the values for the things that you want.  It won't work otherwise... the problem is that the external javascript works like any other includes or resources (css, img, etc..) so all the <cfoutput> does in that case is check for values to be resolved in the path to the file... and not finding any just outputs the actual include call itself.

A few ways of doing this, but for me I've found it easiest to first define a function on your page (wrapped in cfoutput) which stores the values you wish to use, and then write the calls in the included .js file to hit that function.  Naturally you need to define your function higher on the page than the include for the .js file.

Since I'm not sure what exactly you're pulling or how much - you may need more than a simple array or static values... but since javascript is not my specialty - crafting a more complex data structure might take me a little time to research.  Everything I've done has been covered by the example provided.
<cfoutput>
<script language="javascript">
function getcfdatajs() {
var cfdataarray = new Array("#myquery.Name#","#myquery.Address#","#myquery.City#","#myquery.Zip#");
return cfdataarray;
}
</script>
</cfoutput>

<cfscript language="javascript" src="external.js">

Open in new window

0
 
ArticAuthor Commented:
When I call the function with the line of code below it only pulls out the first result of the query from the array.

document.write(getcfdatajs());

How do you loop through the values in the array and pass them to the .js file?  To get the individual fields from the query, would it be better to use a multidimensional array to the values?
0
 
digicidalCommented:
Yes - my example will only work with a single record.  I was not sure how much of the data you wished to work with.  You are correct in your assumption that you would need to create a multidimentional array to store all of the query data.

I've rarely needed to perform something like this, so I was merely showing you a proof of concept as an example.  One thing I would remind you - although you probably are well aware of this, it has caught me off guard a few times when switching back and forth from CFML to Javascript... remember that in Javascript arrays start with a zero element index not a one. ;)
0
NFR key for Veeam Agent for Linux

Veeam is happy to provide a free NFR license for one year.  It allows for the non‑production use and valid for five workstations and two servers. Veeam Agent for Linux is a simple backup tool for your Linux installations, both on‑premises and in the public cloud.

 
ArticAuthor Commented:
On the opening cfouput tag I forgot to put the name of the query: <cfoutput query="queryname">.  Now when I run document.write(getcfdatajs()); I get all of the values from the query write to the screen.  The document.write(getcfdatajs()); was embedded after the code for creating the array in the web page.

I've changed the array to a multidimensional one.  var cfdataarray = new Array(["#myquery.Name#","#myquery.Address#","#myquery.City#","#myquery.Zip#"]);

The array is passing to the external .js file but is only printing the first record from the query. I have tried using a for loop to loop through the array.

for(var i=0; i<=getcfdatajs().length; i++)
{
  // code here
}


0
 
digicidalCommented:
Can you directly access the data for more than the first record in the passed array?  For example can you print the value of cfdataarray[3][1]?  It seems to me that the way you have it written (which is partially due to my code example not being set up for multiple records - you will only get the first record (as I have it written) or the LAST one (as you have it now, if I understand how you did it).  Because you placed the query in the <cfoutput> it is looping over the whole output... but what that is doing, in a sense, is creating as many "function getcfdatajs()" blocks as there are records in the database, however since the name of the function doesn't change.. it will only have the value of the last record.

NOTE: In my example I'm going to do a translation in CFML so we are indexing on a value of the current row -1.  That's because the javascript array starts with [0] as opposed to your recordset which will start with a [1].  You could also use the [0] positions to hold unprinted values and then call them by their row number in javascript as well.  For example, you could store the column names in cfdataarray[0] and then store the RecordID in the cfdataarray[x][0] position.  Basically how you decide to implement will depend on what you really require.

Anyway, try something along these lines and see if you can print values from different rows - and validate that they are the correct data.  For example, the value of the second field of the fifth record in your query should be accessable as cfdataarray[4][1] (because the first column of the first record is in cfdataarray[0][0]) - that's why I mentioned placing 'garbage/extra data' in the zero positions - it can get confusing after awhile.  However, if you already have everything in the javascript designed to expect the first record in position [0] - then it doesn't really matter.
<cfoutput> 
<script language="javascript"> 
function getcfdatajs() { 
   var cfdataarray = new Array(#myquery.recordcount#);     
   <cfloop query="myquery">
      <cfset translatedrowvalue = myquery.CurrentRow - 1>
      cfdataarray[#translatedrowvalue#] = new Array(5);
      cfdataarray[#translatedrowvalue#][0] = "#myquery.columnone#";
      cfdataarray[#translatedrowvalue#][1] = "#myquery.columntwo#";
      cfdataarray[#translatedrowvalue#][2] = "#myquery.columnthree#";
      cfdataarray[#translatedrowvalue#][3] = "#myquery.columnfour#";
      cfdataarray[#translatedrowvalue#][4] = "#myquery.columnfive#"; 
   </cfloop>
   return cfdataarray;
} 
</script> 
</cfoutput> 

Open in new window

0
 
digicidalCommented:
PS - since we're setting each array location independently - you should be able to just 'view code' on the page and see a huge javascript funtion with all of your record data visible in it.  That's why I would recommend against doing things this way on a public site... as anyone with a web browser will be able to view your entire database by looking at the HTML source.  (Not to mention that if you have a very large database - even 1000 rows would do it - your page will take forever to load).

In general, it's always a best practice to use your DB for data-only functions, CFML for anything dynamic, and JS for client interactions (validation, decoration, dhtml).  I would recommend thinking about this now because it may become a huge headache for you down the road.  If you think of server applications as a singluar architecture... use a MVC approach - anything that's part of your MODEL should be done directly in SQL (or whatever you use), anything in the CONTROLLER layer should be done in CFML, and javascript should be used only in the VIEW layer - and should be allowed to 'collapse gracefully' in case the user has javascript disabled in their browser.

Just suggestions, as stated before - I don't know what the parameters are for your project or it's deployment.  If this is for an intranet on a secured LAN location with information that is not security sensitive, and a small recordset - then it may do exactly what you want.
0
 
ArticAuthor Commented:
Thanks
0

Featured Post

Upgrade your Question Security!

Add Premium security features to your question to ensure its privacy or anonymity. Learn more about your ability to control Question Security today.

  • 4
  • 3
Tackle projects and never again get stuck behind a technical roadblock.
Join Now