Coldfusion 10, ISO 8601 dates, and bugs

JavaScript generates an ISO 8601 date like this:

new Date();
// returns Mon Oct 08 2018 11:17:34 GMT+1100 (Australian Eastern Daylight Time)

new Date().toISOString();
// returns "2018-10-08T00:17:34.004Z"

Note the inclusion of milliseconds and the conversion to the UTC time.

If you want to use that date string in parseDateTime() in ColdFusion 10 (and maybe later versions but not tested by me), you need to specify the correct mask. The CF docs seem to be unclear regarding the milliseconds. This is what seems to work:

// ISO 8601 date from JS in UTC

dtStr = "2018-10-08T00:17:34.004Z";

res = parseDateTime(dtStr,"yyyy-MM-dd'T'HH:mm:ss.SSSX");

dateTimeFormat(res, "yyyy-mm-dd hh:nn:ss.LLL z");
// returns: 2018-10-08 11:17:34.004 EST

res = parseDateTime(dtStr,"yyyy-MM-dd'T'HH:mm:ss.SSS");
res = parseDateTime(dtStr,"yyyy-MM-dd'T'HH:mm:ss.SS");
res = parseDateTime(dtStr,"yyyy-MM-dd'T'HH:mm:ss.S");

// For all the above,
dateTimeFormat(res, "yyyy-mm-dd hh:nn:ss.LLL z");
// returns: 2018-10-08 12:17:34.000 EST <== note 12:17, not 11:17 as above

The CF date object created by parseDateTime() uses the time zone of the CF server it is running on. ie converts UTC to local (server) time as long as you specify the ‘X’ in the mask.

1. the 'T' in the mask – the single quotes are required or an error will be thrown.

