ASPCompiler Embedded Compile Time script
ASP Compiler 1.1 documentation is under development. See also the examples.

Tutorial: Writing an embedded Compile Time script

This tutorial teaches you how to write simple Compile Time scripts embedded in HTML or ASP page. It begins with "Hello World!" and is good for both beginners and advanced developers.

The corresponding sample is  in the <ASPCDIR>\Samples\tutorials\embeded (see the shortcut to the samples in the ASPC's group in the start menu).

Introduction

HTML pages will be used in the tutorial. The same techniques can be used with ASP pages as well. 

If you want to follow the tutorial create a new project and create the mentioned files or open the corresponding sample.

The first step in this tutorial may look like a "try to do nothing writing some code" but they are the easiest way to show the basics of the compile time scripting. After passing through them you can see the other tutorials that deal with data bases and once written provide powerful way to generate and regenerate part or the entire site using templates.  Thus please excuse us if the "Hello World!" steps are a little boring - there is no better way to show how one tool works. 

Step 1: Say "Hello World!"

Let name the first page a.htm. Set its processing option to SSIToHTML. We will insert an embedded CTS in it and produce simple output in the output file during the compilation. What the embedded script looks like:

<html>
<body>
<p>
  The first CTS script will write Hello World below
</p>
<p>
   <font color="#FF0000">
      <SCRIPT RUNAT=COMPILER LANGUAGE=VBSCript>
        node("Class") = "Text"
        node("Content") = "Hello World!"
      </SCRIPT>
   </font>
</p>
</body>
</html>

The CTS is placed in <SCRIPT> tag with attribute RUNAT set to COMPILER (case insensetive). The syntax is similar to the scripts in DHTML but RUNAT attribute specifies that the compiler shall execute it. 

What is the "node"? The script uses the node object that is always available for the embedded compile time scripts and represents the page node in which the script is written. Thus the node object in this example represents the entire <SCRIPT> tag.

ASPC translates the entire file in a tree of objects - Page Object Model (POM). Thus the document parts are represented as nodes in a tree. The node object above is an alias for the document node containing the invoked script. There are several node types, but we will concentrate on two of them at this moment:

Text node - this is anything outside any ASPC special tags or ASP tags.
CompileTimeScript (CTS) node - this is a node designated in the page source with <SCRIPT RUNAT=Compiler>...</SCRIPT> tag.

The above page will be presented to the script in it as a chain (in this simple case the tree has no branches) of 3 nodes: Text, CTS, Text. Thus in the above example everything outside the SCRIPT tag in not interesting for the compiler and is treated as some kind of text.

Nodes are collections of attributes and sub-nodes (sub-nodes may appear only if CUSTOM tags are used - discussed later). Every element of the collection can be accessed using nodeObject("name") or nodeObject.Item("name") syntax (Item is the default property of the nodes) or they could be enumerated as collection.

All the nodes have common (and vital) attribute - Class. It specifies the role of the node. After completing the execution of any compile time scripts ASPC will cycle through the page's tree and depending on the role of each node will produce different output in the output file.

Thus the compile time script does its work by inspecting and modifying the Page Object Model (the document tree). Therefore we deal with two node types in the above example - Text and CTS nodes. The script in the <SCRIPT> tag "knows" the node it occupies in the document through the node variable passed by the compiler. Its Class attribute is initially "CompileTimeScript" - e.g. node("Class") contains "CompileTimeScript" when the script starts. During its execution the script can change this attribute and thus change the node role - in this case its own node role. In other words the script is able to replace self with something else. The example sets the node("Class") to "Text". That means the node role is changed to Text node. After executing the script the compiler will have a tree containing 3 Text nodes and it will generate 3 chunks of text sequentially in the output file.

The Content attribute is set to the string "Hello World!" by the second script line:
node("Content") = "Hello World!"
The Content attribute is the second attribute common for the most node types (except some special node types not intended for the compile time scripts). It contains as a string the node content. Thus initially the node("Content") contains the source of the embedded script. After its execution it contains "Hello World!".

And the output from the above code will be:

=== BEGIN ===

The first CTS script will write Hello World below

Hello World!

=== END ===

What will happen if the first line is removed - e.g. Class not set to "Text"? The output will be:

=== BEGIN ===

The first CTS script will write Hello World below

=== END ===

The ASPC hides the nodes with class "CompileTimeScript" thus it will reconstruct in the output file only the other two nodes - the Text nodes only. And if the script should produce output depending on a condition it needs to do something only when the output is to be produced.

Conclusion: The CTS sees the processed page as tree of objects representing the page parts. Although it looks similar to the DHTML document model in ASPC page object model is limited to the parts designated by the ASPC special tags only. The script has direct access to the node it occupies. The script is able to change the role and content of its own node and thus modify the document tree. If the script does not change its own node - the entire script tag will be omitted in the output. 

Step 2: Obtain information from the outer world using the compiler variables.

The example in the previous step does nothing useful - we can write this text ourselves in the page. Thus let's make it a bit more useful.

Let change the <SCRIPT> like this:

<html>
<body>
<p>
  The second CTS script will put compiler 
  variable defined in the project
  settings below
</p>
<p>
   <font color="#FF0000">
      <SCRIPT RUNAT=COMPILER LANGUAGE=VBSCript>
        node("Class") = "Text"
        node("Content") = GlobalVariables("var1")
      </SCRIPT>
   </font>
</p>
</body>
</html>

What are the GlobalVariables? The compiler passes to the embedded script a collection of variables defined by the user in the "project settings" dialog (Button Compiler variables). Every variable has a name and a string value. Thus by changing the value in the project settings dialog the user instructs the embedded script to produce different output. And if we set the variable "var1" to the value "Blah" the output will be:

=== BEGIN ===

The second CTS script will put compiler variable defined in the project settings below

Blah

=== END ===

Well this is a bit more useful indeed. We can change some little texts in all the pages in the project if they contain a little simple script in the place where we want to put the configured text. For example this could be the Title, or the copyright note (if the year in it must be changed).

But what if we want to be able to specify something for a specific file only? Then we can change the code to:

<html>
<body>
<p>
  The third CTS script will put compiler 
  variable defined for the current file below
</p>
<p>
   <font color="#FF0000">
      <SCRIPT RUNAT=COMPILER LANGUAGE=VBSCript>
        node("Class") = "Text"
        node("Content") = Variables("var1")
      </SCRIPT>
   </font>
</p>
</body>
</html>

This will get the value of the variable specified in the File options dialog (Button Compiler variables) for the selected file.

And finally let us implement something that will produce more output:

<html>
<body>
<p>
  The forth CTS script will put compiler 
  variable defined for the current file below.
  It will be repeated several times.
</p>
<p>
   <font color="#FF0000">
      <SCRIPT RUNAT=COMPILER LANGUAGE=VBSCript>
        node("Class") = "Text"
        Dim count, I
        count = CInt(Variables("RepeatCount"))
        node("Content") = ""
        For I = 1 To count
          node("Content") = node("Content") & Variables("var1") & "<BR>"
        Next
      </SCRIPT>
   </font>
</p>
</body>
</html>

 If we set in the File options dialog the RepeatCount variable to 6 and var1 to "Hello World again!" the output will be:

=== BEGIN ===

The forth CTS script will put compiler variable defined for the current file below. It will be repeated several times.

Hello Wrold again!
Hello Wrold again!
Hello Wrold again!
Hello Wrold again!
Hello Wrold again!
Hello Wrold again!

=== END ===

Conclusion: By using the compiler variables named values can be defined for the entire project (gloabal) and for each file (local) in it. The global (project wide) variables are available to the script through the GlobalVariables collection and the local (file specific) variables are available to the scrip through the Variables collection.

Step 3: Make something more useful - an embedded script producing visual element.

Create a file named b.htm (or see the b.htm in the sample project):

<html>
<body>
  <p>
    The CTS script will construct an image button below
  </p>
  <p>
    <SCRIPT RUNAT=COMPILER LANGUAGE=VBSCript>
      node("Class") = "Text"
      Dim text
      text = "<IMG SRC=""" & Variables("IMGOFF") & """ STYLE=""cursor:hand""" & _
        " onMouseOver=""event.srcElement.src='" & Variables("IMGON") & "'"" " & _
        " onMouseOut=""event.srcElement.src='" & Variables("IMGOFF") & "'""" & _
        " onClick=""alert('" & Variables("Message") & "')"">"
      node("Content") = text
    </SCRIPT>
  </p>
</body>
</html>

This will produce a button-like element that changes its image when the mouse is over it and does something when clicked. In the sample all the code is written inline (in the IMG tag's attributes), but this could be easily changed to something more productive.

The script expect the compiler variables to specify the image for "off" state and "on" state and the message text to be shown when the image is clicked. Thus if some of the dynamic elements of the site are generated this way they all can be changed at once by changing a few variables. In the sample project file specific variables are used - in real case usage of global variables make more sense, because it will affect all the pages in the project and not only one of them.

Well it looks ok but should we repeat all this code in every page we create? Of course not! After testing a code like above you are able to perform the next step - moving it in a separate file and just refer it. Let create a file script1.vbs in the same directory where the HTML file resides and put in it:

    node("Class") = "Text"
    Dim text
    text = "<IMG SRC=""" & Variables("IMGOFF") & """ STYLE=""cursor:hand""" & _
        " onMouseOver=""event.srcElement.src='" & Variables("IMGON") & "'"" " & _
        " onMouseOut=""event.srcElement.src='" & Variables("IMGOFF") & "'""" & _
        " onClick=""alert('" & Variables("Message") & "')"">"
    node("Content") = text

And change the script tag in the above HTML file to:

<SCRIPT RUNAT=COMPILER LANGUAGE=VBSCript SRC="Script1.vbs">
</SCRIPT>

(Corresponding file in the example project -  c.htm).

This will produce the same result but now it is much easier to put it in many pages. the script is loaded from the external file and is one for all the pages referring it. Now a site with many pages using this script will be a bit more easier.

A little digression: What really happens above? Is it possible to use this SRC attribute that refers the script file, but also put some code in the SCRIPT tag? The answer is "yes". This feature could be very useful in some phases of development when part of the code is common and other part uses the common part as library.

(... tutorial text not finished yet ...)

newObjectsSite4All.nl Copyright 2001-2006 newObjects [ ]