OpenBD Wiki

From OpenBD
Revision as of 01:54, 1 February 2010 by Alan (Talk | contribs)
Jump to: navigation, search

CFJS

The CFJS tag permits the use of Javascript 1.7 to be run at the server side, instead of at the client side within a browser. This allows you to write dynamic pages using Javascript as your primary language. By running on top of OpenBD, Javascript can plunder the depths and richness of CFML to easily help building server side pages much easier.

this is a very early release and is subject to change as we iron out how this should be integrated


Contents

Features

The following features exist:

  • Write pure Javascript syntax
  • Load external Javascript files
  • Declared Top-Level variables are made available to the CFML page
    • Basic data types (ints, strings, dates, booleans)
    • Structures and Array (included heavily nested)
    • Declared CFC's
  • Create and call external CFC's from within Javascript
  • Easily declare and use all JDK Java classes (see section later in this page)

Important Reminders

  • This is not CFSCRIPT; Use pure Javascript 1.7 syntax only http://en.wikipedia.org/wiki/JavaScript_syntax
  • Javascript Arrays are ZERO (0) based not 1 based as in CFML
  • Javascript is typeless like CFML
  • This is server-side Javascript, so no "window" or "document" scopes are available. That said you can mimic these scopes by declaring them in an environment file which would allow you to use frameworks such as prototype and jquery

Getting Started

Use of the CFJS tag can be anywhere, and once marked on the page, you simply start writing Javascript code.

<cfjs>
/* Place javascript code here */
myFunc = function(){
  return 2+3;
};

x = myFunc();

y = {
  "months" : [
    'jan', 'feb', 'mar'
  ]
};

$cf.tocfml( "x" );
$cf.tocfml( "y" );
</cfjs>

<cfoutput>x = #x#</cfoutput>
<cfdump var="#y#">

As can be seen by the above, simple, example, you can declare Javascript functions and variables, with the variables available to the outside CFML page. But you can only do so much with that. You need to be able to interact with the request and the underlying CFML engine.

To facilitate that the following top-level objects are available to the Javascript:

  • $cf
    • $cf.load( pathtojsfile )
    • $cf.print( line )
    • $cf.get( fullpathtovar )
    • $cf.tocfml( "name of javascript variable" )
  • CFML Scopes:
    • form
    • url
    • cgi
    • application
    • client
    • session

$cf

This $cf variable is a very powerful handle into the CFML world. This allows you to not only read variables and load external Javascript libraries/files, but more importantly allows you to execute all the core CFML functions.

<cfset ss = StructNew()>
<cfset ss.age = 32>

<cfset aa = ArrayNew(1)>
<cfset aa[1] = "a">
<cfset aa[2] = "b">
<cfset aa[3] = "c">
<cfset aa[4] = ss>

<cfjs>
x = $cf.random();

x1 = $cf.get("cgi.script_name");
x2 = $cf.get("ss");
x3 = $cf.get("aa");

$cf.writeoutput( "<br/>1: " + x1 );
$cf.writeoutput( "<br/>2: " + cgi.script_name );
$cf.writeoutput( "<br/>3: " + form.id );
$cf.writeoutput( "<br/>4: " + x2.age );
$cf.writeoutput( "<br/>5: " + x3[3].age );

// Calling a CFC
var c = $cf.CreateObject("component","mycfc");
$cf.print( c.testMethod2(1972) );

// Setting variables that will be available to CFML
x2.age = 19;
form.id = 32;
form.name = "myname";
</cfjs>

Looping around Query objects

You can easily get at Query objects

<cfquery name="qry" datasource="wikidb">select * from obdw_history limit 20</cfquery>

<cfjs>
print = function( p ){
  $cf.print( "<li>" + p + "</li>" );
};

/* Use one of the following to get the query */
var q = $cf.QueryRun( wikidb, "select * from obdw_history limit 20" );

// Or access it from the outside CFML
//var q = $cf.get("qry");

print( q.recordcount );
print( q['columnlist'] );

var totalRecords = q.recordcount;
for ( var x=0; x < totalRecords; x++ ){
  print( "— " + q.hist_id[x] );
}

/* You can also set cells in the query by directly accessing them */
q.hist_id[1] = 9999;
</cfjs>

$cf.load()

You can split up your Javascript into separate files and load them as and when you require them. This has a major performance gain, where by you only need bring in the specific libraries on-demand.

Once a Javascript block/file has been compiled, it is cached for later use in other requests/files.

For example, you could utilise the popular Javascript MD5 library http://pajhome.org.uk/crypt/md5 with the following code, which would display the result out in the browser stream using the standard CFML writeOutput function.

<cfjs>
$cf.load("md5.js");
$cf.writeoutput( "MD5:" + hex_md5("This is a test string") );
</cfjs>

The URL to the javascript is relative to the current page context.

The call to $cf.load() does not have to appear at the start, and can appear anywhere in the CFJS block. Any top level data declared in the external files will also be available from there on in, as part of that block.

$cf.print()

This is a shortcut to output display information straight to the browser

$cf.get( exp )

This method lets you reach into the variables of the CFML stack and return them to Javascript. Fully qualified variables here work best.

Using Java from <CFJS>

You are not limited to just the functions within CFML, you can also reach into the full Java language. Consider the following example to pull back the home page of Google

<cfjs>
var con = new java.net.URL("http://www.google.com/").openConnection();
var stream = new java.io.InputStreamReader(con.getInputStream());
var buffer = new java.io.BufferedReader(stream);
var line;

var responseText = "";
while ( (line = buffer.readLine()) != null)
  responseText += line;

stream.close();

$cf.print( responseText );
</cfjs>


Known Limitations

Currently, this plugin is in the very early stages of development, and as such, many of the features haven't been rounded out yet. The following limitations exist:

  • CFC's are not yet callable from within javascript
  • Javascript functions are not available for calling by the CFML page
  • Separate <CFJS> blocks on the same page request do not share the same script context (more ethical question than a technical one)
  • This is server-side Javascript; therefore window / document are not available
    • That is a separate discussion at how we can create a server-side DOM model

To Do

  • Improve the performance of the loading of the libraries
  • Make the libraries only load once

Personal tools