JScript in DOpus: Initial questions

I have now read and worked through much of Dino Esposito's "JScript Tutorial" at
http://www.inf.unideb.hu/~fazekasg/oktatas/VBScript/JScript_%20tutorial.doc
and I've also read quite a bit of the JScript material in Stanek's "Powershell, VBScript and JScript Bible". All this I can follow and implement with the necessary effort, but although I can now edit other people's DOpus scripts a little, the "Scripts" sections of the DOpus manual are just not making sense to me at all, despite hours and hours of reading. (My previous experience has been with TeX, DOS and TurboBasic, none of which has objects, and pure mathematics.) I will therefore suppress my embarrassment and self-criticism to ask some extremely basic initial questions, because I think my confusions lie at the very beginning.

  1. WScript and DOpus:
    (a) I have been using WScript to run JScript files. Is it possible to use WScript in a rename script, a button script, or a script addin?
    (b) In particular, WScript.Echo (". . .") doesn't seem to work, so is there an easier way to print something to the screen than
    dlg = clickData.func.Dlg
    dlg.message = "Hello World"
    dlg.Show
    (c) In Windows, VBScript and JScript can be combined within an XML wrapper in a .wsf file. Is that sort of thing possible within a DOpus rename script, button script or addin?
    (d) When there are errors in the code, WScript prints to screen a careful statement of the problem and the line and column where it occurred. At the moment, all I get from a faulty DOpus button script is silence. Is there a way to reproduce the WScript text?

  2. The DOpus object:
    (a) Are all the usual objects in JScript accessible from within DOpus? Can ordinary JScript procedures be used within DOpus scripts?
    (b) Have any objects been added to JScript besides the DOpus object? What are all the new functions? Are they all part of the DOpus object, or have other things been added? In particular, why can "OnClick" and "clickData" be used on their own without having been defined before, and what exactly are they anyway?
    (c) What is "ByRef"? Or is it only a VBScript object?

  3. . . . and two really basic questions to get me started on a particular problem that I want to solve:
    (a) How (in a button script) do I read the path of a selected file into a new string? Presumably something like
    TheFilePath = new String (DOpus.PathOfSelectedFile)
    (b) What is meant by the sentence, "You can create a new Path object from a string (or another Path) using the DOpus.NewPath method." (DOpus Manual, p791)

1(a) It depends what you want to do I guess, but you can instantiate the WScript-provided objects and use them like any other object.
1(b) An object named WScript doesn't exist by default, so WScript.Echo won't work (although possibly you could create the object and then use it? Dunno). But you can print a string to the script log (see below) using DOpus.Output.
1(c) No I don't think so.
1(d) The script log shows errors and also text you print using DOpus.Output. If you get an error you should see a blinking ! icon on the status bar that you can click to display the log, but otherwise you get to it from the Help -> Logs -> Other Logs menu command.

Combining the above, the following will print the path of your desktop folder to the script log:

@script jscript shell = new ActiveXObject("WScript.Shell"); DOpus.Output(shell.SpecialFolders("Desktop"));

2(a) As far as I know, yes. The JScript interpreter is independent of Opus.
2(b) Opus is acting as the scripting host in the same way wscript.exe does. wscript.exe adds a global WScript object to the script namespace - Opus adds the global DOpus object, which has various methods and properties. "OnClick" etc are just function names that Opus queries the script for - these aren't added by Opus - your script defines them if required, and Opus will look for them and invoke them as appropriate. "clickData" is just a placeholder variable name - you could call it "foo" if you wanted, all it means is the function is passed one parameter which is an object that has its own properties and methods.
2(c) It's a VBScript thing.

3(a) A button can access its selected files through the clickData.func.sourcetab.selected property.
3(b) What part of that sentence don't you understand? :slight_smile:

Thank you very much, jon, for these answers. They have been most helpful. I'm now much clearer about questions 1 and 2, and I feel that I am now making progress, getting output in the log and in a message box from a script button and from the CLI.

I'm still unclear about Question 3.

