Created by: gwideman, Oct 7, 2010 6:57 am
Revised by: gwideman, Nov 3, 2011 4:27 pm (29 revisions)

------ Draft! -----

Overview

This set of pages discusses the topic of how to add features and functionality ("addons") to wikispaces sites and pages.

Wikispaces does not have a formal set of guidelines for adding functionality to wikispaces sites or pages. However, the structure of WS pages, and the features that the WS service offers, lead to particular opportunities and constraints for adding functionality. This page presents an analysis of the facilities available, and some principles and conventions that I have found helpful for creating add-on functionality.

Orientation


The wikispaces server assembles pages by combining several inputs that us users can control with some some standard boilerplate html, CSS and Javascript. Here are the components we users can access:

  • Page content: Obviously we can create and edit pages, at least the "content area" of pages.
  • space.menu This is an ordinary page which has the special additional feature that the wikispaces server includes it in all other page views, usually in the left or right sidebar as controlled by the theme, specifically the $WikiContent$ variable). This is the page which you can edit if you click on "edit navigation".
  • Theme "file": This file provides a skeleton of instructions to the wikispaces server for building pages. It is essentially an HTML/CSS/Javascript file with some extensions for inserting "components". Users of paid wikispaces can edit this file using Manage Wiki > Look and Feel > Themes and Colors, and follow the steps to create and edit a "custom" theme.
  • User content CSS "file" ("Wiki stylesheet"). This file provides CSS intended to style the content area of a page. It is invoked for normal browser view of pages, and also by the WYSIWYG editor, and for the wikispaces Page > Print view. It is not the only CSS stylesheet invoked, as CSS for peripheral areas of the page (title, sidebar, menus) appears in the theme file, and other CSS for popups, editor controls etc comes from other CSS files. (Hence, the term "Wiki stylesheet" is a little misleading, but perhaps refers obliquely to the ".wiki" class for the div around the content area.) Users of paid wikispaces can edit this file using > Manage Wiki > Look and Feel > "Edit your wiki stylesheet".

(Note: access equivalent to paid access is also available for 30 days on new trial sites.)

The system of components just described gives considerable flexibility to determine the look, feel and function of pages. To take control of these facilities, it's helpful to have a fuller understanding of how they fit together.

Structure of an "addon"

In general, we will want an addon to incorporate some or all of the following parts:
  • CSS: To change how elements look, where they are positioned, or whether they appear at all.
  • Javascript: To make more drastic rearrangements of the DOM. Although editing the Theme allows rearranging some of the major components of the page, you cannot rearrange the details within the components, for example the elements within the set of tabs, or a menu. Javascript allows you to get at any level of detail you want.
  • HTML (such as a div): We may wish to add additional HTML explicitly, for example adding a div in the navigation area (space.menu), which will be the target of more additions generated with a script.
  • One or more "data files". An addon could include additional pages, or load files, which provide "data" for the addon to digest and turn into a display.

With all this in mind, we move on to look at where these elements may be placed in the structure of a wikispaces page.

Assembly and structure of wikispaces page

The following figure shows how the wikispaces server assembles the html for a page.

img-addonprinc-themetopage.gif

The wikispaces server assembles html to send to the browser, starting from a theme file, and inserting some additional standard data, plus data from a particular content page, and a page providing the navigation column. After the html is delivered to the browser, the browser fetches additional CSS and javascript files.

This diagram is obviously a simplification of the actual theme file and html, but the major landmarks are shown, which you will see if you inspect a theme file, or inspect the html using "save source" in a web browser (or better yet, a web browser debugger, such as firebug).

Different views load different sets of CSS

As part of our consideration of where to interpose our own CSS, we need to know which locations will or will not provide CSS rules to views other than the normal "browser" view. The following table summarizes the different scenarios.



Location of CSS rules or invocation of CSS file
Rendering scenario
Browser "media"
status
Theme head,
via <link>
User content
CSS
Theme body,
loaded via JS
Page content,
loaded via JS






