/**
* @module output
*/
import $ from 'jquery';
export default {
/**
* Updates output values, optionally filtered by those values that contain a changed node name
*
* @param {UpdatedDataNodes} [updated] - The object containing info on updated data nodes.
*/
update( updated ) {
const outputCache = {};
let val = '';
const that = this;
if ( !this.form ) {
throw new Error( 'Output module not correctly instantiated with form property.' );
}
const $nodes = this.form.getRelatedNodes( 'data-value', '.or-output', updated );
const clonedRepeatsPresent = this.form.repeatsPresent && this.form.view.html.querySelector( '.or-repeat.clone' );
$nodes.each( function() {
const $output = $( this );
const output = this;
// nodes are in document order, so we discard any nodes in questions/groups that have a disabled parent
if ( $output.closest( '.or-branch' ).parent().closest( '.disabled' ).length ) {
return;
}
const expr = output.dataset.value;
/*
* Note that in XForms input is the parent of label and in HTML the other way around so an output inside a label
* should look at the HTML input to determine the context.
* So, context is either the input name attribute (if output is inside input label),
* or the parent with a name attribute
* or the whole document
*/
let context = output.closest( '.question, .or-group' );
if ( !context.matches( '.or-group' ) ) {
context = context.querySelector( '[name]' );
}
let contextPath = that.form.input.getName( context );
/*
* If the output is part of a group label and that group contains repeats with the same name,
* but currently has 0 repeats, the context will not be available. See issue 502.
* This same logic is applied in branch.js.
*/
if ( $( context ).children( `.or-repeat-info[data-name="${contextPath}"]` ).length && !$( context ).children( `.or-repeat[name="${contextPath}"]` ).length ) {
contextPath = null;
}
const insideRepeat = ( clonedRepeatsPresent && $output.parentsUntil( '.or', '.or-repeat' ).length > 0 );
const insideRepeatClone = ( insideRepeat && $output.parentsUntil( '.or', '.or-repeat.clone' ).length > 0 );
const index = ( insideRepeatClone && contextPath ) ? that.form.input.getIndex( context ) : 0;
if ( typeof outputCache[ expr ] !== 'undefined' ) {
val = outputCache[ expr ];
} else {
val = that.form.model.evaluate( expr, 'string', contextPath, index, true );
if ( !insideRepeat ) {
outputCache[ expr ] = val;
}
}
if ( $output.text() !== val ) {
$output.text( val );
}
} );
}
};