Table of Contents

Web Server SSJS Template System

The default web pages use a SSJS Template engine which also allows for Theme support.

[Note: With this latest implementation of SSJS, @@ codes no longer can be nested.]

The SSJS Template Scheme

Each page consists of four parts:

The Header

../web/templates/default/header.inc  

This file contains the basic requirements for the HTML page. The opening HTML, doctype, title, CSS file link, etc. The header file includes the open body, System Name, and User greeting plus the initial page layout table start. The rest of the layout is continued in the next files.

Top Navigation

../web/templates/default/topnav.inc
../web/lib/topnav_html.ssjs

The topnav.inc file contains the basic design of the “breadcrumbs” The links are dynamically generated by topnav_html.ssjs so both files need to be addressed when modifying or creating themes. In the case of the default layout, topnav.inc has a left and right graphic and a middle section that the dynamic content goes. The background image is handled by CSS. You can change this to anything you like.

The topnav_html.ssjs file may seem daunting at first, but it is pretty straight forward. It has a series of if statements that check the current page location and sets up the breadcrumbs based on what you want it to say.

For example: You want to add a Links page called links.html in the main directory. You would add a check for the path to links.html as:

if(http_request.virtual_path=="/links.html")
    template.topnav.push({html: '<span class="tlink">Some Links</span>'});

Left Side Navigation

../web/templates/default/leftnav.inc
../web/lib/leftnav_nodelist.ssjs
../web/lib/leftnav_html.ssjs

This starts the main table layout in the default layout and also provides two other things – the main navigation links and a brief nodelisting that displays when users are online via telnet. The links are dynamically created as in the Top Navigation example above with the exception of the two static links.

Main Content (various files)

This is where the layout of the main content is created. It is best to look at the various files in ../web/templates/default & ../web/templates/default/msgs to see how the code is displayed for the various functions of the Web side of Synchronet. Some details on what each of the special codes contained in those files do will follow.

Fооter

../web/templates/default/footer.inc

This file contains the closing HTML and whatever bottom information you would like. In the case of the default layout, the Web Server/Synchronet versions and the XHTML 1.0 logo. Links to privacy statements or anything else can be placed here and they will be displayed at the bottom of each page.

Custom .inc

To Add a custom link to the left side navigation list using the nightshade theme edit ../web/lib/nightshade/leftnav_html.ssjs and add the link to the list.
note: the link expects an html tag “<li><a href=“some-script.ssjs”>My Link</a></li>”

template.leftnav.push({html: '<li><a href="/members/externals.ssjs">External Programs</a></li><li><a href="logout.ssjs">Logout</a></li><li><a href="/members/lastcallers.ssjs">Last Callers</a></li><li><a href="/members/info.ssjs">Information</a></li><li><a href="/members/newpw.ssjs">Change Password</a></li><li><a href="/logout.ssjs">Logout</a></li><li><a href="/msgs/msgs.ssjs?msg_sub=mail">E-mail</a></li>' });  

Here we added the link Logout to the left side navigation that points to logout.ssjs. Now create the script called ../web/root/logout.ssjs

<!-- ../web/root/logout.ssjs -->
 
template.logout = '<br><br>'+user.alias+' Logging out ...<br><br><br>';
write('<meta http-equiv="refresh" content="2; url=index.ssjs">');
 
user.number = 0;
 
if(do_header)
    write_template("header.inc");
if(do_topnav)        
    load(topnav_html);
if(do_leftnav)        
    load(leftnav_html);
if(do_rightnav)
        write_template("rightnav.inc");
write_template("logout.inc");
if(do_footer)    
    write_template("footer.inc");

Now you need a corresponding ../web/root/templates/nightshade/logout.inc

<!-- ../web/templates/nightshade/logout.inc -->
 
<div id="contentcontainer">
	<div id="content2">
	    @@logout@@
	</div>
</div>	

SSJS Theme Support

Theme Layouts can be added to Synchronet by creating them and placing the *.inc files in their own directory under ../web/templates/

