const Component = use('util.Component');
export default def(class CodeEntryView extends Component {
static ID = 'ui.component.CodeEntryView';
static PROPERTIES = {
value: {},
error: {},
is_checking_code: {},
}
static RENDER_MODE = Component.NO_SHADOW;
static CSS = /*css*/`
.wrapper {
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
color: #3e5362;
}
fieldset[name=number-code] {
display: flex;
justify-content: space-between;
gap: 5px;
}
.digit-input {
box-sizing: border-box;
flex-grow: 1;
height: 50px;
font-size: 25px;
text-align: center;
border-radius: 0.5rem;
-moz-appearance: textfield;
border: 2px solid #9b9b9b;
color: #485660;
}
.digit-input::-webkit-outer-spin-button,
.digit-input::-webkit-inner-spin-button {
-webkit-appearance: none;
margin: 0;
}
.confirm-code-hyphen {
display: inline-block;
flex-grow: 2;
text-align: center;
font-size: 40px;
font-weight: 300;
}
`
create_template ({ template }) {
// TODO: static member for strings
const submit_btn_txt = i18n('confirm_code_generic_submit');
$(template).html(/*html*/`
`);
}
on_focus () {
$(this.dom_).find('.digit-input').first().focus();
}
on_ready ({ listen }) {
listen('error', (error) => {
if ( ! error ) return $(this.dom_).find('.error').hide();
$(this.dom_).find('.error').text(error).show();
});
listen('value', value => {
// clear the inputs
if ( value === undefined ) {
$(this.dom_).find('.digit-input').val('');
return;
}
})
listen('is_checking_code', (is_checking_code, { old_value }) => {
if ( old_value === is_checking_code ) return;
if ( old_value === undefined ) return;
const $button = $(this.dom_).find('.code-confirm-btn');
if ( is_checking_code ) {
// set animation
$button.prop('disabled', true);
$button.html(``);
return;
}
const submit_btn_txt = i18n('confirm_code_generic_try_again');
$button.html(submit_btn_txt);
$button.prop('disabled', false);
});
const that = this;
$(this.dom_).find('.code-confirm-btn').on('click submit', function(e){
e.preventDefault();
e.stopPropagation();
const $button = $(this);
$button.prop('disabled', true);
$button.closest('.error').hide();
that.set('is_checking_code', true);
// force update to trigger the listener
that.set('value', that.get('value'));
})
// Elements
const numberCodeForm = this.dom_.querySelector('[data-number-code-form]');
const numberCodeInputs = [...numberCodeForm.querySelectorAll('[data-number-code-input]')];
// Event listeners
numberCodeForm.addEventListener('input', ({ target }) => {
const inputLength = target.value.length || 0;
let currentIndex = Number(target.dataset.numberCodeInput);
if(inputLength === 2){
const inputValues = target.value.split('');
target.value = inputValues[0];
}
else if (inputLength > 1) {
const inputValues = target.value.split('');
inputValues.forEach((value, valueIndex) => {
const nextValueIndex = currentIndex + valueIndex;
if (nextValueIndex >= numberCodeInputs.length) { return; }
numberCodeInputs[nextValueIndex].value = value;
});
currentIndex += inputValues.length - 2;
}
const nextIndex = currentIndex + 1;
if (nextIndex < numberCodeInputs.length) {
numberCodeInputs[nextIndex].focus();
}
// Concatenate all inputs into one string to create the final code
let current_code = '';
for(let i=0; i< numberCodeInputs.length; i++){
current_code += numberCodeInputs[i].value;
}
const submit_btn_txt = i18n('confirm_code_generic_submit');
$(this.dom_).find('.code-confirm-btn').html(submit_btn_txt);
// Automatically submit if 6 digits entered
if(current_code.length === 6){
$(this.dom_).find('.code-confirm-btn').prop('disabled', false);
this.set('value', current_code);
this.set('is_checking_code', true);
} else {
$(this.dom_).find('.code-confirm-btn').prop('disabled', true);
}
});
numberCodeForm.addEventListener('keydown', (e) => {
const { code, target } = e;
const currentIndex = Number(target.dataset.numberCodeInput);
const previousIndex = currentIndex - 1;
const nextIndex = currentIndex + 1;
const hasPreviousIndex = previousIndex >= 0;
const hasNextIndex = nextIndex <= numberCodeInputs.length - 1
switch (code) {
case 'ArrowLeft':
case 'ArrowUp':
if (hasPreviousIndex) {
numberCodeInputs[previousIndex].focus();
}
e.preventDefault();
break;
case 'ArrowRight':
case 'ArrowDown':
if (hasNextIndex) {
numberCodeInputs[nextIndex].focus();
}
e.preventDefault();
break;
case 'Backspace':
if (!e.target.value.length && hasPreviousIndex) {
numberCodeInputs[previousIndex].value = null;
numberCodeInputs[previousIndex].focus();
}
break;
default:
break;
}
});
}
})