2025-10-03 11:00:05 +00:00
import { keys } from "./keycode.js" ;
import { getMaskTemplate , getPlaceholder , getTest } from "./validation-tests" ;
2025-09-24 06:24:52 +00:00
import {
2025-10-03 11:00:05 +00:00
caret ,
determineNewCaretPosition ,
getBuffer , getBufferTemplate ,
getLastValidPosition ,
isMask ,
resetMaskSet ,
seekNext
2025-09-24 06:24:52 +00:00
} from "./positioning" ;
2025-10-03 11:00:05 +00:00
import { isComplete , refreshFromBuffer } from "./validation" ;
import { ie } from "./environment" ;
import { EventHandlers } from "./eventhandlers" ;
2025-09-24 06:24:52 +00:00
2025-10-03 11:00:05 +00:00
export { applyInputValue , clearOptionalTail , checkVal , HandleNativePlaceholder , unmaskedvalue , writeBuffer } ;
2025-09-24 06:24:52 +00:00
2025-10-03 11:00:05 +00:00
function applyInputValue ( input , value ) {
const inputmask = input ? input . inputmask : this , opts = inputmask . opts ;
input . inputmask . refreshValue = false ;
if ( typeof opts . onBeforeMask === "function" ) value = opts . onBeforeMask . call ( inputmask , value , opts ) || value ;
value = ( value || "" ) . toString ( ) . split ( "" ) ;
checkVal ( input , true , false , value ) ;
inputmask . undoValue = inputmask . _valueGet ( true ) ;
if ( ( opts . clearMaskOnLostFocus || opts . clearIncomplete ) && input . inputmask . _valueGet ( ) === getBufferTemplate . call ( inputmask ) . join ( "" ) && getLastValidPosition . call ( inputmask ) === - 1 ) {
input . inputmask . _valueSet ( "" ) ;
}
2025-09-24 06:24:52 +00:00
}
2025-10-03 11:00:05 +00:00
//todo put on prototype?
2025-09-24 06:24:52 +00:00
function clearOptionalTail ( buffer ) {
2025-10-03 11:00:05 +00:00
const inputmask = this ;
2025-09-24 06:24:52 +00:00
2025-10-03 11:00:05 +00:00
buffer . length = 0 ;
var template = getMaskTemplate . call ( inputmask , true , 0 , true , undefined , true ) , lmnt ;
while ( ( lmnt = template . shift ( ) ) !== undefined ) buffer . push ( lmnt ) ;
return buffer ;
2025-09-24 06:24:52 +00:00
}
function checkVal ( input , writeOut , strict , nptvl , initiatingEvent ) {
2025-10-03 11:00:05 +00:00
const inputmask = input ? input . inputmask : this ,
maskset = inputmask . maskset ,
opts = inputmask . opts , $ = inputmask . dependencyLib ;
var inputValue = nptvl . slice ( ) ,
charCodes = "" ,
initialNdx = - 1 ,
result = undefined , skipOptionalPartCharacter = opts . skipOptionalPartCharacter ;
opts . skipOptionalPartCharacter = "" ; //see issue #2311
function isTemplateMatch ( ndx , charCodes ) {
var targetTemplate = getMaskTemplate . call ( inputmask , true , 0 ) . slice ( ndx , seekNext . call ( inputmask , ndx , false , false ) ) . join ( "" ) . replace ( /'/g , "" ) ,
charCodeNdx = targetTemplate . indexOf ( charCodes ) ;
//strip spaces from targetTemplate
while ( charCodeNdx > 0 && targetTemplate [ charCodeNdx - 1 ] === " " ) charCodeNdx -- ;
var match = charCodeNdx === 0 && ! isMask . call ( inputmask , ndx )
&& ( getTest . call ( inputmask , ndx ) . match . nativeDef === charCodes . charAt ( 0 )
|| ( getTest . call ( inputmask , ndx ) . match . static === true && getTest . call ( inputmask , ndx ) . match . nativeDef === ( "'" + charCodes . charAt ( 0 ) ) )
|| ( getTest . call ( inputmask , ndx ) . match . nativeDef === " " && ( getTest . call ( inputmask , ndx + 1 ) . match . nativeDef === charCodes . charAt ( 0 )
|| ( getTest . call ( inputmask , ndx + 1 ) . match . static === true && getTest . call ( inputmask , ndx + 1 ) . match . nativeDef === ( "'" + charCodes . charAt ( 0 ) ) ) ) ) ) ;
if ( ! match && charCodeNdx > 0 && ! isMask . call ( inputmask , ndx , false , true ) ) {
var nextPos = seekNext . call ( inputmask , ndx ) ;
if ( inputmask . caretPos . begin < nextPos ) {
inputmask . caretPos = { begin : nextPos } ;
}
}
return match ;
2025-09-24 06:24:52 +00:00
}
2025-10-03 11:00:05 +00:00
resetMaskSet . call ( inputmask ) ;
maskset . tests = { } ; //reset tests ~ possible after alternating
initialNdx = opts . radixPoint ? determineNewCaretPosition . call ( inputmask , {
begin : 0 ,
end : 0
} , false , opts . _ _financeInput === false ? "radixFocus" : undefined ) . begin : 0 ;
maskset . p = initialNdx ;
inputmask . caretPos = { begin : initialNdx } ;
var staticMatches = [ ] , prevCaretPos = inputmask . caretPos ;
inputValue . forEach ( function ( charCode , ndx ) {
if ( charCode !== undefined ) { //inputfallback strips some elements out of the inputarray. $.each logically presents them as undefined
/ * i f ( m a s k s e t . v a l i d P o s i t i o n s [ n d x ] = = = u n d e f i n e d & & i n p u t V a l u e [ n d x ] = = = g e t P l a c e h o l d e r . c a l l ( i n p u t m a s k , n d x ) & & i s M a s k . c a l l ( i n p u t m a s k , n d x , t r u e ) & &
isValid . call ( inputmask , ndx , inputValue [ ndx ] , true , undefined , true , true ) === false ) {
inputmask . caretPos . begin ++ ;
} else * /
{
var keypress = new $ . Event ( "_checkval" ) ;
keypress . key = charCode ;
charCodes += charCode ;
var lvp = getLastValidPosition . call ( inputmask , undefined , true ) ;
if ( ! isTemplateMatch ( initialNdx , charCodes ) ) {
result = EventHandlers . keypressEvent . call ( inputmask , keypress , true , false , strict , inputmask . caretPos . begin ) ;
if ( result ) {
initialNdx = inputmask . caretPos . begin + 1 ;
charCodes = "" ;
}
} else {
result = EventHandlers . keypressEvent . call ( inputmask , keypress , true , false , strict , lvp + 1 ) ;
}
if ( result ) {
if ( result . pos !== undefined && maskset . validPositions [ result . pos ] && maskset . validPositions [ result . pos ] . match . static === true && maskset . validPositions [ result . pos ] . alternation === undefined ) {
staticMatches . push ( result . pos ) ;
if ( ! inputmask . isRTL ) {
result . forwardPosition = result . pos + 1 ;
}
}
writeBuffer . call ( inputmask , undefined , getBuffer . call ( inputmask ) , result . forwardPosition , keypress , false ) ;
inputmask . caretPos = { begin : result . forwardPosition , end : result . forwardPosition } ;
prevCaretPos = inputmask . caretPos ;
} else {
if ( maskset . validPositions [ ndx ] === undefined && inputValue [ ndx ] === getPlaceholder . call ( inputmask , ndx ) && isMask . call ( inputmask , ndx , true ) ) {
inputmask . caretPos . begin ++ ;
} else inputmask . caretPos = prevCaretPos ; //restore the caret position from before the failed validation
}
}
2025-09-24 06:24:52 +00:00
}
2025-10-03 11:00:05 +00:00
} ) ;
if ( staticMatches . length > 0 ) {
var sndx , validPos , nextValid = seekNext . call ( inputmask , - 1 , undefined , false ) ;
if ( ( ! isComplete . call ( inputmask , getBuffer . call ( inputmask ) ) && staticMatches . length <= nextValid )
|| ( isComplete . call ( inputmask , getBuffer . call ( inputmask ) ) && staticMatches . length > 0 && ( staticMatches . length !== nextValid && staticMatches [ 0 ] === 0 ) ) ) { //should check if is sequence starting from 0
var nextSndx = nextValid ;
while ( ( sndx = staticMatches . shift ( ) ) !== undefined ) {
var keypress = new $ . Event ( "_checkval" ) ;
validPos = maskset . validPositions [ sndx ] ;
validPos . generatedInput = true ;
keypress . key = validPos . input ;
result = EventHandlers . keypressEvent . call ( inputmask , keypress , true , false , strict , nextSndx ) ;
if ( result && result . pos !== undefined && result . pos !== sndx && maskset . validPositions [ result . pos ] && maskset . validPositions [ result . pos ] . match . static === true ) {
staticMatches . push ( result . pos ) ;
} else if ( ! result ) break ;
nextSndx ++ ;
}
} else { //mark al statics as generated
// while ((sndx = staticMatches.pop())) {
// validPos = maskset.validPositions[sndx];
// if (validPos) {
// validPos.generatedInput = true;
// }
// }
2025-09-24 06:24:52 +00:00
}
}
2025-10-03 11:00:05 +00:00
if ( writeOut ) {
writeBuffer . call (
2025-09-24 06:24:52 +00:00
inputmask ,
2025-10-03 11:00:05 +00:00
input ,
getBuffer . call ( inputmask ) , result ? result . forwardPosition : inputmask . caretPos . begin ,
initiatingEvent || new $ . Event ( "checkval" ) ,
initiatingEvent && ( ( initiatingEvent . type === "input" && inputmask . undoValue !== getBuffer . call ( inputmask ) . join ( "" ) ) || initiatingEvent . type === "paste" ) ) ;
// for (var vndx in maskset.validPositions) {
// if (maskset.validPositions[vndx].match.generated !== true) { //only remove non forced generated
// delete maskset.validPositions[vndx].generatedInput; //clear generated markings ~ consider initializing with a value as fully typed
// }
// }
2025-09-24 06:24:52 +00:00
}
2025-10-03 11:00:05 +00:00
opts . skipOptionalPartCharacter = skipOptionalPartCharacter ;
2025-09-24 06:24:52 +00:00
}
function HandleNativePlaceholder ( npt , value ) {
2025-10-03 11:00:05 +00:00
const inputmask = npt ? npt . inputmask : this ;
if ( ie ) {
if ( npt . inputmask . _valueGet ( ) !== value && ( npt . placeholder !== value || npt . placeholder === "" ) ) {
var buffer = getBuffer . call ( inputmask ) . slice ( ) ,
nptValue = npt . inputmask . _valueGet ( ) ;
if ( nptValue !== value ) {
var lvp = getLastValidPosition . call ( inputmask ) ;
if ( lvp === - 1 && nptValue === getBufferTemplate . call ( inputmask ) . join ( "" ) ) {
buffer = [ ] ;
} else if ( lvp !== - 1 ) { //clearout optional tail of the mask
clearOptionalTail . call ( inputmask , buffer ) ;
}
writeBuffer ( npt , buffer ) ;
}
2025-09-24 06:24:52 +00:00
}
2025-10-03 11:00:05 +00:00
} else if ( npt . placeholder !== value ) {
npt . placeholder = value ;
if ( npt . placeholder === "" ) npt . removeAttribute ( "placeholder" ) ;
2025-09-24 06:24:52 +00:00
}
}
function unmaskedvalue ( input ) {
2025-10-03 11:00:05 +00:00
const inputmask = input ? input . inputmask : this ,
opts = inputmask . opts ,
maskset = inputmask . maskset ;
2025-09-24 06:24:52 +00:00
2025-10-03 11:00:05 +00:00
if ( input ) {
if ( input . inputmask === undefined ) {
return input . value ;
}
if ( input . inputmask && input . inputmask . refreshValue ) { //forced refresh from the value form.reset
applyInputValue ( input , input . inputmask . _valueGet ( true ) ) ;
}
2025-09-24 06:24:52 +00:00
}
2025-10-03 11:00:05 +00:00
var umValue = [ ] ,
vps = maskset . validPositions ;
for ( let pndx = 0 , vpl = vps . length ; pndx < vpl ; pndx ++ ) {
if ( vps [ pndx ] && vps [ pndx ] . match && ( vps [ pndx ] . match . static != true || ( Array . isArray ( maskset . metadata ) && vps [ pndx ] . generatedInput !== true ) ) ) {
//only include generated input with multiple masks (check on metadata)
umValue . push ( vps [ pndx ] . input ) ;
}
2025-09-24 06:24:52 +00:00
}
2025-10-03 11:00:05 +00:00
var unmaskedValue = umValue . length === 0 ? "" : ( inputmask . isRTL ? umValue . reverse ( ) : umValue ) . join ( "" ) ;
if ( typeof opts . onUnMask === "function" ) {
var bufferValue = ( inputmask . isRTL ? getBuffer . call ( inputmask ) . slice ( ) . reverse ( ) : getBuffer . call ( inputmask ) ) . join ( "" ) ;
unmaskedValue = opts . onUnMask . call ( inputmask , bufferValue , unmaskedValue , opts ) ;
2025-09-24 06:24:52 +00:00
}
2025-10-03 11:00:05 +00:00
return unmaskedValue ;
2025-09-24 06:24:52 +00:00
}
function writeBuffer ( input , buffer , caretPos , event , triggerEvents ) {
2025-10-03 11:00:05 +00:00
const inputmask = input ? input . inputmask : this ,
opts = inputmask . opts ,
$ = inputmask . dependencyLib ;
2025-09-24 06:24:52 +00:00
2025-10-03 11:00:05 +00:00
if ( event && typeof opts . onBeforeWrite === "function" ) {
// buffer = buffer.slice(); //prevent uncontrolled manipulation of the internal buffer
var result = opts . onBeforeWrite . call ( inputmask , event , buffer , caretPos , opts ) ;
if ( result ) {
if ( result . refreshFromBuffer ) {
var refresh = result . refreshFromBuffer ;
refreshFromBuffer . call ( inputmask , refresh === true ? refresh : refresh . start , refresh . end , result . buffer || buffer ) ;
buffer = getBuffer . call ( inputmask , true ) ;
}
if ( caretPos !== undefined ) caretPos = result . caret !== undefined ? result . caret : caretPos ;
}
2025-09-24 06:24:52 +00:00
}
2025-10-03 11:00:05 +00:00
if ( input !== undefined ) {
input . inputmask . _valueSet ( buffer . join ( "" ) ) ;
if ( caretPos !== undefined && ( event === undefined || event . type !== "blur" ) ) {
// console.log(caretPos);
caret . call ( inputmask , input , caretPos , undefined , undefined , ( event !== undefined && event . type === "keydown" && ( event . key === keys . Delete || event . key === keys . Backspace ) ) ) ;
}
if ( triggerEvents === true ) {
var $input = $ ( input ) , nptVal = input . inputmask . _valueGet ( ) ;
input . inputmask . skipInputEvent = true ;
$input . trigger ( "input" ) ;
setTimeout ( function ( ) { //timeout needed for IE
if ( nptVal === getBufferTemplate . call ( inputmask ) . join ( "" ) ) {
$input . trigger ( "cleared" ) ;
} else if ( isComplete . call ( inputmask , buffer ) === true ) {
$input . trigger ( "complete" ) ;
}
} , 0 ) ;
2025-09-24 06:24:52 +00:00
}
}
}