Adding new functionality

In order to add new functionality, such as a jQuery plugin, you will want to develop within the appropriate src folder and build the finished code with an Ant script.

jQuery Plugins

Changes to jQuery integration

WET v3.0 jQuery integration is different from previous versions. There are a few major changes to how jQuery is integrated into WET that developers should be aware of.

  1. jQuery is called at the end of the body of an HTML page instead of in the header. The reason for this is to allow asynchronous loading of PE object. This means that the plugins are loaded at the same time as the DOM, not after.
  2. The new PE object does not employ the progress method call in the head any more. Everything is handled by the PE file at the bottom of the page.
  3. Plugins are called using a class-based system, eliminating the param tag in the header. (ex: <table class="wet-boew-zebra">)

WET v2.3

<script src="../js/lib/jquery.min.js"></script>
<script src="../js/pe-ap.js" id="progressive"></script>
<script>
/* <![CDATA[ */
var params = {
};
PE.progress(params);
/* ]]> */
</script>
</head>

WET v3.0

<script src="../../build/theme-gcwu-fegc/js/theme-min.js"></script>
<script src="../../build/js/settings.js"></script>
<script src="../../build/js/pe-ap-min.js"></script>

</body>
</html>

Creating plugins

To create a new plugin navigate to src/js/workers and add your code in a separate .js file. Make sure to follow the coding conventions used in the other jQuery plugins so your code will properly compile during the build process. Fortunately, there is already an ant script which will build our plugin. All you have to do is worry about the plugin file.

You will need to always follow these conventions when creating a jQuery plugin:

  1. Begin your code with:
    (function ($) {
    	var _pe = window.pe || {
    		fn: {}
    	};
  2. Specify your plug-in name in _pe.fn.pluginName. This will be the name of your file. Also the class name you will use to call the plugin is always wet-boew-pluginname
  3. Run the plugin using _exec: function (elm) { }.
  4. Finally, end the plugin with the following:
    window.pe = _pe;
    	return _pe;
    }(jQuery));

