newObjects IE ScriptBar Events reference
How to create an IE toolbar step-by-step.

This page is intended to explain the toolbar development process step-by-step. As you will see we will not try to construct an actually useful IE toolbar application, instead we will try to follow the way almost any IE ScriptBar application would follow and deviate a little from the straight line so we can pay more attention to some basic techniques which are useful for a big number of applications. To avoid mixing everything up this page doesn't discuss the IE ScriptBar's menu system. After reading this article you can move on to the menu system chapter.

How to proceed.

If you have a start-up package received with the license install it and go to the installation directory (Program Files\<Company name>\<TB name>). It will be convenient to create a shortcut to this directory on your desktop so that you can get quickly there the next time you need to continue your work. If you are working with the demo version go to its install directory (Program Files\newObjects\ScriptBarDemo) and do the same. All the work you are going to do with the demo can be just moved to the licensed version and used without changes, so you can start over the demo version and purchase license in the way and continue.

In the install directory you will see the following files:
toolbar.cfg - the toolbar configuration.
newObjectsIEScriptBar.DLL - the toolbar core DLL
toolbar.htm - The toolbar user interface HTML. This file is almost empty and is there as placeholder only. You can overwrite it with the file you will create
logo.gif - an image shown in the above file (remove it when no longer needed).
toolbar.vbs and toolbar.js - two template files for the toolbar script. The both files contain a few comments and empty prototypes for all the events that can be possibly handled.

Note: It is not recommended to work over one of the samples, get the demo version of the start-up package instead. The samples come with configurations and surrounding files designed to fit the sample's needs. Therefore they may differ from what you read on this page. Furthermore, to avoid making the code too complex this page does not include any code related to the Menu system. You can see how to create and show menus on the IE ScriptBar menus page.

Step 1:

Create a directory where you will edit and create files. Copy all the files from the install directory except the DLL. Work only in this especially created directory in order to avoid mistakes that will overwrite your files when you come to the installation testing phases. Whenever you want to test your application - copy the current files from your working directory to the toolbar install directory and open a new browser to see how it works with them. If you want you can create a BAT file that does this.

Step 2:

Decide what scripting language you will use for your toolbar script and change the settings in the Scripts section of toolbar.cfg. E.g. change the script language and the script file. You can specify one of the template files (toolbar.js or toolbar.vbs) there or specify a new file name and rename the template that corresponds to the selected script language if you want to use it as a starting point. Remove the unneeded script file - for the language you wont use.

Step 3:

Determine how the toolbar user interface will be loaded. We will assume Direct below. But if you are going to use the ScriptBar and ALP together you can also specify ALP instead. If you want to use different name for the toolbar UI HTML file (e.g. different from toolbar.htm) set it in the Control setting of the toolbar.cfg and create that file (or rename the dummy file supplied for a start).

Strep 4:

Design the toolbar user interface. Assuming that in step 2 you chose toolbar.htm open it in a HTML editor or edit it in a text editor (as preferred).

Make sure that it has <BASE HREF="%BASE%"> in its HEAD area (Assuming the Direct method is used for load). For example:

<head>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
<title>Toolbar</title>
<BASE HREF="%BASE%">
... something else if needed ...
</head>


Take care to specify color and margin settings for the page body. Using the IE defined color names to match the current Windows color scheme is a good approach if you are not going to use image for the background. A good choice will be something like this:

<body bgcolor="buttonface" text="buttontext" topmargin="0" leftmargin="0" SCROLL="NO">

Create a style sheet. You can embed it into the HTML file or create a separate file and use a LINK tag to link it into the HTML file. It is a good idea to define font sizes for the body the links and the other elements you are going to use. In general you will return to the style sheet and add more styles as needed. Use pixels (px) to specify font sizes because the toolbar size is calculated in pixels on the screen. This way you will know for certain that your texts on the toolbar will always occupy the same areas whatever is the configuration on the user's PC. For example you can start with some styles like these:

