JScript doesn't support the VBScript InputBox function, and WSH doesn't provide a method for user input. For example, you can't use a command such as the following, which you might recognize from HTML scripts:
var txt = window.prompt("WSH sample ", "Name: "); |
You can't use this command because WSH doesn't provide a window object or a prompt method. To overcome these limitations, you can use the solutions described in the following sections.
In WSH 2, you can combine multiple scripts in a single .wsf file. If JScript doesn't support a particular function but VBScript does, you can combine the two languages in one .wsf file. For example, you can write a user-defined VBScript function to expose the InputBox function to a JScript script program that's included in the .wsf file, as shown here:
Function WSHInputBox(Message, Title, Value) ' Provides an InputBox function for JScript ' Can be called from JScript as: ' var result = WSHInputBox("Enter a name", "Input", test); WSHInputBox = InputBox(Message, Title, Value) End Function |
This code uses an ordinary user-defined VBScript function named WSHInputBox. (The function has this name to avoid a naming conflict with the original VBScript InputBox function.) The user-defined function has three parameters: Message contains the text shown in the dialog box, Title contains the title bar text, and Value is the default value shown in the text box. WSHInputBox passes the parameters received from the caller to the corresponding parameters of the VBScript InputBox function. The following line assigns the result obtained from the InputBox function to WSHInputBox, which defines the return value of the user-defined function WSHInputBox:
WSHInputBox = InputBox(Message, Title, Value) |
After defining the WSHInputBox function, you can use it in JScript. The following code snippet defines two variables and calls the new function:
var title = "InputBox function for JScript"; var prompt = "Enter a name:"; var result = WSHInputBox(prompt, title, "New York"); |
The user input obtained from the dialog box is returned in the variable result. If the value is null, the user clicked the Cancel button. If result has any other value, the user clicked the OK button.
Listing 8-2, which runs only in WSH 2, assembles all these parts in one .wsf file. Both scripts are kept in one <job> element but in two separate <script> elements. Using one <job> element is required because the scope of a function or procedure is limited to the job in which the function or procedure is defined. The processing instruction on the first line forces validation of the file's content as a valid XML document:
<?xml version="1.0" encoding="ISO-8859-1"?> |
As a result, the content of the <script> elements must be inserted into CDATA elements (as described in Chapter 1). Figure 8-3 shows the input dialog box and two dialog boxes with input results.
Figure 8-3 An input dialog box and results created from a WSH 2 script
Listing 8-2 WSH2Input.wsf
<?xml version="1.0" encoding="ISO-8859-1"?> <job id="IncludeExample"> <script language="VBScript"> <![CDATA[ Function WSHInputBox(Message, Title, Value) ' Provides an InputBox function for JScript ' Can be called from JScript as: ' var result = WSHInputBox("Enter a name", "Input", test); WSHInputBox = InputBox(Message, Title, Value) End Function ]]> </script> <script language="JScript"> <![CDATA[ // This is the JScript script, which reads user input // and displays it in a dialog box. It uses the // VBScript function WSHInputBox to create the // dialog box. var vbOKOnly = 0; // Constants for Popup var vbInformation = 64; var title = "InputBox function for JScript"; var prompt = "Enter a name:"; // Create the WshShell object (needed for using Popup). var WshShell = WScript.CreateObject("WScript.Shell"); // Open the input dialog box using a function in the .wsf file. var result = WSHInputBox(prompt, title, "New York"); // Test whether the Cancel button was clicked. if (result != null) { // Cancel wasn't clicked, so get input. var intDoIt = WshShell.Popup("You entered: " + result, 0, "Result", vbOKOnly + vbInformation); } else { // Cancel button was clicked. var intDoIt = WshShell.Popup("Sorry, no input", 0, "Result", vbOKOnly + vbInformation); } //*** End ]]> </script> </job> |
The solution you've learned so far for retrieving user input in JScript works well in WSH 2. Because WSH is designed to act as the "glue" for assembling objects and methods into one application, you can use other ways to retrieve user input in JScript. To prepare for Chapter 9, which deals with forms, let's now look at how to access Microsoft Internet Explorer and use an input box method.
If you've programmed scripts in HTML documents using JavaScript, you're probably familiar with the prompt method, which retrieves user input as shown here:
var result = prompt("Please enter a name", "Chicago"); |
The prompt method has two parameters: the first contains the string shown in the input dialog box, and the second is the default value in the text box.
The Internet Explorer object model supports the prompt method, but the WSH object model doesn't provide a similar method, so to use prompt in your WSH JScript programs you need a technique to "incorporate" Internet Explorer objects into your WSH scripts. (You can also use this technique for other objects, and it works for either WSH 1 or WSH 2 as long as the objects are accessible.)
To use Internet Explorer and its objects from a WSH script, you must obtain a reference to the Internet Explorer Application object. You can use the following JScript statement to create the object:
var oIE = WScript.CreateObject("InternetExplorer.Application"); |
This statement does two things. First, it loads an instance of the object into memory, which means that an instance of Internet Explorer is launched. Second, it stores a reference to this object in the object variable oIE, which you can use later to access the properties and methods of the Application object.
Unfortunately, the prompt method isn't part of the Application object; it's a method of the Script object, which is a subobject of the Document object, which is in turn a subobject of the Application object. Therefore, you must obtain a reference to the Script object. This part of the Internet Explorer object model is depicted in Figure 8-4.
Figure 8-4 Part of the Internet Explorer 4 and Internet Explorer 5 object model
Before you can create a reference to the Document object, a document must be loaded into the Application object. The Script subobject is supported automatically whether or not the document contains script code (because Internet Explorer also supports internal script commands). Therefore, you can use the object hierarchy to access the prompt method of the Script object.
We haven't yet reached our final destination. The browser requires that the document be loaded before the Document object is accessible. Also, you don't want to see the browser window on the desktop—you need only the input dialog box. Loading a document and hiding the browser window might seem complicated, but the solution is rather simple. To load a document into the Internet Explorer Application object, you can use the navigate method of the Application object. To use a method, you simply write the object name, a dot, the method name, and then the required parameters. Thus, you can load a document into Internet Explorer using the following (JScript) statement:
oIE.navigate("about:blank"); |
This command uses the navigate method of the object variable oIE (which contains a reference to Internet Explorer's Application object instance). The parameter submitted to the method uses a little trick: because you don't need a real document, you can submit the internal resource "about:blank" to force Internet Explorer to display a blank document page (the same thing you'd get if you typed the URL about:blank in Internet Explorer's address bar).
To hide or show the browser window, you can use the Visible property of the Application object:
oIE.Visible = 0; |
In this statement, the Visible property is set to 0, which hides the browser window. The value Visible = 1 shows the browser window. Because the default value for Visible is 0, you need no oIE.Visible statement within your code.
After these preliminary steps, you could try to get a reference to the Script object in order to call the prompt method. Unfortunately, Script objects are children of the Document object, and the Document object is inaccessible while Internet Explorer loads a document. Because you have two processes (the script and the browser) running asynchronously, any attempt to retrieve a reference to the Script object might fail. Instead, the script should wait until the browser has loaded the document.
You could use the Busy property, which the browser uses to flag its internal state. This property provides a simple and reliable way to check whether the browser is ready to call methods. If Busy is set to true, the browser is loading the document (and no calls are allowed).
The loop used within the following statement delays the script until Internet Explorer is ready to load the document:
while (oIE.Busy) {} |
If the browser is ready for further queries, you can create a reference to the Script object using the following JScript statement:
var obj = oIE.Document.Script; |
After this statement is executed, the object variable obj contains a reference to the Script object. You can then use a statement such as the following to call the prompt method:
var input = obj.prompt("Enter a name", "Chicago"); |
The first parameter defines the text in the dialog box, and the second parameter contains the default input value, as shown in Figure 8-5.
Figure 8-5 An input dialog box invoked using the prompt method in JScript
The title bar is filled from Internet Explorer, and the string "JavaScript Prompt:" is inserted from the browser (Internet Explorer 5 in this example).
NOTE
I've discussed this Internet Explorer example in depth because many macro programmers don't understand the advantages of programming with objects. When I began programming with objects, I had similar doubts. But once I realized that you need only six JScript statements to embed a feature from another application into a WSH script, I decided that programming with objects is the best thing since sliced bread. In my book Advanced Development with Microsoft Windows Script Host 2.0, I'll introduce scripts that use features from Microsoft Word, Microsoft Excel, Microsoft Outlook, and other applications using similar techniques.
To simplify the use of the prompt method in JScript, I put all the code that interacts with Internet Explorer into a simple function, MyPrompt. (I chose the name MyPrompt, and not Prompt, to avoid naming conflicts with the prompt method itself.) The following JScript code uses this function.
// A helper function to view a prompt window function MyPrompt(text, value) { // Create Internet Explorer application object. var oIE = WScript.CreateObject("InternetExplorer.Application"); oIE.navigate("about:blank"); // Empty HTML document oIE.Visible = 0; // Keep Internet Explorer invisible. while (oIE.Busy) {} // Important: Wait until Internet // Explorer is ready. var obj = oIE.Document.Script; // Get scripting object. var input = obj.prompt(text, value); // Open prompt window. oIE.Quit(); // Close Internet Explorer object. return input; } |
In addition to the statements discussed earlier, the function calls the Quit method of the Internet Explorer Application object using the following statement to terminate Internet Explorer and release the object:
oIE.Quit(); |
The next statement is required to return the user input obtained from prompt to the calling script:
return input; |
Using the function MyPrompt requires one statement:
var temp = MyPrompt("Enter a name", "Chicago"); |
MyPrompt returns a string containing the user input if the user clicked the OK button. If the user clicked the Cancel button, MyPrompt returns the value null. You can use the following code to check the return value:
if (temp != null) // Check return value. |
Listing 8-3 contains a full implementation of these code snippets. The script invokes an input dialog box, examines the user input, and shows it in a second dialog box.
Listing 8-3 Input1.js
//*************************************************** // File: Input1.js (WSH sample in JScript) // Author: (c) G. Born // // Retrieving user input in JScript using the prompt // method. The script uses Internet Explorer. //*************************************************** // A helper function to view a prompt window function MyPrompt(text, value) { // Create Internet Explorer application object. var oIE = WScript.CreateObject("InternetExplorer.Application"); oIE.navigate("about:blank"); // Empty HTML document oIE.Visible = 0; // Keep Internet Explorer invisible. while (oIE.Busy) {} // Important: Wait until Internet // Explorer is ready. var obj = oIE.Document.Script; // Get scripting object. var input = obj.prompt(text, value); // Open prompt window. oIE.Quit(); // Close Internet Explorer object. return input; } // Here goes the main program. var temp = MyPrompt("Enter a name", "Chicago"); if (temp != null) // Check return value. { WScript.Echo(temp); } else WScript.Echo("No input"); //*** End |