Themes are activated by editing the ../web/templates/html_themes.ssjs file. This file contains:

/* Set default theme name */
var DefaultTheme="Default";
 
/* Edit this bit to add/remove/modify theme descriptions and dirs */
Themes["Default"]=new Object;
Themes["Default"].desc="Default Synchronet Theme";
Themes["Default"].dir="default";
Themes["Default"].css="/synchronet.css"; 

Themes are added by editing below the Default Theme such as:

Themes["CoolTheme"]=new Object;
Themes["CoolTheme"].desc="My Cool Theme";
Themes["CoolTheme"].dir="cooltheme";
Themes["CoolTheme"].css="/cooltheme.css";

To change the Default Theme, change:

var DefaultTheme="Default";

to:

var DefaultTheme="CoolTheme";

Special Codes Used in the SSJS Template System

By looking at at the message related files located in templates/default/msgs, it can be seen that some special codes are used to display dynamically created content. It is very important to maintain the information EXACTLY as seen in each file or else the messaging system will fail. While how it is displayed can be changed, the correct information will only be dispayed by following the format in the *.inc files.

For example the groups.inc:

<!-- Main Content -->  
 
<td class="main" valign="top"><br />
 
<table class="grouplist" border="0" cellpadding="2" cellspacing="2">
<tr>
<th class="grouplist">Message Group</th><th class="grouplist">Subs</th>
</tr>
<<REPEAT groups>>
<tr>
  <td class="grouplist">
      <a class="grouplist" href="subs.ssjs?msg_grp=^^groups:name^^">
          %%groups:description%%</a></td>
  <td class="grouplist" align="right">
      @@JS:msg_area.grp_list[RepeatObj.index].sub_list.length@@</td>
</tr>
<<END REPEAT groups>>
</table>
<br />
 
<!-- end Main Content -->

While the table layout can be changed or even eliminated, the information within the «REPEAT groups>> and «END REPEAT groups>> must remain intact. To remove the table yet keep the correct infomation, the resulting groups.inc would be changed to (while maintaining the main table layout in this case) to:

<!-- Main Content -->  
 
    <td class="main" valign="top"><br />
 
  <<REPEAT groups>>
    <a class="grouplist" href="subs.ssjs?msg_grp=^^groups:name^^">
        %%groups:description%%</a>
    @@JS:msg_area.grp_list[RepeatObj.index].sub_list.length@@<br />
  <<END REPEAT groups>>
 
  <br />
 
  <!-- end Main Content -->

This principle applies to all the .inc files in msgs respectively.

The SSJS Template Library

name is replaced with the HTML encoded value of template.name

i.e.; Spaces are replaced with: this&nbsp;is&nbsp;html

^^name^^ is replaced with the URI encoded value of template.name

i.e.; Spaces are replaced with: this%20is%20URI

@@name@@ is replaced with the value if template.name

No changes or encoding is performed.

@@name:sname@@ is replaced with the value of template.name.sname (^^ and are also supported) ''@@JS:js_expression@@'' is replaced with the return value of ''js_expression'' (^^ and are also supported)

<<REPEAT name>>
  @@name:sname@@
<<END REPEAT name>>

Iterates over the array/object template.name and replaces name:sname with the value of template.name.sname. (^^ and %% are also supported)

SSJS Message Configuration

Configuration settings for the SSJS Messaging system is located in the ../web/lib/msgsconfig.ssjs file:

max_messages=20;
max_pages=30;
next_msg_html="Next Message";
prev_msg_html="Previous Message";
next_page_html="NEXT";
prev_page_html="PREV";
showall_subs_enable_html="Show all subs";
showall_subs_disable_html="Show subs in new scan only";
show_messages_all_html="Show all messages";
show_messages_yours_html="Show messages to you only";
show_messages_your_unread_html="Show unread messages to you only";
show_messages_spacer_html="&nbsp;<b>|</b>&nbsp;";
anon_only_message="Message will be posted anonymously";
anon_allowed_message='<input type="checkbox" name="anonymous" value="Yes" /> Post message anonymously';
anon_reply_message='<input type="checkbox" name="anonymous" value="Yes" checked /> Post message anonymously';
private_only_message="Message will be marked private";
private_allowed_message='<input type="checkbox" name="private" value="Yes" /> Mark message as private';
private_reply_message='<input type="checkbox" name="private" value="Yes" checked /> Mark message as private';

