enketo-core
The engine that powers Enketo Smart Paper and various third party tools.
This repo is meant to use as a building block for any enketo-powered application.
Follow the Enketo blog or Enketo on twitter to stay up to date.
Usage as a library
- Install with
npm install enketo-core --save
or include as a git submodule. - Develop a way to perform an XSL Transformation on OpenRosa-flavoured XForms inside your app. The transformation will output an XML instance and a HTML form. See enketo-transformer for an example. For development purposes you may also use the free (and slow, not robust at all) API provided by Enketo LLC at http://xslt-dev.enketo.org/transform (add
?xform=http://myforms.com/myform.xml
to use API). - Add themes to your stylesheet build system (2 stylesheets per theme, 1 is for
media="print"
). - Override config.json and optionally widgets.js with your app-specific versions.
- Main methods illustrated in code below:
var Form = require('enketo-core');
var formSelector = 'form.or:eq(0)';
var data = {
modelStr: globalXMLInstance,
instanceStr: null,
submitted: false,
external = []
};
var form = new Form( formSelector, data);
var loadErrors = form.init();
$( '#submit' ).on( 'click', function() {
form.validateForm()
.then(function (valid){
if ( !valid ) {
alert( 'Form contains errors. Please see fields marked in red.' );
} else {
var record = form.getDataStr();
form.resetView();
form = new Form( formSelector, { modelStr: modelStr } );
}
});
} );
Browser support
The following browsers are officially supported:
- latest Android webview on latest Android OS
- latest WKWebView on latest iOS
- latest version of Chrome/Chromium on OS X, Linux, Windows, Android and iOS
- latest version of Firefox on OS X, Windows, Linux, Android and iOS
- latest version of Safari on OS X, Windows, and on the latest version of iOS
- latest version of Microsoft Edge
We have to admit we do not test on all of these, but are committed to fixing browser-specific bugs that are reported for these browsers. Naturally, older browsers versions will often work as well - they are just not officially supported.
Note that some applications using Enketo Core (e.g. Enketo Express) may have more limited browser support.
How to develop Enketo Core
- install node and grunt-cli
- install dependencies with
npm install
- build with
grunt
- start built-in auto-reloading development server with
grunt develop
- browse to http://localhost:8005/forms/index.html
How to create or extend widgets
To create new widgets, we recommend using this plugin template. The option {touch: [boolean]}, is added automatically to all widgets to indicate whether the client is using a touchscreen device.
Each widget needs to fulfill following requirements:
- be an CommonJS/AMD-compliant jQuery plugin
- it needs to return an object with its own name and selector-to-instantiate with
- path to stylesheet scss file relative to the widget's own folder to be added in _widgets.scss (this will be automated in the future)
- be responsive up to a minimum window width of 320px
- use JSDoc style documentation for the purpose of passing the Google Closure Compiler without warnings and errors
- if hiding the original input element, it needs to load the default value from that input element into the widget
- if hiding the original input element, it needs to keep it synchronized and trigger a change event on the original whenever it updates
- it is recommended to apply the
widget
css class to any new elements it adds to the DOM (but not to their children) - new input/select/textarea elements inside widgets need to get the
ignore
class - it requires the following methods (which can be automatically obtained by extending the Widget base class as demonstrated in the plugin template
destroy(element)
to totally destroy widgets in repeat groups/questions when these groups/questions are cloned This may be an empty function if:
- a deep
$.clone(true, true)
of the widget (incl data and eventhandlers) works without problems (problems are likely!)
enable()
to enable the widget when a disabled ancestor gets enabled. This may be an empty function if that happens automatically.disable()
This may be an empty function if the widgets gets disabled automatically cross-browser when its branch becomes irrelevant.update()
to update the widget when called after the content used to instantiate it has changed (language or options). In its simplest form this could simply call destroy() and then re-initialize the widget, or be an empty function if language changes are handled automatically and it is not a <select>
widget.
- any eventhandlers added to the original input should be namespaced (if extending the Widget base class, the namespace is available as
this.namespace
) - if the widget needs tweaks or needs to be disabled for mobile (touchscreen) use, build this in. The option
{ touch: [boolean] }
is passed to the plugin by default. If your widget requires tweaks for mobile, you could create an all-in-one widget using the options.touch
check or you could create separate widgets for desktop and mobile (as done with select-desktop and select-mobile widgets) - allow clearing of the original input (i.e. setting value to '')
- send a
fakefocus
and fakeblur
event to the original input when the widget gets focus or looses it (see select-desktop) - please write test specs in the widget's /test folder.....(yeah, need to do that for the existing widgets too...)
Notes for All Developers
- build with grunt
- helpful to use
grunt develop
to automatically compile (sass and js) when a source file changes, serve, and refresh - adding the querystring
touch=true
and reducing the window size allows you to simulate mobile touchscreens
Notes for JavaScript Developers
- The JS library uses CommonJS modules, but all the modules are still AMD-compliant. It may be quite a bit of work to get them working properly using requirejs though (AMD-specific issues won't be fixed by us, but AMD-specific patches/PRs are welcome)
- Will be moving back to Google Closure (Advanced Mode) in future (hence JSDoc comments should be maintained)
- Still trying to find a JS Documentation system to use that likes Closure-style JSDoc
- JavaScript style see JsBeautifier config file, the jsbeautifier check is added to the grunt
test
task. You can also manually run grunt jsbeautifier:fix
to fix style issues. - Testing is done with Jasmine and Karma (all:
grunt karma
, headless: grunt karma:headless
, browsers: grunt karma:browsers
) - When making a pull request, please add tests where relevant
Notes for CSS Developers
The core can be fairly easily extended with alternative themes.
See the plain, the grid, and the formhub themes already included in /src/sass.
We would be happy to discuss whether your contribution should be a part of the core, the default theme or be turned into a new theme.
For custom themes that go beyond just changing colors and fonts, keep in mind all the different contexts for a theme:
- non-touchscreen vs touchscreen (add ?touch=true during development)
- default one-page-mode and multiple-pages-mode
- right-to-left form language vs left-to-right form language (!) - also the UI-language may have a different directionality
- screen view vs. print view
- questions inside a (nested) repeat group have a different background
- large screen size --> smaller screen size ---> smallest screen size
- question in valid vs. invalid state
The development of this app and enketo-core was sponsored by:
Related Projects
Change log
See change log
Performance (live)
See graphs