This section provides information about developing user interfaces (UI) for edX applications.
All new edX pages should be composed of elements and styling shown in the edX Pattern Library. You can use JavaScript from the edX UI Toolkit JavaScript library to implement pages in a way that is consistent with edX UI architecture.
The Open edX wiki includes additional details about developing edX user interfaces. For more information, see edX Front End Development.
The edX Pattern Library is a collection of web application components and visual styles that you can use to develop UIs that are consistent with the edX platform.
The edX Pattern Library is available at ux.edx.org.
The edx-platform GitHub repository includes an example web page that demonstrates using the Pattern Library. You can use the example page as a template for creating your own new LMS or Studio pages.
To create a new page using the Pattern Library, you use the same main.html
template as for non-Pattern Library pages, and pass the following context
parameters.
{ ... 'disable_courseware_js': True, 'uses_pattern_library': True, }
When you create a page using the Pattern Library, create two new root syntactically awesome style sheets (Sass) files for your page, one for left-to- right (LTR) and one for right-to-left (RTL) localizations. For more information about Sass, see the Sass site.
The RTL version of the style sheet must have the same filename as the
LTR version but ending with -rtl
.
Register the two new style sheets in the PIPELINE_CSS
configuration. You
can see the full list for the LMS in lms/envs/common.py.
After you register the LTR and RTL style sheets, you refer to the configuration name in your Mako template. Mako will then dynamically pick either the LTR or the RTL version based upon the current user’s localization preference.
The following example shows how a pair of style sheets are registered in the
PIPELINE_CSS
configuration.
'style-learner-dashboard': {
'source_filenames': [
'css/lms-learner-dashboard.css',
],
'output_filename': 'css/lms-learner-dashboard.css',
},
'style-learner-dashboard-rtl': {
'source_filenames': [
'css/lms-learner-dashboard-rtl.css',
],
'output_filename': 'css/lms-learner-dashboard-rtl.css',
},
After you register your Sass style sheets, you must also declare the name of
your Sass files at the top of your main Mako file. The following example
declares files that are configured with the names style- learner-dashboard
and style-learner-dashboard-rtl
.
<%! main_css = "style-learner-dashboard" %>
You can refer to the following examples.
The edX UI Toolkit is a JavaScript library for building edX web applications. The UI toolkit consists of:
The edX UI Toolkit is available from the edx-ui-toolkit GitHub repository . For more information about the UI Toolkit, see ui-toolkit.edx.org .
For more information about writing JavaScript for edX UIs, see EdX JavaScript Style Guide.
This topic is a collection of things to think about when creating a new page in Studio or the LMS.
You should also read Contributing to Open edX to understand more general best practices, as well as how to submit your new code for review.
The edX front end code base is currently a mixture of CoffeeScript and JavaScript. The edX development team is now standardizing the use of JavaScript for new work. There are a number of reasons for this decision, including the following list.
All new front end development should be done in JavaScript, while legacy CoffeeScript code will be converted on an as-needed basis. For pragmatic reasons, targeted changes to CoffeeScript will still be accepted.
For more information about writing JavaScript for edX UIs, see EdX JavaScript Style Guide.
All new pages should use RequireJS to manage loading of file dependencies.
Use the standard syntax to load JavaScript dependencies.
Note
For the LMS, you have to wrap each call to define or require in order for it to work with the namespaced version of RequireJS.
;(function (define) {
'use strict';
define([...], function (...) {
...
});
}).call(this, define || RequireJS.define);
Use RequireJS Text for your templates (see Ensure That RequireJS Optimizer Can Optimize Your JavaScript for details).
Create a factory class that is included by your Mako template using
require_module
.
- This Mako function ensures that the factory is loaded correctly for both the optimized and non-optimized pipeline.
- When accessed in the optimized mode, the query parameter
?raw
will be added to the URL to ensure that the file is not post-processed.
Note
require_module
is needed for the unified optimizer pipeline in Studio.
If you need server-side data passed to your page, pass it as one or more parameters to your factory.
For information about avoiding cross-site scripting, see JavaScript Context in Mako.
For information about adding third-party JavaScript libraries, see Adding JavaScript Libraries.
If the dependency is pre-loaded, then be sure to specify its path as empty in build.js so that the optimizer does not include it in the bundled file. This is especially important for files that are used by both by JavaScript leveraging RequireJS and “non-RequireJS JavaScript” within the same page.
paths: {
'gettext': 'empty:',
'jquery': 'empty:',
...
}
See an example Mako code block in JavaScript Context in Mako.
The following list includes more examples.
Note
Using RequireJS in XBlocks is not currently supported. Future development is planned to add this support.
Install JavaScript libraries using the npm
package manager.
If the library you want to add is available from npmjs.com, update edx-
platform’s package.json file to reference the library. Use the tilde ~
prefix for the version to allow patches to be picked up automatically.
For more information about versioning, see semver.org.
Execute the following command to install your library.
paver install_prereqs
Add the new library to the list of npm-installed libraries.
Execute the following command to make your library available as a Django static asset (choose LMS, Studio, or both).
paver update_assets lms --settings=devstack
To add the new library to the LMS, follow these steps.
Add the new library to the list of vendor libraries that are installed by
update_assets
. Update the variable NPM_INSTALLED_LIBRARIES
in
/pavelib/assets.py.
Note
Reference the unminified version of the library. This allows debugging tools to step through readable library code, and the Django static asset pipeline will ensure that it get optimized for production.
If you cannot use npm, check the file into the common/static/js/vendor directory.
The edX development team has standardized using Underscore for all client-side templates. There are some things to consider.
mock
.RequireJS Text is superior to the old mechanism of statically including the templates in the Mako-generated HTML for several reasons.
Here are a few examples.
We use RequireJS Optimizer to optimize the JavaScript that we use in production. This works as part of the production pipeline to merge all of a page’s JavaScript and templates into a single minified file. This greatly reduces the number of files that the browser needs to request, as well as the number of bytes that need to be fetched. Furthermore, in the LMS un-optimized RequireJS files are never cached, leading to significant performance degradation.
The basic approach is to move all of the page view construction logic into a single factory file. This factory is responsible for creating the models and views required to render the page. The idea is that the optimizer can produce a single minified file for the factory by statically determining all of its dependencies.
Structure your page so that it has a single root factory file (see Use RequireJS to Manage File Dependencies).
Be sure to use require_module
to load the factory as described above.
List your factory in the RequireJS Optimizer build file.
By default, devstack runs with unoptimized files so that changes are picked up immediately.
To run with optimized files, specify the --optimized
parameter to Paver’s
devstack
command:
paver devstack lms --optimized
Note that Bokchoy tests run with optimized files to verify that they are being generated as expected.
Be sure to test your page in a production environment, checking that all dependencies are included in the optimized factory file.
- For LMS files, take care that all of the JS files have a MD5 hash code between their filename and the js extension. Files without MD5 hash codes will not be cached in production and indicate incorrect optimization.
- Studio RequireJS files currently do not use the MD5 hashing mechanism, and instead store files within a unique directory that changes with each release. We hope to change this in the future.
Code written with Backbone is more modular, more extensible, and more easily unit tested with Jasmine.
See How to add a new feature to LMS or Studio to see how to structure your Backbone code.