Browser
screen
Yes
Yes
Yes
Yes
WYSIWYG editor
screen
-
Yes
-
-
Browser print Note 1
print
Yes
Yes
Yes
Yes
Wikispaces Page > Print
screen!
-
Yes
-
Yes
Wikispaces Page > PDF
???
-
-
-
-







Notes:
1. The Browser print function does not rebuild the DOM, it simply re-renders it, taking into account the different "media" status and corresponding media directives in the CSS. (Also taking into account the zoom percentage and other print or print-prevew settings.) Consequently, whatever CSS rules and files have been loaded are still in effect, and any changes to the DOM already made by Javascript remain in the DOM.

Update: I later decided that neither the "Wikspaces Page > Print" nor the "Wikispaces Page > PDF" features are worth bothering with. See separate article: Position on printing.

Different views run different sets of Javascript

As part of our consideration of where to interpose our own Javascript, we need to know which Javascript will run in each view.


Location of Javascript script or link to JS file
Rendering scenario
Theme head
script
Theme body
script
space.menu
widget
Page content
widget





Browser
Yes
Yes
Yes
Yes
WYSIWYG editor
Note 1
Note 1
Note 1
-
Wikispaces Page > Print Note 2
-
-
-
Yes
Wikispaces Page > PDF
-
-
-
Yes






Notes
1. The WYSIWYG editor loads the content (without peripheral area) into a separate iframe , and does not execute embedded widgets, so does not run any Javascript. It is conceivable that Javascript loaded before the editor is launched could interact with the editor, though I have not tried this.

2. The Wikispaces Page > Print view commands the wikispaces server to send a new version of the page, minus the peripheral area. This page is therefore not based on the Theme file, thus does not execute Javascript embedded or linked in the theme. Javascript embedded or linked in the page content (by virtue of an HTML widget) will be included and will execute.

Update: I later decided that neither the "Wikspaces Page > Print" nor the "Wikispaces Page > PDF" features are worth bothering with. See separate article: Position on printing.

Plausible locations for addon CSS and Javascript

The following diagram is a simplification of the previous one, indicating where we might usefully interpose our own CSS or Javascript, noted in red.

img-addonprinc-cssjslocs.gif

As can be seen, there are several locations to either add CSS or Javascript explicitly, or using links or Javascript to load separate files.

For many addon scenarios, the most favorable location would be at the end of the html head section, marked [X] in the diagram. Being within the head section, CSS rules could be written explicitly, or a CSS file could be invoked from a link tag (not dependent on Javascript being enabled). Since these rules would appear after other CSS, they would override other matching rules. Javascript for the addon could be kept at the same location to keep the components for the addon together. Unfortunately, the Wikispaces theme file does not provide a way to place CSS or Javascript at that location.

Of the available locations, each has different pros and cons, listed in the table below. Basic (unpaid) wikispaces are restricted to just a few of these locations, as noted in the "Unpaid" column.

[n]
Location
Unpaid?
(Sept-2010)
CSS
Javascript
0
User CSS file
No
An obvious place to put CSS additions, but server restricts rules to scopes within .wiki class.
(Not applicable. CSS files cannot include Javascript)
1
Theme file, head section, and possibly separate file(s)
No
CSS can appear explicitly here, or an external CSS file can be invoked via a link tag.
Javascript can appear explicitly here, or an external JS file can be involved via a link tag.
2 and 3
Theme body section, anywhere, but begin or end make sense
No
CSS not allowed in body, but could be loaded by Javascript. Not much point.
Javascript could be inserted explicitly. Could load external Javascript file. Might be useful to write in additional html at a particular point in the stream of html.
4
space.menu page ("Edit navigation")
Since the space.menu page is invoked by every other page, and available even to unpaid wikispaces, this is a useful place for addon features.
YES
CSS cannot appear explicitly, but you can use javascript to load a CSS file or modify the DOM CSS directly.
Javascript can be included here within one or more "Other HTML" widgets. Even for paid wikispaces, this may be a useful place to perform development and testing of simple addon code.
5
User content page
YES
CSS cannot appear explicitly, but can you can use javascript to load a CSS file or modify the DOM CSS directly.
Javascript can be included here within one or more "Other HTML" widgets. A more refined idea is to place the widget on a separate page, and include that on content pages where needed using an Include Page widget.






