How to use the cfwddx tag in ColdFusion
I would like to send a ColdFusion framework to Javascript. While looking at how I can do this, I found the cfwddx tag. It looks like I got there from there. I created a test program
<head>
<script type = "text/javascript" src = "frag3.js"> </script>
</head>
<body>
<cfset str = StructNew()>
<cfset str['betty'] = 1>
<cfset str['nancy'] = 2>
<cfdump var = "#str#">
<cfwddx action="CFML2JS"
input="#str#"
toplevelvariable="xyz"
output = "genstr">
<cfoutput>
<script type = "text/Javascript">
test('betty')
function test (arg) {
alert("got to test");
#genstr#
alert ("xyz " + xyz[arg]);
}
nothing()
</script>
</cfoutput>
cfdump gives the correct answer
When I look at the # genstr # output, it contains the correct javascript code:
xyz = new Object(); xyz["betty"] = "1"; xyz["nancy"] = "2";
When I run the inline code as shown above, the warning gives the correct answer. And when I call the "nothing ()" function, which is on frag3.js, the alert shows it was running, so the src operator works.
However, when I move the function test (arg) itself to frag3.js, it doesn't run.
Can anyone tell me how to get a "test" to work as an external function and not just embedded in my ColdFusion code? By the way, I haven't studied jquery, so the jquery answers won't help. I need basic javascript.
source to share
Rather than writing variable bits (call them "initialization" or "configuration") to the source code of your site (or worse, the source code of your static JS files), I recommend the following.
Create a remote invocation component that returns a structure with all configuration. You can now call this method from the ColdFusion code on the server (where you get the structure) and via Ajax from the JavaScript code on the client (where you get the JSON).
/** Config.cfc (or call it something similar)
*
*/
component {
remote struct function getConfig() returnformat="JSON" {
var str = StructNew();
str['betty'] = 1;
str['nancy'] = 2;
return str;
}
}
your main.cfm (for simplicity of example, I include jQuery to handle the Ajax request):
<html>
<head>
<script type="text/javascript" src="frag3.js"></script>
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
</head>
<body>
<h1>Config, as seen by the server</h1>
<cfinvoke component="Config" method="getConfig" returnvariable="cfg">
<cfdump var="#cfg#">
<h1>Config, as seen by the client</h1>
<pre id="cfgDump"></pre>
<script type="text/javascript">
$(function () {
$.get("Config.cfc?method=getConfig").done(function (cfg) {
// cfg already is a regular JS object at this point
// convert to JSON again for display purposes
$("#cfgDump").text( JSON.serialize(cfg, null, 2) );
});
});
</script>
</body>
</html>
Clean and simple.
source to share
The most effective solution to your problem is probably to include dynamic content within the document itself.
When you copy a function test(arg)
to a Javascript file I assume you are copying too #genstr#
? So it looks exactly the same in the js file as you do above?
This works as intended..js does not handle cold fusion, and if you look at the developer console you will probably get a syntax error.
You can either keep it inline in your document or change the js file extension to .cfm.
At this point, your file js_main.cfm
(example) will be processed like any other file requested by the browser, and it will fall from headers and footers if your request processing does so, so it will throw more errors. You need to protect these files from this. You can do it with some cfifs in your application file like
<!--- This checks the path to make sure it doesn't contain livemedia. --->
<cfif not listfind(cgi.script_name,"livemedia","/")>
... do includes
</cfif>
Or you can do as I probably do and lock these files in a folder just to serve up JS files, CSS cfm with your own application.cfc / cfm to override the global site file if I run into a situation where I felt that dynamically geerated js / css was really the best option.
Then you can do as you show in your OP and client side relay variables if you really need to. Alternatively, you can call the two "applications" the same, and while this makes exchanging data very easy, I should still advise you to carefully monitor what you report and you open and ensure that the sub-application is properly protected.
And yes, as others have suggested, #SerializeJSON()#
this is a modern approach to copying a server variable / object on the client side.
For example..
<cfset CFStruct = {big = "little", red = "blue", subArray = ["A","B","C","D"]} />
<script>
<cfoutput>JSObj = #SerializeJSON(CFStruct)#;</cfoutput>
</script>
<!--- While I use shorthand to form the struct and subArray, that only for speed,
structs, arrays, queries, etc formed in any fashion work just fine. --->
Creates JSObj
with elements big, red, subArray
(which have children A, B, C, D
).
However, no matter which method you choose ( wddx
or SerializeJSON()
) they will not work in the .js file.
I should mention that the other option is to allow the server to parse .js files, but that would be much more painful than worth it. Many cases where you are using a simple js file will get in the way.
Please note that your files, called client-side tags like <script>
and <link>
, are completely separate requests . They will not use areas url, form, request, variables
. However, they can share scopes cookies
and client
and session
if both applications have the same name.
Finally, the great thing about external content called via html tags, regardless of the extension, is that it is usually cached by default. This is great for bandwidth and even fast page loading, until you have a scenario where you want to consistently load an uncached copy.
For this reason, when you feel like you have to dynamically generate what you want to stick to in an external file, you have several methods.
- You can set no-cache in the header (CF or Htaccess can do this).
- You can provide a random number in the request line of the script call.
<script src="/livemedia/js_main.cfm?randomizer=#randrange(1,1000000)#"></script>
- Maybe the file doesn't need to be updated every time for every user, maybe it's just that every user should see a different copy. You are appending the query string anyway, because multiple users can log in from the same computer. This, however, would be user specific.
<script src="/livemedia/js_main.cfm?#session.username#"></script>
- Redefine how your page compiles and stores data to be embedded in a page within a page.
If you attach something to the query string of a javascript file, you should move the static content of the file into a separate file that doesn't need to be regenerated every time. There is no need to reload 15 javascript functions with every page request, because 1 contains dynamic content.
source to share
I'm not a big CF developer, but the easiest way I know to output structures and arrays for javascript consumption is JSON using SerializeJson()
For example, like a JS variable on a CF page:
<script>
var myVar = <cfoutput>#SerializeJson(str)#</cfoutput>;
</script>
Although JSON is a string ... when it prints in a script tag, javascript will read it as an array or object without having to parse it in the client.
I am using the same output for ajax delivery as well
source to share