Welcome to the Simpler framework documentation index. Here you will find detailed written documentation to assist with your development needs. 

This is supplemental and detailed documentation, versus the overview found on the main Developer page.

 

Search for a topic:

Environment Setup

Overview

The following is a guide to help setup the initial environment for the Simpler platform for client-hosted sites, and/or a development workstation.

System Requirements

While the latest and greatest hardware and software are always recommended, the following are the minimum requirements to run the Simpler platform:

Hardware Requirements

The following hardware requirements* must be met:

  • 4GB of RAM or greater
  • 2 Logical CPU cores or more
  • 2GB of free disk space for temporary files (application binaries and templates are <100MB) 
  • Additional storage for synchronized tables (to be determined based on scope and data source(s))

* These are minimums. Additional CPU and RAM resources may be necessary based on usage.

Software Requirements

Simpler is developed in .NET, and runs on Windows Server. Requirements are:  

  • Windows Server 2008 R2 or higher (Server)
  • SQL Server 2008 R2 or higher
    • Database size set to 10% unlimited growth
    • Truncate transaction logs set to “Yes”
    • Scheduled weekly full backup – recommended
    • Create an application user with read/write privileges
  • .NET 4.0 or higher
    • automatically be installed with Microsoft Visual Studio
  • Text editor or IDE
    • Visual Studio IDE recommended
  • IIS 6.0 or higher (only required on web server)
  • Browser
  • Gurock SmartInspect Redistributable Console

.NET 4.0 or higher

Simpler Systems requires the full installation of .NET 4.0 framework. The desktop profile may not provide the full installation. For example, Windows 7 will have .NET but not the full components. Installing Microsoft Visual Studio as recommended in the next section will make sure that all components necessary for development are available.

Text Editor