The following is optional:

  • Specify any dependencies. These are a series of libraries located in src/js/dependencies. (e.g., depends: (_pe.mobile ? [] : ['easytabs', 'calendar']),)
  • Include a mobile function if your plugin should run in mobile mode. (e.g., mobile: function (elm) {)

When the plugin is finished, and the project has been built, your plugin will be added to the dist folder. It will reside in \dist\js\pe-ap-min.js. Notice that all plugins in the workers folder have been added to this one file. However, the code has been minified and variables names have been changed for optimization.

Note 1: You can test your plugin without building the entire project. Simply include the path at the bottom of your html page where the rest of the javascript files are added. Once you see that it works, start the build process.

Note 2: You can still create or add additional plugins that do not depend on the PE object or WET and leverage the _pe.document.on('wb-init-loaded', function() {...});, to execute the code after WET has finished loading.

Executing plugins on unenhanced content

The wb_load function (_pe.wb_load(options, finished_event)) allows you to execute plugins on unenhanced content (e.g., content that was added to the page after the initial page load). It's useful to developers who want to dynamically add a tabbed interface or a multimedia player after the page has already loaded.

The first parameter is an object with all the options and the second is the event name to use for the event handler (used to determine when loading has finished).

Here are the options that can be included in the options object (all optional) that handle the loading of the plugins, dependencies and polyfills:

  • plugins: {'plugin_name1': elms1, 'plugin_name2': elms2, ...} - Names of plugins to load and elements to load them on (no longer need to specify dependencies or polyfills separately)
  • global: ['plugin_name1', 'plugin_name2', ...] - Names of global plugins to load
  • dep: ['dependency_name1', 'dependency_name2', ...] - Names of dependencies to load
  • poly: ['polyfill_name1', 'polyfill_name2', ...] - Names of polyfills to load
  • checkdom: true/false - Enable/disable checking the DOM for "wet-boew-*" triggers
  • polycheckdom: true/false - Enable/disable checking the DOM for elements to polyfill

For example, if you just want to load the tabbed interface plugin on $('.target') then you would call the following:

pe.document.on('my-event-name', function () {
	//... do something ...
});
pe.wb_load({'plugins': {'tabbedinterface': $('.target')}}, 'my-event-name');

To load a polyfill when it's already declared in your plugin, you would just do this:

pe.polyfills.enhance('polyfill_name', objs);

Where polyfill_name is the key in _pe.polyfills.polyfill and objs is either a DOM object (preferred) or a jQuery object. For example:

pe.polyfills.enhance('detailssummary', document.getElementsByTagName('details'));

[or]

pe.polyfills.enhance('detailssummary', tblSrcContainer); // where tblSrcContainer is already a jQuery object

Otherwise, to load a polyfill only on request, you would just do this:

pe.document.on('my-event-name', function () {
	//... do something ...
});
pe.wb_load({'datepicker', "my-event-name");

To load a dependency, you would just do this:

pe.document.on('my-event-name', function () {
	//... do something ...
});
pe.wb_load({'dep': ['parserTable']}, 'my-event-name');

Loading dependency only on request

Target Audience: Intermediate and advanced WET developers

As previously described in the section "Executing Plugins on Unenhanced Content" you would just do this to load a dependency:

pe.document.on('my-event-name', function () {
	//... do something ...
});
pe.wb_load({'dep': ['parserTable']}, 'my-event-name');

The rule is simple, make sure that your make only one call to load the dependency. So the previous code snippet would do the work as long it's not included in a loop.

You wont be notified of any error until you have two or more call to the "_exec" function in the plugins.

For example, the zebra stripping applied on a complex table require the dependency "parserTable" to complete the styling. If there is only one complex table on the web page, that are not causing any issue, but if there is more than one complex table that required the zebra stripping can break the rule of make only one call. For reference you can take a look at issue #508.

  1. Function that would be executed once the dependency is loaded

    Create your function at the same level of your "._exec" declaration, but before the "_exec" method.

    _pe.fn.yourPluginName = {
    	type: 'plugin',
    	fnExecutedOnDependencyLoad: function (elem) {
    
    	},
    	_exec: function (elem) {
    
    	}
    };
  2. Check the dependency requirement
    _pe.fn.yourPluginName = {
    	type: 'plugin',
    	fnExecutedOnDependencyLoad: function (elem) {
    
    	},
    	_exec: function (elem) {
    		[...] Put your logic here regarding whether the dependency is required [...]
    	}
    };
  3. Check if your dependency is already loaded, if yes then call it. Before each plugin execution call, check if the dependency is already loaded.
    if (_pe.fn.parsertable) {
    	_pe.fn.yourPluginName.fnExecutedOnDependencyLoad(elem);
    	return;
    }

    Replace the "_pe.fn.parsertable" by the function name from the dependency that you would attempts to use later.

  4. Check if your already defined a plugin execution stack, if yes just stack it and return
    if (_pe.fn.yourPluginName.execStack) {
    	_pe.fn.yourPluginName.execStack.push(elem);
    	return;
    }
  5. Stack initialization and insertion of the first item
    _pe.fn.yourPluginName.execStack = [];
    _pe.fn.yourPluginName.execStack.push(elem);
  6. Function Event triggered once the dependency is loaded

    It is here where your stack would be processed one at the time.

    $(document).on('my-event-name', function () {
    	while (_pe.fn.yourPluginName.execStack.length > 0) {
    		__pe.fn.yourPluginName.fnExecutedOnDependencyLoad(_pe.fn.yourPluginName.execStack.shift());
    	}
    });
  7. Load your dependency
    _pe.wb_load({'dep': ['parserTable']}, 'my-event-name');

The Zebra striping plugin has implemented this method.

Loading your own dependency after the PE

Technically you could wait for the "wb-init-loaded" event and then fire pe.add._load(js, msg) where "js" is the path to the JS file and "msg" is a string with the event name to fire once loading is complete.

So something like the following would work:

_pe.document.one('my-custom-event', function () {
	//...form stuff...
});

_pe.document.one('wb-init-loaded', function () {
    _pe.add._load(js, 'my-custom-event');
});

Adding SASS/SCSS

SASS overview

SASS is an extension to the CSS format that adds extra feature like variables, nested rules, math, mixins, etc. SASS needs to be converted into CSS when used on the web, so part of the build process involves converting your SASS into CSS usable in your web project. In WET, there are different SASS files which style the website depending upon how it is being viewed (e.g., base-print.scss is for print view while base-ie.scss includes old Internet Explorer specific styling).

View information about SASS

Compass Overview

Compass is a helper library for SASS which is also used in WET. It includes libraries of shared mixins, a package manager to add additional extension libraries, and an executable that can easily convert SASS files into CSS.

Learn more about Compass

Developing with SASS

When creating new SASS code, make sure to add it in the appropriate directory inside the src folder in the root. Where to add the SASS depends on what you want to do. For example, if you would like to add CSS for your jQuery plugins, you will add your files to src/js/sass.

In order to test your code, you may want to compile it from SASS to CSS prior to building since the build process takes some time. A great tool to do this is Scout, which does not require that you have a working knowledge of Ruby and the command line.

There are a series of different SASS files that are used in the website:

  • src/base/sass: The SASS in this folder includes the basic css that is used in any WET site. It is not template dependant; as all templates include these SASS files.
  • src/grids/sass: This folder includes SASS used for the grid system.
  • src/js/sass: jQuery plugin specific SASS files. The scss files should be seperated into a different file for each plugin.
  • src/theme-gcwu-fegc/sass: This folder includes a series of different theme-specific SASS files. The SASS is initially broken up into different files based upon how your website can be viewed. These files are located in the "includes" folder.

Theme development

The following details the steps for creating a new theme in WET.

In order to create a new theme, you will have to add a folder named after your theme to src. This folder will contain any theme specific components you want to build into your website.

Your new theme should generally follow the theme-gcwu-fegc folder structure which includes folders called images, jquery.mobile, js and sass. In order to remain consistent, and to modify less of the build script, use these naming conventions.

There are a few different things to add/modify when building a new theme. Note: "new-theme" is used below to represent a new theme folder name.

  1. The build.xml in the root needs to have some additional code to call the build.xml file for your new theme.
    1. Copy + paste the code from the root build.xml under "---Building GCWU Theme---" into that same file.
    2. Change the comment to reflect the name of your new theme.
    3. Add your new theme folder name to the directory path: <ant dir="${src.dir}/new-theme" antfile="build.xml" target="build" inheritAll="false"/>
    4. Add code to clean up your new theme folder under <target name="clean-css"> and <target name="clean">. Just copy paste the code used for another theme and change the path to point to your new theme folder.
    <target name="clean-css">
    	<ant dir="${src.dir}/base" target="clean-css" antfile="build.xml" inheritAll="false"/>
    	...
    <target name="clean">
    	<ant dir="${src.dir}/base" target="clean" antfile="build.xml" inheritAll="false"/>
    	...
  2. The build.xml in your theme folder needs to be created, as well as other build-related files. The easiest way to do this is to copy paste the following from an existing theme, and just edit the files as needed.
    1. build.properties: Change the build.dir path so that it points to where your theme folder will be located in the build.
    2. build.xml: Change
      <project name="new-theme" default="default" basedir=".">
      to your new theme name.
  3. At this point, your theme folder should have the following files and folders in it:
    1. folders: images, jquery,mobile, js, sass
    2. files: build.properties, build.xml, build.tasks.xml, compile.rb
  4. Edit your SASS and jQuery files for your theme. Use the file names used in existing themes.

    Note: Remove mobile support deleting the theme.js file under the js folder in your new theme.