When does Javascript execute?

While we are considering the merits of these different locations, particularly for Javascript code, it's helpful to keep in mind when it is that we want the Javascript to execute, and why.

In general, the browser executes scripts at the time they are encountered during the process of digesting the html and building the DOM. For example, if you insert a script that writes some HTML, like this:
<script type="text/javascript">
  document.write('Message from javascript<br>');
</script>
 
then the browser takes the output html message and inserts it next in the sequence of html. Sometimes that's the effect we want, and for this we would place the Javascript exactly at that desired spot in the html.

(Aside: Why use a script to do this? Why not just write in the desired html? Wikispaces widget editor will not save html whose tags are unbalanced. So if we want to use a widget to insert an html fragment to start a div, for example, the unbalanced opening div tag will be rejected when we try to save it. We can work around that by using a snippet of javascript to write out that tag instead. See link to SealWyf for example).

Usually, however, we want javascript to operate on some objects in the DOM, objects whose state might not be ready at the point in time when the browser reaches and digests our script. Take, for example, a script that is supposed to build a page table-of-contents by inspecting the content area of the page looking for headings. If you put this script in the space.menu page, it will execute when the browser builds the navigation column the page, which will likely be before the browser encounters the html for the content area,and hence there is not content area yet included in the DOM. Result -- empty table of contents.

For that reason, rather than execute the intended function at that time, instead we have our script prepare a function to be executed when the browser has finished loading the html and building the DOM. Most easily we can do this using the jQuery "document ready" facility.). For these cases it doesn't really matter where our script is located, since it's just preparing a function to be executed later, even after the "latest" place in the document that we can put our script.

On the other hand, generally we would prefer all CSS to be prepared before the browser starts building the DOM, so that as the page is gradually displayed, the browser doesn't have to rearrange it due to late-appearing CSS rules or files. If we are obliged to load CSS using Javascript in the body section of the hml (as we are for Basic unpaid wikispaces), then we would like such a script to execute as early as possible, and not wait for a document ready function.

Conventions for addon structure

When implementing an addon, we might want to make it modular; that is to keep the components of the addon distinct from the html, css and javascript of the base theme, and from the components of other addons. Doing so will allow us to add or remove features in an orderly and more robust fashion, and make it easier to share addons with other users. Setting a consistent convention for the location and naming of components of addons will help to achieve that goal.

Convention for Basic (unpaid) wikispaces

Addons for unpaid wikispaces do not have much choice regarding where to implement addon functionality: the most attractive location is the space.menu page, since that page is included as the "Navigation area" on all other pages.. One convention for such addons looks like this:

img-addonprinc_addonstruc01.gif
Note: actual syntax for include is: [[include component="page" page="addonXxx.nav" ]]

In this convention, the space.menu page contains only "include page" widgets, where each of these other pages encapsulates whatever is needed for a particular addon. The diagram shows two typical addon pages (addonXxx and addonYyy), which each contain an Other HTML widget. The HTML widget can provide a script which might load a CSS file, and might include explicit Javascript, or load a separate Javascript file.

The naming convention for these components could be as follows. Assuming the base name of the addon is: addonXxx
Item
Naming pattern
Comments
"Nav Include page" which includes javascript,
and possibly loads a CSS file
addonXxx.nav
Use this as page title
CSS file
addonXxx.css

Javascript file
addonXxx.js