Each of these are configurable.

See the actual file for the defaults currently in use.

Embedded Javascript

The *.inc files can (and do in the default layout) have embedded JavaScript which is parsed by the JavaScript engine. Care should be taken as a large number of embedded JavaScript in the *.inc files slow down overall processing of pages.

Anything contained within @@JS: @@ is processed by the Server-side JavaScript engine.

For example, it can check if the user is Guest or an actual user with this line:

@@JS:if(user.number==0 || user.security.restrictions&UFLAG_G) '<html code for Guest>'; \
else '<html code for registered user>';@@

What this does is display links specific for Registered Users only to them and not Guest. There are many things that can be done with @@JS: @@ code. Note, it also can be used to display HTML based on location as in the node listing stuff. In this case, it checks for whether or not a user is online, or if the user is anywhere but the Who's Online page before displaying the Left side node listing.

IMPORTANT! Anything contained within @@JS: @@ MUST be on one line or there will be errors in parsing.

global_defs.ssjs

This version of the Web Layout now includes a new file called global_defs.ssjs. It is located in the ../web/lib directory. This file can be used for creating global definitions that span all pages of a site. For example:

template.user_alias=user.alias;

Now @@user_alias@@ can be in any *.inc template files and it will display the user's alias.

Care should be exercised when using this file as loading it up with hundreds of predefined definitions may slow down overall page rendering as the file is loaded on every page. It would be better to just put a few popular definitions that are truly global rather many definitions. It would be inefficient to have thirty of forty message definitions being loaded when a user is looking at the statistics page.

Embedding fTelnet

To add an fTelnet Logon Screen to your Main landing page there are a few steps you can follow

1). Copy ../web/root/ftlnet.ssjs to ftelnet_main.ssjs 2). Edit ../web/root/ftelnet_main.ssjs and remove (otherwise just using ftelnet.ssjs there would be a mirroring of the leftnav)

/* comment out this
if(do_header)
    write_template("header.inc");
if(do_topnav)        
    load(topnav_html);
if(do_leftnav)        
    load(leftnav_html);
if(do_rightnav)
	write_template("rightnav.inc");
write_template(templatefile);
if(do_footer)    
    write_template("footer.inc");
*/
 

3). Continuing editing ../web/root/ftelnet_main.ssjs and add contents of the ftelent spalsh screen

