I'm facing this bug with jQuery maskedinput.
Pasting a value on an masked input triggers the completed event twice. This behavior can be seen on their oficial website.
Open this link and click on Demo
.
Select Product Key
input and type aa-999-a999
.
After that, try to paste the same value in the field.
There are some other issues related to NOT triggering the event on paste, but none of them helped me with this bug...
Dows anyone know why or had a similar problem?
Thanks in advance.
So I've tried a simplest case like this (using this for maskedinput.js
, though note that I edit it, below, and this for jquery-1.11.2.js
):
<html>
<body>
<script type="text/javascript" src="./jquery-1.11.2.js"></script>
<script type="text/javascript" src="./jquery.maskedinput.js"></script>
<script type="text/javascript">
jQuery(function($) {
$.mask.definitions['~']='[+-]';
$("#tin").mask("99-9999999",{completed:function(){alert("Now you typed: "+this.val());}});
});
</script>
<table border="0">
<tbody>
<tr>
<td>Tax ID</td>
<td><input type="text" tabindex="5" id="tin"></td>
<td>99-9999999</td>
</tr>
</tbody>
</table>
</body>
</html>
And I edited the maskedinput source a bit to see when and from where stuff fires. I'll paste.ee it here, but here are the main parts...
.on("blur.mask")...
lineblur
, keydown
, input
, and paste
. console.log
to tell you what specific event is firing each time to debug pasting.Here's what I did (note that if you're using IE8-, you need to "protect" the console.log
call or run it with Dev Tools open):
}).on("blur.mask", blurEvent).on("keydown.mask", keydownEvent).on("keypress.mask", keypressEvent).on("input.mask", function() {
console.log("mask called: " + arguments[0].type); // <<< New debugging line.
input.prop("readonly") || setTimeout(function() {
var pos = checkVal(!0);
input.caret(pos);
tryFireCompleted("mask");
}, 0);
}), chrome && android && input.off("input.mask").on("input.mask", androidInputEvent),
When you paste stuff in, two event handlers are called for the "same" action.
mask called: paste
mask called: input
Those both eventually call tryFireCompleted
, which fires off the .completed
function we set up in this line of our own code, above:
$("#tin").mask("99-9999999",{completed:function(){alert("Now you typed: "+this.val());}});
If you remove the paste.mask
event handler, that problem will go away. Here's the crucial part:
.on("input.mask paste.mask",
... changes into...
.on("input.mask",
... so paste.mask
is gone. (And before releasing to production, remove the console.log
line, of course.)
Now that might work all by itself. Pastes were firing off input
, so having paste
too might be overkill. But I'd check around more before I used that as a permanent fix. I did try right-clicking a paste with the mouse, which was fine with this change. Not sure when paste
is fired and input
isn't.
If there is an edge case where paste
is called and input
isn't (or a case where you really would want tryFireCompleted
to fire twice), you'll need to find a way to suppress the second tryFireCompleted
with more convoluted code.
Without a completed
function, though, firing off twice wouldn't be an obvious problem, I don't think, which explains why this might have slipped through. Good find.