3.(a) The command DOpus.Output (clickData.func.sourcetab.selected) prints "2033150" into the log rather than the paths of the selected files or folders. Obviously I'm badly misunderstanding some simple thing.

(b) My problem with the sentence is that I don't know what the "DOpus.NewPath method" is. There are many other such methods mentioned in the manual, so I am clearly missing something very significant and basic about defining objects.

Given that you referred to a page number (721) I'm going to guess you're using the PDF manual. This is probably not the best choice. If you were using the F1 help or the help on the website, you'd find that sentence includes a link that takes you to the appropriate page.

You need to have a look at the Scripting Reference section of the online manual (or via the F1 help). Then to answer 3(a) it's just a matter of going to clickData, from there to func, from there to sourcetab and looking up the selected property where you would find:

(and of course the word Item in that description is also a link).

The Simple Script Function example in the manual includes an example of using an enumerator to examine a collection of Item objects (in this example it comes from clickData.func.sourcetab.files but the selected collection is handled the same way).

Got it! The example script was very clear, and when only one filename is selected, it can be done in just two lines:
enumFiles = new Enumerator(clickData.func.sourcetab.selected);
DOpus.Output (enumFiles.item().name)

Once again, thanks very much, jon, and you are right that the web form of the "Help" file is easier to handle.

3.(b) But I'm still stuck on my final question, which now has an added confusion — the .pdf manual (p791) talks about the "DOpus.NewPath method", and the online manual at the very same place talks about the "Opus.FSUtil.NewPath method". I understand neither, and I thus still seem to be missing some vital elementary way to create a new object.

The PDF manual is a bit out of date. At some point in the past the old "DOpus.NewPath" method was deprecated (although it still works for backwards compatibility) as it made more sense to move towards using factory objects to create new instances of various other objects.

So if you want a Path object, you can simply do:

path = DOpus.FSUtil.NewPath();

Again, use the script reference manual to find the DOpus object, from there FSUtil and from there look up the NewPath method.

Thanks you, jon, for the third time. So straightforward — I had of course misunderstood the word "method" to mean "procedure" rather than a method attached to an object. After these exchanges, I feel more confident that I can now steadily learn things using the various resources.

No worries! Please ask if you have any other questions!

Only one problem now remains in the first task that I have set myself. In a button script, the command:
ClickData.Func.Command.RunCommand ("Go " + ThePathString + " OpenInDest");
works fine when there are no spaces in the path, but it fails when the ThePathString has spaces.

How do I change to a directory with spaces? Even this very simple command fails:
ClickData.Func.Command.RunCommand ("Go C:\Program Files");
and despite my searching of the online manual and my googling, all sorts of inventive substitutions of the space, and alternations of single and double quotes, do not solve the problem.

You need to put quotes around the path name, like in a normal (non-scripted) button.

In JScript you can do this by putting a backslash before the quote mark:

ClickData.Func.Command.RunCommand ("Go \"" + ThePathString + "\" OpenInDest");

They do at times, see this.. o)

RunCommand('Go "' + ThePathString + '" OpenInDest');

Thanks, jon and tbone — I now understand escape characters better, and I will now alternate ' and " the right way around.

