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.]
Each page consists of four parts:
../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.
../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>'});
../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.
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.
../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.
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>
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";
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.
name
is replaced with the HTML encoded value of template.name
i.e.; Spaces are replaced with: this is 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)
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=" <b>|</b> "; 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.
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.
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.
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
!-- Begin Left Nav --> <div id="navcontainer"> <div id="navigation"> <h4>Navigation</h4> <ul> <li><a href="/nodelist.ssjs">Who's Online</a></li><li><a href="/ftelnet.ssjs">fTelnet Login</a></li><<REPEAT leftnav>>@@leftnav:html@@<<END REPEAT leftnav>></ul> </div> </div> <!-- End Left Nav -->
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