input-format
Version:
Formatting user's text input on-the-fly
1 lines • 8.86 kB
Source Map (JSON)
{"version":3,"file":"inputControl.js","names":["edit","parse","format","isReadOnly","getOperation","getSelection","getCaretPosition","setCaretPosition","onCut","event","input","_parse","_format","on_change","setTimeout","formatInputText","undefined","onPaste","selection","eraseSelection","onChange","onKeyDown","operation","preventDefault","text","value","slice","start","end","caret","newValueAndCaret","formatted"],"sources":["../source/inputControl.js"],"sourcesContent":["import edit from './edit.js'\r\nimport parse from './parse.js'\r\nimport format from './format.js'\r\n\r\nimport\r\n{\r\n\tisReadOnly,\r\n\tgetOperation,\r\n\tgetSelection,\r\n\tgetCaretPosition,\r\n\tsetCaretPosition\r\n}\r\nfrom './dom.js'\r\n\r\n// Deprecated.\r\n// I don't know why this function exists.\r\nexport function onCut(event, input, _parse, _format, on_change)\r\n{\r\n\tif (isReadOnly(input)) {\r\n\t\treturn\r\n\t}\r\n\r\n\t// The actual cut hasn't happened just yet hence the timeout.\r\n\tsetTimeout(() => formatInputText(input, _parse, _format, undefined, on_change), 0)\r\n}\r\n\r\n// Deprecated.\r\n// I don't know why this function exists.\r\nexport function onPaste(event, input, _parse, _format, on_change)\r\n{\r\n\tif (isReadOnly(input)) {\r\n\t\treturn\r\n\t}\r\n\r\n\tconst selection = getSelection(input)\r\n\r\n\t// If selection is made,\r\n\t// just erase the selected text\r\n\t// prior to pasting\r\n\tif (selection)\r\n\t{\r\n\t\teraseSelection(input, selection)\r\n\t}\r\n\r\n\tformatInputText(input, _parse, _format, undefined, on_change)\r\n}\r\n\r\nexport function onChange(event, input, _parse, _format, on_change)\r\n{\r\n\tformatInputText(input, _parse, _format, undefined, on_change)\r\n}\r\n\r\n// \"Delete\" and \"Backspace\" keys are special\r\n// in a way that they're not handled by the regular `onChange()` handler\r\n// and instead are intercepted and re-applied manually.\r\n// The reason is that normally hitting \"Backspace\" or \"Delete\"\r\n// results in erasing a character, but that character might be any character,\r\n// while it would be a better \"user experience\" if it erased not just any character\r\n// but the closest \"meaningful\" character.\r\n// For example, if a template is `(xxx) xxx-xxxx`,\r\n// and the `<input/>` value is `(111) 222-3333`,\r\n// then, if a user begins erasing the `3333` part via \"Backspace\"\r\n// and reaches the \"-\" character, then it would just erase the \"-\" character.\r\n// Nothing wrong with that, but it would be a better \"user experience\"\r\n// if hitting \"Backspace\" at that position would erase the closest \"meaningful\"\r\n// character, which would be the rightmost `2`.\r\n// So, what this `onKeyDown()` handler does is it intercepts\r\n// \"Backspace\" and \"Delete\" keys and re-applies those operations manually\r\n// following the logic described above.\r\nexport function onKeyDown(event, input, _parse, _format, on_change)\r\n{\r\n\tif (isReadOnly(input)) {\r\n\t\treturn\r\n\t}\r\n\r\n\tconst operation = getOperation(event)\r\n\tswitch (operation)\r\n\t{\r\n\t\tcase 'Delete':\r\n\t\tcase 'Backspace':\r\n\t\t\t// Intercept this operation and perform it manually.\r\n\t\t\tevent.preventDefault()\r\n\r\n\t\t\tconst selection = getSelection(input)\r\n\r\n\t\t\t// If a selection is made, just erase the selected text.\r\n\t\t\tif (selection)\r\n\t\t\t{\r\n\t\t\t\teraseSelection(input, selection)\r\n\t\t\t\treturn formatInputText(input, _parse, _format, undefined, on_change)\r\n\t\t\t}\r\n\r\n\t\t\t// Else, perform the (character erasing) operation manually.\r\n\t\t\treturn formatInputText(input, _parse, _format, operation, on_change)\r\n\r\n\t\tdefault:\r\n\t\t\t// Will be handled normally as part of the `onChange` handler.\r\n\t}\r\n}\r\n\r\n/**\r\n * Erases the selected text inside an `<input/>`.\r\n * @param {DOMElement} input\r\n * @param {Selection} selection\r\n */\r\nfunction eraseSelection(input, selection)\r\n{\r\n\tlet text = input.value\r\n\ttext = text.slice(0, selection.start) + text.slice(selection.end)\r\n\r\n\tinput.value = text\r\n\tsetCaretPosition(input, selection.start)\r\n}\r\n\r\n/**\r\n * Parses and re-formats `<input/>` textual value.\r\n * E.g. when a user enters something into the `<input/>`\r\n * that raw input must first be parsed and the re-formatted properly.\r\n * Is called either after some user input (e.g. entered a character, pasted something)\r\n * or after the user performed an `operation` (e.g. \"Backspace\", \"Delete\").\r\n * @param {DOMElement} input\r\n * @param {Function} parse\r\n * @param {Function} format\r\n * @param {string} [operation] - The operation that triggered `<input/>` textual value change. E.g. \"Backspace\", \"Delete\".\r\n * @param {Function} onChange\r\n */\r\nfunction formatInputText(input, _parse, _format, operation, on_change)\r\n{\r\n\t// Parse `<input/>` textual value.\r\n\t// Get the `value` and `caret` position.\r\n\tlet { value, caret } = parse(input.value, getCaretPosition(input), _parse)\r\n\r\n\t// If a user performed an operation (\"Backspace\", \"Delete\")\r\n\t// then apply that operation and get the new `value` and `caret` position.\r\n\tif (operation)\r\n\t{\r\n\t\tconst newValueAndCaret = edit(value, caret, operation)\r\n\r\n\t\tvalue = newValueAndCaret.value\r\n\t\tcaret = newValueAndCaret.caret\r\n\t}\r\n\r\n\t// Format the `value`.\r\n\t// (and reposition the caret accordingly)\r\n\tconst formatted = format(value, caret, _format)\r\n\r\n\tconst text = formatted.text\r\n\tcaret = formatted.caret\r\n\r\n\t// Set `<input/>` textual value manually\r\n\t// to prevent React from resetting the caret position\r\n\t// later inside a subsequent `render()`.\r\n\t// Doesn't work for custom `inputComponent`s for some reason.\r\n\tinput.value = text\r\n\t// Position the caret properly.\r\n\tsetCaretPosition(input, caret)\r\n\r\n\t// If the `<input/>` textual value did change,\r\n\t// then the parsed `value` may have changed too.\r\n\tif (on_change) {\r\n\t\ton_change(value)\r\n\t}\r\n}"],"mappings":"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"}