Skip to content

Commit

Permalink
changed: goto functionality is now separated from form.init() into fo…
Browse files Browse the repository at this point in the history
…rm.goTo(xpath)

fixed: determine relevancy instead of visibility for goto unctionality,
fixed: goto functionality is not working if form is hidden during loading,

kobotoolbox/enketo-express#989
  • Loading branch information
MartijnR committed Apr 19, 2018
1 parent f369f03 commit d9defc9
Show file tree
Hide file tree
Showing 5 changed files with 30 additions and 40 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@ Change Log
All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/).

[Unreleased]
----------------------
##### Changed
- GoTo function separated from form.init and should now be called separately with form.goTo(xpath). **WARNING: Update app if GoTo functionality was used.**

[4.49.0] - 2018-04-14
---------------------
##### Removed
Expand Down
25 changes: 7 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,17 +42,21 @@ var data = {
session: {}
};

// form-specific configuration
// Form-specific configuration
var options = {
clearIrrelevantImmediately: true // this is the default, it can be omitted
}

// instantiate a form, with 2 parameters
// Instantiate a form, with 2 parameters
var form = new Form( formSelector, data, options);

// initialize the form and capture any load errors
// Initialize the form and capture any load errors
var loadErrors = form.init();

// If desired, scroll to a specific question with any XPath location expression,
// and aggregate any loadErrors.
loadErrors = loadErrors.concat( form.goTo( '//repeat[3]/node' ) );

// submit button handler for validate button
$( '#submit' ).on( 'click', function() {
// clear irrelevant questions and validate
Expand Down Expand Up @@ -142,21 +146,6 @@ If `clearIrrelevantImmediately` is set to `true` or not set at all, Enketo will

In the second case the irrelevant values will not be cleared until `form.validate()` is called (usually when the user marks a record as complete).

#### Go to specific question upon load

```
new Form(formselector, data, {
goTo: true
});
```

This feature is designed for views that show an existing record (e.g. edit views) and want to jump to a specific question upon load. This can be done with a hash (fragment identifier) in the URL. The hash contains a valid XPath to the XML model node. It could have any valid format eg:

* http://example.org/form#/path/to/node
* http://example.org/form#//node
* http://example.org/form#//repeat[3]/node
* http://example.org/form#//repeat[enk:ordinal="3"]/node

#### Print only the "relevant" parts of the form

If `printRelevantOnly` is set to `true` or not set at all, printing the form only includes what is visible, ie. all the groups and questions that do not have a `relevant` expression or for which the expression evaluates to `true`.
Expand Down
3 changes: 1 addition & 2 deletions app.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,7 @@ function initializeForm() {
webMapId: 'f2e9b762544945f390ca4ac3671cfa72',
hasZ: true
},
'clearIrrelevantImmediately': true,
'goTo': true
'clearIrrelevantImmediately': true
} );
// for debugging
window.form = form;
Expand Down
35 changes: 16 additions & 19 deletions src/js/Form.js
Original file line number Diff line number Diff line change
Expand Up @@ -218,15 +218,6 @@ Form.prototype.init = function() {

this.editStatus = false;

if ( this.options.goTo === true && location.hash ) {
// if goTo fails (not found), it will return false
if ( !this.goTo( this.getGoToTarget( location.hash ) ) ) {
loadErrors.push( t( 'alert.gotonotfound.msg', {
path: location.hash.substring( 1 )
} ) );
}
}

if ( this.options.printRelevantOnly !== false ) {
this.view.$.addClass( 'print-relevant-only' );
}
Expand All @@ -247,13 +238,22 @@ Form.prototype.init = function() {
return loadErrors;
};

Form.prototype.goTo = function( xpath ) {
var errors = [];
if ( !this.goToTarget( this.getGoToTarget( xpath ) ) ) {
errors.push( t( 'alert.gotonotfound.msg', {
path: location.hash.substring( 1 )
} ) );
}
return errors;
};

/**
* Obtains a string of primary instance.
*
* @param {!{include: boolean}=} include optional object items to exclude if false
* @return {string} XML string of primary instance
*/

Form.prototype.getDataStr = function( include ) {
include = ( typeof include !== 'object' || include === null ) ? {} : include;
// By default everything is included
Expand Down Expand Up @@ -768,7 +768,7 @@ Form.prototype.validateContent = function( $container ) {
.eq( 0 );

if ( $firstError.length > 0 ) {
that.goTo( $firstError[ 0 ] );
that.goToTarget( $firstError[ 0 ] );
}
return $firstError.length === 0;
} )
Expand Down Expand Up @@ -887,20 +887,18 @@ Form.prototype.updateRequiredVisibility = function( n ) {
};


Form.prototype.getGoToTarget = function( hash ) {
var path;
Form.prototype.getGoToTarget = function( path ) {
var hits;
var modelNode;
var target;
var intermediateTarget;
var selector = '';
var repeatRegEx = /([^[]+)\[(\d+)\]([^[]*$)?/g;

if ( !hash ) {
if ( !path ) {
return;
}

path = hash.substr( 1 );
modelNode = this.model.node( path ).get().get( 0 );

if ( !modelNode ) {
Expand Down Expand Up @@ -932,20 +930,19 @@ Form.prototype.getGoToTarget = function( hash ) {
return target ? this.input.getWrapNodes( $( target ) ).get( 0 ) : target;
};


/**
* Scrolls to a HTML Element, flips to the page it is on and focuses on the nearest form control.
*
* @param {HTMLElement} target A HTML element to scroll to
*/
Form.prototype.goTo = function( target ) {
Form.prototype.goToTarget = function( target ) {
if ( target ) {
if ( this.pages.active ) {
// Flip to page
this.pages.flipToPageContaining( $( target ) );
}
// check if the nearest question or group is hidden after page flip (e.g. by being irrelevant)
if ( $( target ).closest( '.question, .or-group, .or-group-data' ).is( ':hidden' ) ) {
// check if the nearest question or group is irrelevant after page flip
if ( $( target ).closest( '.or-branch.disabled' ).length ) {
// It is up to the apps to decide what to do with this event.
$( target ).trigger( 'gotohidden.enketo' );
}
Expand Down
2 changes: 1 addition & 1 deletion src/js/branch.js
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,7 @@ module.exports = {
* Activates form controls.
* This function is separated so it can be overridden in custom apps.
*
* @param {[type]} $brancNode [description]
* @param {[type]} $branchNode [description]
* @return {[type]} [description]
*/
activate: function( $branchNode ) {
Expand Down

0 comments on commit d9defc9

Please sign in to comment.