keydown event new value

2020-02-09 09:25发布

问题:

Browser: Google Chrome V19.0.1084.52

I have a textbox which needs to be a number less than or equal to 255, on keydown I want to check if this value is above or equal to 255 else prevent the event.

In the Console when I console.log the event it will show event.srcElement.value as the value will appear i.e. from 12 => 123, when I console.log just event.srcElement.value it will show as the input was, not will be.

Console.log's are happening one after the other, nothing in between, no pauses.

How can I find what the new value of a textbox will be on keydown and why is the console.log returning different results?

Here's my code:

function inputNumeric(event,max) {

    console.log (event);
    console.log ('event.originalEvent.srcElement.value: '+event.originalEvent.srcElement.value);
    console.log ('event.srcElement.value: '+event.srcElement.value);

}

$("#rs485addr").keydown(function(event) {
    inputNumeric(event);
});

Console.log:

event.originalEvent.srcElement.value: 12
event.srcElement.value: 12

event.srcElement:

accept: ""
accessKey: ""
align: ""
alt: ""
attributes: NamedNodeMap
autocomplete: ""
autofocus: false
baseURI: "http://10.50.50.60/controller/?bid=10"
checked: false
childElementCount: 0
childNodes: NodeList[0]
children: HTMLCollection[0]
classList: DOMTokenList
className: "width-60"
clientHeight: 18
clientLeft: 2
clientTop: 2
clientWidth: 62
contentEditable: "inherit"
dataset: DOMStringMap
defaultChecked: false
defaultValue: "1"
dir: ""
dirName: ""
disabled: false
draggable: false
files: null
firstChild: null
firstElementChild: null
form: null
formAction: ""
formEnctype: "application/x-www-form-urlencoded"
formMethod: "get"
formNoValidate: false
formTarget: ""
hidden: false
id: "rs485addr"
incremental: false
indeterminate: false
innerHTML: ""
innerText: ""
isContentEditable: false
jQuery17102950612970162183: 22
labels: NodeList[1]
lang: ""
lastChild: null
lastElementChild: null
localName: "input"
max: ""
maxLength: 3
min: ""
multiple: false
name: ""
namespaceURI: "http://www.w3.org/1999/xhtml"
nextElementSibling: null
nextSibling: Text
nodeName: "INPUT"
nodeType: 1
nodeValue: null
offsetHeight: 22
offsetLeft: 183
offsetParent: HTMLBodyElement
offsetTop: 365
offsetWidth: 66
onabort: null
onbeforecopy: null
onbeforecut: null
onbeforepaste: null
onblur: null
onchange: null
onclick: null
oncontextmenu: null
oncopy: null
oncut: null
ondblclick: null
ondrag: null
ondragend: null
ondragenter: null
ondragleave: null
ondragover: null
ondragstart: null
ondrop: null
onerror: null
onfocus: null
oninput: null
oninvalid: null
onkeydown: null
onkeypress: null
onkeyup: null
onload: null
onmousedown: null
onmousemove: null
onmouseout: null
onmouseover: null
onmouseup: null
onmousewheel: null
onpaste: null
onreset: null
onscroll: null
onsearch: null
onselect: null
onselectstart: null
onsubmit: null
onwebkitfullscreenchange: null
onwebkitfullscreenerror: null
onwebkitspeechchange: null
outerHTML: "<input class="width-60" id="rs485addr" maxlength="3" type="textbox" value="1">"
outerText: ""
ownerDocument: HTMLDocument
parentElement: HTMLSpanElement
parentNode: HTMLSpanElement
pattern: ""
placeholder: ""
prefix: null
previousElementSibling: HTMLLabelElement
previousSibling: Text
readOnly: false
required: false
scrollHeight: 16
scrollLeft: 0
scrollTop: 0
scrollWidth: 60
selectionDirection: "forward"
selectionEnd: 3
selectionStart: 3
size: 20
spellcheck: true
src: ""
step: ""
style: CSSStyleDeclaration
tabIndex: 0
tagName: "INPUT"
textContent: ""
title: ""
translate: true
type: "text"
useMap: ""
validationMessage: ""
validity: ValidityState
value: "123"
valueAsDate: null
valueAsNumber: NaN
webkitGrammar: false
webkitRegionOverflow: "undefined"
webkitSpeech: false
webkitdirectory: false
webkitdropzone: ""
willValidate: true

回答1:

I'm not sure if it could be of any help, but when I had to deal with a similar situation in an event listener I used a setTimeout() with 1ms timeout where I put the main functionality checking for the value, etc.

That is because when the keydown event is fired the input field is not yet populated with the new data.

Simple jQuery example:

$('#input').on('keydown', function(e) {
  var field = $(this);
  var prevValue = field.val();
  setTimeout(function() {
    // check if new value is more or equal to 255
    if (field.val() >= 255) {
      // fill with previous value
      field.val(prevValue);
    }

  }, 1);
});

UPDATE

Use 'input' event in modern browsers.

var prevValue = 0;
$('#input').on('input', function(e) {
  var field = $(this);
  // check if new value is more or equal to 255
  if (field.val() >= 255) {
    // fill with previous value
    field.val(prevValue);
  } else {
    // If value is lower than 255 set it in prev value.
    prevValue = field.val();
  }
});


回答2:

You should not use keydown but keypress. Then you will receive the actual character code of the char to-be-typed.

See keypress, keydown, keyup value of input box AFTER event, http://www.quirksmode.org/dom/events/keys.html and especially http://www.quirksmode.org/js/keys.html.

inputElement.addEventListener("keypress", function(e) {
     var curval = e.srcElement.value;
     var newchar = String.fromCharCode(e.charCode || e.keyCode);
     if (/* condition */)
         e.preventDefault();
}, false);

If you just want to get the input value after something is typed, you need to use the keyup event.



回答3:

The only thing I can come up with is that the srcElement Object that is outputted in the console is still linked to the event Object, even after the keydown Event so that the Object in the console is updated from 12 to 123 even when already in the console.

It doesn't happen with the direct output of event.srcElement.value because that is a literal value and is copied on logging, not referenced...

If you would be real fast you could check if you could see it change in the Console from 12 to 123 ;-)



回答4:

Adding on @Bergi's comment here, so as to include text selections and caret position, you can do it as follows:

inputElement.addEventListener("keypress", (event) => {
    let curval = event.srcElement.value;
    let newchar = String.fromCharCode(event.charCode || event.keyCode);
    let curval_arr = curval.split("");
    curval_arr.splice(event.target.selectionStart, (event.target.selectionEnd - event.target.selectionStart), newchar);
    let newval = curval_arr.join("");

    //TODO: your logic here with "newval" containing the value to be.
    //console.log(curval, newchar, newval);
    //event.preventDefault();
}, false);