While any text editor will work, including Notepad, Simpler Systems recommends Visual Studio 2010 (VS 2010 Express C#) or higher; .NET 4.0 will automatically be installed when we install Visual Studio. Whichever editor we choose, Simpler recommends an editor with an XML interpreter, so we will have access to the Intellisense and auto-complete functionality.

Internet Information Services (IIS) 6.0 or higher

Internet Information Services (IIS) is an extensible web server created by Microsoft for use with Windows servers. IIS supports HTTP, HTTPS, FTP, FTPS, SMTP and NNTP. IIS is not activated by default when Windows is first configured. The IIS Manager is accessed through the Microsoft Management Console or Administrative Tools in the Control Panel.

Gurock SmartInspect Redistributable Console

SmartInspect is a third party logging tool for debugging and monitoring .NET,
Java and Delphi applications. SmartInspect allows us to identify bugs faster,
and monitor applications in real-time, allowing us to find solutions to user-reported
issues. Go to www.gurock.com/smartinspect for more information.

  1. Download and install executable here (will prompt .exe file download).
  2. See Gurock Support page for FAQs and tutorials.

Installing Simpler Application

The following instructions will install the Simpler application on our workstation/server. The Simpler application has been developed to install and execute identically locally and on servers, with the only difference being IIS for web services.

Install

  1. With a valid license to use Simpler, we will receive a zip folder (simpler.zip) containing all the necessary default files and binaries to run the application. 
  2. Save simpler.zip to a directory of your choice. 
  3. Extract the contents of the zip file into the same folder. Voila!
    The Simpler application is installed. It’s that simple. There are no registry changes,
    and no security is needed at this point.

Uninstall

To uninstall, simply delete the entire contents of the /../Simpler folder from its root directory.

Updates

 

Folder Contents

The simpler.zip folder may actually contain more than the following, but the stripped down application folder described below reflects the required (or at least extremely convenient) contents to have with a fresh build.

rootfolder.PNG

Root folder

  • Configuration.xml - A configuration file for global application settings.
  • custom-frame.xml - The fully customizable frame banner at the top of the browser window
  • helloworld.xml - A simple template provided for Tutorial demonstration.
  • simpler.exe - An executable file that starts the Simpler Server (sssvr.exe) in /bin folder.
  • Template.xsd - Defines the template schema allowing xml editors to provide IntelliSense.
  • web.config - Contains configuration settings redirecting web pages to the simpler server for interpretation
    • only needed for "live" IIS applications

Bin folder

binfolder.PNG
  • dynamic link libraries (DLL files)
  • simpler.dll
  • other third party DLLs
  • executable files (.exe)
  • ss.exe – The “SS Server” is the core of the simpler platform. It handles the interpretation of the XML templates and generates the HTML pages. Ss.exe can be called from the command prompt with a URL parameter and output destination.
  • sssvr.exe – The “SS Server” console provides a graphic interface to control the server. When this file is executed, the console is started. The console allows you to enable or disable an instance of the “ss server”, set a port to use, and provides a link to the start page using that instance of the server. Running the templates from the console allows the web pages to run through the browser without setting up a website in IIS.
  • ssupdate.exe – The “SS Update” feature automatically downloads and updates the bin folder.
  • Zip folders - The bin folder contains several zip folders (about, build,configure, dynamic, source & start) 

Zip folders

zipfolders.PNG

The bin folder contains several zip folders (about, build, configure, dynamic, source & start), which contain the default versions of the various XML templates contained within. They can be overridden by creating a folder in the root folder with
the same name, and including any template files you wish to override.

  • about - about.zip contains default built-in reference framework documentation for "hello world!", scripting, script functions, and system architecture
  • build - the most frequently overridden zip folder, build.zip defines the default XML build structure for dynamically-generated select, compose and search templates of a datapp. 
  • configure - configure.zip contains templates for updating global configuration settings, if we prefer to make changes through browser interface, versus through Configuration.xml in the root folder. 
  • dynamic - dynamic.zip stores the templates that drive the dynamic templates defined in build.zip, serving as an intermediary between the data itself and the datapp XML build templates.
  • source - source.zip contains templates for viewing source code and syntax highlighting.
  • start - start.zip stores the default start.xml template, which serves as the developer "Start" page, or dashboard interface, for administering the application through the browser. 

Starting Simpler Application

Start-up

1. Run simpler.exe in your root directory, which will load a local server command prompt:

localhostunchecked.PNG

2. You will notice three "Options" along the top: 

localhostoptions.PNG

Leaving everything else as the default, check the Enabled checkbox.

  • Enabled checkbox - Checking this box initiates the local server development environment
  • Allow Remote Access checkbox - Checking this box allows the site to be accessible in the local network, without being directly logged in to the workstation or server where the application resides
  • Port - This textbox controls the port for the local server to run from, which defaults to port 180. You can have as many instances of simpler.exe running on the same machine, so long as the port is distinct for each application root directory. 

3. You will see that the localhost server is now running, and a hyperlink has appeared in the upper-right corner of the local server command prompt:

localhost.PNG

 

 

Click the localhost:180/start.html link. This will allow you to
view the Start page in its basic form.

The Start Page

The Start page is the browser interface for everything the developer does. It provides a place from which to manage global configuration settings, authentication settings, database connection strings and application passwords.

It appears with various headings and links to the dynamic template builders such as Select, Compose, and Present templates, which will be explained in further sections of this guide. In its default state, the Start page appears as follows:

startpage.PNG

Configuration 

Overview

As developers, we have the ability to administer global settings for the Simpler application, as well as maintain connection strings and application passwords. Depending on our preference, we can control most of these settings from the Start page, or the configuration.xml file that should be in the root directory. 

From the Start Page

You can add or change application configuration elements from the start page, if a browser interface is preferred. We will elaborate on how to do so for each respective configuration type below.

From Configuration.xml

Some will want to control configuration elements directly in the XML, in a text editor instead of a browser interface. We will ultimately have more control and visibility if editing the XML directly.

Settings

Built-in Settings

Custom Settings

 

Data Sources

From the Start Page

From Configuration.xml

Application Passwords 

From the Start Page

 

Hello, World!

The Simpler framework is programmed with XML templates, which are XML documents enhanced with SimplerScript. The following walkthrough will introduce the essentials of the framework scripting and general structure. The walkthrough will use the Tutorial layer, which provides a basic set of printing and iteration services.

Getting Started

Localhost

To begin this Hello World tutorial:

1. Run simpler.exe in your root directory, and check the "Enabled" box in the top left corner of the command prompt that opens.

localhost.PNG

2. Then, in your browser's address bar, go to http://localhost:180/helloworld.xml

3. Open the file, helloworld.xml in your root application directory, and follow along with the tutorial below.

helloworlddirectory.PNG


Tutorial Layer

Below is the <Tutorial> template in XML + SimplerScript:

<?xml version="1.0" encoding="utf-8"?>
<Template Access="AllUsers" Description="Hello World Tutorial" xmlns="http://simplersystems.com/suite" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://simplersystems.com/suite ......\Template.xsd">
    <Tutorial>
        <Print>Hello World!</Print>
    </Tutorial>
</Template>

Result of this template:

The <Template> element declares that this is a Simpler XML template. The Access attribute specifies that this template is accessible by all users. There are also some required XML housekeeping attributes. The <Tutorial> element declares that this template will be using the services of the Tutorial layer. The <Print> element, when executed, writes its value to the output.


SimplerScript

Below is the Tutorial template enhanced with SimplerScript:

<?xml version="1.0" encoding="utf-8"?>
<Template Access="AllUsers" Description="Hello World Tutorial" xmlns="http://simplersystems.com/suite" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://simplersystems.com/suite ......\Template.xsd">
    <Tutorial>
        <Print>{'Hello ', 'World', '!'}</Print>
    </Tutorial>
</Template>
The literal "Hello World!" text has been replaced by a script. Scripts are delimited by curly braces { }. They can be used in any attribute or element.

Scripts are lists of strings, numbers, dates, or booleans. The script in this example is a list of three strings: the literal 'Hello ', the literal 'World', and the literal '!'.

After scripts are evaluated, they are assigned to an attribute or an element's value. In many cases, this means "reducing" a list of several values to a single value. Lists of strings are reduced by concatenation, lists of numbers are reduced by addition, and lists of booleans are reduced by the logical and operation. In this example, the list {'Hello ', 'World', '!'} is reduced to 'Hello World!'.

Result of this template:

Notice, the result in this case is the same as the unscripted version.

 

Identifiers

Below is another version of the Tutorial template, in which the literal 'World' has been replaced by an identifier, Name.

<?xml version="1.0" encoding="utf-8"?>
<Template Access="AllUsers" Description="Hello World Tutorial" xmlns="http://simplersystems.com/suite" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://simplersystems.com/suite ......\Template.xsd">
    <Tutorial>
        <Print>{'Hello ', Name, '!'}</Print>
    </Tutorial>
</Template>
When this script is executed, the value of the Name identifier is determined by the query string:


/helloworld.xml?Name=Calvin


Result of this template with Name=Calvin as the query string:


Result of this template with Name=Hobbes as the query string:


The "When" Attribute

Below is yet another version of the Tutorial template, which has a second <Print> element, and When attributes with scripts. Every element in an XML template has a When attribute that determines whether or not the element is processed. The When attributes contain scripts that compare the value of the Direction identifier to a literal string. The first <Print> element is executed when the value of Direction is 'Coming', and the second <Print> element is executed when the value of Direction is 'Going'.

<?xml version="1.0" encoding="utf-8"?>
<Template Access="AllUsers" Description="Hello World Tutorial" xmlns="http://simplersystems.com/suite" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://simplersystems.com/suite ......\Template.xsd">
    <Tutorial>
        <Print When="{Direction = 'Coming'}">{'Hello ', Name, '!'}</Print>
        <Print When="{Direction = 'Going'}">{'Goodbye ', Name, '!'}</Print>
    </Tutorial>
</Template>
Result of this template with Name=Calvin&Direction=Coming as the query string:


Result of this template with Name=Calvin&Direction=Going as the query string:


Conditional Scripting 

The next version of the Tutorial template implements the same functionality as the previous version, but uses the SimplerScript when keyword instead of the When attribute. Every element in a list can be followed by a when clause. The expression following the when keyword determines whether or not the element is included in the list.

<?xml version="1.0" encoding="utf-8"?>
<Template Access="AllUsers" Description="Hello World Tutorial" xmlns="http://simplersystems.com/suite" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://simplersystems.com/suite ......\Template.xsd">
    <Tutorial>
        <Print>{'Hello ' when Direction = 'Coming', 'Goodbye ' when Direction = 'Going', Name, '!'}</Print>
    </Tutorial>
</Template>
Result of this template with Name=Calvin&Direction=Coming as the query string:


Result of this template with Name=Calvin&Direction=Going as the query string:


Complex Conditions

More complex conditional scripting can be achieved with the logical "and", as well as logical "or" operations.

The first <Print> element is executed when the value of Direction is 'Coming' AND the value of Greeting is 'Y', so both must be true to print the text.

The second <Print> element is executed when the value of Direction is 'Going' OR the value of Greeting is 'Y', so one identifier or the other must be true to print the text.

<?xml version="1.0" encoding="utf-8"?>
<Template Access="AllUsers" Description="Hello World Tutorial" xmlns="http://simplersystems.com/suite" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://simplersystems.com/suite ......\Template.xsd">
    <Tutorial>
        <Print>{'Hello World!' when Direction = 'Coming' and Greeting = 'Y'}</Print>
        <Print>{'Hello World!' when Direction = 'Coming' or Greeting = 'Y'}</Print>
    </Tutorial>
</Template>

Result of this template with Direction=Coming&Greeting=Y as the query string:


Result of this template with Greeting=Y as the query string:


Notice how both 'Hello World!'``<Print> elements are executed in the first result, since both Direction=Coming and Greeting=Y, which satisfies both <Print> elements. However, in the second result, only Greeting=Y, so the <Print> statement with the "and" operation does not have both conditions satisfied, and is not executed.


The next <Print> element combines both "and" and "or" operations. It executes 'Hello ' followed by a name, if the Name identifier is not null ('Name!=null'), AND either Direction is equal to 'Coming', OR Greeting is equal to 'Y'. However, if Name is null (Name=null), 'World' will be executed instead, followed finally by an unconditional '!' at the end.
<?xml version="1.0" encoding="utf-8"?>
<Template Access="AllUsers" Description="Hello World Tutorial" xmlns="http://simplersystems.com/suite" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://simplersystems.com/suite ......\Template.xsd">
    <Tutorial>
        <Print>{'Hello ', Name when Name!=null and (Direction = 'Coming' or Greeting = 'Y'), 'World' when Name = null, '!'}</Print>
    </Tutorial>
</Template>

Result of this template with Name=Calvin&Greeting=Y as the query string:

Result of this template with Direction=Coming as the query string:


Another way to achieve more complex results is through nested scripting, where the results of a nested script are used to evaluate whether or not an item in the parent script is included in the list. This next <Print> element contains a number of nested scripts, delinieated with curly brackets "{}" embedded in the parent script.

<?xml version="1.0" encoding="utf-8"?>
<Template Access="AllUsers" Description="Hello World Tutorial" xmlns="http://simplersystems.com/suite" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://simplersystems.com/suite ......\Template.xsd">
    <Tutorial>
        <Print>{{{'Hello ' when Direction = 'Coming', 'Goodbye ' when Direction = 'Going'}, Name, '!'} when Direction !=null and Name!=null, {Name, ', are you coming or going?'} when Direction=null and Name!=null, else 'No one to greet'}</Print>
    </Tutorial>
</Template>
From left to right, the first nested script prints 'Hello ' when Direction is 'Coming', and 'Goodbye ' when Direction is 'Going':

{'Hello ' when Direction = 'Coming', 'Goodbye ' when Direction = 'Going'}

The result of this script is then concatenated with the contents of another nested script, that includes the Name identifier, and a literal '!'. However, this nested script is only returned if both Direction is not null and Name is not null:

{{'Hello ' when Direction = 'Coming', 'Goodbye ' when Direction = 'Going'}, Name, '!'} when Direction !=null and Name!=null

The next nested script is evaluated if the Direction is null, but the name was provided (Name!=null). It returns the Name concatenated with the string ', are you coming or going?', prompting the user to provide a direction:

{Name, ', are you coming or going?'} when Direction=null and Name!=null

Finally, the last component of the script is an else clause, that is the default reply if neither Name and Direction are assigned values, which prints No one to greet:

else 'No one to greet'

Result of this template with Name=Calvin&Direction=Going as the query string:

Result of this template with Name=Calvin as the query string:

Result of this template with no identifiers assigned as the query string:


The Script Element

Sometimes, when conditional scripts begin to get too complex, we will want to parse out the items of the script to make the code more readable and configurable, using the <Script> element.

The <Script> element can be placed as a child element of nearly any element in the framework. Besides making scripting more readable, they also serve a purpose of declaring global identifiers, to be used to evaluate the script throughout a template. Since they can be assigned nearly anywhere, they can be as global or as local to a given element or group of elements as needed.

In the following <Print> element, we produce the same results as the prior Tutorial example, however we opt instead to parse out the nested scripts using the <Script> element into different identifiers, replacing the longer <Print> script with these identifiers.

<?xml version="1.0" encoding="utf-8"?>
<Template Access="AllUsers" Description="Hello World Tutorial" xmlns="http://simplersystems.com/suite" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://simplersystems.com/suite ......\Template.xsd">
    <Tutorial>
        <Script>
          Greeting {'Hello ' when Direction = 'Coming', 'Goodbye ' when Direction = 'Going'}
          FullGreeting {Greeting, Name, '!'}
          GetDirection {Name, ', are you coming or going?'}
        </Script>
        <Print>{FullGreeting when Direction !=null and Name!=null, GetDirection when Direction=null and Name!=null, else 'No one to greet'}</Print>
    </Tutorial>
</Template>


Result of this template with Name=Calvin&Direction=Going as the query string:

Result of this template with Name=Calvin as the query string:

Result of this template with no identifiers assigned as the query string:

Template XML Schema Documentation (XSD)

Overview

The Template XML schema documentation (XSD) includes a list of the templates and all elements and attributes available in the framework.

The XSD is organized in a tree node format, with ancestor/descendant relationships displayed for each respective element, with Template types at the root of each tree. 

Get Template.xsd

To get a local copy of your environment's Template.xsd (if it doesn't already exist in the root directory), you can obtain it from your localhost server. This can be done through the following:

1. Run simpler.exe in your root directory.

localhost.PNG

2. Then, in your browser's address bar, go to: http://localhost:180/template.xsd

  • This should prompt you to save the file, which should then be placed in your root directory.
templatexsd.PNG

Reading Local Template.xsd

In our local copy of the Template.xsd file (in the root application directory), the documentation is organized in a standard tree node structure, where most IDEs will be able to have expandable nodes to see child elements and respective attributes for each element, as seen below: 

xsdvisualstudio.PNG

Clicking on Select.Query.CsvFile in Visual Studio will take you to the detailed XML schema location of this particular element of the framework, as seen here:

xsdexpanded.PNG

In this detailed view of the Select.Query.CsvFile element, you can see all of its available child elements (i.e. Column), as well as the element's available attributes (i.e. Path).


Interactive XSD 

In the Interactive XSD in the link below, the branches (descendant elements) are denoted with indentations.

For example, in the accompanying screenshot below, Query is a branch (or child descendant), of Select, and CsvFile is a child of Query. Therefore, CsvFile is a grandchild descendent of Select. The fully qualified notation of CsvFile would therefore be: Select.Query.CsvFile.

xsdlivenode.PNG

Clicking on CsvFile will take you to this child element's schema location, where you can see all it's Childen, Parents, and Attributes delineated with headers. Note that required element attributes are shown in red.

Whether we decide to use the local copy of template.xsd or the interactive XSD, this same tree node model can be used to explore all elements of the template schema. 
 

Interactive XML Schema Documentation (XSD)

The columnar Templates and Functions listed below are an up-to-date index of all the Simpler framework's schema elements, attributes, and functions.

 

Templates Column

The Templates column is laid out similar to a tree-node format, however instead of expandable tree nodes, indentation represents a child element of the parent that precedes it.

Clicking on an item from the "Templates" column will drill-down to its child elements, with description of the element and its available attributes.

When clicking into an element, we can click the Create button. With this, we'll be able to fill out the attributes for the respective element, and generate an XML snippet that we can use in an XML template file. 

 Functions Column

Clicking on an item from the "Functions" column will drill-down to a description of the function's usage. 

When clicking into a function, we again have a Create button that allows you to test the function's output with test arguments. 

Returning to Index

At any time while navigating the Interactive XSD, click "Back to Index" link to return to the main index.

For more on the XSD in general, see Template Schema documentation. 

SimplerScript

 

Overview

SimplerScript is the propriety framework language developed by Simpler Systems. The script is what allows the data to be drilled down into, to allow the data to be the user interface.

Script Notation

SimplerScript evaluates a list of items, separated by commas. Lists are delimited by curly braces: { }. The items in a list can be literals, identifiers, or expressions. They can be used in any attribute or element.

After scripts are evaluated, they are assigned to an attribute or an element's value. In many cases, this means "reducing" a list of several values to a single value. 

Lists

The items in a list can be literals, identifiers, or expressions.

  • The list {1, 2, 3} contains three items.

  • The list {'Hello'} contains one item.

Lists can be nested to any depth, but lists are always one-dimensional. Nested lists are "flattened".

  • The list {1, 2, {3, 4}} is the same as the list {1, 2, 3, 4}.

  • The list {{1, {2, {3}}}} is the same as the list {1, 2, 3}.


Types

