UNPKG

enketo-core

Version:

Extensible Enketo form engine

134 lines (125 loc) 4.92 kB
import $ from 'jquery'; import Widget from '../../js/widget'; import events from '../../js/event'; /** * Enhances radio buttons * * @augments Widget */ class Radiopicker extends Widget { /** * @type {string} */ static get selector() { return 'form'; } _init() { const $form = $(this.element); const that = this; $form // Applies a data-checked attribute to the parent label of a checked radiobutton. .on( 'click', 'input[type="radio"]:not([readonly]):checked', function () { $(this) .parent('label') .siblings() .removeAttr('data-checked') .end() .attr('data-checked', 'true'); } ) // Same for checkbox. .on('click', 'input[type="checkbox"]:not([readonly])', function () { that._updateDataChecked(this); }) // Detect programmatic changes to update data-checked attribute. .on( events.InputUpdate().type, 'input[type="radio"], input[type="checkbox"]', function () { this.closest('.option-wrapper') .querySelectorAll( 'input[type="radio"],input[type="checkbox"]' ) .forEach((input) => that._updateDataChecked(input)); } ) // Readonly buttons/checkboxes will not respond to clicks. .on( 'click', 'input[type="checkbox"][readonly],input[type="radio"][readonly]', (event) => { event.stopImmediatePropagation(); return false; } ) /* * In Safari a click on a readonly checkbox/radio button sets `checked` to true, **before** the click event fires. * This causes the model to update. The above clickhandler will set the checked back to false, but there is * no way to propagate that reversion back to the model. * * Disabling change handling on readonly checkboxes/radiobuttons is not an option, because of the scenario * described in Form.js in the comment above the change handler. * * The solution is to detect here whether the change event was triggered by a human, by checking if the * originalEvent property is defined. * * See more at https://github.com/enketo/enketo-core/issues/516 */ .on( events.Change().type, 'input[type="checkbox"][readonly],input[type="radio"][readonly]', function (event) { const byProgram = typeof event.originalEvent === 'undefined'; if (!byProgram) { event.stopImmediatePropagation(); /* * For radiobuttons, this is ugly and relies on the data-checked attribute. * Without this, is it still possible to check a readonly radio button (although it won't propagate to the model). * I think this is the only remnant of the usage of data-checked in Enketo. However, it is * also still relied upon by Esri/Survey123. */ if ( this.checked && this.parentNode.dataset.checked !== 'true' ) { this.checked = false; } } return byProgram; } ) // Add unselect radio button functionality. .on( 'click', '[data-checked]>input[type="radio"]:not(.no-unselect)', function () { $(this) .prop('checked', false) .trigger('change') .parent() .removeAttr('data-checked'); } ); // Defaults this.element .querySelectorAll( 'input[type="radio"]:checked, input[type="checkbox"]:checked' ) .forEach((input) => this._updateDataChecked(input)); } /** * @param {Element} el - Element to update */ _updateDataChecked(el) { if (el.checked) { el.parentNode.dataset.checked = true; } else { delete el.parentNode.dataset.checked; } } } export default Radiopicker;