template.splash = 'G1swOzQwOzM3bQ0KG1sxOzMwbSQkJCQkyMjIyMjIJCQkJCQkJCQkJMjIyMjIyCQkJCQkJCQkJCQkJCQkJCQkJCQkJLy8vLy8vCQkJCQkJCQkJCQkJCQkJCQkvLy8vLy8JCQNCiQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJLy8vP0nG1szMW0sG1swOzMxbSwsLHl5eXkkJCQkIBtbMTszMG0kJCQkJCS8vLy8vLwkJCQkJCQkJCQkJCQkDQokJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQgG1swOzMxbSQkJCQbWzFt/RtbMDszMW39/f0nJycnJCQkG1sxbSQgG1szMG0kJCQkJCQgG1szMW0kJCQkG1swOzMxbXl5eXksLCwsG1sxOzMwbWD9vLy8JA0KJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkIBtbMzFtJBtbMDszMW0kJBtbMW0kIBtbMzBteXl5JCS8IBtbMzFtJBtbMDszMW0kJBtbMW0kIBtbMzBtJCQkJCQkIBtbMzFtJCQbWzA7MzFtJCRgYGBg/f39/SQkJCQgG1sxOzMwbSQNCiQbWzA7MzFtLnMkJCIiIiIiIiQkcy4bWzE7MzBtICQkJCAbWzA7MzFtLnMkJCIiIiIiIiQkcy4bWzE7MzBtJCQgG1swOzMxbSQkJBtbMW0kIBtbMzBtJCQnYCQgG1szMW0kG1swOzMxbSQkJCAbWzE7MzBteSQkJCQkJCAbWzMxbSQbWzA7MzFtJBtbMW0kJCAbWzMwbSQkJHl5eSAbWzA7MzFtJCQkJCAbWzE7MzBtJA0KJBtbMDszMW0kJCQkG1szN20gG1sxOzMwbSQkJCQbWzBtIBtbMzFtJCQkJBtbMTszMG0gJCQkG1swbSAbWzMxbSQkJCQbWzM3bSAbWzE7MzBtJCQkJBtbMG0gG1szMW0kJCQkG1sxOzMwbSQkIBtbMDszMW0kG1sxbSQkG1swOzMxbSQgG1sxOzMwbcgkLiwkIBtbMzFtJCQbWzA7MzFtJBtbMW0kIBtbMzBtJCQkJCQkJCAbWzMxbSQbWzA7MzFtJBtbMW0kG1swOzMxbSQgG1sxOzMwbcgkJCQkvCAbWzMxbSQbWzA7MzFtJBtbMW0kG1swOzMxbSQgG1sxOzMwbSQNCiQbWzA7MzFtJCQkJBtbMzdtIBtbMTszMG0kICAkG1swbSAbWzMxbSQkJCQbWzM3bSAbWzE7MzBtJCQkG1swbSAbWzMxbSQkJCQbWzM3bSAbWzE7MzBtJCQkJCQkJCQkJCR5IBtbMDszMW0kJBtbMW0kG1swOzMxbSQgG1sxOzMwbSQkJCQgG1szMW0kJCQbWzA7MzFtJCAbWzE7MzBtJCQkJCQkJHkgG1szMW0kG1swOzMxbSQkJCAbWzE7MzBtJCQkJCAbWzA7MzFtJCQbWzFtJCQgG1szMG15JA0KJBtbMDszMW0ksCQkG1szN20gG1sxOzMwbSQkJCQbWzBtIBtbMzFtJLAkJBtbMzdtIBtbMTszMG0kJCQbWzBtIBtbMzFtJCQkJBtbMzdtIBtbMTszMG0kJCQkJCQkJCQkJCQgG1szMW0kG1swOzMxbSQkG1sxbSQgG1szMG0kvLy8c3NzeXl5JCQkJCQkJCQgG1szMW0kG1swOzMxbSQkG1sxbSQgG1szMG0kJCQkIBtbMDszMW0kG1sxbSQkJCAbWzMwbSQkDQokG1swOzMxbSQkJCQiIiIiICAkJCQkG1szN20gG1sxOzMwbSQkJBtbMG0gG1szMW0kJCQkG1szN20gG1sxOzMwbSQkJCQkJCQkJCwkJCAbWzMxbSQkG1swOzMxbSQbWzFtJCAbWzMwbSQgG1swOzMxbSQkJCR5eXl5LCwsLCAbWzE7MzBtJLy8IBtbMzFtJCQbWzA7MzFtJCQgG1sxOzMwbcjIyMhcc3l5eXkkJA0KJBtbMDszMW0kJCQkG1szN20gG1sxOzMwbSQkJCQbWzBtIBtbMzFtJCQkJBtbMzdtIBtbMTszMG0kJCQgG1swOzMxbSSxJCQbWzM3bSAbWzE7MzBtJCQkJCQkJCQkeXkkIBtbMzFtJCQbWzA7MzFtJCQgG1sxOzMwbSR5eXl5IBtbMDszMW0kJCQbWzFtJBtbMDszMW39/f39IBtbMTszMG0kIBtbMDszMW1gYGAbWzFtYP39G1swOzMxbf39JCQkJHl5eXksLCwNChtbMTszMG0kG1swOzMxbSQkJCQbWzM3bSAbWzE7MzBtJCQkJBtbMG0gG1szMW0kJCQkG1szN20gG1sxOzMwbSQkJBtbMG0gG1szMW0kJCQkG1szN20gG1sxOzMwbSQkJCQkJCQkJCQkJCAbWzMxbSQbWzA7MzFtJBtbMW0kG1swOzMxbSQgG1sxOzMwbSQkJCQkIBtbMDszMW0kJCQkIBtbMTszMG3IJCQkJCQkJCQkeXl5eSwsLCwsIBtbMDszMW0kG1sxbSQbWzA7MzFtJCQNChtbMTszMG0kG1swOzMxbSQkJCQbWzM3bSAbWzE7MzBtJCQkJBtbMG0gG1szMW0ksiQkG1szN20gG1sxOzMwbSQkJBtbMG0gG1szMW0kJCQkG1szN20gG1sxOzMwbSQkJCQkJCQkJCQkJCAbWzA7MzFtJBtbMW0kG1swOzMxbSQkIBtbMTszMG3IJCQkJHkgG1szMW0kG1swOzMxbSQkJCAbWzE7MzBtJCQkJCQkvLy8vLy8JCQkJCQkIBtbMDszMW0kJCQkDQobWzE7MzBtJBtbMDszMW0kJCQkG1szN20gG1sxOzMwbSQkJCQbWzBtIBtbMzFtJCQkJBtbMzdtIBtbMTszMG0kJCQbWzBtIBtbMzFtJLIkJBtbMzdtIBtbMTszMG0kJCQkJCQkJCQkJCR5IBtbMDszMW0kJBtbMW0kG1swOzMxbSQgG1sxOzMwbSQkJCQkIBtbMDszMW0kG1sxbSQbWzA7MzFtJCQgG1sxOzMwbSQkJCQkJCAbWzA7MzFtJBtbMW0kJBtbMDszMW0kIBtbMTszMG0kJCQkJLwgG1szMW0kG1swOzMxbSQbWzFtJBtbMDszMW0kDQobWzE7MzBtJBtbMDszMW0kJCQksRtbMzdtIBtbMTszMG0kJCQkG1swbSAbWzMxbSQkJCQbWzM3bSAbWzE7MzBtJCQkG1swbSAbWzMxbSQkJCQbWzM3bSAbWzE7MzBtJCQkJBtbMG0gG1szMW0kJCQkG1sxOzMwbSQkJCAbWzA7MzFtJCQkJCAbWzE7MzBtJCQkJCQgG1szMW0kG1swOzMxbSQbWzFtJBtbMDszMW0kIBtbMzdtIBtbMTszMG3IJCQkvCAbWzMxbSQkG1swOzMxbSQbWzFtJCAbWzMwbSQkJCQkIBtbMDszMW0kJBtbMW0kJCAbWzMwbXkNCiQbWzA7MzFtcy4kJCQgG1sxOzMwbSQkJCQbWzA7MzFtICQkJCQgG1sxOzMwbSQkG1swbSAbWzMxbWD9JCQsLCwsLCwkJP0nG1sxOzMwbSQkJCQgG1swOzMxbSQbWzFtJBtbMDszMW0kJCAbWzE7MzBtyMjIJCR5IBtbMDszMW0kG1sxbSQkG1swOzMxbSQgG1sxOzMwbSQkJCQgG1szMW0kG1swOzMxbSQbWzFtJBtbMDszMW0kIBtbMTszMG15JCQkJCQgG1szMW0kG1swOzMxbSQbWzFtJBtbMDszMW0kIBtbMTszMG0kDQokJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCAbWzA7MzFtJCQkJHl5eRtbMW15G1swOzMxbSwbWzFtLCwbWzA7MzFtLBtbMW0kJBtbMDszMW0kG1sxbSQgG1szMG0kJEkkIBtbMDszMW0kJCQkIBtbMTszMG0kJCS8vLwgG1swOzMxbSQkG1sxbSQkIBtbMzBtJA0KJCQkJCQkG1swbW0bWzE7MzBtJBtbMG1vG1sxOzMwbSQbWzBtchtbMTszMG0kG1swbXQbWzE7MzBtJBtbMG1pG1sxOzMwbSQbWzBtZhtbMTszMG0kG1swbWkbWzE7MzBtJBtbMG1zG1sxOzMwbSQkG1swbTIbWzE7MzBtJBtbMG0wG1sxOzMwbSQbWzBtMhtbMTszMG0kG1swbTEbWzE7MzBtJCQkJCQkJCR5eXl5IBtbMDszMW1gYGBgG1sxbf0bWzA7MzFt/RtbMW39G1swOzMxbf0gG1sxOzMwbXl5eXkkJDskIBtbMDszMW0kJCQkLBtbMW0sG1swOzMxbSwsG1sxbXkbWzA7MzFteRtbMW15eRtbMDszMW0kG1sxbSQkJCAbWzMwbSQNCiQkJCQkJCQkJCQkJCQkJCQkyP39/bwkJCQkJCQkJCQkJCQkJCQkJCQkU7z9/f28UyQkJCQkJCQkJCR8JHl5eXkgG1swOzMxbf39G1sxbf0bWzA7MzFt/ScbWzFtJycnIBtbMzBteXl5eSQNCg==';