SimplerScript understands four simple types of data (strings, numbers, dates, booleans), and one complex type (lists).

  • The list {'A string', 'A ''string'' with nested quotes'} contains strings.

  • The list {1, 2.5, 3.14159, -42} contains numbers. SimplerScript numbers are equivalent to the Microsoft .Net decimal data type.

  • The list {#12/31/2009#} contains a date. SimplerScript dates are equivalent to the Microsoft .Net DateTime data type.

  • The list {true, false} contains booleans.

SimplerScript also has a special null value that is equivalent to an empty list ({}), and empty string (''), zero, and false.


Type Conversion and List Reduction

SimplerScript values are automatically converted to the required type, so if a number is provided where a string is expected, the number will be converted to a string. If a specific type conversion is required, the as clause explicitly converts a list from one type to another.

  • The list {42} as String is equal to the list {'42'}.

  • The list {'42'} as Number is equal to the list {42}.

When a list that contains more than one item is converted to a simple type, the list is "reduced". If the list is converted to a string, each item in the list is converted to a string and then the strings are concatenated together. If the list is converted to a number, each item in the list is converted to a number and then the numbers are added together. If the list is converted to a boolean, each item in the list is converted to a boolean and then the booleans are added together.

  • The list {1, 2, 3} as String is equal to the list {'123'}.

  • The list {'1', '2', '3'} as Number is equal to the list {6}.

  • The list {0, 1} as Boolean is equal to the list {false}.

It is also sometimes useful to do a list reduction that doesn't include a type conversion.

  • The list {'1', '2', '3'} as String is equal to the list {'123'}.


Identifiers

Identifiers can be used in place of literals to make scripts return different results depending on the context in which the script is evaluated. For example, when a template is executing, the values of identifiers are assigned by the query string or by <Script> elements. When a Select template is evaluating the value of a column, the values of identifiers are assigned based on the columns in the row that is being processed.

Basic identifiers start with a letter or underscore, and are followed by any number of letters, digits, or periods, or underscores.

Extended identifiers can contain any character, but must be delimited by double quotes.

Reserved identifiers are basic identifiers that contain a period. The values of reserved identifiers are assigned by the system.

  • The list {BasicIdentifier, _BasicIdentifier2} contains basic identifiers.

  • The list {"Extended identifier", """Extended"" identifier 2"} contains extended identifiers.

  • The list {Url.Path, Settings.DefaultPage} contains reserved identifiers.


Expressions

Arithmetic, boolean, and comparison expressions can be used in place of literals to perform computations.

  • The expression {3 * 4} is equal to 12.
  • The expression {12 / 3} is equal to 4.
  • The expression {1 + 2} is equal to 3.
  • The expression {1 - 2} is equal to -1.
  • The expression {1..4} is equal to the list {1, 2, 3, 4}.
  • The expression {0 = 1} is equal to false.
  • The expression {0 != 1} is equal to true.
  • The expression {0 < 1} is equal to true.
  • The expression {0 <= 1} is equal to true.
  • The expression {0 > 1} is equal to false.
  • The expression {0 >= 1} is equal to false.
  • The expression {true and false} is equal to false.
  • The expression {true or false} is equal to true.
  • The expression {not false} is equal to true.


Conditionals

Any item in a list can be followed by a when clause, or be preceded by the else keyword. If the expression following the when keyword evaluates to false, the item that precedes the when keyword is not included in the list. If a list is not empty when an item is encountered that is preceded by the else keyword, then the item that follows is not included in the list.

  • The expression {'A' when 0 = 1, 'B', 'C'} is equal to the list {'B, 'C'}.
  • The expression {'A' when 0 != 1, 'B', 'C'} is equal to the list {'A', 'B', 'C'}.
  • The expression {'A' when 0 = 1, 'B' when 0 != 1, 'C'} is equal to the list {'B', 'C'}.
  • The expression {'A' when 0 != 1, 'B' when 0 != 1, else 'C'} is equal to the list {'A', 'B'}.
  • The expression {'A' when 0 = 1, 'B' when 0 = 1, else 'C'} is equal to the list {'C'}.


Script Functions

Scripts can call built-in framework functions. A function is invoked by specifying the function name followed by parentheses. Any parameters for the function are listed inside the parenthesis and are separated by commas.

Function Usage

Function names have the same form as reserved identifiers. For example, String.Length is the function that returns the length of a string. The first part of the function name is the namespace. If the function is in the List namespace, then the namespace can be omitted. The following functions all take a single argument:

  • The result of String.Length('Hello') is 5.

  • The result of List.Count({1, 2, 3}) is 3.

  • The result of Count({1, 2, 3}) is 3.

Depending on the function, one to many arguments may be required to evaluate the result, while others require no arguments, or optional arguments:

  • The result of Date.Today() is

  • The result of Date.Now() is

  • The result of String.Random() is

Lastly, here are some functions that require more than one argument:

  • The result of String.Replace('Goodbye','Good','') is 'bye'.
  • The result of List.Contains({1,2,3}, 1) is true.
  • The result of Date.AddDays(Date.Today(),7) is

For a detailed listing of all built-in SimplerScript functions, see the Script Function Reference in the link below:

URL Evaluation 

Urls can be called as functions. Generally, the return value of a url will be a string containing html, but urls also can return non-html text. If the url is a template and the url extension is '.xml', then the return value may be a list if the template supports function calls.

Urls are invoked by delimiting a string with square braces: [ ]. If there are multiple values within the square braces, the values will be concatenated.

For example, let's say we have the following Tutorial template, /helloworld.xml, sitting in the root directory.

<?xml version="1.0" encoding="utf-8"?>
<Template Access="AllUsers" Description="Hello World Tutorial" xmlns="http://simplersystems.com/suite" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://simplersystems.com/suite ......\Template.xsd">
    <Tutorial>
        <Print>Hello World!</Print>
    </Tutorial>
</Template>

The result of ['/helloworld.txt'] is 'Hello World!'.

The square braces invoke the URL and return the results of this external URL to the page we have invoked it from. In this case, the <Print> statement is executed and 'Hello World!' is evaluated as the result.

Now let's say we have the same Tutorial template, /helloworld.xml, but we modified the <Print> element to accept a Name identifier through the URL query string.

<?xml version="1.0" encoding="utf-8"?>
<Template Access="AllUsers" Description="Hello World Tutorial" xmlns="http://simplersystems.com/suite" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://simplersystems.com/suite ......\Template.xsd">
    <Tutorial>
        <Print>{'Hello ', Name, '!'}</Print>
    </Tutorial>
</Template>

The result of ['/helloworld.txt', 'Name=Calvin'] is 'Hello Calvin!'.

Notice how we separated each component of the square-braces script notation: first, we provide the base url '/helloworld.txt'; second, we then add the argument(s) we pass as the query string, 'Name=Calvin'.

Script Functions

 

Framework Functions

Within any script, we can call built-in framework functions. A function is invoked by specifying the function name followed by parentheses. Any parameters for the function are listed inside the parenthesis and are separated by commas.

Function Usage

Function names have the same form as reserved identifiers. For example, String.Length is the function that returns the length of a string. The first part of the function name is the namespace. If the function is in the List namespace, then the namespace can be omitted. The following functions all take a single argument:

  • The result of String.Length('Hello') is 5.

  • The result of List.Count({1, 2, 3}) is 3.

  • The result of Count({1, 2, 3}) is 3.

Depending on the function, one to many arguments may be required to evaluate the result, while others require no arguments, or optional arguments:

  • The result of Date.Today() is

  • The result of Date.Now() is

  • The result of String.Random() is

Lastly, here are some functions that require more than one argument:

  • The result of String.Replace('Goodbye','Good','') is 'bye'.
  • The result of List.Contains({1,2,3}, 1) is true.
  • The result of Date.AddDays(Date.Today(),7) is

For a detailed listing of all built-in SimplerScript functions, see the Script Function Reference in the link below:

URL Evaluation 

URLs can be called as functions. Generally, the return value of a URL will be a string containing html, but URLs also can return non-html text. If the URL is a template and the URL extension is '.xml', then the return value may be a list if the template supports function calls.

URLs are invoked by delimiting a string with square braces: [ ]. If there are multiple values within the square braces, the values will be concatenated.

For example, let's say we have the following Tutorial template, /helloworld.xml, sitting in the root directory.

<?xml version="1.0" encoding="utf-8"?>
<Template Access="AllUsers" Description="Hello World Tutorial" xmlns="http://simplersystems.com/suite" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://simplersystems.com/suite ......\Template.xsd">
    <Tutorial>
        <Print>Hello World!</Print>
    </Tutorial>
</Template>

The result of ['/helloworld.txt'] is 'Hello World!'.

The square braces invoke the URL and return the results of this external URL to the page. In this case, the <Print> statement is executed and 'Hello World!' is evaluated as the result.

Now let's say we have the same Tutorial template, /helloworld.xml, but we modified the <Print> element to accept a Name identifier through the URL query string.

<?xml version="1.0" encoding="utf-8"?>
<Template Access="AllUsers" Description="Hello World Tutorial" xmlns="http://simplersystems.com/suite" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://simplersystems.com/suite ......\Template.xsd">
    <Tutorial>
        <Print>{'Hello ', Name, '!'}</Print>
    </Tutorial>
</Template>

The result of ['/helloworld.txt', 'Name=Calvin'] is 'Hello Calvin!'.

Notice how we separated each component of the square-braces script notation: first, we provide the base url '/helloworld.txt'; second, we then add the argument(s) we pass as the query string, 'Name=Calvin'.

The Script Element

Overview

The <Script> element can be placed as a child element of nearly any element in the framework. Besides making scripting more readable, the <Script> element also serves a purpose of declaring global identifiers, to be used to evaluate the script throughout a template. Since they can be assigned nearly anywhere, they can be as global or as local to a given element or group of elements as needed.

Format

Script elements can define one or more named scripts, and have a unique format in SimplerScript. The scripts being defined are listed as inner text, and are evaluated in the order they are listed.

The advantage of evaluating scripts in order, is primarily that scripts can be built in whole or in part from the scripts declared prior to it.  Take the example below:

<?xml version="1.0" encoding="utf-8"?>
<Template Access="AllUsers" Description="Hello World Tutorial" xmlns="http://simplersystems.com/suite" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://simplersystems.com/suite ......\Template.xsd">
    <Tutorial>
        <Script>
          Greeting {'Hello ' when Direction = 'Coming', 'Goodbye ' when Direction = 'Going'}
          FullGreeting {Greeting, Name, '!'}
          GetDirection {Name, ', are you coming or going?'}
        </Script>
        <Print>{FullGreeting when Direction !=null and Name!=null, GetDirection when Direction=null and Name!=null, else 'No one to greet'}</Print>
    </Tutorial>
</Template>

Here we see three scripts declared in the <Script> element: Greeting, FullGreeting, and GetDirection. 

Usage

Readability

Reusability

As Global Identifiers

As Local Identifiers

 

Select Layer

Prerequisites

We will assume you have:

  • Watched the Navigate video, or are already familiar with the Simpler user interface.
  • Setup the Simpler environment, either on your computer or a development environment for your organization.

Overview

The Select layer provides services for selecting raw data stored in a variety of formats, including csv, sql, excel, text, and xml. The Select layer also provides services for synchronizing data, so that data stored in low performance formats (such as text files on the web) can be transferred into higher performance data stores (relational databases, for example).

Generating the Select Template

The Select template is the mechanism for the Select Layer to do its work. It can call various forms of raw data by calling the child elements within it. 

Start Page

The Start page is our starting point as developers. Among other essential administrative needs, It is also where template builders can be accessed, which will be used to create our first datapp select template.

Select Template Builder

Generating a select template is quite simple. From the Start page, under the header Select Template Builders, choose the type of data source your data is stored in (CSV, SQL table, XLS) and click on the link.

selecttemplatebuilder.PNG

In this example, we will create a Select template from a SQL object (a view or table).

1. Click SQL Table link.

 

selecttemplatebuilder_sqltable.PNG

2. Enter the Data Source, Schema, and object Name.

  • Data Source - Alias for the SQL connection string, defined in configuration.xml.
  • Schema - SQL schema for your SQL object (dbo is the typical default)
  • Name - SQL object name (could be table or view)
  Note: The Data Source "simpler_rpt" in this case is an alias for an underlying connection string. Rather than having to specify the connection string every time, we just call this alias to get data from this SQL data source.

Note: The Data Source "simpler_rpt" in this case is an alias for an underlying connection string. Rather than having to specify the connection string every time, we just call this alias to get data from this SQL data source.

 

3. After filling out the three above fields, click Build. A new browser tab should open with the generated XML code as the output:

4. Save the contents of this output as an xml file somewhere in the root application folder, naming it select.xml.

Note: For organizational purposes, it's strongly recommended that this file be saved in the /datapp folder, and then in a sub-directory named after the dataset being queried. Since this dataset is related to "Trees" data, we will put the select template in /datapp/trees.

The Select XML File

We should already be familiar with the general XML declarations outlined in the Hello World! section, so we will elaborate on the elements and attributes of the Select template in particular. 

Select 

The <Select> template is the parent for selecting and projecting raw data. It has the potential to select various data formats, represented by the child elements of the <Query> element. The <Query> child element must always follow the <Select> template declaration.

<?xml version="1.0" encoding="utf-8"?>
<Template Access="AuthenticatedUsers" Description="Select" xmlns="http://simplersystems.com/suite" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://simplersystems.com/suite Template.xsd">
  <Select>
      <Query>
      <!--Declare Query type here-->
      </Query>
  </Select>
</Template>

Query

The <Query> element will always accompany the <Select> element when creating a Select template. The <Query> element is an abstract query that must be followed by a <[DataFormat]> element. Sibling queries will be appended together, or unioned, while child queries will iterate over the parent query results, similar to a for loop.

Select.Query.[DataFormat]

There are numerous child elements of Select.Query that indicate the different data formats to be queried. However, for this tutorial, we will focus on the <SqlTable>.

Choosing <SqlTable> as the Select.Query child element will indicate a SQL object is the dataset format. Continuing with our dbo.Trees template we generated above, let's explore the elements and attributes of a typical datapp Select template.

<?xml version="1.0" encoding="utf-8"?>
<Template Access="AuthenticatedUsers" Description="" xmlns="http://simplersystems.com/suite" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://simplersystems.com/suite Template.xsd">
  <Select>
    <Query>
        <SqlTable DataSource="simpler_rpt" Schema="dbo" Name="trees" AutoFilter="Y" AutoSelect="Y" AutoSort="Y" SampleOnly="{SampleOnly}" Group="{Group}">
            <!--Declare Column elements here-->
          <SqlTable>
        </Query>
    </Select>
</Template>
Select.Query.SqlTable Attributes:

  • DataSource – Indicates alias of data source connection string to be selected from.
  • Schema – specifies the schema of the data source to be selected from.
  • Name – The name of the table or view to be selected from.
  • AutoFilter – Indicates whether column filters can be specified by the query string. If AutoFilter is “Y”, the value of the column name's query string parameter is used as the filter.
  • AutoSelect – Indicates whether column selection can be specified by the query string. If AutoSelect is “Y”, the value of the ‘Select’ query string parameter is used to determine which columns are sorted.
  • AutoSort – Indicates whether sorting can be specified by the query string. If AutoSort is “Y”, the value of the 'Sort' query string parameter is used to determine which columns are sorted.
  • SampleOnly – Indicates whether to process only a sample of the results.
  • Group – Indicates whether the results will be grouped. When enabled, data is grouped by all non-aggregated fields.

Sibling Queries

We may call as many <Query> elements as children of <Select> as are necessary. If they are siblings, meaning they share the same parent, these queries will be appended together, or unioned.

The only requirement to append queries together is that they must have the same underlying column names selected and in the same order, but they may otherwise come from disparate data sources, such as a different SQL instance, or a different data format all together (i.e., CSV and a SQL Object).

In the snippet below, notice how there is a <Query> element on line 4 and on line 9, but their <SqlTable> DataSource attributes are pointing to two different aliases on line 5 and 10. Assuming these two SQL objects have the same underlying column selections, they will be appended together in the datapp.

<?xml version="1.0" encoding="utf-8"?>
<Template Access="AuthenticatedUsers" Description="" xmlns="http://simplersystems.com/suite" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://simplersystems.com/suite Template.xsd">
  <Select>
    <Query>
        <SqlTable DataSource="simpler_rpt" Schema="dbo" Name="trees" AutoFilter="Y" AutoSelect="Y" AutoSort="Y" SampleOnly="{SampleOnly}" Group="{Group}">
            <!--Declare Column elements here-->
        <SqlTable>
    </Query>
    <Query>
        <SqlTable DataSource="test_db" Schema="dbo" Name="trees" AutoFilter="Y" AutoSelect="Y" AutoSort="Y" SampleOnly="{SampleOnly}" Group="{Group}">
            <!--Declare Column elements here-->
        <SqlTable>
    </Query>
   </Select>
</Template>

Child Queries

When there is a child <Query> element to a parent <Query> (Select.Query.Query), the results of the parent query will iterate over the child query for each result.

For example, you may iterate over a lookup table, using one or more of the columns to pass onto the child query for the final results of the Select template.

In the below snippet, notice how the parent <Query> on lines 4 and 5 is pointing to a <SqlTable> Name of dbo.tree_types in the same database, the results of which will iterate over its child <Query>, querying dbo.trees, on lines 8 and 9. The results of dbo.trees will be altered by the results of dbo.tree_types, before the user ever has any interaction with the datapp.

<?xml version="1.0" encoding="utf-8"?>
<Template Access="AuthenticatedUsers" Description="" xmlns="http://simplersystems.com/suite" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://simplersystems.com/suite Template.xsd">
  <Select>
    <Query>
        <SqlTable DataSource="simpler_rpt" Schema="dbo" Name="tree_types" AutoFilter="Y" AutoSelect="Y" AutoSort="Y" SampleOnly="{SampleOnly}" Group="{Group}">
            <!--Declare Column elements here-->
        <SqlTable>
        <Query>
            <SqlTable DataSource="simpler_rpt" Schema="dbo" Name="trees" AutoFilter="Y" AutoSelect="Y" AutoSort="Y" SampleOnly="{SampleOnly}" Group="{Group}">
                <!--Declare Column elements here-->
            <SqlTable>
        </Query>
    </Query>
   </Select>
</Template>

Column

The <Column> element defines a column in the dataset. It is not a required child element in any Select.Query.[DataFormat], but excluding a specific column selection will default to selecting all underlying columns in the dataset.

<?xml version="1.0" encoding="utf-8"?>
<Template Access="AuthenticatedUsers" Description="" xmlns="http://simplersystems.com/suite" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://simplersystems.com/suite Template.xsd">
  <Select>
    <Query>
        <SqlTable DataSource="simpler_rpt" Schema="dbo" Name="trees" AutoFilter="Y" AutoSelect="Y" AutoSort="Y" SampleOnly="{SampleOnly}" Group="{Group}">
            <Column Name="TreeId" />
            <Column Name="Genus" />
            <Column Name="Species" />
            <Column Name="Cultivar" />
            <Column Name="OtherPartOfName" />
            <Column Name="CommonName" />
            <Column Name="Diameter" />
            <Column Name="Height" />
            <Column Name="CrownWidth" />
            <Column Name="DatePlanted" />
            <Column Name="Condition" />
            <Column Name="PlantingSiteId" />
            <Column Name="StreetAddress" />
            <Column Name="StreetName" />
            <Column Name="HasTaxRoll" />
            <Column Name="HasMeter" />
          </SqlTable>
        </Query>
    </Select>
</Template>
Some Select.Query.[DataFormat].Column Attributes:

  • Name – The identifier of the column in the result set.
  • Type – Specifies the data type of the column in the result set. If compatible, source data will be converted to the specified type. (ex. Type= “Number”).
  • Value - A script that computes the value of th column.

Calculated Columns

Besides those columns that exist in the data source, we can also create calculated columns from Select.Query.[DataFormat].Column element, and using the Value attribute. This allows us to build additional columns on the fly, through some combination of existing columns in the Select template. The new Column element can be placed anywhere alongside its sibling Column elements, however for clarity, they often are placed following the column or columns that the new column is comprised of.

In the example below, we create a new column called "Radius" in line 13, which calculates the tree radius by dividing the Diameter by 2. Note that calculated columns must always be defined using script notation "{}", so that concatenation, math, and conditional values can be created.

<?xml version="1.0" encoding="utf-8"?>
<Template Access="AuthenticatedUsers" Description="" xmlns="http://simplersystems.com/suite" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://simplersystems.com/suite Template.xsd">
  <Select>
    <Query>
        <SqlTable DataSource="simpler_rpt" Schema="dbo" Name="trees" AutoFilter="Y" AutoSelect="Y" AutoSort="Y" SampleOnly="{SampleOnly}" Group="{Group}">
            <Column Name="TreeId" />
            <Column Name="Genus" />
            <Column Name="Species" />
            <Column Name="Cultivar" />
            <Column Name="OtherPartOfName" />
            <Column Name="CommonName" />
            <Column Name="Diameter" />
            <Column Name="Radius" Value="{Diameter / 2}" />
            <Column Name="Height" />
            <Column Name="CrownWidth" />
            <Column Name="DatePlanted" />
            <Column Name="Condition" />
            <Column Name="PlantingSiteId" />
            <Column Name="StreetAddress" />
            <Column Name="StreetName" />
            <Column Name="HasTaxRoll" />
            <Column Name="HasMeter" />
          </SqlTable>
        </Query>
    </Select>
</Template>
calculatedcolumnselect.PNG

Notice, the calculated "Radius" column is a whole number rounding to the nearest integer, rather than showing decimal places. Formatting such as this are addressed in the Schema section of the Select layer.

Schema

Note that so far we have only specified our datapp column selection in Select.Query.[DataFormat], and have not mentioned the topic of formatting. Formatting in the [Compose][/developer/documentation/compose] and [Search][/developer/documentation/search] layers, as well as other functionality, are controlled from the metadata assigned in the Schema element (Select.Schema) of the Select template.

While Schema is not a required element of the Select template, it is almost always used, as this metadata drives the core look-and-feel of the datapp. On line 25 in the example below, notice the <Schema> element only has the Title attribute assigned, which drives the title on the compose and search layers. If we do not assign the Schema Title attribute, the datapp will default to taking the file name or object name of the data source, which is not very user-friendly.

<?xml version="1.0" encoding="utf-8"?>
<Template Access="AuthenticatedUsers" Description="" xmlns="http://simplersystems.com/suite" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://simplersystems.com/suite Template.xsd">
  <Select>
    <Query>
        <SqlTable DataSource="simpler_rpt" Schema="dbo" Name="trees" AutoFilter="Y" AutoSelect="Y" AutoSort="Y" SampleOnly="{SampleOnly}" Group="{Group}">
            <Column Name="TreeId" />
            <Column Name="Genus" />
            <Column Name="Species" />
            <Column Name="Cultivar" />
            <Column Name="OtherPartOfName" />
            <Column Name="CommonName" />
            <Column Name="Diameter" />
            <Column Name="Radius" Value="{Diameter / 2}" />
            <Column Name="Height" />
            <Column Name="CrownWidth" />
            <Column Name="DatePlanted" />
            <Column Name="Condition" />
            <Column Name="PlantingSiteId" />
            <Column Name="StreetAddress" />
            <Column Name="StreetName" />
            <Column Name="HasTaxRoll" />
            <Column Name="HasMeter" />
          </SqlTable>
        </Query>
     <Schema Title="Trees"/>
    </Select>
</Template>
selectschematitle.PNG

Schema.Column

Typically, we will add much more metadata to the Schema section. Namely, we will have a Select.Schema.Column element for every Select.Query.[DataFormat].Column element declared above. In the next snippet below, on lines 26-42, we see that we have done just that, with various metadata attributes to modify the format and functionality of the column.

<?xml version="1.0" encoding="utf-8"?>
<Template Access="AuthenticatedUsers" Description="" xmlns="http://simplersystems.com/suite" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://simplersystems.com/suite Template.xsd">
  <Select>
    <Query>
        <SqlTable DataSource="simpler_rpt" Schema="dbo" Name="trees" AutoFilter="Y" AutoSelect="Y" AutoSort="Y" SampleOnly="{SampleOnly}" Group="{Group}">
            <Column Name="TreeId" />
            <Column Name="Genus" />
            <Column Name="Species" />
            <Column Name="Cultivar" />
            <Column Name="OtherPartOfName" />
            <Column Name="CommonName" />
            <Column Name="Diameter" />
            <Column Name="Radius" Value="{Diameter / 2}" />
            <Column Name="Height" />
            <Column Name="CrownWidth" />
            <Column Name="DatePlanted" />
            <Column Name="Condition" />
            <Column Name="PlantingSiteId" />
            <Column Name="StreetAddress" />
            <Column Name="StreetName" />
            <Column Name="HasTaxRoll" />
            <Column Name="HasMeter" />
        </SqlTable>
     </Query>
     <Schema Title="Trees">
           <Column Name="TreeId" Title="Tree|ID" />
           <Column Name="Genus" Title="Genus" Width="8" />
           <Column Name="Species" Title="Species" Width="8" />
           <Column Name="Cultivar" Title="Cultivar" Width="8" />
           <Column Name="OtherPartOfName" Title="Other|Part|Of|Name" />
           <Column Name="CommonName" Title="Common|Name" />
           <Column Name="Diameter" Title="Diameter" DecimalPlaces="1" />
           <Column Name="Radius" Title="Radius" DecimalPlaces="1" />
           <Column Name="Height" Title="Height" DecimalPlaces="1" />
           <Column Name="CrownWidth" Title="Crown|Width" DecimalPlaces="2" />
           <Column Name="DatePlanted" Title="Date|Planted" />
           <Column Name="Condition" Title="Condition" />
           <Column Name="PlantingSiteId" Title="Planting|Site|ID" />
           <Column Name="StreetAddress" Title="Street|Address" Assist="Y" />
           <Column Name="StreetName" Title="Street|Name" Assist="Y" />
           <Column Name="HasTaxRoll" Title="Has|Tax|Roll" />
           <Column Name="HasMeter" Title="Has|Meter" />
     </Schema>
    </Select>
</Template>
These <Column> elements must have the same Name identifier as those defined in Select.Query.[DataFormat].Column, in order for the metadata assigned to represent a selected column.

Notice the various attributes declared: Title, Width, DecimalPlaces, and Assist. These are just a subset of the attributes available in Select.Schema.Column, all of which represent optional metadata to be applied to a column.

Notice the complementary Column for "Radius", which now has the decimal places to display the exact value of this calculated column.

selectschemacalculatedcolumndecimal.PNG

The <Link> is another important child element of the Schema section (Select.Schema.Link). The <Link> declares a hyperlink to be added to the result set, loaded at the end of the column list. This can be a relative link to another datapp, or an external link to a third party website. They can be literal URLs, or use the value of one or more columns in the result set to script the parameters of a dynamic URL.

<Link Name="TestLink" Url="{'/datapp/trees/compose.html?TreeId=', TreeId}" Text="Test Link"/>
In the above example, we have created a mock URL that will pass the "Tree ID" to a relative URL within the same datapp website. We specified a unique Name attribute, as well as the Url and the Text to be displayed in the results. Here is how this <Link> appears in a datapp, after the last column specified in Select.Query.[DataFormat]:

selectschemalink.PNG

Schema Build Types

A key metadata attribute of Select.Schema is the BuildType attribute. This attribute dynamically assigns the Select template to the desired build of the Compose and Search layers. The datapp build type will be discussed in more detail in the Compose section, but below is a brief overview.

Basic Build

 

Advanced Build

 

Menu System

 

Prerequisites

We will begin with a few assumptions:

  • Watched the Navigate video, or are already familiar with the Simpler user interface.
  • Setup the Simpler environment, either on your computer or a development environment for your organization.
  • Created a Basic datapp, or datapps have already been created on your site.

Overview

The menu can be easily customized. A site has two options for the menu:

  • Either all menu items can be displayed on a single Home page, or
  • You can create multiple menu pages with tabs along the top of the page. This tabular menu are ideal if we need to break menus out by department or by software application, and can also include drop-down submenus.
  Notice the tabular menu along the header banner, as well as the the content of the current "Trees" tab.

Notice the tabular menu along the header banner, as well as the the content of the current "Trees" tab.

Each tab has a heading, subheading, and menu groups that are organized using columns. Each menu group contains one or more links, or URLs, that are jumping off points into the data. 


Tabular Menu Configuration

To create a tabular menu, we need to verify the setting in the configuration.xml file is set.

configurationfile.PNG
  • If the TabularMenu setting exists but is set to "N", we must switch it to "Y" to activate the tabular menu system.
  • If the <Setting> is not defined, we need to define it and set it to "Y".

<!--Custom Frame Settings-->
<Setting Name="FrameStyle" Value="Custom" />
<Setting Name="FrameColor" Value="#fff" />
<Setting Name="HeadingColor" Value="#000" />
<Setting Name="LogoUrl" Value="/images/ss_icon_medium.png" />
<Setting Name="LogoWidth" Value="50" />
<Setting Name="LogoHeight" Value="50" />
<Setting Name="TabularMenu" Value="Y" />

Your datapp site is now activated to allow for the tabs across the header banner.


Folder Structure

Home Menu

The Home menu is derived from the home.xml file in the root of the Simpler folder. Whether we are using a single menu or tabular menu, home.xml should always be placed in the root. 

Tabular Menu

There is also a menu folder located in the root directory where the menu for each tab will be saved, if we choose to create a tabular menu. The menu file name(s) must be named as we’d like the tabs to appear to the end user.

  Notice the Home menu (home.xml) is in the root directory, while any menu tabs would be place in the menu folder. (above)

Notice the Home menu (home.xml) is in the root directory, while any menu tabs would be place in the menu folder. (above)

For example, if we want two tabs named "Properties" and "Trees", create a properties.xml and a trees.xml menu and save them in the menu folder. The framework will automatically parse the file name and proper-case it, for the end interface. 

tressproperties.PNG
tabmenusexample.PNG

If you have a multi-word tab, use an underscore ("_") where a space would be. The system will convert that underscore to a space automatically. See the "Tree Inventory" tab above.

treeinventory.PNG
treeinventorylive.PNG

Sub-menus

To add a sub-menu to a tab, which renders as a drop-down list when the mouse hovers over the tab, do the following:

  1. create a sub-folder in the /menu directory with the same name as the parent menu file.
  2. Then, create a new menu file in this folder, naming the file as we’d like the sub-menu to appear to the end user.
treesubmenudirectory.PNG

For example, to create a sub-menu called “California Trees” for Trees tab, create a new folder called "trees" in /menu directory ("/menu/trees"), and create a new menu called california_trees.xml in this folder.

californiatreessub.PNG
californiatreessublive.PNG

The Menu XML File

We should already be familiar with the general XML declarations outlined in the Hello World! section, so we will elaborate on the elements and attributes of the Menu templates in particular. 

Present

The <Present> template is the parent for the <Menu> element, since the menu is in the Present layer of the framework. All of the elements that define the menu frame, groups, and links must reside inside of the <Present> template.


<?xml version="1.0" encoding="utf-8"?>
<Template Access="AuthenticatedUsers" Description="Home" xmlns="http://simplersystems.com/suite" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://simplersystems.com/suite Template.xsd">
  <Present>
      <!--Declare Menu here-->
  </Present>
</Template>

Frame

The <Frame> element defines various page items such as the title, as well as some of the icons along the sidebar, like the Search icon.

framelive.PNG

The Title attribute of the <Frame> controls the title on the browser tab, as well as the frame banner title. In the example below, the Title is being created from the MenuTitle script, which selects the file name of the current URL and proper-cases it. So in this case our trees.xml menu, is taking the file name, "Trees", as the Title.

<Script>
    MenuTitle {String.ProperCase(String.FormatIdentifier(String.Replace(Url.GetName(Url.This),Url.GetExtension(Url.This),'')))}
</Script>
<!--The Frame should take dynamic MenuTitle for Menu templates-->
<Frame Title="{MenuTitle}"/>
Note: for full understanding of how theMenuTitlescript is calculated, see the Script Function reference page.

Menu

The <Menu> element defines a Menu template. It will set the number of columns organized on the menu, the menu's title, and an auxiliary description text under the title.

menulive.PNG

By default, the Title attribute uses the same MenuTitle script calculated for the Frame's title, as seen below:

<Menu Title="{MenuTitle}" Columns="1" Description="This menu contains data used to catalog trees in the city of San Francisco." >

Menu Groups

The content of a menu is organized into columnar groups, which display links to datapps under a related category, or subject area.

menugrouplive.PNG

Each menu group on the page has its own <Group> element, which then contains at least one <Link> element for that group.

<Group Column="1" Description="Group One" Access="Administrators">
    <Link Description="Link One" Url="/datapp/folder/search.html"/>
</Group>

  • The Column attribute indicates which column on the page to place the group in. If there is more than one group in that column, the groups are displayed in the order they are listed in the file.
  • The Description will appear as the heading for that group.
  • The Access attribute is not typically used, but can be included in order to restrict access to specific roles or individuals.
    • Access may be controlled at the Menu, Group, or Link level, by specific user name or by user role. For more on access, see our Access page.

See example below incorporating multiple groups in a column, and multiple columns: 

menugrouplive2.PNG
<Menu Title="{MenuTitle}" Columns="2" Description="This menu contains data used to catalog trees in the city of San Francisco.">
  <Group Description="Group One" Column="1">
      <Link Description="Link One" Url="/datapp/folder1/search.html"/>
  </Group>
  <Group Description="Group Two" Column="1">
      <Link Description="Link One" Url="/datapp/folder2/search.html"/>
      <Link Description="Link Two" Url="/datapp/folder3/search.html"/>
  </Group>
  <Group Description="Group Three" Column="2">
      <Link Description="Link One" Url="/datapp/folder4/search.html"/>
      <Link Description="Link Two" Url="/datapp/folder5/search.html"/>
  </Group>
</Menu>

Dynamic Links

Unlike the more common <Link>, <DynamicLinks> will generate links depending on some condition, or external list of links from elsewhere.

As an example, let's look at Shortcuts, which reside on the Home menu.

First we must declare our <Script.Url> elements, to grab user-specific Shortcuts and Shared Shortcuts. More on the <Script.Url> here.

<?xml version="1.0" encoding="utf-8"?>
<Template Access="AuthenticatedUsers" Description="Home" xmlns="http://simplersystems.com/suite" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://simplersystems.com/suite Template.xsd">
    <Present>
        <Script>
      MenuTitle {String.ProperCase(String.FormatIdentifier(String.Replace(Url.GetName(Url.This),Url.GetExtension(Url.This),'')))}
        </Script>
    <Script.Url Identifier="SelectUserShortcutsUrl" BaseUrl="/administer/shortcuts/select.xml">
        <Parameter Name="Select" Value="{'ShortcutName,Category,Url'}"/>
        <Parameter Name="Sort" Value="{'Category,ShortcutName'}"/>
        <Parameter Name="Category"/>
    </Script.Url>
    <Script.Url Identifier="SelectSharedUserShortcutsUrl" BaseUrl="/administer/shortcuts/shared/select.xml">
        <Parameter Name="Select" Value="{'ShortcutName,Category,Url'}"/>
        <Parameter Name="SharedWith" Value="{User.Id}"/>
        <Parameter Name="Sort" Value="{'Category,ShortcutName'}"/>
    </Script.Url>

Next we declare our DynamicLinksUrl for our "Shortcuts" and "Shared Shortcuts" menu groups, which will then query the aforementioned <Script.Url> elements by their Identifier, as highlighted in lines 20 and 23 below.

Then, using <DynamicLinks> element, we iterate through this external URL and assign the link Description and Url based off the query results.

<?xml version="1.0" encoding="utf-8"?>
<Template Access="AuthenticatedUsers" Description="Home" xmlns="http://simplersystems.com/suite" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://simplersystems.com/suite Template.xsd">
  <Present>
      <Script>
      MenuTitle {String.ProperCase(String.FormatIdentifier(String.Replace(Url.GetName(Url.This),Url.GetExtension(Url.This),'')))}
       </Script>
    <Script.Url Identifier="SelectUserShortcutsUrl" BaseUrl="/administer/shortcuts/select.xml">
        <Parameter Name="Select" Value="{'ShortcutName,Category,Url'}"/>
        <Parameter Name="Sort" Value="{'Category,ShortcutName'}"/>
        <Parameter Name="Category"/>
    </Script.Url>
    <Script.Url Identifier="SelectSharedUserShortcutsUrl" BaseUrl="/administer/shortcuts/shared/select.xml">
        <Parameter Name="Select" Value="{'ShortcutName,Category,Url'}"/>
        <Parameter Name="SharedWith" Value="{User.Id}"/>
        <Parameter Name="Sort" Value="{'Category,ShortcutName'}"/>
    </Script.Url>
    <!--Lines 1-16 merged in from previous snippet for full context-->
    <Frame Title="{MenuTitle}" />  
    <Menu Title="Home" Columns="3" >
        <Group Description="Shortcuts" DynamicLinksUrl="{SelectUserShortcutsUrl}" ManageUrl="/administer/shortcuts/manage.html" Column="2">
            <DynamicLinks Description="{ShortcutName}" Url="{Url}" />
        </Group>
        <Group Description="Shared Shortcuts" DynamicLinksUrl="{SelectSharedUserShortcutsUrl}" ManageUrl="/administer/shortcuts/shared/manage.html" Column="3">
            <DynamicLinks Description="{ShortcutName}" Url="{Url}" />
        </Group>
       </Menu>
    </Present>
</Template>
shortcutslive.PNG

In the above screenshot, we have 3 shortcuts and 1 shared shortcut populated from our "Trees" demo datapp, none of which were explicitly coded into the menu. Rather, all the links were dynamically populated from querying our Shortcut datasets.

For more on Shortcuts, see our Shortcuts page.