Using J Query With Foswiki

Introduction

jQuery is an industry-standard Javascript framework, used by a lot of Foswiki extensions and many foswiki developers. jQuery is the "javascript framework of choice" for use with Foswiki. That doesn't mean you can't use other frameworks (such as Dojo, YUI, or Mootools), just that we focus our efforts on supporting jQuery first.

Getting started

We're going to assume you are familiar with the following:
  • HTML
  • CSS
  • Javascript
If you have ever hand-crafted an HTML page, styled it using CSS, and maybe written a bit of Javascript (for example to validate forms input) then you are well positioned to use jQuery. If you are new to any of these, then sorry, you have a steep learning curve ahead of you. There are a wealth of resources on the web to help you get started, though.

Before you start trying to use jQuery in Foswiki, we'd also recommend that you familiarize yourself with how Foswiki works, especially:
  • templates
  • macros

JQueryPlugin

The easiest way to get started using jQuery is to install the JQueryPlugin. Once you have done that, all you need to do is to add the appropriate %JQREQUIRE directive, and you will be able to use the required plugin in your HTML, as described in the plugin documentation. That really is all there is to it!

Adding more jQuery plugins

The plugins shipped with JQueryPlugin itself live in
  • pub/System/JQueryPlugin/plugins/myplugin/
    This is the where all js and css code of the default plugins are located. All plugins except jQuery-ui and themes live next to this directory.
  • lib/System/JQueryPlugin/MYPLUGIN.pm
    This is the perl stub that takes care of loading the library into a page as well as all of its dependencies.

Other Foswiki extensions can also add new jQuery plugins to the set managed by JQueryPlugin, and the recommended approach to adding new jQuery plugins is to package the JQuery plugin as a Foswiki extension module. The advantage of packaging as a contrib module is that you don't incur the overhead of a Foswiki plugin module, which can be significant. The process for both is very similar.

The first step is to create an extension - we'll focus on creating an contrib module called "JEditableContrib" which packages the excellent jQuery edit-in-place support from Miko Tuupola. We're going to assume you are working in a subversion checkout of the Foswiki development repository, and have done a pseudo-install developer as described elsewhere in the DevelopersBible. The process for packaging in a Foswiki plugin is almost identical, with some small exceptions that we'll cover at the end.

Step 1 create the extension framework:

$ cd to the root of your subversion checkout
$ core/create_new_extension.pl JEditableContrib

This should give you:

JEditableContrib/
  data/
    System/
      JEditableContrib.txt
  lib/
    Foswiki/
      Contrib/
        JEditableContrib.pm
        JEditableContrib/
          build.pl
          DEPENDENCIES
          MANIFEST

Step 2 Create a directory JEditableContrib/pub/System/JEditableContrib, and put the source (uncompressed) javascript there (you can call it _src.js or =.uncompressed.js, your choice)

  pub/
    System/
      JEditableContrib/
        jquery.jeditable_src.js

Step 3 Edit JEditable/lib/Foswiki/Contrib/JEditableContrib/MANIFEST and add the following lines:

lib/Foswiki/Contrib/JEditableContrib/JEDITABLE.pm 0644 Plugin stub
lib/Foswiki/Contrib/JEditableContrib/Config.spec 0644 Configuration data
pub/System/JEditablePlugin/jquery.jeditable_src.js 0644 Uncompressed javascript
pub/System/JEditablePlugin/jquery.jeditable.js 0644 Compress javascript

Step 4 Edit JEditable/lib/Foswiki/Contrib/JEditableContrib/DEPENDENCIES and add

Foswiki::Plugins::JQueryPlugin,>4.02,perl,Required

Step 5 Edit JEditable/lib/Foswiki/Contrib/JEditableContrib.pm. You are best to clear this file out and start again. It's a very simple stub.

package Foswiki::Contrib::JEditableContrib;

use strict;
use warnings;

use version 0.77; our $VERSION = version->declare('v1.7.1');
our $RELEASE = '1.7.1'; # keep in synch with jquery.jeditable.js
our $SHORTDESCRIPTION = 'The JQuery "JEditable" plugin, packaged for use in Foswiki';
1;

Step 6 Edit JEditable/lib/Foswiki/Contrib/JEditableAddO/JEDITABLE.pm. This describes meta-data about the plugin, and is the most complicated code you will write today.

package Foswiki::Contrib::JEditableContrib::JEDITABLE;
use strict;
use warnings;

use Foswiki::Plugins::JQueryPlugin ();
our @ISA = qw( Foswiki::Plugins::JQueryPlugin::Plugin );

use Foswiki::Plugins::JQueryPlugin::Plugin ();
use Foswiki::Contrib::JEditableContrib ();

sub new {
    my $class = shift;
    my $session = shift || $Foswiki::Plugins::SESSION;
   
    my $this = $class->SUPER::new( 
        $session,
        name          => 'JEditable',
        version       => $Foswiki::Contrib::JEditableContrib::RELEASE,
        author        => 'Mika Tuupola',
        homepage      => 'http://www.appelsiini.net/projects/jeditable',
        puburl        => '%PUBURLPATH%/%SYSTEMWEB%/JEditableContrib',
        documentation => "$Foswiki::cfg{SystemWebName}.JEditableContrib",
        summary       => $Foswiki::Contrib::JEditableContrib::SHORTDESCRIPTION,
        javascript    => [ "jquery.jeditable.js" ]);
    
    return $this;
}
1;