body { font-family: Arial; font-size: 11px }
td { font-family: Arial; font-size: 10px }

Design the body. Here you should use tables (TABLE), divisions (DIV) and other elements structured in such a fashion that will guarantee that the height of the content will be easy to control and limit. Here is one example structure without actual content:

<table border="0" cellspacing="0" cellpadding="1" width="100%" height="24">
  <tr>
    <td valign="middle" align="center" width="24" height="24">
    ...
    </td>
    ...
    <td valign="middle" align="center" width="100%" height="24">
    ...
    </td>
    ...
    <td valign="middle" align="center" width="24" height="24">
    ...
    </td>
  </tr>
</table>  

The above sample uses a table with several cells on the left with explicitly specified sizes and several cells on the right and a cell in the middle that will extend to fill the gap between them. Design the images to match the chosen height and put them in the same directory or create a subdirectory for them.

When the design begins to take a shape you can start writing your scripts in it (if any are needed at this time). For example you may want to implement several simple routines that change images as the mouse hovers over them, some routines to hide/show some parts of the HTML and so on.

When the design reaches usable form you can start writing routines that intercept onClick events for example and call from them prospective functions from the toolbar script. For example if you put an image in your toolbar and you want that clicking it the user must invoke something you can do it this way:

<SCRIPT>
...
function MyImg1() {
  external.MyRoutine(some_parameters);
}
....
</SCRIPT>
...
<IMG SRC="myimg.gif" ALT="tool tip text" onClick="MyImg1()">

The toolbar script is accessible for you through the external property. In the above sample we assume that in the toolbar.vbs (or toolbar.js if you decided to use JScript for the toolbar script) you have implemented a Function or Sub named MyRoutine. It may have as many parameters as needed you just need to call it with all of them. Thus you can access any of your routines in the toolbar script by calling external.<routine name>(... parameters ...).

Better keep the code in the HTML page dedicated explicitly to UI effects and initial invocation of actions but do not implement anything related to the actual work in it. This will keep it clean and easy to work with. Another reason for this is that your actual work will require state variables and other resources, spreading the work in two files will only make the access to them difficult and even impossible sometimes.

Step 5: 

When the UI is prepared enough to allow testing you can start writing the toolbar script. It is a plain script file. In the template files (toolbar.vbs or toolbar.js) you have empty prototypes for all the events that may occur. You will not need them all - even the most complicated toolbars will need approximately 1/5 of them. However better leave all the prototypes for the initial phase of the development so that you can use them as the need arises. When it becomes clear which will not be needed you can delete them. By deleting the unused event handlers you will speed up the performance drastically.

Under or above the event handlers make space for the routines you will implement for your own usage. You can split them in two parts (with appropriate comments and empty lines for example): One part for the routines called from the toolbar UI (see the previous step) and the rest routines used only internally.

If you have some initialization work to be done when the toolbar loads implement it in the beginning outside any Sub or Function. If you need to pack part of this work in Sub-s or Functions place them before the code that calls them!

If you have a corresponding clean up tasks needed when the toolbar unloads from the computer's memory implement them in the OnUnload event handler prototype.

Lets try to do something for an example. We will implement something very simple - search google for pages referring the page currently viewed in the browser. To this we need the following:
- A button or image that invokes the action
- A routine that asks the browser what is displayed in it and forces it to navigate to Google with appropriate parameters.