I have completed a button-script, which I will post here to show jon that I am learning something, and to express my appreciation for jon's careful and patient help. I won't put it in the "completed scripts" section because it seems rather too specialised. The purpose of the script is to sit at one computer with DOpus running in some source directory, and in the other panel, open the parallel directory in one of the other computers on our home network (the computers are constantly synced with each other using GoodSync, but they don't all have the same directories).

The problem is that two of the computers are HP computers on which everything is in C: drive because HP has helpfully reserved D: drive for its Windows backup (grrr!). Hence with these two computers, the parallel directories to D: drive and Y: drive are respectively C:@Data and C:@Archive. That complexity made the task impossible without a script, and the script in turn made error messages possible.

@script jscript

function OnClick (ClickData) {
  DOpus.Output ("- - - - - - - -");

// STEP 1: Initialise the variables and read in the source path to a string.
  var dlg = DOpus.Dlg;
  var TheComputer = new String ("");
  var Choice = new String (null);
  var TheType = new String ("");
	
  ThePath = new String (ClickData.Func.SourceTab.Path);
  var TheNewPath = ThePath;
  DOpus.Output (ThePath + " is the source path.");

// STEP 2: Strip the computer name off the path.
// Strip the drive off the path, and replace it with shared name on the network.
// Deal with the C:\@Data and C:\@Archive problems on two computers.

  if (TheNewPath.substr(0,2)=="\\\\") {
    TheNewPath = TheNewPath.substr(2);
	TheNewPath = TheNewPath.substr(TheNewPath.indexOf("\\"));
  }

  if (TheNewPath.substr(0,8)=="C:\\@Data")
    TheNewPath = "\\DDrive" + TheNewPath.substr(8);
  if (TheNewPath.substr(0,11)=="C:\\@Archive")
    TheNewPath = "\\YDrive" + TheNewPath.substr(11);
  if (TheNewPath.substr(0,2)=="C:") 
    TheNewPath = "\\CDrive" + TheNewPath.substr(2);

  if (TheNewPath.substr(0,2)=="D:")
    TheNewPath = "\\DDrive" + TheNewPath.substr(2);
  if (TheNewPath.substr(0,2)=="Y:")
    TheNewPath = "\\YDrive" + TheNewPath.substr(2);
  DOpus.Output (TheNewPath + " is the path stripped and provided with its shared name.");

// STEP 3: Set TheType to invalid if these processes had no effect, and issue an error message.
  if (ThePath==TheNewPath) {
    TheType = "invalid";
	DOpus.Output ("The stripping processes had no effect, and the operation has therefore failed.");
	dlg.window = DOpus.Listers(0);
    dlg.message = "Locations parallel to\n\n" + ThePath + "\n\ndo not exist or are inaccessible.";
    dlg.title = "The operation has failed";
    dlg.buttons = "OK";
	dlg.icon = "warning";
    dlg.show ();
  } else {

// STEP 4: If everything is OK so far, select the target computer.
    dlg.window = DOpus.Listers(0);
    dlg.message = "Choose the target computer:";
    dlg.title = "Open the parallel directory";
    dlg.buttons = "&Munsalvaesche|&Pelrapeire|Mant&ua|&Heorot|Ma&lvern|&Aachen|&Cancel";
    Choice = dlg.show()
    if (Choice == 1)
      TheComputer = "Munsalvaesche";
    if (Choice == 2)
      TheComputer = "Pelrapeire";
    if (Choice == 3)
      TheComputer = "Mantua";
    if (Choice == 4)
      TheComputer = "Heorot";
    if (Choice == 5)
      TheComputer = "Malvern";
    if (Choice == 6)
      TheComputer = "Aachen";

// STEP 5: Set TheType to invalid if the parallel directory does not exist.
    TheNewPath = "\\\\" + TheComputer + TheNewPath;
    DOpus.Output (TheNewPath + "is the parallel path on the target computer.");
    TheType = DOpus.FSUtil.GetType (TheNewPath);
    DOpus.Output ('"' + TheType + '" is the GetType type of the new path.');
  
// STEP 6: Open the parallel directory in the target computer, or issue an error message.
    if (!(TheType=="invalid")) {
      ClickData.Func.Command.RunCommand ('Go "' + TheNewPath + '" OpenInDest');
      ClickData.Func.Command.RunCommand ("Set Focus=Toggle");
    } else {
      dlg.window = DOpus.Listers(0);
      if (Choice == 0) {
        dlg.message = "The operation has been cancelled";
        dlg.title = "Operation cancelled";
      } else {
        dlg.message = "For the computer " + TheComputer + ", the location parallel to\n\n" + ThePath + "\n\ndoes not exist or is inaccessible.";
        dlg.title = "The operation has failed";
      }  
      dlg.buttons = "OK";
      dlg.icon = "warning";
      dlg.show ();
    }
  }
  
  DOpus.Output ("- - - - - - - -");
}

Compared to your initial questions, this is surely to be called progress! Congrats! o)