ccs-digitalmarketplace-govuk-frontend
Version:
Digital Marketplace GOV.UK Frontend contains the code you need to start building a user interface for Digital Marketplace.
209 lines (164 loc) • 5.5 kB
JavaScript
const MAX_NUMBER_OF_ROWS = 10
class AnswerListRowInput {
constructor ($row) {
this.$input = $row.find('.dm-list__item-input')
this.$label = $row.find('.govuk-label')
this.$labelCounter = this.$label.find('.dm-list__item-label-counter')
this.$prefixText = $row.find('.govuk-input__prefix')
}
getValue () {
return this.$input.val()
}
clearValue () {
this.$input.val('')
this.$input.attr('value', '')
}
updateIndex (newIndex) {
const newId = `input-${this.$input.attr('name')}-${newIndex}`
this.$label.attr('for', newId)
this.$labelCounter.text(newIndex + 1)
this.$prefixText.text(`${newIndex + 1}.`)
this.$input.attr('id', newId)
}
}
class AnswerListRowRemoveButton {
constructor (answerListRow, $row) {
this.answerListRow = answerListRow
this.$button = $row.find('.dm-list__item-remove')
this.$removeButtonCounter = this.$button.find('.dm-list__item-remove-counter')
}
init () {
this.toggleVisibility(true)
this.$button.on('click', () => {
this.answerListRow.removeRow()
})
}
toggleVisibility (isShown) {
this.$button.toggleClass('govuk-visually-hidden', !isShown)
}
updateIndex (newIndex) {
this.$removeButtonCounter.text(newIndex + 1)
}
}
class AnswerListRow {
constructor (answerList, index, $row) {
this.$row = $row
this.answerList = answerList
this.index = index
this.answerListRowInput = new AnswerListRowInput($row)
this.answerListRowRemoveButton = new AnswerListRowRemoveButton(this, $row)
}
init () {
this.answerListRowRemoveButton.init()
}
updateIndex (newIndex) {
this.index = newIndex
this.answerListRowInput.updateIndex(newIndex)
this.answerListRowRemoveButton.updateIndex(newIndex)
}
removeRow () {
this.answerList.removeRow(this.index)
this.deleteRow()
}
deleteRow () {
this.$row.remove()
}
toggleRemoveButtonVisibility (isShown) {
this.answerListRowRemoveButton.toggleVisibility(isShown)
}
inputValue () {
return this.answerListRowInput.getValue()
}
}
class AnswerListAddButton {
constructor (answerList, $button) {
this.answerList = answerList
this.$button = $button
this.$buttonCounter = $button.find('.dm-list__item-add-counter')
}
init (numberOfRows) {
this.$button.on('click', () => {
this.answerList.addRow()
})
this.updateButtonText(MAX_NUMBER_OF_ROWS - numberOfRows)
}
updateButtonText (numberRemaining) {
this.$buttonCounter.text(numberRemaining)
}
toggleVisibility (isShown) {
this.$button.toggleClass('govuk-visually-hidden', !isShown)
}
}
class AnswerList {
constructor (answerList) {
this.$answerList = $(answerList)
this.$answerListItems = this.$answerList.find('.dm-list__items')
this.answerListRows = this.$answerList.find('.dm-list__item').get().map((row, index) => new AnswerListRow(this, index, $(row)))
this.answerListAddButton = new AnswerListAddButton(this, this.$answerList.find('.dm-list__item-add'))
}
init () {
const rowValues = this.answerListRows.map((answerListRow) => answerListRow.inputValue())
let indexToDeleteFrom
if (rowValues.every((rowValue) => !rowValue)) {
indexToDeleteFrom = 2
} else {
indexToDeleteFrom = rowValues.indexOf('')
}
if (indexToDeleteFrom >= 0) {
this.answerListRows.slice(indexToDeleteFrom).forEach((answerListRow) => answerListRow.deleteRow())
this.answerListRows.splice(indexToDeleteFrom)
}
this.answerListAddButton.init(this.answerListRows.length)
this.answerListRows.forEach((answerListRow) => answerListRow.init())
this.updateIfMinRows()
this.updateAnswerButton()
}
removeRow (indexToRemove) {
this.answerListRows.splice(indexToRemove, 1)
this.answerListRows.slice(indexToRemove).forEach((answerListRow, index) => {
answerListRow.updateIndex(indexToRemove + index)
})
this.updateIfMinRows()
this.updateAnswerButton()
this.focusOnRow(indexToRemove)
}
addRow () {
const numberOfRows = this.answerListRows.length
if (numberOfRows < MAX_NUMBER_OF_ROWS) {
const $newRow = this.answerListRows[0].$row.clone()
const answerListRow = new AnswerListRow(this, numberOfRows, $newRow)
answerListRow.updateIndex(numberOfRows)
answerListRow.answerListRowInput.clearValue()
this.answerListRows.push(answerListRow)
this.$answerListItems.append($newRow)
this.answerListRows[numberOfRows].init()
this.updateIfMinRows()
this.updateAnswerButton()
this.focusOnRow(numberOfRows)
}
}
updateIfMinRows () {
if (this.answerListRows.length === 1) {
this.answerListRows[0].toggleRemoveButtonVisibility(false)
} else {
this.answerListRows[0].toggleRemoveButtonVisibility(true)
}
}
updateAnswerButton () {
if (this.answerListRows.length === MAX_NUMBER_OF_ROWS) {
this.answerListAddButton.toggleVisibility(false)
} else {
this.answerListAddButton.toggleVisibility(true)
this.answerListAddButton.updateButtonText(MAX_NUMBER_OF_ROWS - this.answerListRows.length)
}
}
focusOnRow (targetIndexToFocus) {
const numberOfRows = this.answerListRows.length
let indexToFocus = targetIndexToFocus
if (targetIndexToFocus >= numberOfRows) {
indexToFocus = numberOfRows - 1
}
this.answerListRows[indexToFocus].answerListRowInput.$input.focus()
}
}
export default AnswerList