2025-10-06 09:38:54 -04:00
( function ( window ) {
2016-08-07 09:17:49 +01:00
"use strict" ;
2025-10-06 09:38:54 -04:00
var Modules = window . NotifyModules ;
2019-05-22 13:11:48 +01:00
2025-07-31 12:47:40 -04:00
// Template functions for rendering component states
let renderStates = {
'initial' : function ( data ) {
return `
${ data . showNowAsDefault ? `
<div class="radio-select__column margin-y-2">
<div class="usa-radio">
<input class="usa-radio__input" checked="checked" id=" ${ data . name } -0" name=" ${ data . name } " type="radio" value="">
<label class="usa-radio__label" for=" ${ data . name } -0">Now</label>
</div>
</div>
` : '' }
2023-09-15 12:26:31 -04:00
<div class="radio-select__column margin-y-2">
2025-07-31 12:47:40 -04:00
${ data . categories . map ( category =>
`<input type='button' class='usa-button usa-button--outline radio-select__button--category' aria-expanded="false" value=' ${ category } ' />`
). join ( '' ) }
2016-12-19 10:36:17 +00:00
</div>
2025-07-31 12:47:40 -04:00
` ;
},
'choose' : function ( data ) {
return `
${ data . showNowAsDefault ? `
<div class="radio-select__column margin-y-2">
<div class="usa-radio">
<input class="usa-radio__input" checked="checked" id=" ${ data . name } -0" name=" ${ data . name } " type="radio" value="">
<label class="usa-radio__label" for=" ${ data . name } -0">Now</label>
</div>
</div>
` : '' }
2023-09-15 12:26:31 -04:00
<div class="radio-select__column margin-y-2">
2025-07-31 12:47:40 -04:00
${ data . choices . map ( choice => `
<div class="usa-radio js-option">
<input class="usa-radio__input" type="radio" value=" ${ choice . value } " id=" ${ choice . id } " name=" ${ data . name } " />
<label class="usa-radio__label" for=" ${ choice . id } "> ${ choice . label } </label>
</div>
` ). join ( '' ) }
<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-12-19 10:36:17 +00:00
</div>
2025-07-31 12:47:40 -04:00
` ;
},
'chosen' : function ( data ) {
return `
${ data . showNowAsDefault ? `
<div class="radio-select__column margin-y-2">
<div class="usa-radio">
<input class="usa-radio__input" id=" ${ data . name } -0" name=" ${ data . name } " type="radio" value="">
<label class="usa-radio__label" for=" ${ data . name } -0">Now</label>
</div>
2016-12-19 10:36:17 +00:00
</div>
2025-07-31 12:47:40 -04:00
` : '' }
2023-09-15 12:26:31 -04:00
<div class="radio-select__column margin-y-2">
2025-07-31 12:47:40 -04:00
${ data . choices . map ( choice => `
<div class="usa-radio">
<input class="usa-radio__input" checked="checked" type="radio" value=" ${ choice . value } " id=" ${ choice . id } " name=" ${ data . name } " />
<label class="usa-radio__label" for=" ${ choice . id } "> ${ choice . label } </label>
</div>
` ). join ( '' ) }
2016-12-19 10:36:17 +00:00
</div>
2025-07-31 12:47:40 -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' />
</div>
` ;
}
2016-10-11 14:17:29 +01:00
};
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
2025-10-06 09:38:54 -04:00
Modules [ 'radio-select' ] = function () {
2016-08-07 09:17:49 +01:00
this . start = function ( component ) {
let $component = $ ( component );
2016-12-19 10:36:17 +00:00
let render = ( state , data ) => {
2025-07-31 12:47:40 -04:00
$component . html ( renderStates [ state ]( data ));
2016-12-19 10:36:17 +00:00
};
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-08-07 09:17:49 +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-08-07 09:17:49 +01:00
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-08-07 09:17:49 +01:00
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
2019-07-08 10:42:54 +01:00
})
2020-02-06 14:49:07 +00:00
. on ( 'click' , '.radio-select__button--done' , function ( event ) {
2019-07-08 10:42:54 +01:00
event . preventDefault ();
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
})
2020-02-06 14:49:07 +00:00
. on ( 'click' , '.radio-select__button--reset' , function ( event ) {
2016-10-11 14:17:29 +01:00
event . preventDefault ();
2019-07-08 10:42:54 +01:00
reset ();
2021-01-20 11:23:01 +00:00
shiftFocus ( 'default' , component );
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 );