CanalPlanAC

The places subsystem

Introduction

During the Covid-19 lockdown of spring 2020 I reworked the entire place and other gazetteer pages. Previously the pages were autogenerated when needed, although there was some half-hearted serving of pages stored in /html/cached_gazetteer. There was a complicated system of caching for the data used to create the pages.

In the new system, there is maintained a set of complete HTML pages for all areas, features, places and waterways. These are served whenever needed. User preferences are managed by manipulating the pages using Javascript.

Note that if any significant changes are made to the plugins it will be necessary to delete all generated files for these to have any effect.

File structure

Just about everything is held in the "pages" directory at the top level. Below this is divided into:

Under code are the following major directories:

Scripts

There are four scripts - generate_xxx_html.can which make the four types of pages.

Plugins

These provide blocks of information for the ready-to-serve place, waterway, area and feature pages. The entire main-content part of the page is generated from plugins. Each plugin is used for any subset of the pages, depending on its configuration.

To create a plugin:

each of these is further documented below.

code.can

This file should contain a function Plugin that takes two lookup parameters. The first is the parsed config.hdf file and the second is placeinfo for the place being built.

If it calls any sub functions or procedures, it should use the name of the plugin as a namespace - for example nearest$do_stuff

template.cst

This should access the plugin data and configuration using data.plugins.plugin-name.data and data.plugins.plugin-name.config

To call a javascript function from the generated HTML, do it using Page_Call_Plugin_JS('plugin-name','function name,parameters) This will load the plugin javascript file if needed and call the function.

javascript.js

Contains all JavaScript code in support of the plugin. Most functions should be called using Page_Call_Plugin_JS in response to user activity. All functions should be placed in an object derived namespace named after plugin_plugin-name - this means that a function definition looks like, for example plugin_photos.options_display = function() {

Can contains a function called personalise

This function will be called at page load if conditions met in config.hdf are met. This is to reconfigure the plugin display to user preferences (hiding some items for example).

Can contain a function called options_display

If the config for this plugin contains the "need_configuring" flag in the options block, then the JavaScript file will be loaded and this function called whenever the plugin is selected and the options relating to it displayed. It will also be called when any option containing the "has_dependencies" flag is altered. It should consist of a series of tests of option value that turn on and off, or set defaults, for other options.

config.hdf

All files should contain:

config.hdf - the options block

This block defines all options that are shown on the preference page, and captured in sessions and user records.

Each option should be named by the value that will be used elsewhere in the code. So, for example, a block called "photomode" in the "photos" plugin will be displayed on the preferences page as pageopt_option_photos_photomode, and will be stored in the options variable as pages.photos.photomode. The block of code for setting it on the preferences page will be called page_options_plugin_option and this is useful for showing/hiding individual options.

Because of this, option names must not contain underscores and must be valid identifiers otherwise (alphabetic strings recommended).

An option can contain the following fields:

Option types has specific fields

A "comment" block will have each line printed at the bottom of the options page. This is useful to indicate, say, things that are controlled by other plugins (such as the layout of geograph photos)

Generic options

There are generic options that are shown for all plugins with an options menu. This makes it easier than calling up the main preferences screen. They are stored in the options variable as pages.

Dynamic information

To add dynamic information to a plugin:

  1. add a "dynamic" section to the config file, which contains "datacalled = [variable]"
  2. if the plugin template needs format options (say for dates) then set "formats = yes" inside the dynamic section
  3. add a file "dynamic_code.can" to the plugin directory. This should contain a function "plugin" which takes the same parameters as a normal plugin function. The data it returns will end up in data.[variable] as defined above
  4. add a file "dynamic_template.cst" which will render that data correctly
  5. ensure the normal template includes plugin_helpers.cst
  6. add a call to the normal template.cst call:dynamic_text(plu) where you want that text embedded.