The constructor for the Foswiki::Plugins::JQueryPlugin::Plugin supports a number of fields:
Field Description
name symbolic name of the module; mandatory
version semi-numeric version number of the plugin; this is added to the urls loading this module
summary Descriptive text
documentation topic holding the plugin's documentation
author creator and/or copyright holder of this plugin
homepage url where the bulk of the module's documentation is located
puburl url base for finding CSS and Javascript files. By default this points to the %PUBURLPATH%/%SYSTEMWEB%/JQueryPlugin/plugins/<name> but can be redirected to your own plugin, as in the example above.
css Reference to a perl array of CSS filenames. These files must exist in puburl.
javascript Reference to a perl array of Javascript filenames. These files must exist in puburl.
dependencies names of other plugins to be loaded before this library is added to the head. Each entry can either be the symbolic name of another jquery library registered to JQueryPlugin, or any other identifier used in an ADDTOHEAD call
tags list of macros this plugin implements; only used for documentation
debug Set to 1 to enable debug
Step 7 Create/edit JEditable/lib/Foswiki/Contrib/JEditableContrib/Config.spec=

# ---+ Extensions
# ---++ JQueryPlugin
# ---+++ Extra plugins
# **STRING**
$Foswiki::cfg{JQueryPlugin}{Plugins}{JEditable}{Module} = 'Foswiki::Contrib::JEditableContrib::JEDITABLE';
# **BOOLEAN**
$Foswiki::cfg{JQueryPlugin}{Plugins}{JEditable}{Enabled} = 1;
1;

See also the example module in =EMPTY.pm and jquery.empty.uncompressed.js as well as the other plugins shipped with JQueryPlugin.

Packaging in a plugin

If you want your plugin to be usable with JQueryPlugin versions < 4.02, then you can add a "plugin stub" to make it compatible.

Step 8 Create the directory JEditable/lib/Foswiki/Plugins/JEditableContribPlugin.

Step 9 Create/edit JEditable/lib/Foswiki/Plugins/JEditableContribPlugin.pm=

package Foswiki::Plugins::JEditableContribPlugin;
use strict;
use warnings;
use Foswiki::Plugins::JQueryPlugin::Plugins ();
use Foswiki::Contrib::JEditableContrib::JEDITABLE ();

sub initPlugin {
    Foswiki::Plugins::JQueryPlugin::registerPlugin(
   'JEditable', 'Foswiki::Contrib::JEditableContrib::JEDITABLE');
    Foswiki::Plugins::JQueryPlugin::createPlugin('JEditable');
}

1;

Plugins have to be enabled via =configure. Only then are they loadable via %JQREQUIRE{"mynewplugin"}%.

ALERT! The plugin should be disabled in configure when running with JQueryPlugin 4.02 or later.

Debug mode

The $Foswiki::cfg{JQueryPlugin}{Debug} flag is used to switch on debug mode for JQueryPlugin itself as well as all of its sub-modules. If enabled, it will load the uncompressed variants of a module's static file, e.g. jquery.myplugin.uncompressed.js instead of jquery.myplugin.js

So make sure your source files are called ...uncompressed.js and ...uncompressed.css as the plugin won't work in debug mode otherwise.

Documentation

The documentation property of a jquery plugin points to a separate topic that holds all documentation for it, including a pointer to the third-party homepage. Use System.JQueryPluginEmpty as a template. The default documentation topic is System.JQuery + PluginName unless otherwise specified. For example, the docu for rubberduck should be located in System.JQueryRubberduck.

Instead of specifying a summary on perl level, defined a named summary section in this topic.

Please make sure to document how your plugin is integrated into Foswiki, that is how to make use of it and which class name enables your plugin on a html element (see #LiveQuery below).

JQuery Coding Standards

See JQueryCodingStandards for information on:
  • Good coding practice
  • Using jQuery with other libraries
  • Propagating perl settings to Javascript
  • Avoiding Internet Explorer errors
  • Using Metadata and livequery

Using jQuery and AJAX

The main jQuery documentation is located at http://docs.jquery.com/Ajax.

Making a simple query to the server

The easiest way to make a request to the server is to get it to give you a page of results already formatted in a way that jQuery understands. The simplest approach is to use JSON. For example, let's say I want to perform a search for the string "look for this" on the server. In my Javascript I have:

$.get(viewurl+'/Myweb/JsonSearch',
      {
         skin: "text", 
         contenttype: "text/plain",
         inweb: web,
         string: "look for this"
      },
      function(results) {
         // do something with the array of results
      }, "json");

viewurl is the result of calling SCRIPTURL{view}%, and can easily be passed to the Javascript, as described in Propagating perl settings to javascript, above. This request makes Javascript request a topic Myweb.JsonSearch from the server.

When raw-edited, Myweb.JsonSearch contains:

[%SEARCH{"%URLPARAM{string}%" web="%URLPARAM{inweb}%" nonoise="on" format="'$topic'" separator=","}%]

The use of the contenttype and skin parameters stops Foswiki from generating any template furniture around the result, and the formatted search produces a JSON format array, which is then read by jQuery and converted to a Javascript array object results.

Loading part of the UI asynchronously

jQuery supports a short form of the above $.get method by directly injecting the HTML result of a REST handler into the DOM tree:

$("#container").load("<url>, [<params>], [<callback>]");

Optionally a jQuery selector can be specified in the URL. Doing so will filter the incoming HTML document, only injecting the elements that match the selector:

$("#mysidebar .installedplugins-list").load("%SCRIPTURLPATH{"view"}/%SYSTEMWEB%/InstalledPlugins ul:first li");

Note also, that javascript included in the HTML fragment will be executed after load()ing it.

Complex queries involving plugin functions

Foswiki supports plugin handlers (called REST handlers) that can be called by issuing a request to the server with a specifically crafted URL. Exactly the same approach can be used to call these handlers, except that the URL specifies the function to call. See the extensive documentation on plugin REST handlers for more information.
Topic revision: r20 - 27 Feb 2013, 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