2. the mask for the ms when passed to parseDateTime is ‘S’ NOT ‘L’ (as it is for timeFormat() and dateTimeFormat

3. the final X is required to maintain UTC adjustments and you must also have the same number of digits in the ms part.
ie: if the date string ms is three digits (eg “.004Z”) the mask must also be three digits (ie “.SSSX”).
“.SSX” or “.SX” etc will throw errors if the mask is three digits.

4. Time Zone bug: Today (Oct 8th) is in daylight saving time. If I dump out getTimeZoneInfo(), the utcHourOffset is correct at -11. But notice that the time zone displayed is EST. It should be AEDT (Australian Eastern Daylight Time). If I use a test date before DST (eg Oct 1st) it still says EST when it should say AEST (Australian Eastern Standard Time).

5. Daylight Saving Time: the test date here (Oct 8th) converts accounting for DST as long as I specify the “X” in the mask. If I use a test date NOT in DST (eg Oct 1st) it correctly converts the time to 2018-10-01 10:17:34.004 EST ie 10am, not 11am.

Note I am using the dateTimeFormat() function, not timeFormat(). Despite what the docs say, the ‘z’ mask does not work as expected.

dateTimeFormat(res, "yyyy-mm-dd hh:nn:ss.LLL z");
// returns: 2018-10-08 11:17:34.000 EST 
// but 
timeFormat(res,"hh:nn:ss.LLL z");
// returns 2018-10-08 11:17:34.004 z  <== ie literal z

Using quotes around ‘z’ makes no difference.

See also:


Coldfusion cfquery: running mySql user-defined functions

CF10, mySql 5

I was creating a very complex sql query for my app with lots of conditional code and realised it would be simpler to have some mySql functions to abstract some of the complexity. This was new territory for me.

One immediate gotcha was with sqlYog: If you are testing your function in sqlYog and get a 1305 error: FUNCTION not found, make sure you are clicking the button to Execute ALL queries, not just your one test SELECT query. Doh!

Related to this, if you combine all the statements below into a single cfquery statement your CF server must be configured to run multiple queries. Since that is not a great idea from a security point of view the solution is to run each one separately as shown below.

This is what I eventually found to work (a highly simplified example to demonstrate the syntax):

<cfquery datasource="#request.dsn#" >



Define the function:

<cfquery datasource="#request.dsn#">
    CREATE FUNCTION my_func(str1 VARCHAR(30), str2 VARCHAR(30))
       DECLARE res VARCHAR(100);
       SET res = CONCAT(str1, ' ', str2);
       RETURN res;

Test just the function:

<cfquery datasource="#request.dsn#" NAME="recordset1">

SELECT my_func('abc1','def2') as myString;

<cfdump var="#recordset1#">
<!--- myString = "abc1 def2" --->

Use in an SQL SELECT:

<cfquery datasource="#request.dsn#" NAME="recordset2">

my_func(members.firstname, members.lastname) as myFullName 
FROM members;

<cfdump var="#recordset2#">
<!--- Outputs myFullName like "Murray Hopkins"  --->

Same thing using CFSCRIPT:

	sql = "DROP FUNCTION IF EXISTS my_func;";
	qry = new Query( sql = sql, dsn=request.dsn );	
	sql = "CREATE FUNCTION my_func(str1 VARCHAR(30), str2 VARCHAR(30)) RETURNS VARCHAR(100) BEGIN DECLARE res VARCHAR(100); SET res = CONCAT(str1, ' ', str2); RETURN res; END";
	qry = new Query( sql = sql, dsn=request.dsn );	
	sql = "SELECT my_func('abc','def') as myString;";
	qry = new Query( sql = sql, dsn=request.dsn );	
	qryObj = qry.execute();		

	sql = "SELECT members.userid, my_func(members.firstname, members.lastname) as myFullName FROM members;";
	qry = new Query( sql = sql, dsn=request.dsn );
	qryObj = qry.execute();		


I hope this saves someone some time.

Go well,

Getting GluJS to play with Sencha Cmd

GluJS is an MVVM framework and optionally a Specification-Model-View-ViewModel (SMVVM) framework (BDD driven by Jasmine) that works with ExtJS (3 and 4). This post is not about GlusJS itself, rather it  is about a solution to a problem that there didn’t seem to be a solution to on the forum.

This guide gives a detailed overview of GluJS and there is also this video.

For this blog post and discussion I am using ExtJS4.2, Sencha Cmd 5, GluJS 1.2 and Jasmine 2.3.4 (for the BDD specs that are an integral part of GluJS).

First thing to say is that I am new to GluJS and have found a number of hurdles getting it going. Some of the info on the main GitHub repo is out of date. I was given a lot of help by Ryan Smith and I have forked his fork and am adding to that. On the plus side, once the obstacles have been worked through or fixed it is an amazing framework and I look forward to building a useful piece of software with it. This post is about one of those hurdles – a very important one for many of us. That is, how to be able to use GluJS and then build with Sencha Cmd. GluJS can be used in two ways:

  1. what I will call “pure” mode, where GluJS takes over the whole app starting at the ViewPort layer
  2. what I will call “mixed” mode, where you can include GluJS “modules” within an existing normal ExtJS MVC app via xtype : 'glupanel'. In other words, to “embed” GluJS into ExtJS where you want to do that (eg as a migration path to convert to a full GluJS app)

One of the goals here is to is normalise those two modes into a single architecture where the only difference is the relative amounts of MVVM and MVC. Obviously they both actually use ExtJS – it is just the architecture that varies. I explain that below. Now, I have a large existing project that needs the mixed mode approach and I also wanted to write a new “Admin Control Panel” type app in pure mode. In both cases I needed to build for production using Sencha Cmd.

Ok, enough background. This is what I did. Taking pure mode first – an app built from scratch using the GluJS approach. The working example for this blog post is in the examples folder of the repo (see AdminControlPanel folder) and the rest of what I am going to say will be a lot easier to understand if you reference that example. I will summarise the solution first before going into more detail (there are some gotchas to take care of). The post by Sharon Kong was close (thanks Sharon!). What you need to do is to wrap the GluJS functions within ExtJS classes like this:

 * Root viewmodel for the App
Ext.define('App.gluwrap.viewmodels.vmMain', {
    constructor: function() { 

        glu.defModel('App.glu.Main', {

            vmVPMainMenu: {
                mtype: 'VPMainMenu'

            vmVPCentreComponent: {
                mtype: 'VPCentreComponent'



Notice that the glu.defModel() is contained within a constructor. That was the missing piece of the puzzle (and yes, there is a little more to it than that). Each ViewModel, View, Model, Locale, etc has it’s own file as you would for ExtJS MVC. See the demo. You then “require” the files as you would for any other ExtJS class in your Application.js file:

Ext.define('App.Application', {
    name: 'App',
    extend: '',
    requires: [
      // These need to be required so they exist for GluJS
      // to modify on initialisation

      // ExtJS wrapper files containing GluJS components

      // GluJS Library files
      , 'Glu.glu-extjs-4', 'Glu.glu'

      // Your GluJS app files
      , 'App.gluwrap.locale.locale_en'

      , 'App.gluwrap.models.mUsers'
      , 'App.gluwrap.models.mUsersActivity'

      , 'App.gluwrap.viewmodels.vmMain'

      // etc
    // etc

Note that the Glu Library files are also wrapped in an ExtJS constructor and required here. See the demo code.

Note: this is the high level overview. I will suggest some reorganisation of this in the detail below – I am just giving you the summary.

(A word about my naming conventions: I have found it beneficial to prefix the ExtJS MVC file names with ‘v’ for a view, ‘m’ for a model, ‘c’ for a controller, etc. That way, when I have the files open in my editor I know which file is the view and which is the controller and if there are lots of files open and the tabs are abbreviated the letter is first so I can still see it. I have continued that when using glujs (vm prefix) so I can tell my viewModel from my view in the editor. Additionally, and nothing to do with this demo, I name my internal variables with the same convention. So instead of var panel = btn.up('window'); I use var vStatusWin = btn.up('vStatusWin') since ‘vStatusWin’ is also the alias (and the filename). That way, everytime I see vStatusWin in my code I know exactly what it is. Also in event handlers eg onActivateOpsManualPanel: function(vOpsManualPanel){}  )

Ok, back to the topic. You no longer need to include your GluJS files in script tags in index.html. By wrapping the Glu library and your Glu modules within ExtJS wrappers, Ext.Loader is happy to dynamically load the files just like regular ExtJS class files.

The next step is to use Ext.create() on each file
eg Ext.create('App.gluwrap.viewmodels.vmMain')
What that does is to execute the constructor that wraps around the Glu function which in turn loads the Main viewModel App.glu.Main into the App.glu namespace. From that point on Glu is happy and you can also run your Jasmine specs (see below for how).

So that is the summary. Now to deal with the detail and the issues this raises!

1. Create your new app structure using Sencha generate as normal and test that it works (default ViewPort). In order to use my demo code easily I suggest you use the namespace of App ie Sencha generate app App {path to your new app folder}

2. Download the demo files and merge them into your app folder. I have only included the relevant changed folders and files in the demo. Now you can follow along.

3. To keep it simple we will keep the GluJS and Jasmine libraries within this new app. Of course, you can put these folders anywhere in your web root if you wish. After merging the example folders you will see a BDDlib folder in the root of your new app’s workspace that contains Glu and Jasmine.

4. Edit the app.classpath property in .sencha/app/sencha.cfg to point to the location of the BDDlib folder. ie add ,${app.dir}/BDDlib to the classpath.

5. A Glu namespace and path has also been added to the Ext.Loader.setConfig() in your app.js file.

4. There is a new folder at app/gluwrap. This is where you put your Glu viewmodels and models etc as described in the summary above.

5. Have a look at the BDDlib/glu files. Notice that they are the GluJS library files wrapped in an ExtJS class and constructor. This is the same process as for your app glujs files, just with a separate namespace. The file glu-test-custommatchers.js is not wrapped since it is optional and only used in the specRunner.html file.

I wanted a consistent way to implement GluJS in both pure and mixed mode so I did the following:

1. See the files app/Application.js, app/applicationGlu.js and app.js. I wanted to keep the GluJS bits separate so they all live in applicationGlu.js. The only change to your Application.js from the Sencha generate is to change the extend:
extend: 'App.applicationGlu',
so that it includes applicationGlu.js

2. Look at app.js. Here we add a launch() function that calls this.callParent() which refers to launch() in applicationGlu.js. And, of course, the call to glu.viewport() to kick off the app.

3. Now turn to applicationGlu.js. The requires array lists all the ExtJS “native” files we need plus the ExtJS “wrapper” files containing the GluJS objects. The launch() function creates the Glu Library files then calls this.createAppGluClasses('gluwrap'); which iterates the App.gluwrap namespace (already populated by Ext.Loader via the requires array) and runs Ext.create() for each class it finds there. That gets your Glu app files into the App.glu namespace as glu objects. Finally we create some mock data via the createMockBackend() function before returning to app.js to launch the viewport.

That’s basically it for the app itself. At this point you can run index.html in your browser and you should see a working app (as simple as it currently is!). I have tested it in Chrome, FF and IE, just to be sure. All good. Activity list tab has no data – it isn’t broken, I just haven’t done that yet.

If you run Sencha app build testing (or production) it should build ok. There was a gotcha here that you should be aware of. The glu-extjs-4.js code choked Sencha Cmd because Cmd added a random semi colon to the minified glu code when it packaged it. I added a do-nothing variable to the src/providers/sencha/binder_adapter.js file which fixed that misunderstanding. That fix is in the repo and is included in the build you are using.


1. See SpecRunner.html. That should be self explanatory.

2. The difference is that the specs are in appSpec.js. Open that up. You will see that it is a variant of app.js. Some differences:

  1. We extend ‘App.applicationGlu’
  2. autoCreateViewport = false so the UI doesnt start.
  3. In launch() the this.callParent() initialises the glujs in applicationGlu.js
  4. Then you include the specs directly.

Try SpecRunner.html in your browser. All should be green.

Mixed mode MVVM and MVC

I haven’t provided a complete demo of that but I have included some files in /sampleMixedMode. I used the same architecture as above so I have consistency across the projects. I am assuming you have an existing app that was generated by Sencha Cmd. We will add a simple glupanel called ‘PanelA’ in an ExtJS window.

1. Copy the BDDlib folder from the example above to an appropriate place. I have the BDDlib folder in my web root so I can share it across multiple projects.

2. Edit the app.classpath property in .sencha/app/sencha.cfg to point to the location of the BDDlib folder. eg add ,${app.dir}/../../BDDlib or similar to the classpath. Adjust your path according to where the BDDlib folder is.

3. Add the Glu namespace and path to the Ext.Loader.setConfig() in your app.js file.

4. Save a copy of the applicationGlu.js file from /sampleMixedMode/app next to your Application.js file. If you are not using namespace ‘App’ amend the root namespace in the requires array and the createAppGluClasses() function.

5. Open your existing Application.js file and:

  1. change the extend to: extend: 'App.applicationGlu',
  2. leave all your existing entries in the requires array

6. Copy the folder gluwrap from /sampleMixedMode/app to /app (ie /app/gluwrap ). This contains our sample PanelA glu files wrapped in ExtJS classes.

7. Finally, copy the file vTestingWin.js from  /sampleMixedMode/app/view to your ExtJS app/view folder (where all your ExtJS view are). Adjust the Ext.define classname to suit your app structure. Notice the standard this.items[] array contains an xtype of ‘glupanel’ with an mtype of ‘App.glu.PanelA’ which loads that viewmodel and renders the glu view to the window.

8. Wire up the test window to a button handler in your app as you normally would for any other ExtJS window (because that is exactly what it is).

That’s it. Test your app and when you click the button you should see the glu view render the html. Test build using Sencha build testing (or production). All should still work.


Again, basically the same as the Admin Control Panel example above. Remember that we are only testing the GluJS components in your app, not the whole app. One of the reasons I started using GluJS was that I needed to start unit testing my ExtJS app and hadn’t done that before. My search for how to do that lead me to GluJS and since I had already decided that I liked the BDD “red to green” approach to spec driven development this was very attractive. I am thinking that it might be possible to build Jasmine tests for the non-GluJS objects in appSpec.js too but I am yet to look at that.

1. Copy the SpecRunner.hmtl file from /sampleMixedMode and adjust the paths in the script tags to your BDDlib folder

2. Copy the appSpec.js file from /sampleMixedMode and adjust the loader paths and the namespace in the spec to suit your app.

Test SpecRunner.html in your browser.

Conclusion So, I am looking forward to using GluJS more now that I have worked out how to integrate it into my normal workflow that relies upon Sencha Cmd. As an aside, the existing ExtJS MVC app that now has my test glupanel in it is packaged for desktop using nwjs. That packaging still worked without a hitch. I thought it would but one can never tell. 😉

Signing the OSX version of your NWJS (node-webkit) app for GateKeeper (for Mac noobs like me!)

NOTE: These instructions are for v12 of nw.js. Current instructions are here: Signing-your-app-but-NOT-for-Mac-Apple-Store-(MAS)

These are also useful:


The problem: I am new to Mac. I want my nwjs (node-webkit) app to be able to be downloaded from my website as a DMG file so users can install it. I am not intending to put this app in the Apple Store. I am using Yosemite.

Rant paragraph: The first thing you need to know is that Apple run a kind of racket in this case. In order to do this simple task you need to pay them AU $149 (per annum) just to get a Developer ID so you can sign your app so users can install it without seeing the “unidentified developer” message! The purported reason is that it increases security on the end user’s mac. Well, all the user needs to do is to Control+click the app then click Open. So much for the security! To charge $149 for that is a racket IMJ. Anyway, rant aside…

Gatekeeper info is here if you dont know about it.

The overall steps are:

  1. Get a Developer ID (and certificate and install it on your development Mac).
  2. Use that certificate to sign your app
  3. Package the signed app into a DMG file for distribution

This post also has some useful background info, as does this post. – especially the comment about making sure you have downloaded XCode (from Apple Developer area)

However, this post  had the most helpful checklist for doing steps 1 and 2 above. Thanks Jean-Baptiste Escoyez!
Since it was written a couple of things have changed which is what prompted me to write this blog post.

  • Part A:
  • Keychain is an app in Applications/Utilities
  • If you are taking responsibility for the whole process, ignore the step “Send the newly created file to your agent”
  • Part B:
  • “Upload the CSR file sent by admin (or dev)” means navigate to where you saved the certificate you created in Part A
  • Ignore the “Send it to the requetser” step. You are the requester.
  • Part C:
  • The “User ID” mentioned is the Developer ID which is a long hash. I couldnt find where the ID was mentioned within the Keychain item (probably missed the obvious) but you can get the ID by opening a Terminal window on your Mac and entering security find-identity in a Terminal session. If all is well you should see the Developer ID displayed.
  • Part D:
  • The Terminal commands neeed to change slightly because node-webkit is now called nwjs (since v0.12). If you are using that version or later, change the …./Frameworks/node-webkit references to …./Frameworks/nwjs
  • Of course you can put all that in a “command” script file so you dont need to keep typing it.
  • Part E:
  • I added those commands to my script file

Gotchas found:

  • You need to have internet access in order to run the codesign command. It seems it accesses a Timestamp server when it runs. My internet access had gone down and I got a codesign message about not finding a Timestamp.
  • Dont leave random files in the package or the code signing might fail with a “code object is not siged at all” message. I had made a copy of the info.plist file as info.plistCopy while I was trying to work all this out and codesign didnt like it!

To package the app in a DMG file I am using DropDMG. It seems you can make DMGs manually, and there might be other solutions, but I found this worked really well. At $24 I found the time saving worth it.

There are a few issues around changing the nwjs icon to your custom icon and getting DropDMG to use it in the installer which I will write about in another post soon. Ask if you need it.

Creating a command script for OSX (for Mac noobs like me)

In Windows you have batch files.

In OSX you can create “command” files. Open a text editor eg Sublime Text. (I noticed that TextEdit wouldnt allow me to save the file with a .command extention)

Enter your terminal (command line) commands into your file and save it with a .command extention.

To allow OSX to run that file via a double click you need to change the permissions. Open a Terminal window and enter

sudo chmod 755 your_command_file_path_and_name

You will be asked for your OSX password. Note that as you type it does NOT give any feedback about the key presses so just enter the password anyway.

You should be able to then navigate to your command file in the Finder and double click it to execute the script.

Packaging an ExtJS4 application using Node-Webkit part 3

This is a continuation of Part 1 and Part 2

How to install Node modules in your app

At this point you might want to install a node module and extend the demo. For example, you might want to make use of the neDB module. This is a way to persist data locally. There are a number of modules that do that. This one has no other dependencies so is a good candidate for our demo.

To install the module, open a command line shell in the root of your development app. The process below will install that module into the node_modules folder. I assume you have set a PATH to your NodeJs install folder so npm can be found.

1. From your command prompt:

npm install nedb --save

2. Open resources/js/NWK-requires.js and add

NWK.Datastore = require('nedb');

Add some code to a new button and handler in Main.js to add and find some docs then test. eg:

    xtype: 'button',
    text: 'neDb',
    handler: function(btn, e) {
        NWK.mydb = new NWK.Datastore({
            filename: 'mydb',
            autoload: true

        var docs = [{
            mykey: '2f4vn9l1NGW',
            data: 'blah blah'
        }, {
            mykey: '2f4vn9l1rAB',
            data: 'Boo hoo'

        NWK.mydb.insert(docs, function(err, newdoc) {
            console.log('INSERT callback')

            mykey: '2f4vn9l1rAB'
        }, function(err, docs) {

Packaging an ExtJS4 application using Node-Webkit part 2

In Part 1 of this tutorial we generated an ExtJS4 app and got it running in the node-webkit context. Now we want to build, package and deploy our demo app.


1. Build using sencha cmd as usual. eg From your command prompt:

sencha app build production

2. You also need to copy some files to the production folder that sencha cmd doesnt know about. I have done this for you in the demo files but if you have changed anything you will need to do this yourself. Copy these to the app root of the production build – the same folder as index.html
node-modules folder
mydocs folder (our sample files to launch via your app)

You might want to edit the package.json file to set the “toolbar” property to false as an example of how you can have your production deployed version configured differently than your development version. You could also have different window constraints etc. And, of course, in your production app you would probably turn off the debugging window! ie in package.json set toolbar:false and remove the code from Applications.js.

3. Test the production version by double clicking the nw.bat file in the production build app root. (Again, adjust the path in the batch file to suit your NWK install).


There are a number of ways to package your app in node-webkit for Windows, OSX and Linux. I developed a batch file to do this for Windows which you will find in the included build/production/AppNWK folder.

For my system you need 7-zip since I am using it’s command line options to automate the process. So get that and install it if you dont already have it.

1. Copy the required files from your node-webkit installation to the AppNWK/nwFiles folder. You only need to do this once (but update these if you install a new version of node-webkit). The files currently in that folder are the ones that are required to be packaged with Windows apps for v0.10.2 of node-webkit. I left them there as a guide.

2. Double click the package.bat batch file. This will copy the production build app files to the AppNWK folder and package it all into a zip file called

3. The resulting file is your packaged app. Create a new folder somewhere, unzip the file and double click the nwkTest.exe file to launch your app!

Part 3 shows how to install extra NodeJs modules using the npm (Node Package Manager)

Packaging an ExtJS4 application using Node-Webkit part 1

In a recent post I explored whether node-webkit could be used to package an ExtJS4 application for the desktop. I found that it could. I then went on to package the app that I am currently building which has dozens of js files. It is all working really well!

This post details the process I am using by starting with “sencha generate app App” and ending with a packaged nwkTest.exe standalone. It includes installation instructions as well as how to debug etc etc. Some caveats:

  1. I have only done this for Windows. OSX and Linux users could adapt what I am doing and it would be great if you could report back the amended steps.
  2. My idea was to build a “hybrid” app – one that will work in a normal browser and have extra functionality when run in the node-webkit (NWK) package – eg access to the local file system. You dont have to do that – you could easily build a NWK only version.
  3. This tutorial will not teach you about ExtJS, ExtDirect or NodeJs, and only a little about node-webkit itself. It is designed for those that are on top of those technologies and who want to package their apps for the desktop.
  4. I use ColdFusion server-side so you might need to adjust the simple CF scripts to suit your server architecture if you want to amend the demo.
  5. There are a few “hacks” to keep the demo simple that you might not do in a production version.


If you dont know anything about node-webkit you might find the info in my first post useful. If you have suggestions for improvements in what follows I am keen to hear them. For this tutorial I am using node-webkit version 0.10.2 and ExtJS 4.2.1.

All the files mentioned below are available here. There seems to be a lot to do when you read this post but it isnt as bad as it looks. I am being as detailed as I can so hang in there.

Step 1 – Generate an ExtJS4 app.

I will assume you know how to do this or you probably wouldnt be reading this post. For the exercise I used:

sencha generate app App {path to webroot}/nwktest

Nothing special here. Of course, make sure the default app is working in your web browser before proceeding.

 Step 2 – Install node-webkit

Download for your OS from GitHub.

Step 3 – Install NodeJs

Download NodeJs from here. I found the easiest was to install it to C:\nodejs to avoid issues of file permissions. See my previous post for details. When you install NodeJs you get the npm package manager as well. This is necessary so that you can install any extra node packages you might want. Again, see the previous post for more details.

It makes it easier if you add a PATH to your nodejs install folder eg C:\nodejs\; The instructions for this demo assume you have set such a path.

Step 4 – Copy the sample files to your nwktest app

Copy all the sample files to your test app. I will explain each of the extra files below. Note that the sample file set does NOT contain the ExtJS library or config files which is why you need to generate your app first. See step 1.

Step 5 – Test the browser version

At this point, you should refresh the browser version of the app to make sure everything works so far. The first three buttons should return a message that the operation was not allowed since these are all NWK specific operations.

The “RPC request using ExtDirect” works in the browser except that since you might not be using ColdFusion I have added two files that return hardcoded JSON responses to simulate a real remoting service. When running the app under NWK it uses a real remoting service on a live CF server.

The “Ajax request using Ext Ajax” will work since the test app has been configured to return a hard coded string from postto.cfm. If you wish to test with your own server side script, upload your script to your server then amend the Ajax request config in Main.js file to point to your script.

Step 6 – Test the demo using NWK

I explain all the ins and outs of this below. At this point however, you can run your app in NWK. What I do is use a batch file (included). Actually, I have two files: nw.bat and nwLocal.bat. The latter includes the commandline switch to tell my app to serve files from localhost. For more details on that, see app/Global.js below.

For now, edit these batch files and adjust them to suit your nwk installation folder.

Then, to run the demo, double click either one. If all is working you should see the familiar app in the node-webkit window and the debugging window open above it. Click the buttons in the centre panel to test. Which tests work depends upon whether you have elected to serve files from the local or remote server:

  1. If you elect the remote server (nw.bat) all buttons should work. The remote server is in Western Australia as the messages will indicate.
  2. If you elect to run using a local server (nwLocal.bat) you will obviously need to adjust the examples to suit your server, and possibly to point to your own remoting service if that is something you need to test. See Global.js and DirectAPI.js

Important info

1. Once you package your app using node-webkit, or execute it within node-webkit for testing, node-webkit uses the file:// protocol to load the *.js files (ie including your ExtJS app files). This means that any Ajax or ExtDirect type calls you make to your server to load the app itself (Ext.Loader), or to get data for your components, will be made in the context of the file:// protocol, not the http:// protocol. That is an obvious problem in terms of getting resources from a remote server. So, the solution I use is to make sure that all urls configured in your components are absolute rather than relative. ie they start with http:// (or https:// obviously). I configure that in my Global.js file which I explain below.

2. Local testing and sencha cmd builds: I go into this in more detail below. Suffice to say that you can easily run your unbuilt, unminified ExtJS app in node-webkit for testing and debugging. Indeed it has become my preferred way of testing since it is really fast to launch because the app files are loaded using the file:// protocol (no web server required). Then, for deployment (detailed below), you can easily include the production build of your app and resources in NWK.

3. Debugging: As you will see below I have included some code to automatically open the debugging window which is the Chromium debugger. Not everything works however. For example you cant get a menu by right clicking an item so you can’t “Replay XHR” in the Network tab. However, breakpoints, console.log() and the debugger; statement etc all work as normal. Breakpoints and debug settings survive an app reload but are all lost once you restart the app from the batch file (naturally enough).

Tip 1: On the main nwk app window toolbar you have 2 reload icons. The one on the right reloads the debugging window and if you click it you get an error because we are opening it automatically. Ignore that icon. The one on the left, however, reloads the app itself (which is what you want). So, if you have a bug in the initialisation code you can set a breakpoint then reload the app via the left reload icon.

Tip 2: If you get any exceptions thrown, you will need to restart via the batch file, not via a reload. The debugger “break on exception” works as long as the exception happens after you have been able to click the break button in the debugger. If not, you will need to use debugger statements to stop just before the crash point.

Tip 3: If your bug relates to an Ext file loader issue or syntax error (eg a missing bracket) you get very little info to help pinpoint your error since NWK crashes immediately. So, here I reload the unminified version of the app using a web browser where you do get helpful diagnostics to solve the problem, then go back to the NWK version to continue testing.

Descriptions of the files in the demo:


The buttons you clicked above are in app/view/Main.js. This is the default file generated by sencha cmd to which I have added some buttons and handlers to the center region in order to test the functionality. Of course, in your real app you would use the standard MVC patterns which works fine. I just wanted to keep this demo as simple as possible.

Ext.define('App.view.Main', {
    extend: 'Ext.container.Container',
    requires: [

    xtype: 'app-main',

    layout: {
        type: 'border'

    items: [{
        region: 'west',
        xtype: 'panel',
        title: 'west',
        width: 150
    }, {
        region: 'center',
        xtype: 'tabpanel',
        dockedItems: [{
            xtype: 'toolbar',
            dock: 'top',
            items: [{
                    xtype: 'button',
                    text: 'About node-webkit',
                    handler: function(btn, e) {
                        var nwkVersion = 'This version of the app isnt using node-webkit';
                        if (NWK.process) {
                            nwkVersion = 'node-webkit version=' + NWK.process.versions['node-webkit'];
                        Ext.Msg.alert('About node-webkit', nwkVersion);

                , {
                    xtype: 'button',
                    text: 'Launch a file',
                    handler: function(btn, e) {
                        if (NWK.gui) {
                            // Launch by extention. eg .txt .doc .xls etc
                            // ie the OS configured application for the relevant extention.
                            // Note that openItem('Test1.txt') will work if the file
                            // is in the app root folder. 
                            // BUT openItem('mydocs/Test1.txt') or openItem('./mydocs/Test1.txt')
                            // WONT WORK because NWK cant correctly resolve the path.
                            // Hence the use of the convenience property NWK.homePath
                            // which is set in resources/js/NWK-requires.js
                            NWK.gui.Shell.openItem(NWK.homePath + 'mydocs/Test1.txt');
                        } else {
                            Ext.Msg.alert('Problem', 'Sorry, you cant do that in a browser')

                , {
                    xtype: 'button',
                    text: 'Browse docs folder',
                    handler: function(btn, e) {
                        if (NWK.fsexplorer) {
                            var startPath = NWK.homePath + &quot;mydocs&quot;;
                            NWK.fsexplorer.readdir(startPath, function(err, path, details) {
                                if (err) {
                                    Ext.Msg.alert('Error', err.message);
                                } else {
                                    var msg = '';
                                    Ext.Array.forEach(details, function(file) {
                                        msg += Ext.String.format('&lt;br&gt;{0}: {1}, Size:{2}', (file.isDir ? 'Dir' : 'File'),, file.size);
                                    Ext.Msg.alert('Files in ' + startPath, msg);
                        } else {
                            Ext.Msg.alert('Problem', 'NWK.fsexplorer isnt found.')

                , {
                    xtype: 'button',
                    text: 'RPC request using ExtDirect',
                    handler: function(btn, e) {
                        if (typeof(RPC) === 'object') {
                            // Ask the server for it's time using ExtDirect.
                            // This works for both browser and nwk versions.
                            // However, the nwk version needs the override in
                            // app/overrides/Connection.js
                            RPC.Util.getdate('dddd, d/m/YYYY', function(res) {
                                Ext.Msg.alert('Message', 'The server time is ' + res + '&lt;br&gt;&amp;nbsp;');
                            }, console);
                        } else {
                            Ext.Msg.alert('Problem', 'Sorry, remoting isnt available.')


                , {
                    xtype: 'button',
                    text: 'Ajax request using Ext Ajax',
                    handler: function(btn, e) {

                        // Server side script. Start with relative path which will work
                        // for the browser version only if the script is on the same server
                        // as the app. ie the normal way of doing things in browser version, 
                        // use the local host or server host as appropriate.
                        var url = &quot;postto.cfm&quot;;

                        // However, for NWK we need to fully qualify the URL
                        // so we are using a http/s: protocol instead of the local file: protocol
                        //if (NWK.isPresent) url = App.Global.getServerURL() + url;

                        // BUT, for this test app, we will fully qualify the browser version as well
                        // so you can test the browser version of the app without needing to 
                        // make an appropriate server side script.
                        url = App.Global.getServerURL() + url;

                        var dataToSend = Ext.JSON.encode({
                            test: 'test data'

                            url: url,
                            method: 'POST',
                            params: {
                                data: dataToSend
                            callback: function(options, success, response) {
                                Ext.Msg.alert('Ext Ajax', 'Request to&lt;br&gt;' + url + ' returned:&lt;br&gt;' + response.responseText + '&lt;br&gt;&amp;nbsp;');


        items: [

                title: 'Center Tab 1',
                html: 'Hello node-webkit demo app.'


Node-webkit requires that you include a package.json file in the root of your app. There are many configuration options for this file. The following is a small example that we will use for this demo. One “gotcha” is that while you can put comments in this file as far as NWK goes, when you use the package manager (npm, see below) it throws an error if there are comments in the package.json file.

    &quot;name&quot;: &quot;nwkTest&quot;,
    &quot;main&quot;: &quot;index.html&quot;,
    &quot;window&quot;: {
        &quot;toolbar&quot;: true,
        &quot;frame&quot;: true,
        &quot;width&quot;: 1000,
        &quot;height&quot;: 600,
        &quot;min_width&quot;: 500,
        &quot;min_height&quot;: 200,
        &quot;max_width&quot;: 1400,
        &quot;max_height&quot;: 800


This file creates a namespace called NWK that helps keep your code tidy and allows you to check whether required node modules have been loaded. Note that you can call it whatever you want. In your app’s index.html file, include

&lt;script src=&quot;resources/js/NWK-requires.js&quot;&gt;&lt;/script&gt;

as per the included example files.

 * Node-Webkit detection and requires.
 * Create a global namespace for node-webkit.
 * Detect if node-webkit is running and set isPresent accordingly.
 * If NWK is present, require the nodejs modules you need and save them to the global namespace.
var NWK = {
    // Just a convenient self-documenting property to know
    // whether we are in a node-webkit environment or not
    isPresent: (typeof(process) === 'object' &amp;&amp; process.versions['node-webkit']) ? true : false

if (NWK.isPresent) {
    // Save the node web-kit process object to the namespace 
    // (for consistency using the NWK namespace in your app)
    NWK.process = process;
    // Tip: There is a lot of useful info in the process object.
    // console.log(process);

    // Use the namespace to hold the required modules
    // These come with node-webkit via NodeJs
    NWK.gui = require('nw.gui');
    NWK.path = require('path');
    NWK.fs = require('fs');

    // This is a sample custom node module for the purposes of this test app.
    // FileSystem explorer. See node_modules/fsexplorer.js
    NWK.fsexplorer = require('fsexplorer');

    // For convenience, save the path to the home folder of this app
    // using the path module.
    // There doesnt seem to be a consistent way to know the actual folder that 
    // the app is launched from. We need a different method depending on whether 
    // the app has been packaged or not. 
    // Hence this &quot;hack&quot;:
    if (process.execPath.toLowerCase().search(&quot;nw.exe&quot;) == -1) {
        // This is what we need in the packaged app which was are assuming
        // is NOT launched from nw.exe
        NWK.homePath = NWK.path.dirname(process.execPath) + '/';
    } else {
        // This is what we need in the unpackaged app that we are 
        // assuming IS launched from nw.exe
        NWK.homePath = NWK.path.resolve(&quot;./&quot;) + '/';

    // Do we want to use the localHost resources to test or use a live server?
    // Look for useLocalHost as a custom command line argument to nw.exe
    // which is set in the nwLocal.bat file.
    // If present, set the useLocalHost flag. You can then use that in your app
    // to use local host resources or live server resources for http requests.

    // Assume live server
    NWK.useLocalHost = false;

    // Get the command line arguments to the nw.exe 
    NWK.args = NWK.gui.App.argv;

    // If 'useLocalHost' command line parameter is present set the property to true
    if (NWK.args.indexOf('useLocalHost') != -1) NWK.useLocalHost = true;

    // See also app/Global.js

app/Global.js singleton

Often ExtJS developers end up with a Global singleton as a way to manage development and server environments. This app does that too. When using NWK we need to make some adjustments to what we would normally do for browser environments. You might have suggestions for a better way to handle this. You will probably need to adjust these properties to suit your server as indicated below.

// For testing in a browser. Are we running on localHost?
var onLocalHost = (, 4) == '127.' ||, 9) == 'localhost');

Ext.define('App.Global', {
    singleton: true,

    config: {
        onLocalHost: onLocalHost,
        webHost: window.location.protocol + '//' +,
            // Set these to suit your server:
        webRoot: (onLocalHost) ? '/sites/nwktest/' : '/nwktest/',
        serverURL: '' // Set in constructor below.              
    }, // config

    constructor: function(config) {

            // Adjustments for node-webkit
            if (NWK.isPresent) {
                // Adjust the webroot etc based on whether 
                // we are using localhost to get server resources, or use the live server.
                // NWK uses the file system protocol so window.location.protocol
                // returns file:// rather than http:// and onlocalhost is irrelevant

                // Reset these since they wont be accurate when set above
                // for a browser

                // Do we want to access the localHost server or the live server?
                // See resources/js/NWK-requires.js for details

                // Set the web root 
                // Set these to suit your server:
                var webRoot = (NWK.useLocalHost) ? '/sites/nwktest/' : '/nwktest/';

                // Set the correct web host
                // Set these to suit your server:
                var host = (NWK.useLocalHost) ? '' : '';

            // Set the url of the server (localhost or live http or live https)
            this.setServerURL(this.getWebHost() + this.getWebRoot());

            // Now, when we need a url in our app (browser or NWK version),
            // we can use App.Global.getServerURL() 

            return this;
        } // constructor



We need to add a few things here. Firstly, we require the relevant files. I will discuss the App.* ones separately. In the init() method below we can adjust the configuration of NWK (defined in package.json) to suit our development environment and there are some examples of NWK methods we can use to adjust the main window.

Ext.define('App.Application', {
    name: 'App',

    extend: '',

    requires: [

    views: [],
    controllers: [],
    stores: [],

    init: function() {

        // If NWK.gui is defined we are running in the node-webkit environment
        // See packages/js/NWK-requires.js
        if (NWK.gui) {
            var win = NWK.gui.Window.get();

            // Open the debugging window if it isnt already open.
            if (NWK.useLocalHost &amp;&amp; !win.isDevToolsOpen()) {
                var devWin = win.showDevTools('', false);
                // eg Move the debugging window to another monitor
                // devWin.moveTo(1940,50);

                devWin.moveTo(300, 250); // left, top
                devWin.resizeTo(1000, 600); // width, height
            // eg changing the zoom level (equivalent of ctrl+ in browser)
            if (win.zoomLevel == 0) {
                win.zoomLevel = 1;

            // eg move the main window
            // left, top
            win.moveTo(100, 50);

            // eg set the main window title
            win.title = &quot;NWK-ExtJS package test&quot;;



This is an override that is necessary if you use Ext.Direct with NWK (which I normally dont use). For the purposes of testing whether NWK was a good candidate for packaging EXTJS apps I made a simple remoting service (thanks to Bruce Lomasky for his help). Since NWK is running on your local computer and you are trying to access resources on a remote server you run into cross origin issues. The override seems to solve those issues.

 * Override to enable cors in ExtDirect for node-webkit
 * Not used for AJAX requests.
Ext.define('App.overrides.Connection', {
    override: '',

    constructor: function(config) {
        config = config || {};

        // Override to set default parameters so that for node-webkit we can
        // POST to the live web server. 
        // ie Do a Cross Domain post via the normal ExtJS requests in ExtDirect.
        // Your server side remoting must set the &quot;Access-Control-Allow-Origin&quot; header.
        // eg for ColdFusion you must use something like:
        //      response = getPageContext().getResponse();
        //      response.setHeader(&quot;Access-Control-Allow-Origin&quot;,&quot;*&quot;);
        // or 
        //      &lt;cfheader name=&quot;Access-Control-Allow-Origin&quot; value=&quot;*&quot;&gt; 
        // Note: If you set these properties when running in a browser context (ie not node-webkit)
        // you can do cross domain posting in that context.
        // However, I couldnt yet get the ExtDirect to do a cross domain post in browser mode.
        // I dont normally use ExtDirect so my knowledge is sketchy here.
        // ExtDirect DOES work for node-webkit environments though, as well as for Ajax requests.

        if (NWK.isPresent) {
            config.cors = true;
            config.useDefaultXhrHeader = false;

        Ext.apply(this, config);



Again, this is only required if you are using Ext.Direct. What this does is makes the initial call to the remoting service to get the RPC API. The extra bit for NWK is that we need to ensure that we are using absolute urls. For this demo in browser mode the remoting “service” is just a couple of JSON files pretending to be CFM pages. I did that so you can run the demo in a browser without needing to actually set up the service. For the NWK version, however, the remoting service is a real service on a live CF server so you can test that it actually does work.

Ext.define('App.DirectAPI', {
    requires: ['*', 'Ext.Ajax']
}, function() {

    /* NOTES:
    For this to work in a Node-webkit context:
    1.  If you use relative paths in your urls, xmlHttpRequest 
    	(used by ExtJS to do Ajax calls (including remote)) will supply the
    	protocol. For browser environments the protocol will be http or https 
    	but for NWK it will be file://
    	So, the Ajax call will therefore try to locate the resource on the 
    	local file system, not the web server.
    	For that reason we need to fully qualify the url when using NWK and ExtJS.
    	Hence the use of the NWK.webRoot variable when setting the URL below
    	(see resources/js/NWK-requires.js)

    2.  Api.cfm returned data must be prefixed with an Ext.ns(); so the global 
    	namespace for the ExtDirect is created. eg we are expecting Ext.ns('RPC') 
    	in this example, which is what our Api.cfm defines.

    3.  In this test app: remoting wont work for the browser version unless 
    	you have implemented remoting
    	on the server that you are running the app on. 
    var hostUrl = App.Global.getServerURL();
    var url = hostUrl + &quot;servicebus/API.cfm&quot;;

    var Loader = Ext.Loader,
        wasLoading = Loader.isLoading;

    //Load the API config from the server
        // The url of the Api.cfm
        // onLoad listener 
        // onError listener
        function(errMsg, synchronous, scope) {
            //throw errMsg
        // Scope
        // Synchronous. We must have the Api config before we continue.

    Loader.isLoading = wasLoading;

    // For node-webkit all http requests MUST use the http protocol (ie not file://)
    // so we are fully qualifying the Router's url. 
    // eg instead of just 'servicebus/Router.cfm' it needs to be something like:
    // 'http://mywebserver/myapp/servicebus/Router.cfm'
    // See comment above.
    if (NWK.isPresent) {
        // Get the url of the remote service
        var directUrl = RPC.REMOTING_API.url.toLowerCase();

        // Set the fully qualified url to the service		
        if (directUrl.indexOf(hostUrl.toLowerCase()) == -1)
            RPC.REMOTING_API.url = hostUrl + directUrl;

    // If we have a valid RPC config,
    // pass the remoting config to the ExtDirect manager
    // whether or not in the browser or NWK environment
    if (typeof(RPC) === 'object');


node-webkit uses nodejs, so you can use pretty much any NodeJs module in your app. There is a repository of NodeJs modules here: which you can install using the package manager that comes with NodeJs  (npm). More on that below.

Or, you can write your own packages. I have supplied a very simple, bare bones package that I wrote that reads the contents of a local file system folder. It is just intended to show how as simply as possible. It is not a good example of best practice!

 * A custom sample node module that handles native file interactions.
 * This is a bit quick and dirty. It is just as a simple example of what a
 * custom node module can look like so we have something to use for our test.
// Require the NodeJs fs (filesystem) module
// See
var fs = require('fs');

function FSExplorer() {

     * Read the contents of a local folder / directory.
     * Simple example. Does not recurse.
    function readdir(path, callback) {

        // Start by getting the status of the folder 
            // The path to the folder
            // The callback. Err will be null if no errors
            function(err, stat) {
                if (err) {
                    return callback(err)
                // Have we got a directory ?
                if (stat.isDirectory()) {
                    // Ok, read the directory
                        function(err, files) {

                            // Get the data for files and folders in this directory 
                            var fileDetails = [];
                            files.forEach(function(file, i) {
                                    var abspath = path + '/' + file;
                                    var fileStat = fs.statSync(abspath);

                                    var details = {
                                        name: file,
                                        size: fileStat.size,
                                        created: fileStat.birthtime,
                                        modified: fileStat.mtime,
                                        isDir: (fileStat.isDirectory())

                                // Return the details as an array
                                // along with the path we started with
                            return callback(null, path, fileDetails);

                } else {
                    return callback(new Error(&quot;path: &quot; + path + &quot; is not a directory&quot;));


    this.readdir = readdir;

module.exports = new FSExplorer;

Step 7 – Building and packaging your app

Ok. At this stage you should have a working test version. Time to actually build it and package it. See Part 2.

Some final comments:

  1. While I have been using this system for a few weeks on a reasonably large app and have included everything I have learned in the process, there will of course be bits of ExtJS that I havent tested yet. If you find any such issues please post your adjustments.
  2. There might be some security issues that I dont know about when using this packaging method. Please post if you know of anything that needs to be taken care of.

Explorations of using node-webkit + ExtJS4 to build a desktop application

Since the demise of Sencha Desktop Packager and the non-arrival of any examples or clues about how TideKit might actually work I decided to have a look at node-webkit and see whether or not it would work as a desktop packager for ExtJS4. What I say below might work with ExtJS5 but I havent upgraded yet since it is still quite new.

Node-webkit is an executable (one each for Win, OSX, Linux). It is a chromium webkit browser wrapped by a “shell” that adds JavaScript libraries so that you can access the local file system, memory, native windows and menus, system tray, etc etc of the computer it is running on. Hence, it creates the opportunity to turn HTML5/JS/CSS into a desktop application. The extra JavaScript is provided by NodeJS (well the V8 JS engine actually, but via NodeJS libraries). Hence the name “node-webkit”.

The first observation is that there was a lack of any “Using node-webkit with ExtJS4” information. Lots of little bits and clues but no overall approach. So, I thought I would share my exploration to make the trail easier for the next person.

The second observation is that you can make a desktop app with just node-webkit. However, unless you want to re-invent the wheel in terms of making Http requests or direct remoting (for example) you will also need to install NodeJS separately so you can use the NPM packager to easily download the various NodeJS libraries that you might want to use. There are nearly 90,000 of them!

And, of course, you will need to be familiar with ExtJS4 and Sencha Cmd. I wont be explaining any of that.

Useful resources

These are the things that helped me get my head around the concept: – A series of 6 videos for beginners. Very helpful. – An introduction by Roger Wang, the guy that made node-webkit.–net-36296 – a short, inexpensive eBook that covers the main aspects clearly. Great for beginners. Even though the book is for Windows users, OSX and Linux users will also find the info useful.

(I will add more resources as I find them).


Installing node-webkit went without a hitch. Just download the installer for your OS from the GitHub page and follow the dots.

First tests

I then used the above mentioned resources to make my first desktop app. I followed the tuts introductory tutorial. That all worked without a hitch. Very excited by now.

With ExtJS4:
To test the ExtJS compatability I created a new ExtJS app using Sencha Cmd generate, built the default production app, then ran it in node-webkit and ….. it worked! More excitement.

Some learnings here:

1. To test your app you basically pass the folder containing your app (ie the folder with the main html file in it) to nw.exe. You *can* drag and drop it but I found the fasted way was to create a batch file (I am using Win7) in the same folder as the app and then run that. The batch file contents (for my machine) looks like:
..\..\node-webkit-v0.10.2-win-ia32\nw ./
which basically says (go back up to the folder containing the nw.exe and run it with the current folder as the parameter. You could also add the node-webkit folder to your PATH (on windows) to avoid needing the path in the batch file.
Edit: And/or of course maybe rename the folder to (say) NW so the folder or path doesnt need updating when you update your version of node-webkt!

Executing nw opens the window and displays your app (as you would have seen in the video series above.

2. Note that my initial testing built the ExtJS app first then passed that to NW. Also at this stage there is no NodeJS library being used, It is just my ExtJS app. It gets a bit more complicated when you want to pass the unbuilt version (so you can debug your app via the NW chrome debugger). More on that below – I am still exploring all that.


Now, installing NodeJS so I can require the appropriate extra libraries. This wasn’t as simple initially. The default installation folder is C:\Program files\nodejs. That seems fair enough. However, even though I am logged in as Adminstrator on my computer file permission problems meant that I couldn’t run npm (the package installer). See this post for details of errors. My solution was to uninstall NodeJS and reinstall in C:\nodejs. That worked perfectly and I could run npm without errors.

Using NodeJS packages (modules)

To use the downloaded NodeJS packages you need to install them in the node_modules folder at the root of your app. It must be called node_modules. So, one way to install a module is to run npm install {package name} from a command line in the root of your app’s folder. The node_modules folder will be created if necessary and the module will be saved in that folder. For me I just ran  C:\nodejs\npm install httpreq from a terminal / command line (to load the httpreq module, for example).

More tests: Adding Node to ExtJS4

This is preliminary. Starting with the default ExtJS app generated by Sencha Cmd I added the following:
1. The require() statements which I placed above Ext.define(‘App.view.Main’, {:

var gui = require('nw.gui');
var httpreq = require('httpreq');

2. a toolbar to the centre Tab panel with some test buttons

        region: 'center',
        xtype: 'tabpanel',
        dockedItems: [{
            xtype: 'toolbar',
            dock: 'top',
            items: [{
                xtype: 'button',
                text: 'Open file',
                handler: function(btn, e) {
                    // Test opening a Word Doc
                    console.log('Pressed open file');
            }, {
                xtype: 'button',
                text: 'Http request',
                handler: function(btn, e) {
                    // Test making a http request
                    // Using
                    var url = &quot;;;
                    httpreq.get(url, function(err, res) {
                        if (err) return console.log(err);
        items: [

                title: 'Center Tab 1',
                html: 'Hello first app'

I then built the production app and loaded it into NW as described above and yes! it works!

Next steps

My next task is to work out the best way to integrate ExtJS4 and node-webkit so that it is possible to run the uncompressed version of my app in NW so I can debug it using the chrome developer tools in NW. I will report back when I have done that!

Edit: Done. See Part 1

CFPOP – deleting an email when there is a comma in the UID

It seems that a problem has existed with the CFPOP delete action for a number of versions and it has not been fixed. The problem occurs when trying to delete a single email (or a list of emails) from the mail server where the mail server has included a comma in the UID. eg “,S=965”

The CF docs for the CFPOP Delete action says: “UID or a comma-separated list of UIDs to get or delete. Invalid UIDs are ignored.”

So, the abovementioned UID gets split into 2 uids (notice that it has a comma in it) and of course the email is not located so cant be deleted. CFPOP does not include a DELIMITERS parameter to use with the UID paramater which would solve the problem, I think. eg

<cfset myUIDlist = ",S=965|,S=966" />  
<cfpop server = "********" username = "********" password = "******** 
	action = "Delete" uid="#myUIDlist#" delimiter="|" >

Fortunately, there is a solution – use POP CFC instead of CFPOP! Thanks to Paul Vernon.

So, here is a sample page to demonstrate a way to use POP CFC.

 * Example of reading, processing then deleting individual emails from the pop mail server
 * using the POP CFC custom component.

	// To make it easier to rescope this example (local, variables ... whatever)
variables.s = {};

			// Initialise the custom POP CFC component. Used instead of CFPOP
			// Set your values here
s.popAccount = createObject("component", "pop").init(myPopServerHostname, myUsername, myPassword)

			// Specify a non-comma separator for the UID lists. 
			// You must do this in order for the list functionality
			// of POP CFC to work (including deletions)
s.mySeparator = "|";

			// Get an array of the UIDs of the messages in the mail account.
			// ie retrieve them from the mail server
			// This is a necessary step to solve the comma-in-uid problem
s.UIDArray = s.popAccount.getUIDList();

if (arrayLen(s.UIDArray)) {
			// Convert the array to a list
			// Keep the list to use for deletions
	s.UIDList = ArrayToList(s.UIDArray, s.mySeparator);

			// Get an array of the raw messages - one entry per UID supplied
			// This gets the raw email data from the pop server for whichever
			// emails are in the UIDList
	s.msgSrcArray = s.popAccount.GetRawMessageByUID(s.UIDList);

			// Turn the array into a query of email structures
	s.messagesQry = s.popAccount.parseRawMessage(s.msgSrcArray);

			// Loop over the array of email messages
	for( s.i=1; s.i <= s.messagesQry.recordcount; s.i=s.i+1) {

			// Process the message as you wish
			// ....
		writeOutput("<br/>" & s.messagesQry.subject[s.i]);

			// Now, delete this email from the server 
			// Note: you can also delete all the emails in your query 
			// in one go after the loop. See below.

			// The UID is NOT present in the messagesQry. Therefore,
			// you need to look up the UID by list position.
			// Obviously, you can also selectively delete single messages 
			// based on your criteria.

		s.uid = listGetAt(s.UIDList, s.i, s.mySeparator);


			// Uncomment to delete all messages in the list in one go, 
			// instead of one by one as above


POP CFC has lots of other useful functions too.