2019-05-22 13:11:48 +01:00
( function ( global ) {
2016-08-07 09:17:49 +01:00
"use strict" ;
2019-05-22 13:11:48 +01:00
var Modules = global . GOVUK . Modules ;
var Hogan = global . Hogan ;
2021-01-20 11:23:01 +00:00
// Object holding all the states for the component's HTML
2016-10-11 14:17:29 +01:00
let states = {
'initial' : Hogan . compile ( `
2020-07-16 10:49:21 +01:00
{ { # showNowAsDefault } }
2023-09-15 12:26:31 -04:00
< div class = "radio-select__column margin-y-2" >
2023-08-25 15:31:44 -04:00
< div class = "usa-radio" >
< input class = "usa-radio__input" checked = "checked" id = "{{name}}-0" name = "{{name}}" type = "radio" value = "" >
< label class = "usa-radio__label" for = "{{name}}-0" > Now < / l a b e l >
2020-07-16 10:49:21 +01:00
< / d i v >
2016-12-19 10:36:17 +00:00
< / d i v >
2020-07-16 10:49:21 +01:00
{ { / s h o w N o w A s D e f a u l t } }
2023-09-15 12:26:31 -04:00
< div class = "radio-select__column margin-y-2" >
2016-10-11 14:17:29 +01:00
{ { # categories } }
2023-09-15 12:26:31 -04:00
< input type = 'button' class = 'usa-button usa-button--outline radio-select__button--category' aria - expanded = "false" value = '{{.}}' / >
2016-10-11 14:17:29 +01:00
{ { / c a t e g o r i e s } }
< / d i v >
` ),
'choose' : Hogan . compile ( `
2020-07-16 10:49:21 +01:00
{ { # showNowAsDefault } }
2023-09-15 12:26:31 -04:00
< div class = "radio-select__column margin-y-2" >
2023-08-25 15:31:44 -04:00
< div class = "usa-radio" >
< input class = "usa-radio__input" checked = "checked" id = "{{name}}-0" name = "{{name}}" type = "radio" value = "" >
< label class = "usa-radio__label" for = "{{name}}-0" > Now < / l a b e l >
2020-07-16 10:49:21 +01:00
< / d i v >
2016-12-19 10:36:17 +00:00
< / d i v >
2020-07-16 10:49:21 +01:00
{ { / s h o w N o w A s D e f a u l t } }
2023-09-15 12:26:31 -04:00
< div class = "radio-select__column margin-y-2" >
2016-10-11 14:17:29 +01:00
{ { # choices } }
2023-08-25 15:31:44 -04:00
< div class = "usa-radio js-option" >
< input class = "usa-radio__input" type = "radio" value = "{{value}}" id = "{{id}}" name = "{{name}}" / >
< label class = "usa-radio__label" for = "{{id}}" > { { label } } < / l a b e l >
2016-12-19 10:36:17 +00:00
< / d i v >
2016-10-11 14:17:29 +01:00
{ { / c h o i c e s } }
2025-05-14 16:16:45 -04:00
< input type = 'button' class = 'usa-button usa-button--outline radio-select__button--done margin-top-4' aria - expanded = 'true' value = 'Back to select a new time' / >
2016-10-11 14:17:29 +01:00
< / d i v >
` ),
'chosen' : Hogan . compile ( `
2020-07-16 10:49:21 +01:00
{ { # showNowAsDefault } }
2023-09-15 12:26:31 -04:00
< div class = "radio-select__column margin-y-2" >
2023-08-25 15:31:44 -04:00
< div class = "usa-radio" >
< input class = "usa-radio__input" id = "{{name}}-0" name = "{{name}}" type = "radio" value = "" >
< label class = "usa-radio__label" for = "{{name}}-0" > Now < / l a b e l >
2020-07-16 10:49:21 +01:00
< / d i v >
2016-12-19 10:36:17 +00:00
< / d i v >
2020-07-16 10:49:21 +01:00
{ { / s h o w N o w A s D e f a u l t } }
2023-09-15 12:26:31 -04:00
< div class = "radio-select__column margin-y-2" >
2016-10-11 14:17:29 +01:00
{ { # choices } }
2023-08-25 15:31:44 -04:00
< div class = "usa-radio" >
< input class = "usa-radio__input" checked = "checked" type = "radio" value = "{{value}}" id = "{{id}}" name = "{{name}}" / >
< label class = "usa-radio__label" for = "{{id}}" > { { label } } < / l a b e l >
2016-12-19 10:36:17 +00:00
< / d i v >
2016-10-11 14:17:29 +01:00
{ { / c h o i c e s } }
< / d i v >
2023-09-15 12:26:31 -04:00
< div class = "radio-select__column margin-y-2" >
< input type = 'button' class = 'usa-button usa-button--outline radio-select__button--reset' aria - expanded = 'false' value = 'Choose a different time' / >
2016-10-11 14:17:29 +01:00
< / d i v >
` )
} ;
2016-08-07 09:17:49 +01:00
2021-01-20 11:23:01 +00:00
let shiftFocus = function ( elementToFocus , component ) {
// The first option is always the default
if ( elementToFocus === 'default' ) {
2021-01-19 14:12:29 +00:00
$ ( '[type=radio]' , component ) . eq ( 0 ) . focus ( ) ;
}
2021-01-20 11:23:01 +00:00
if ( elementToFocus === 'option' ) {
2021-01-19 14:12:29 +00:00
$ ( '[type=radio]' , component ) . eq ( 1 ) . focus ( ) ;
}
2016-10-11 14:17:29 +01:00
} ;
2016-08-07 09:17:49 +01:00
Modules . RadioSelect = function ( ) {
this . start = function ( component ) {
let $component = $ ( component ) ;
2016-12-19 10:36:17 +00:00
let render = ( state , data ) => {
$component . html ( states [ state ] . render ( data ) ) ;
} ;
2021-01-20 11:23:01 +00:00
// store array of all options in component
2016-10-11 14:17:29 +01:00
let choices = $ ( 'label' , $component ) . toArray ( ) . map ( function ( element ) {
let $element = $ ( element ) ;
return {
'id' : $element . attr ( 'for' ) ,
'label' : $ . trim ( $element . text ( ) ) ,
2016-12-19 10:36:17 +00:00
'value' : $element . prev ( 'input' ) . attr ( 'value' )
2016-10-11 14:17:29 +01:00
} ;
2016-08-07 09:17:49 +01:00
} ) ;
2016-10-11 14:17:29 +01:00
let categories = $component . data ( 'categories' ) . split ( ',' ) ;
let name = $component . find ( 'input' ) . eq ( 0 ) . attr ( 'name' ) ;
2019-07-01 11:48:09 +01:00
let mousedownOption = null ;
2020-07-16 10:49:21 +01:00
let showNowAsDefault = (
2020-07-16 19:27:33 +01:00
$component . data ( 'show-now-as-default' ) . toString ( ) === 'true' ?
2020-07-16 10:49:21 +01:00
{ 'name' : name } : false
) ;
2021-01-20 11:23:01 +00:00
// functions for changing the state of the component's HTML
2019-07-01 11:48:09 +01:00
const reset = ( ) => {
2019-07-08 10:42:54 +01:00
render ( 'initial' , {
'categories' : categories ,
2020-07-16 10:49:21 +01:00
'name' : name ,
'showNowAsDefault' : showNowAsDefault
2019-07-08 10:42:54 +01:00
} ) ;
2021-01-20 11:23:01 +00:00
shiftFocus ( 'default' , component ) ;
2019-07-08 10:42:54 +01:00
} ;
2019-07-01 11:48:09 +01:00
const selectOption = ( value ) => {
render ( 'chosen' , {
'choices' : choices . filter (
element => element . value == value
) ,
2020-07-16 10:49:21 +01:00
'name' : name ,
'showNowAsDefault' : showNowAsDefault
2019-07-01 11:48:09 +01:00
} ) ;
2021-01-20 11:23:01 +00:00
shiftFocus ( 'option' , component ) ;
2019-07-01 11:48:09 +01:00
} ;
2021-01-20 11:23:01 +00:00
// use mousedown + mouseup event sequence to confirm option selection
2019-07-01 11:48:09 +01:00
const trackMouseup = ( event ) => {
const parentNode = event . target . parentNode ;
if ( parentNode === mousedownOption ) {
const value = $ ( 'input' , parentNode ) . attr ( 'value' ) ;
selectOption ( value ) ;
// clear tracking
mousedownOption = null ;
$ ( document ) . off ( 'mouseup' , trackMouseup ) ;
}
} ;
2016-10-11 14:17:29 +01:00
2021-01-20 11:23:01 +00:00
// set events
2016-10-11 14:17:29 +01:00
$component
2020-02-06 14:49:07 +00:00
. on ( 'click' , '.radio-select__button--category' , function ( event ) {
2016-10-11 14:17:29 +01:00
event . preventDefault ( ) ;
2016-10-11 17:59:09 +01:00
let wordsInDay = $ ( this ) . attr ( 'value' ) . split ( ' ' ) ;
let day = wordsInDay [ wordsInDay . length - 1 ] . toLowerCase ( ) ;
2016-10-11 14:17:29 +01:00
render ( 'choose' , {
'choices' : choices . filter (
2016-10-11 17:59:09 +01:00
element => element . label . toLowerCase ( ) . indexOf ( day ) > - 1
2016-10-11 14:17:29 +01:00
) ,
2020-07-16 19:27:33 +01:00
'name' : name ,
'showNowAsDefault' : showNowAsDefault
2016-10-11 14:17:29 +01:00
} ) ;
2021-01-20 11:23:01 +00:00
shiftFocus ( 'option' , component ) ;
2016-10-11 14:17:29 +01:00
} )
2019-07-01 11:48:09 +01:00
. on ( 'mousedown' , '.js-option' , function ( event ) {
mousedownOption = this ;
2016-10-11 14:17:29 +01:00
2019-07-01 11:48:09 +01:00
// mouseup on the same option completes the click action
$ ( document ) . on ( 'mouseup' , trackMouseup ) ;
2016-10-11 14:17:29 +01:00
} )
2019-07-01 11:48:09 +01:00
// space and enter, clicked on a radio confirm that option was selected
2016-10-11 14:17:29 +01:00
. on ( 'keydown' , 'input[type=radio]' , function ( event ) {
2019-07-01 11:48:09 +01:00
// allow keypresses which aren’ t enter or space through
2016-10-11 14:17:29 +01:00
if ( event . which !== 13 && event . which !== 32 ) {
return true ;
}
event . preventDefault ( ) ;
let value = $ ( this ) . attr ( 'value' ) ;
2019-07-01 11:48:09 +01:00
selectOption ( value ) ;
2016-10-11 14:17:29 +01:00
} )
2020-02-06 14:49:07 +00:00
. on ( 'click' , '.radio-select__button--done' , function ( event ) {
2016-10-11 14:17:29 +01:00
event . preventDefault ( ) ;
2019-07-08 10:42:54 +01:00
let $selection = $ ( 'input[type=radio]:checked' , this . parentNode ) ;
if ( $selection . length ) {
render ( 'chosen' , {
'choices' : choices . filter (
element => element . value == $selection . eq ( 0 ) . attr ( 'value' )
) ,
2020-07-16 10:49:21 +01:00
'name' : name ,
'showNowAsDefault' : showNowAsDefault
2019-07-08 10:42:54 +01:00
} ) ;
2021-01-20 11:23:01 +00:00
shiftFocus ( 'option' , component ) ;
2019-07-08 10:42:54 +01:00
} else {
reset ( ) ;
2021-01-20 11:23:01 +00:00
shiftFocus ( 'default' , component ) ;
2019-07-08 10:42:54 +01:00
}
2016-10-11 14:17:29 +01:00
2019-07-08 10:42:54 +01:00
} )
2020-02-06 14:49:07 +00:00
. on ( 'click' , '.radio-select__button--reset' , function ( event ) {
2019-07-08 10:42:54 +01:00
event . preventDefault ( ) ;
reset ( ) ;
2021-01-20 11:23:01 +00:00
shiftFocus ( 'default' , component ) ;
2019-07-08 10:42:54 +01:00
2016-10-11 14:17:29 +01:00
} ) ;
2021-01-20 11:23:01 +00:00
// set HTML to initial state
2016-10-11 14:17:29 +01:00
render ( 'initial' , {
'categories' : categories ,
2020-07-16 10:49:21 +01:00
'name' : name ,
'showNowAsDefault' : showNowAsDefault
2016-08-07 09:17:49 +01:00
} ) ;
2016-10-11 18:11:20 +01:00
$component . css ( { 'height' : 'auto' } ) ;
2016-08-07 09:17:49 +01:00
} ;
} ;
2019-05-22 13:11:48 +01:00
} ) ( window ) ;