Implementing an addon using the space.menu page is adequate for a variety of addon scenarios, but it is less than ideal.
  • CSS rules added here will be digested by the browser at a late stage in the arrival and rendering of the page, and thus may cause the partially-rendered page to redraw.
  • Some addons would be improved if their CSS rules could be loaded by the editor, which space.menu-based addons can't effect.

Convention for paid wikispaces

With a paid wikispace we have access to the Theme file and the User CSS file, which opens up possibilities for more ambitious addons. It may seem obvious that for best effect we would take advantage of the User CSS file, or place Javascript and CSS in the head part of the html, either directly, or via link tags. However, things are not so simple:
  • Problem with order: As you can see from the diagrams above, the Wikispaces Theme and User CSS system does not give us the opportunity to place our code in the head section of the html, after the standard CSS code and jQuery library.
  • Use by the WYSIWYG content editor and print views: As noted in the earlier section "Different views load different sets of CSS", the choice of where to place CSS rules is influenced by whether we need the rules to be effective in the WYSIWYG editor, and/or in one or other of the print scenarios.
  • The User CSS file is restricted to ".wiki" class:The editor for the User CSS reports an error for CSS rules that do not include the".wiki" class. It does permit ids and classes to precede the .wiki class, so we can set qualifications that distinguish between normal browser view, WYSIWYG editor, and the Print view
    • Update: 2010-Dec: Currently, there is no way to target CSS solely to the WYSIWYG editor. That editor appears in an iframe having a body tag with class="mceContentBody wiki", so should be selectable with ".mceContentBody.wiki", but this is rejected by the wikispaces CSS editor. I have filed a bug report on this, and wikispaces has acknowledged that this needs fixing. See my issues page: Wikispaces issues.

Javascript

For javascript, we want our component to execute after the jQuery library is loaded, but jQuery gets loaded by the boilerplate code that the wikispaces server places last in the head section, right before the </head> tag. If our code needs to call the jQuery library, then the earliest place we can put our javascript code is at the beginning of the body section.

CSS

For CSS we have some trickier criteria to consider. The choices are summarized in the table below.

(XXXX Update table based on newer testing ! XXXX)


Location, form of CSS

[1] End of theme head section, as <style> or <link>
[0] End of User CSS file, as plain CSS
[2] Beginning of body section; add rule, or load file, using JS
CSS Purpose



Peripheral area CSS: Override the base theme's CSS that applies to the "peripheral" area (title, menus, sidebar).
Possible location, since this can override most of peripheral area CSS which appears earlier in the theme file.
Generally not feasible due to rules without ".wiki" class being rejected by CSS editor.
Little benefit, unless trying to consolidate all changes in Javascript module
Content area: Override or augment the content area CSS, and also take effect in the WYSIWYG content editor and wikispaces Print view.
Not feasible, since rules here will not take effect in the editor or Print version (but do take effect in browser Print view!)
This is the most reasonable location: rules here will take effect on normal pages, and in the editor
Not feasible, since rules here will not take effect in the editor..
Content area: Override the content area CSS, and need NOT take effect in the WYSIWYG content editor or for Print version
Won't override, since it's before the User CSS.
Possible; use additional id or class ahead of .wiki to control browser/editor/Print effect.
Possible location, especially to load external CSS file.
Content area: Augment the content area CSS (ie: new rules are distinct from existing CSS rules), and need NOT take effect in the WYSIWYG content editor or for Print version
Possible, since we don't care about the order of these rules relative to other rules.
Possible; use additional id or class ahead of .wiki to control browser/editor/Print effect.
Possible location, especially to load external CSS file.

Positioning added HTML

Some addons might usefully add some plain html to either the content or the peripheral area. For example, an addon's Javascript might be intended to produce some output in the sidebar "navigation area". One way to provide a suitable target for the output is to place a <div> in the space.menu page using an Other HTML widget. (See also Includes and widgets).

Utility function "library" addon

To-do

Mistake recovery feature

To-do



Page info
Image prefix: img-addonprinc-nnn.gif/jpg