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
                ...) 
               
             |