4). optionally you can visit https://embed-v2.ftelnet.ca/ and using their form generate the code using an ansi of your choosing.

  note: you only need to copy/paste the Options.SplashScreen= 'whatever code' and save it as template.splash similar to above.
  close and save.
  

5). add template.splash = '' value from above in ftelnet.ssjs as well

6). edit ../web/templates/nightshade/ftelnet.inc and add Options.SplashScreen = '@@splash@@';

  your ../web/templates/nightshade/ftelnet.inc options should like similar to
  
<!-- fTelnet --> 
 
	<div id="fTelnetContainer" class="fTelnetContainer"></div>
	<script>document.write('<script src="//embed-v2.ftelnet.ca/js/ftelnet-loader.norip.xfer.js?v=' + (new Date()).getTime() + '"><\/script>');</script>
	<script>
		var WSS = (location.protocol.toLowerCase() == 'https:');
		var Options = new fTelnetOptions();
		Options.BareLFtoCRLF = false;
		Options.BitsPerSecond = 57600;
		Options.ConnectionType = 'telnet';
		Options.Emulation = 'ansi-bbs';				
		Options.Enter = '\r';
		Options.Font = 'CP437';
		Options.ForceWss = false;
		Options.Hostname = '@@HostName@@';
		Options.LocalEcho = false;
		Options.Port = (WSS ? @@WSSPort@@ : @@WSPort@@);
		Options.ScreenColumns = 80;
		Options.ScreenRows = 25;
		Options.WebSocketUrlPath = '/?Port=@@TelnetPort@@';
		Options.SplashScreen = '@@splash@@';
		var fTelnet = new fTelnetClient('fTelnetContainer', Options);
	</script>
 
<!-- end fTelnet -->

7). edit ../web/root/index.ssjs and have it look similar to

if(do_rightnav)
        write_template("rightnav.inc");
 
//write_template("main.inc"); /* comment this out */
 
load('ftelnet_main.ssjs');  /* add this (this will add ftlenet logon screen to the main center portion */
 
if(do_footer)    
    write_template("footer.inc");

8). edit ../web/templates/nightshade/leftnav.inc and add an <li><a href=“/ftelnet.ssjs”>fTelnet Login</a></li> link to the exist nav list

9). Confirm that your ws/wss ports are configured properly in ../ctrl/modopts.ini and that enabled and router ports are listening

You should now have fTelnet links and fTelnet Logon Screen with a custom splash

See Also