UNPKG

ccs-digitalmarketplace-govuk-frontend

Version:

Digital Marketplace GOV.UK Frontend contains the code you need to start building a user interface for Digital Marketplace.

151 lines (121 loc) 4.4 kB
const QuestionType = { CONTROLLER: 0, CONTROLLER_AND_TARGET: 1, TARGET: 2 } class QuestionInput { constructor (question, $input) { this.question = question this.$input = $input const targets = this.$input.attr('data-target') this.targets = targets ? targets.split(' ') : [] } setEventListener () { this.$input.on('click', () => { this.question.updateTargetQuestionsVisibility() }) } isChecked () { return this.$input.is(':checked') } } class Question { constructor (questionWatcher, $question, questionType) { this.questionWatcher = questionWatcher this.$question = $question this.id = this.$question.attr('id') this.questionType = questionType if (this.questionType === QuestionType.CONTROLLER) { this.enableControllerQuestionMethods() } else { this.enableTargetQuestionMethods() } } enableControllerQuestionMethods () { this.questionInputs = this.$question.find('input').get().map((inputElement) => new QuestionInput(this, $(inputElement))) this.possibleTargetIds = new Set(this.questionInputs.map((questionInput) => questionInput.targets).flat()) } enableTargetQuestionMethods () { this.targetOf = [] } isVisible () { return !this.$question.hasClass('govuk-visually-hidden') } currentTargetIds () { let targets if (this.isVisible() && this.questionInputs) { targets = this.questionInputs.filter((questionInput) => questionInput.isChecked()).map((questionInput) => questionInput.targets).flat() } else { targets = [] } return new Set(targets) } updateTargetQuestionsVisibility () { this.questionWatcher.updateTargetQuestionsVisibility(this.possibleTargetIds) } appendTargetOf (questionId) { this.targetOf.push(questionId) } toggleVisibility (isShown) { this.$question.toggleClass('govuk-visually-hidden', !isShown) this.$question.attr('aria-hidden', (!isShown).toString()) } } class QuestionWatcher { constructor () { this.questions = {} $('[data-module="dm-question-with-follow-up"]').each((_index, question) => { this.push(new Question(this, $(question), QuestionType.CONTROLLER)) }) for (const [questionId, question] of Object.entries(this.questions)) { for (const questionTargetId of question.possibleTargetIds) { if (questionTargetId in this.questions) { if (this.questions[questionTargetId].questionType === QuestionType.CONTROLLER) { this.questions[questionTargetId].questionType = QuestionType.CONTROLLER_AND_TARGET this.questions[questionTargetId].enableTargetQuestionMethods() } } else { this.push(new Question(this, $(`#${questionTargetId}`), QuestionType.TARGET)) } this.questions[questionTargetId].appendTargetOf(questionId) } } } init () { for (const question of Object.values(this.questions)) { if (question.questionType < QuestionType.TARGET) { for (const questionInput of question.questionInputs) { questionInput.setEventListener() } if (question.questionType === QuestionType.CONTROLLER) { this.updateTargetQuestionsVisibility(question.possibleTargetIds) } } } } push (question) { this.questions[question.id] = question } updateTargetQuestionsVisibility (possibleTargetIds, isShown) { for (const possibleTargetId of possibleTargetIds) { const targetQuestion = this.questions[possibleTargetId] let questionIsShown if (isShown === undefined) { const controllerQuestions = targetQuestion.targetOf.map((questionId) => this.questions[questionId]) const targetsToShow = new Set(controllerQuestions.map((controllerQuestion) => Array.from(controllerQuestion.currentTargetIds())).flat()) questionIsShown = targetsToShow.has(possibleTargetId) } else { questionIsShown = isShown } targetQuestion.toggleVisibility(questionIsShown) if (targetQuestion.questionType === QuestionType.CONTROLLER_AND_TARGET) { if (questionIsShown) { this.updateTargetQuestionsVisibility(targetQuestion.possibleTargetIds) } else { this.updateTargetQuestionsVisibility(targetQuestion.possibleTargetIds, false) } } } } } export default QuestionWatcher