HTML templates

With P*, you don't need any external template engine. Templates are in-language!

Templates look like blocks and are defined in the main scope of the program. When a template is called, it inherits all variables available from the location of the call.

Inside templates, you can use the special syntax {@variable} to interpolate variables. Actually, everything inside {@ } is parsed as an expression, and you can do anything here which you could do elsewhere in the program except for declaring variables.

Example of a program using a HTML template

HTML_TEMPLATE document {
	<!DOCTYPE HTML>
	<html>
	<head>
	<title>{@title}</title>
	</head>
	<body>
	</body>
	</html>
}

SCENE main {
	string title = "P* Web Programming Language test page";

	#CONTENT_TYPE text/html;
	#HTML_TEMPLATE document;
}

In the above example, the template document is calledby a fixed string. If you store the name of the template which should be used in a variable, you can use the @ to parse it as an expression instead.

HTML_TEMPLATE test_template {
	Test output
}

HTML_TEMPLATE test_template_again {
	Test output again
}

SCENE main {
	array<string> names;
	names[0] = "test_template";
	names[1] = "test_template_again";

	/* Loop the array with the two template names */
	int i = 0;
	while (i < @names) {
		#HTML_TEMPLATE @names[i];
		i++;
	}
	return 0;
}

Conditional blocks

LOOP and CONDITION blocks removed in pstar-1.2~alpha10

You can use if, while, for and foreach blocks to control the flow of the HTML template. The blocks work in the same way as elsewhere in the program, only that they contain text to be printed and not P* code.

Here is an example program which loops an array of struct to print out all its data. Note that we use and if block to check if the array rows contains any elements at all by using the count operator @. If there are some values in it, we proceed with printing a table by looping the array in a foreach loop. Inside the loop, we call another template, template_row which contains the layout of the table row.

/* Object we use to hold some data */
struct row {
	public int id;
	public string description;
	row (int _id, string _description) {
		id = _id;
		description = _description;
	};
};

HTML_TEMPLATE template_row_header {
	<th>ID</th>
	<th>Description</th>
}
HTML_TEMPLATE template_row {
	<td>{@row->id}</td>
	<td>{@row->description}</td>
}

HTML_TEMPLATE document {
	<!DOCTYPE HTML>
	<html>
	<head>
	<title>{@title}</title>
	</head>
	<body>
{@if (@rows > 0)
	<p>We have rows to print!</p>
	<table>
		<tr>
			{@#HTML_TEMPLATE template_row_header}
		</tr>
	{@foreach (auto row; rows)
		<tr id="{@row->id}">{@#HTML_TEMPLATE template_row}</tr>
	}
	</table>
} else {
	<p>We do not have any rows to print</p>
}
	</body>
	</html>
}

SCENE main {
	string title = "P* Web Programmin Language test page";

	array<row> rows;

	rows[@rows](1, "First row");
	rows[@rows](2, "Second row");
	rows[@rows](3, "Third row");

	#CONTENT_TYPE text/html;
	#HTML_TEMPLATE document;
}

AJAX output

P* supports common AJAX-operations like replacing text inside a <div>. If you want to output a variable interpolated into the template, the id-tag of the previous element in you HTML is used as variable name when the JSON is generated. In the example below, a jQuery scripts does this job.

You can also have P* generate JSON output for you. You can choose variables to output from a template, and P* will create a key/value pair to output to the browser. The key is taken from the expression block ({@ ... } preceeded by the text "id=" from where in the template the variable was. You may call another template or function inside that expression if you wish, everything inside will be JSON encoded into a variable named after the ID parameter.

Under follows an example which outputs a variable using JSON if the GET-variable do_ajax is set.

HTML_TEMPLATE document {
	<!DOCTYPE HTML>
	<html>
	<head>
	<title>P* Web Programming Language</title>
	</head>
	<body>
	<h1 id="{@"header"}">{@header_text}</h1>
	<h2 id="{@"subheader"}">{@subheader_text}</h2>
	</body>
	</html>
}

SCENE fullpage {
	#CONTENT_TYPE text/html;
	#HTML_TEMPLATE document;
}

SCENE json {
	#JSON_BEGIN;
	/* Call the template "document" and print the
	expression inside the tag with id "header" and "subheader" */
	#HTML_TEMPLATE_VAR document "header", "subheader";
	#JSON_END;
}

SCENE config {
	public GET get;
	public string header_text = "This is the header";
	public string subheader_text = "This is the useless subheader";
}

/* The main scene extends the config-scene which 
   we use to set some variables. */
SCENE main : config {
	if (defined get["do_ajax"]) {
		/* Call the json scene */
		#SCENE json;
	}
	else {
		/* Call the fullpage scene */
		#SCENE fullpaga;
	}
}

Output of program when "do_ajax" is not set

Content-type: text/html;

<!DOCTYPE HTML>
<html>
<head>
<title>P* Web Programming Language</title>
</head>
<body>
<h1 id="header">This is the header</h1>
<h2 id="header">This is the useless subheader</h2>
</body>
</html>

Output of program when "do_ajax" is set

Content-type: application/json

{
	"header": "This is the header",
	"subheader": "This is the useless subheader",
	"": ""
}

Output templates as JSON variables

To output a whole template as a JSON variable, you can use the #HTML_TEMPLATE_AS_VAR template_name-pragma. The JSON variable name is set to be the same as the name of the template. This output method is useful if you want to output larger parts of a page.

HTML_TEMPLATE head {
	<!DOCTYPE html>
	<html>
	<head>
	<title>P* template as var output test</title>
	</head>
	<body>
	<div id="body">
}

HTML_TEMPLATE foot {
	</div>
	</body>
	</html>
}

HTML_TEMPLATE body {
	This is the body
}

SCENE json {
	/* Print the whole body as a JSON variable */
	#JSON_BEGIN;
	#HTML_TEMPLATE_AS_VAR body;
	#JSON_END;
}

SCENE fullpage {
	#CONTENT_TYPE text/html;
	#HTML_TEMPLATE head;
	#HTML_TEMPLATE body;
	#HTML_TEMPLATE foot;
}

SCENE main {
	GET get;
	if (defined get["do_ajax"]) {
		#SCENE json;
	}
	else {
		#SCENE fullpage;
	}
}

Output of program when "do_ajax" GET variable is not set

Content-type: text/html;

<!DOCTYPE html>
<html>
<head>
<title>P* template as var output test</title>
</head>
<body>
<div id="body">
This is the body
</div>
</body>
</html>

Output with the "do_ajax" GET variable set

Content-type: application/json

{
	"body": "\tThis is the body\n",
			"": ""
}