So lets begin with the UI HTML. In the file toolbar.htm (assuming you didn't change its name) we put this for example:

<head>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
<title>Toolbar</title>
<BASE HREF="%BASE%">
<STYLE>
  body { font-family: Arial; font-size: 11px }
  td { font-family: Arial; font-size: 10px }
</STYLE>
</head>
<body bgcolor="buttonface" text="buttontext" topmargin="0" leftmargin="0" SCROLL="NO">
  <IMG SRC="srchgoogle.gif" STYLE="cursor:hand" onClick="external.SearchGoogle()">
</body>

The page for the toolbar user interface is very simple. It contains only one image and we are calling a routine from the toolbar script when it is clicked. All the important elements for the toolbar design are bolded in the sample HTML above.

Now we need to implement that SearchGoogle routine which is called when the image is clicked. Thus our toolbar.vbs may look like this:

Sub SearchGoogle
  ' First we need to learn the URL of the page currently viewed by the user
  Dim url
  url = Browser.LocationURL
  ' Then we need to compose a correct search url for Google.
  url = "http://www.google.com/search?q=link:" & url
  ' And now navigate there
  Browser.Navigate2 url
End Sub 

Step 6:

Now, lets write a bit more code and handle some events. Usually the toolbar application handles the browser events as part of its main functionality. Depending on the goal this may be simple or very complex - it can collect information, interfere with the navigation, automate tasks and so on. It is hard to devise an example that will show interesting specifics for the all imaginable applications, but there is one area which deserves special attention.

In many applications the developer may face the need to implement controlled navigation - for example navigating to a given URL, detecting that the navigation is complete and doing something with the page. Do not associate this with tasks automation applications only - the need of such an operation may arise in many cases. The problem is that you cannot be sure that the browser will go exactly where you want. What may happen? In the first place the WEB site may use redirection, the target URL may be invalid at the moment, an error may occur on the server side and so on. Checking for all the possible problems is quite difficult and there is considerable chance that you will forget something or that the site structure may change. So, the best approach is to do this in much simpler way:

What we need to do:
1. Determine how the recognize the final page where we want to go.
2. Implement a code that will allow the application to recycle if something goes wrong. 

We can recognize the final page in many ways - we can dig into its object model and search for certain elements, texts or other elements that are expected to be there, or we can simply identify the right page by using a part of its URL. What is the right way depends on the site structure, your control over it, the way the site is maintained. In other words you must find out what will identify the target page today and if possible even after some site changes. In most cases using part of the URL is good enough because the URL is usually related to the page functionality.

So, we will do this: navigate the browser to the target page, init a timeout, and handle two events - OnDocumentComplete and OnTimeout. In the first event handler we will implement page recognition code which will check for two things - if we are really in a process of navigation to that page and if that is so check if the just completed page is the page we want to go to. In the second event handler (OnTimeout) we will wait for the expiration of the timeout we have set. So, if the timeout elapses before we can recognize the page we assume that something wrong has happened and we cannot perform the operation. Of course, we can add more code - recognize more pages - such as an error page (if the operation depends on some parameters entered into the toolbar by the user at some point we may want to handle the error page shown on the site in such a case), but generally we should implement the event handlers in question to guarantee that the application will know if something is wrong even if it has failed to recognize what is happening  - everything else will be a plus which will improve the work of the application but will not be crucial for its functionality.

First let us declare a global variable and init it - the variable will hold the id of the timeout we will use.

Dim MyTimeout
MyTimeout = 0 ' The actual timeout id-s are always non-zero, so we can use 0 to indicate non-initialized state.

Starting the navigation. Assume that the routine below is invoked in response to an user action over the toolbar (button click, menu item click or something else).

Sub MyStartNav(MyURL)
  MyTimeout = Host.Timeout(60)
  ' We set the timeout to 60 seconds
  Browser.Navigate2 MyURL
  ' We start the navigation here. 
End Sub

For the sake of the example lets assume that we can recognize the target page by using something specific in its URL. If, for instance, the page to which we are directing the browser is some kind of a login page it may have a parameter "ShowLogin=1" or something like that. Over that assumption we can write the following code in the OnDocumentComplete event handler:

Sub OnDocumentComplete(frame,url)
  If MyTimeout <> 0 And Instr(url,"ShowLogin=1") > 7 Then
    Host.DiscardTimeout MyTimeout
    MyTimeout = 0
    ' Our first job is to discard the timeout because we assume the navigation has completed successfully
    ' This is the page we look for, lets fill the login form in it
    If IsObject(Browser.document.forms("loginform")) Then
      Dim form
      Set form = Browser.document.forms("loginform")
      form.Username.value = MyUserName
      form.PassKey.value = MyPassword
      MyTimeout2 = Host.Timeout(60)
      form.SubmitBtn.click()
    End If
  End If
End Sub

The above code uses the timeout id for an indicator value for the current navigation task. A little digression - if this was a frameset page and we have started more than one navigations in different frames we would have needed one timeout for each navigation. This way we could have put very similar If .. Then constructions one after another in the OnDocumentComplete event handler and each of them would have depended on the timeout id assigned to the particular navigation task. Using the timeout id values to distinguish different tasks that need some code in the same even handler is very convenient practice because it is guaranteed that the id-s of the active timeouts are unique for the application. Otherwise we would need separate variables which indicate that the corresponfing navigation task has been initiated. So, using the timeout id for the purpose allows us to use it for the both purposes - recognizing the task and handling total failure events (see below).

The code in blue above is a bit of digression. It assumes that the page to which we have navigated is a login form with a form named "loginform", fields for username and password and a button. The code uses the botton's click()  method to submit the form and initiate a new navigation (which is not considered further in this example code, but it can be handled in a much similar manner). It is possible to use the Browser.Navigate2 to start a navigation which will be packed as form post. Then why use the click() method? The answer is quite simple the click() method of a button imitates a mouse click over the button and the browser will think that the user has actually clicked the button. In browsing automation tasks this is a good way to follow because we cannot be sure about the additional processing the DHTML page may implement in a javascript attached to the form submit or even the button's OnClick events. So, this way we are sure the browser will do whatever the DHTML page is programmed to do without need to dig deeper in its structure. The usefulness of a similar technique depends on how well you know the site over which the toolbar will implement browsing automation tasks - if the site is entirely under your control you can choose the technique you use more freely and even adapt the site to the toolbar. If the site is not yours you would want to stick to the techniques that will work even if considerable changes are made to the site in future and avoid any risks that may arise if your code depends on too much specific details.

Now, lets handle the OnTimeout event.

Sub OnTimeout(id)
  If id = MyTimeout Then
    Host.MsgBox "The toolbar is unable to recognize the page or a network error has occured"
  End If
End Sub

As we said you can add code in the OnDocumentComplete to recognize some of the error pages. Still, there is no guarantee that you will not miss some of them or that they will never change. Thus the timeout gives us the ultimate ability to catch the failure even if we cannot recognize it. In the OnDocumentComplete we discard the timeout if an expected page is recognized (not only thepage we expect, but we can do so also for the error pages we handle) and the timeout would never occur. If nothing is recognized the OnTimeout event allows us to clean up or at least tell the user that we are unable to proceed further. In the real world this navigation process may be part of something more sophisticated - we may have an open database or files for instance. Having the ability to catch the failure in any possible case gives us the opportunity to clean up the application state and may be restart the process or ask the user for some data that may be relevant to the navigation process and then retry it.

The above technique is perhaps the most effective way to program navigation automation tasks in the IE ScriptBar. It allows the developer to implement minimal functionality and then (optionally) add some smarter event handling. Thus the developer can test the navigation process without need to take care about everything and then if it is possible to improve it in order to avoid long timeouts wherever possible.

Step 7:

The previous step illustrated how to construct something simple, where to put the code and how to test it. Most likely your application will do much more. For the purpose it will need to use objects from the toolbar run-time library. We are listing below some hints about which objects to use for a particular purpose in the toolbar script (toolbar.vbs in this example). Still this step is only a hint - there are much more objects in the run-time library. 

Accessing files:
You can use the SFMain object. Create it like this:
Set sf = Host.CreateObject("newobjects.utilctls.SFMain")
Here the Host namespace represents the internal ScriptBar's object which provides several utility methods you can use in your toolbar script.
To open a file you can use the OpenFile method of the just created SFMain object:
Set file = sf.OpenFile( Settings("BasePath") & "myfile.txt,&40)
The files and the other streams (file-like resources) are represented by SFStream objects. I.e. the file variable in the above code receives one such object which drives the opened file.
Reading from a file in text mode:
str = file.ReadText(-1)
and so on. 
You can find the full description of all the file, stream, storage oriented objects and their methods in the Storages and Files section of this documentation.

Using the embedded SQL database engine.
You use the SQLite COM object to work with it:
Set db = Host.CreateObject("newObjects.sqlite.dbutf8")
Open a database:
db.Open Settings("BasePath") & "mydb.db"
Execute a query:
Set res = db.Execute("SELECT * FROM MYTABLE")
See the SQLite COM documentation.

To establish TCP/IP or IRDA communication with other computers and applications you use the NetStreams objects

When needed you can run part of your application in background thread(s). See COMScriptThread object. This may be needed in any scenario that involves slow operations that do not need the constant user's attention. For example synchronization, checking/downloading resources from the network, data analysis and mining, resources indexing and many other cases. Note that the COMScriptThread object allows you create customized environment for the script running in the thread - you are free to define global namespaces in it - such that would suit it best. All this requires just a few lines and saves a lot of dirty work.

When working with databases or textual data that needs formatting you can use the StringUtilities object to compose strings from constant and variable data with minimum effort.

You can transfer data between your application and others or just save restore structured data using the ConfigFile object. This technique is in many respects similar to XML, but in contrast it is more efficient. It supports both inter-machine/inter-application format and human readable format. You can use it to read maintain your own configuration files, transfer data, exchange data with servers and so on.

There are various utility objects such as the VarDictionary which provides you with collection/dictionary object capable not only to store keyed values, but also convenient for complex tree-like structures where the dictionaries/collections can be nested in each other. As it is also used by many other objects as medium through it you can simplify many of the data transfer tasks - see ConfigFile, SQLite COM, SFMain and so on.

Step 8:

After finishing the application you must prepare its setup package. Lets list the tasks you need to do:

  1. Create a copy of the development template setup package in a new directory.
  2. Copy all the files that form your application in the appropriate location in it and remove the unneeded files from the template package.
  3. Edit carefully the setup.cfg to include all the files your application uses and inspect and change as needed some of the setup settings.
  4. Test the setup. You may use another machine or uninstall (and clean up) the template from your development workstation.

Now lets consider each step in more details. We will assume that you will not change the setup structure drastically - which is not needed for the most applications. You may need to change the setup structure if the application you are building is very complex and certainly if you are going to distribute it together or as part of a bigger project. However, this is out of the scope of this step--by-step guide.

1. We will assume that the directory in which we will create the setup package is C:\MyToolbar

Our first task is to copy/unpack the original setup package from the development template. Doing so we preserve its structure (i.e. subfolders and so on).

2. We need to copy our files from the work directory. This is the directory named "tb". Copy the files from your work location there replacing the files from the template with your files. If you have created subdirectories under it copy them too. After that you can take a look and clean up any unnecessary files - for example files from the template package you are not going to use.

Before continuing check the toolbar.cfg to make sure everything is ok. Redesign the AutoShow.htm if you are going to use it - this is the page that shows your toolbar automatically after the setup (unless the user security settings are too high). Check if you have the introductory pages in place (one often forgets these) - this can be combined in the AutoShow page if the instructions are not too big. Anyway it is a good idea to explain what the toolbar does to the user and show this after the setup. Today's concerns about the security are making this very important - you must gain the user's trust by telling him/her what your toolbar does and how to work with it from the beginning. Failing to do so may cause many users to disable or even uninstall it very soon as they would prefer to avoid something they do not understand! This is very important for IE plug-ins because in contrast to the other applications the IE toolbars are with the user almost all the time.

3. The most important step - the setup.

 

 

newObjects Copyright 2001-2006 newObjects [ ]