Skip to content

Commit

Permalink
changed the structure of the library,
Browse files Browse the repository at this point in the history
change the inputs handlers,
replace the inputs with fake inputs to handle to avoid event.key problem.
some fixes.
  • Loading branch information
HichemTab-tech committed Aug 16, 2023
1 parent d4bc444 commit 25fc187
Show file tree
Hide file tree
Showing 8 changed files with 379 additions and 83 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ You can install OTP-designer-jquery via npm:
You can also include OTP-designer-jquery directly from a CDN by adding the following script tag to your HTML file:

```HTML
<script src="https://cdn.jsdelivr.net/gh/HichemTab-tech/OTP-designer-jquery@1.0.1/dist/otpdesigner.min.js"></script>
<script src="https://cdn.jsdelivr.net/gh/HichemTab-tech/OTP-designer-jquery@2.0.0/dist/otpdesigner.min.js"></script>
```

### Local Download
Expand Down
224 changes: 186 additions & 38 deletions dist/otpdesigner.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,28 @@ return /******/ (() => { // webpackBootstrap

var ___CSS_LOADER_EXPORT___ = _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1___default()((_node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0___default()));
// Module
___CSS_LOADER_EXPORT___.push([module.id, `input.otp-input {
width: 40px;
height: 40px
___CSS_LOADER_EXPORT___.push([module.id, `.otp-fake-input {
width: 50px;
height: 50px;
display: flex;
align-items: center;
justify-content: center;
}
.otp-fake-input .otp-content {
font-size: 20px;
font-weight: 600;
color: #111;
padding-bottom: 1px;
}
.otp-fake-input.otpdesigner__focus__ {
border: 2px solid #007bff;
}
.realInput{
position: absolute!important;
z-index: -2000!important;
}`, ""]);
// Exports
/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (___CSS_LOADER_EXPORT___);
Expand Down Expand Up @@ -552,14 +571,14 @@ const otpdesigner = function (options = {}, ...args) {
else code = "";
if (code.length === data.settings.length) {
for (let i = 0; i < code.length; i++) {
$('#'+optInputId + (i) + "_" + data.idSuffix).val(code[i]);
$('#'+optInputId + (i) + "_" + data.idSuffix).trigger('otp-written', [code[i]]);
}
collectOtpCode(data);
}
return results;
},
focus: function (results, data) {
$('#'+optInputId + (data.settings.length - 1) + "_" + data.idSuffix).focus();
$('#'+optInputId + (data.settings.length - 1) + "_" + data.idSuffix).otpdesigner__toggleFocus__(true);
return results;
},
hiddenInput: function (results, data) {
Expand Down Expand Up @@ -603,67 +622,108 @@ const otpdesigner = function (options = {}, ...args) {
};
//save the settings of the element
$(this).data('otpdesigner', data);
$(this).attr('data-otpdesigner-id', idSuffix);

let $inputsParent = $('<div class="inputs d-flex flex-row justify-content-center mt-2">');
$inputsParent.attr('id', 'otp_' + idSuffix);
let $fakeInputsParent = $('<div class="fake-inputs d-flex flex-row justify-content-center mt-2">');
$fakeInputsParent.attr('id', 'otp_' + idSuffix);
if (settings.inputsParentClasses !== "") {
$inputsParent.addClass(settings.inputsParentClasses);
$fakeInputsParent.addClass(settings.inputsParentClasses);
}

let $hiddenInput = $('<input type="hidden">');
$hiddenInput.attr('id', 'otp_hidden_' + idSuffix);
$hiddenInput.attr('name', 'otp_hidden_' + idSuffix);
$hiddenInput.appendTo($parent);

let $realInput = $('<textarea class="realInput" maxlength="2" tabindex="-1">-</textarea>');
$realInput.attr('id', 'otp_real_' + idSuffix);
$realInput.attr('name', 'otp_real_' + idSuffix);
$realInput.appendTo($fakeInputsParent);
$realInput.on('input', function () {
let a = getRealInputValue(data);
resetRealInput(data);
getFocusedFakeInput(data).trigger('otp-written', [a]);
});
$realInput.on('keydown', function (e) {
if (e.key === "ArrowLeft" || e.key === "ArrowRight" || e.key === "ArrowUp" || e.key === "ArrowDown" || e.key === "Tab") {
e.preventDefault();
let focusedInp = getFocusedFakeInput(data);
let $inputs = $fakeInputsParent.find('.otp-fake-input');
let index = $inputs.index(focusedInp);
if (e.key === "ArrowLeft" || e.key === "ArrowUp") {
if (index > 0) $($inputs[index - 1]).otpdesigner__toggleFocus__(true);
}
else {
if (index < $inputs.length - 1) $($inputs[index + 1]).otpdesigner__toggleFocus__(true);
}
}
});
$realInput.on('paste', (event) => {
let pastedText = event.originalEvent.clipboardData.getData('text');
event.preventDefault();
let pastedTextParts = pastedText.split('');
pastedTextParts = pastedTextParts.filter(function (value) {
return isAcceptedCharacter(value, settings.onlyNumbers);
});
pastedText = pastedTextParts.join('');
if (pastedText.length >= settings.length) {
pastedText = pastedText.substring(0, settings.length);
$('[data-otpdesigner-id="' + data.idSuffix + '"]').otpdesigner('set', pastedText);
}
});

for (let i = 0; i < settings.length; i++) {
let $input = $('<input class="m-2 text-center form-control rounded otp-input" maxlength="1" />');
$input.attr('id', optInputId + (i) + "_" + idSuffix);
let $fakeInput = $('<div class="m-2 text-center form-control rounded otp-fake-input"><span class="otp-content"></span></div>');
$fakeInput.attr('id', optInputId + (i) + "_" + idSuffix);
$fakeInput[0].addEventListener('click', function () {
if (!$(this).otpdesigner__isFocused__()) {
$(this).otpdesigner__toggleFocus__(true);
}
else{
toggleRealInputFocus(this, true);
}
});

let type = "text";
if (settings.type === 'numeric') {
type = "number";
}
if (settings.inputsClasses !== "") {
$input.addClass(settings.inputsClasses);
$fakeInput.addClass(settings.inputsClasses);
}
$input.appendTo($inputsParent);
$fakeInput.appendTo($fakeInputsParent);
}
$inputsParent.appendTo($parent);
let $inputs = $inputsParent.find('.otp-input');
$fakeInputsParent.appendTo($parent);
let $inputs = $fakeInputsParent.find('.otp-fake-input');
$inputs.each(function (i) {
$inputs[i].addEventListener("keydown", function (event) {
if (event.key === "Backspace") {
$inputs[i].value = "";
if (i !== 0) $inputs[i - 1].focus();
} else if (event.key === "Enter" && i === $inputs.length - 1 && $inputs[i].value !== "") {
event.preventDefault();
$($inputs[i]).off('otp-written');
$($inputs[i]).on("otp-written", function (event, value) {
if (value === "Backspace") {
$($inputs[i]).otpdesigner__fakeInputVal__("");
if (i !== 0) $($inputs[i - 1]).otpdesigner__toggleFocus__(true);
} else if (value === "Enter" && i === $inputs.length - 1 && $($inputs[i]).otpdesigner__fakeInputVal__() !== "") {
collectOtpCode(data, false);
if (settings.enterClicked != null) {
settings.enterClicked();
}
loseFocus(data);
return;
} else {
if ((event.keyCode > 95 && event.keyCode < 106) || (event.keyCode > 47 && event.keyCode < 58)) {
$inputs[i].value = event.key;
if (i !== $inputs.length - 1) $inputs[i + 1].focus();
event.preventDefault();
} else if (!settings.onlyNumbers && event.keyCode > 64 && event.keyCode < 91) {
$inputs[i].value = String.fromCharCode(event.keyCode);
if (i !== $inputs.length - 1) $inputs[i + 1].focus();
event.preventDefault();
}
else{
event.preventDefault();
if (isAcceptedCharacter(value, settings.onlyNumbers)) {
value = value.toLowerCase();
$($inputs[i]).otpdesigner__fakeInputVal__(value);
if (i !== $inputs.length - 1) $($inputs[i + 1]).otpdesigner__toggleFocus__(true);
}
}
collectOtpCode(data);
collectOtpCode(data, (i === $inputs.length - 1));
});
$inputs[i].addEventListener("focus", function () {
$($inputs[i]).off("focused");
$($inputs[i]).on("focused", function () {
if (!!$($inputs[i]).data('f')) return;
for (let j = 0; j < i; j++) {
if ($inputs[j].value === "") {
if ($($inputs[j]).otpdesigner__fakeInputVal__() === "") {
$($inputs[j]).data('f', "1");
$($inputs[j]).focus();
$($inputs[j]).otpdesigner__toggleFocus__(true);
$($inputs[j]).removeData('f');
break;
}
Expand All @@ -689,10 +749,10 @@ let stringToBool = function (s) {
}

let collectOtpCode = (data, typingDone = true) => {
let $inputs = $('#otp_' + data.idSuffix).find('.otp-input');
let $inputs = $('#otp_' + data.idSuffix).find('.otp-fake-input');
let code = '';
$inputs.each(function (i, e) {
code += $(e).val().trim();
code += $(e).otpdesigner__fakeInputVal__().trim();
});
$('#otp_hidden_' + data.idSuffix).val(code);
if (code.length === $inputs.length && typingDone) {
Expand All @@ -705,8 +765,96 @@ let collectOtpCode = (data, typingDone = true) => {

let loseFocus = (data) => {
if (data.settings.enterClicked != null) return;
$('.otp-input:focus').blur();
$('.otpdesigner__focus__').otpdesigner__toggleFocus__(false);
};

$(document)[0].addEventListener('click', function(event) {
let $target = $(event.target);
let focused = $('.otp-fake-input');
if(
!$target.closest('.otp-fake-input').length &&
focused.length !== 0 &&
focused.is(":visible")
) {
focused.otpdesigner__toggleFocus__(false)
}
});

function onFakeInputFocused(ele) {
toggleRealInputFocus(ele, true);
$(ele).trigger('focused');
}

$.fn.otpdesigner__toggleFocus__ = function (toFocus = null) {
$(this).each(function () {
if (toFocus !== null) {
if (toFocus === true) {
$('.otpdesigner__focus__').removeClass('otpdesigner__focus__');
$(this).addClass('otpdesigner__focus__');
onFakeInputFocused(this);
}
else {
$(this).removeClass('otpdesigner__focus__');
}
return;
}
if ($(this).hasClass('otpdesigner__focus__')) {
$(this).removeClass('otpdesigner__focus__');
}
else {
$('.otpdesigner__focus__').removeClass('otpdesigner__focus__');
$(this).addClass('otpdesigner__focus__');
onFakeInputFocused(this);
}
});
}

function getFocusedFakeInput(data) {
return $('#otp_' + data.idSuffix).find('.otp-fake-input.otpdesigner__focus__');
}

$.fn.otpdesigner__isFocused__ = function () {
return $(this).hasClass('otpdesigner__focus__');
}

$.fn.otpdesigner__fakeInputVal__ = function (val = "RETURN_REQUESTED") {
if (val === "RETURN_REQUESTED") {
return $(this).find('.otp-content').html();
}
$(this).find('.otp-content').html(val);
}

function toggleRealInputFocus(fakeInput, toFocus) {
// noinspection JSCheckFunctionSignatures
let $realInput = $(fakeInput).parents('.fake-inputs').find('.realInput');
if (toFocus) {
$realInput.focus();
$realInput[0].setSelectionRange($realInput.val().length, $realInput.val().length);
}
else {
$realInput.blur();
}
}

function resetRealInput(data) {
let $realInput = $('#otp_' + data.idSuffix).find('.realInput');
$realInput.val("-");
$realInput[0].setSelectionRange($realInput.val().length, $realInput.val().length);
}

function getRealInputValue(data) {
let $realInput = $('#otp_' + data.idSuffix).find('.realInput');
if ($realInput.val() === "") return "Backspace";
else if ($realInput.val() === "-\n") return "Enter";
return $realInput.val().substring(1);
}

const isAcceptedCharacter = (char, onlyNumbers) => {
return (otpdesigner__alphabets__.includes(char) && !onlyNumbers) || otpdesigner__numbers__.includes(char);
};

const otpdesigner__alphabets__ = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'.split("");
const otpdesigner__numbers__ = '0123456789'.split("");
;// CONCATENATED MODULE: ./index.js


Expand Down
Loading

0 comments on commit 25fc187

Please sign in to comment.