Using Internet-Explorer As A GUI For VBScript & JScript

This Post Is For All Those People Who Want I GUI For A Script But Find HTAs Clunky!

Also see (new and improved):here and here

Scripts are fine, but sooner or later you are going to want to show something to a user, or interact with a user. People expect Graphical User Interfaces and are no longer happy to see text scrolling by in a CMD box. The next step what we all seem to take is to look into Hyper Text Applications. These seem like the perfect solution as they are scripted but have an HTML GUI with them. However, more often than not, this approach becomes unstuck.

HTAs Fail Because Their Programming Model Is Wrong

HTAs mix up the presentation of the application with the co-ordination of that application with the underlying data that feeds it. All the management code is embedded into the pages that are presented to the user. This results in everything becoming a mess of interdependencies that eventually trips over its own feet. After a few days of being very excited at how fast you are at creating this new HTA you become all sad as development grinds to a halt.

This is not a new problem and it is not isolated to HTAs. Indeed, IBM researched it a long time ago and came up with a programming model to help overcome it. The snag is that over the years the simplicity of their model has been covered over by countless poor descriptions. Please do not switch off at this point - this is very simple - really!

Model View Controller IS VERY SIMPLE INDEED - just read on

As a software architect, I feel very passionate about this, so I am going to say it again: MVC is very simple indeed!.

Here is a picture that illustrates my point:

Just stare at it a bit and let it sink in...

  1. At the bottom is data. The data is stored in a data model. So the data base at the bottom is M for Model.
  2. At the top is a Graphical User Interface. So the GUI at the top is V for View.
  3. In the middle is a brain. Brains control things. So the brain in the middle is C for Controller.
So - let us look at this picture again!

In keeping with the Exsead concept, the brain (controller) is one or more scripts. The GUI (view) is an application which is being controlled by the script. This application could be MS Excel or Word, but in this post it will be Internet Explorer. The database (model) may be an SQL database, web-service, file or internal scripting data-structure. The point is that it has a separate existence to both the controller and the view!

A JScript Class To Use Internet Explorer (IE) As A GUI


function GUIWindow()
{
    var objExplorer = WScript.CreateObject("InternetExplorer.Application")

    with(objExplorer)
    {
        Navigate("about:blank");   
        ToolBar   = 0;
        StatusBar = 0;
        Width     = 500;
        Height    = 400; 
        Left      = 200;
        Top       = 100;
        Visible   = 0;
        document.title = 'Script GUI Window';
    }
    
    this.SetTitle    = function(title)
    {
        objExplorer.document.title=title;
    }
    this.GetDocument = function()
    {
        return objExplorer.document;
    }
    this.SetHTML     = function(html)
    {
        objExplorer.document.body.innerHTML=html;
    }
    this.Quit        = function()
    {
        objExplorer.quit();
    }
    this.MoveTo      = function(top,left)
    {
        objExplorer.Left=left;
        objExplorer.Top=top;
    }
    this.SetSize     = function(width,height)
    {
        objExplorer.Width=width;
        objExplorer.Height=height;
    }
    this.GetWindow   = function()
    {
        return objExplorer.document.parentWindow;
    }    
    this.Alert       = function(msg)
    {
        objExplorer.document.parentWindow.alert(msg);
    }
    this.ScrollTo    = function(x,y)
    {
        objExplorer.document.parentWindow.scrollTo(x,y);
    }
    this.SetVisible  = function(tf)
    {
        if(tf==true)
        {
            objExplorer.Visible=1;
        }
        else
        {
            objExplorer.Visible=0;
        }
    }
    this.WaitOnId    = function(id)
    {
        var elem=objExplorer.document.getElementById(id);
        var val=elem.value;
        while(elem.value==val)
        {
            WScript.sleep(20);
        }
        return elem.value;
    }
}

There it is; it is not the most complex class in the whole world. However, it is very powerful. I am not going to show all the things that can be done with it here. This is an introductory posting. Many of the postings which are in the pipeline will give examples of the sort of stuff which can be done with this class. For now here is a very simple example that uses a script (controller) to get data from a web-server (data) and places it in a GUI windows (view).

Run();

function Run()
{
    // Create an AJAX object
    var ajax=WScript.CreateObject('Microsoft.XMLHTTP');

    // Try to get the file 32 times then give up
    for(var i=0;i<32;++i)
    {
        try
        {
            // Set it to point to the web service
            // Note the last argument being false forces the script to
            // wait for the response
            ajax.open('GET','http://www.nerds-central.com/Logs/nerds.csv',false);
            
            // Set the request header so that the connection is closed right
            // away to avoid locking up server resource
            ajax.setRequestHeader
            (
                'Connection',
                'close'
            );
            
            // Send the request and wait
            ajax.send();

            // The server returned an error
            if(!ajax.status==200) throw('Got Wrong Status:'+ajax.status);
            break;
        }
        catch(e)
        {
            for(var a in e)
            {
                WScript.Echo(a + '=' + e[a]);
            }
            // Note the use of the () around the maths makes the numeric calculation
            // occure and the result be turned into a string by the + opperator 
            WScript.echo('Failed to get csv feed for Nerds-Central: tries left='+(32-i));
        }
    }
    // If the loop exited due to counting out then give up
    if(i==32)WScript.Quit(1);

    // OK, we got the data, now let's display it in a GUI

    // Create a GUI
    var gui= new GUIWindow();
    
    // Make the data nice to view in HTML
    var out=ajax.responseText;
    // Remove (escape) all tag open symbols
    out=out.replace(/</g,'&lt;');
    // Wrap data in pre to make sure it looks OK
    gui.SetHTML('<pre>'+out+'<pre>');
    // We can get hold of the document to style it
    var doc=gui.GetDocument();
    var styleSheet;
    // Now make sure it has a style sheet and set some rules
    if(doc.styleSheets.length==0)
    {
        styleSheet=doc.createStyleSheet();
    }
    else
    {
        styleSheet=doc.styleSheets[0];
    }
    styleSheet.addRule('body','color: black;');
    styleSheet.addRule('body','font-family: courier, fixed;');
    styleSheet.addRule('body','background-color: #FFD;');

    // By default the GUI window is hidden, once it is populated, 
    // show it
    gui.SetVisible(true);
}

// GUI CLASS GOES HERE //

To try this script, copy both code blocks into your editor and name it something like MVCExample.js, then just run it as csript MVCExample.js or double click on it from explorer. Nice a simple!