Formalise JS libraries in Foswiki

JQueryPlugin provides a good model already:

%JQREQUIRE{"foo"}%

This goes off and processes something called "foo", which will use ADDTOHEAD/ZONE to insert some code which will load some JS, maybe some CSS, resolving/satisfying dependencies which are defined similarly.

ADDTOHEAD/ZONE by itself is not enough. It does nothing if you have a requires parameter which is never resolved. We must come up with a standard way to require something into a page, along with its dependencies.

Case study is Tasks.Item8571, where NatSkin does not provide foswikiLib.js by default, but it is required by EditTablePlugin. EditTablePlugin has no clean way of asking for foswikiLib.js, and even if it did, the JS developers have no clean way to offer the dependencies anyway. So it is just "assumed" by the plugin author(s) that editTable.js will always be available.

%JQREQUIRE{"thing"}% is a working example of what we need. It provides:
  • Define a "thing"
  • Define thing's dependencies
  • Define code to be added to head/a zone associated with "thing"
  • Define an author
  • Define a homepage
  • Resolves a DEBUG (source/uncompressed) version of the .js or .css
  • Define a version (which, when the js/css files are rendered to HTML in the <script> tags, append a ?version=1.2.3 param so we can confidently use far reaching future expires headers to exploit browser cache properly)

I think there should be a registry of "tags" (in the ADDTOHEAD/ZONE sense) and what they expand out as, what they depend on, the preferred target zones they should be expanded into.

JQueryPlugin does this by creating a unique FOO.pm for every js lib/thing; is this the best way forward?

JQueryPlugin also provides a registerPlugin() method, which can be used by plugins to register new "foo" tags which can be required elsewhere. Is this the way forward?

To be discussed elsewhere

  • Rationalising the actual JS itself, or the foswiki core JS/"API"
  • Adding JSLint as a part of our nightly build process, alongside perlcritic

The Question

Do we just keep JQueryPlugin as it is and convert our core extensions - and the rest of Foswiki for that matter - to use the JQueryPlugin::Plugins::registerPlugin() API as a way for other components to intelligently include JS libs?

Or do we abstract out this stuff and merge it to core?

I have an idea on how ADDTOZONE could take care of the file versioning:
%ADDTOZONE{"body" 
  text="<script src='%foo%'></script>" 
  foo="%PUBURLPATH%/%SYSTEMWEB%/FooPlugin/foo.uncompressed.js"
  requires="bar"
}%

%foo% could expand out as a few different things:
  • foo.js?version=20100219 (date derived from stat() to learn mtime)
  • foo.js?version=(etag value)
  • foo.js?version=(foswiki RCS rev)
  • foo.js/ver20100219
  • foo.js/(etag value)

Last two examples would avoid troubles with proxy caches which don't cache anything that has URL params. Of course you would need an apache rewriterule to strip the date/etag junk off the end of the filename so you don't get 404s.

-- PaulHarvey - 19 Feb 2010

Most of the code in these JavascriptFiles are written rather copious. Using jQuery would reduce it in size quite a bit.

Another idea would be to rewrite/move/swallow/replace all JavascriptFiles and put them into JQueryPlugin. Theres a foswiki module already that does the housekeeping. For instance, it provides a leaner and more flexible way to propagate perl preferences to js land using meta tags. Fully foswikilib.js and co will also needed adapter functions for backwards compatibility.

One very important extension depending on this kind of code is TwistyPlugin.

Anyway, the idea is to

-- MichaelDaum - 19 Feb 2010
Topic revision: r2 - 19 Feb 2010, MichaelDaum
The copyright of the content on this website is held by the contributing authors, except where stated elsewhere. See Copyright Statement. Creative Commons License    Legal Imprint    Privacy Policy