Javascript按键事件没有给我在EDGE中的char @

时间:2019-03-22 08:46:38

标签: javascript angular typescript

我正在使用提及指令,基本上,当用户在输入字段中键入时(在这种情况下为contentEditable=true的div),它将显示用户列表,然后插入用户名用户使用特定格式,现在将在用户按下@之后显示该列表,因为chrome和firefox的工作非常好,但是对于EDGE和IE(不幸的是,我需要支持)不起作用,因为在这种情况下@显然不存在。

现在按键,我正在使用@HostListener('keydown', ['$event'])

HostListener

  @HostListener('keydown', ['$event']) keyHandler(event: any, nativeElement: HTMLInputElement = this._element.nativeElement) {
    let val: string = getValue(nativeElement);
    let pos = getCaretPosition(nativeElement, this.iframe);
    let charPressed = this.keyCodeSpecified ? event.keyCode : event.key;
    if (!charPressed) {
      let charCode = event.which || event.keyCode;
      if (!event.shiftKey && (charCode >= 65 && charCode <= 90)) {
        charPressed = String.fromCharCode(charCode + 32);
      } else if (event.shiftKey && charCode === KEY_2) {
        charPressed = this.triggerChar;
      } else {
        charPressed = String.fromCharCode(event.which || event.keyCode);
      }
    }
    if (event.keyCode == KEY_ENTER && event.wasClick && pos < this.startPos) {
      // put caret back in position prior to contenteditable menu click
      pos = this.startNode.length;
      setCaretPosition(this.startNode, pos, this.iframe);
    }
    // console.log('=== keyHandler', this.startPos, pos, val, charPressed, event);
    this.triggerList(event, charPressed, nativeElement, val, pos);
  }

现在您可以看到我正在使用event.keycodeevent.key从事件keydown中获取密钥,我将值传递给方法this.triggerList()

基本上并且仅当用户按下作为触发字符(@的{​​{1}}时,才会显示提及选项列表。

TriggerList方法

this.triggerChar

现在的问题是,如果要插入字符 private triggerList(event, charPressed, nativeElement, val, pos): any { if (charPressed == this.triggerChar) { this.startPos = pos; this.startNode = (this.iframe ? this.iframe.contentWindow.getSelection() : window.getSelection()).anchorNode; // console.log('=== HERE CHAR', this.startNode, this.startPos); // check if mentioning is allowed based on the text before the mention start char if (!this.configService.appConfig.platform.EDGE) { let position = this.getHtmlCaretPosition(nativeElement); const charBefore = val[position - 1]; if (charBefore == undefined || charBefore.trim() == '' || charBefore == ':') { this.log.trace('Start mentioning'); this.stopSearch = false; this.searchString = null; this.showSearchList(nativeElement); this.updateSearchList(); } } else { this.stopSearch = false; this.searchString = null; this.showSearchList(nativeElement); this.updateSearchList(); } } else if (this.startPos >= 0 && !this.stopSearch) { if (pos <= this.startPos) { this.searchList.hidden = true; } // ignore shift when pressed alone, but not when used with another key else if (event.keyCode !== KEY_SHIFT && !event.metaKey && !event.altKey && !event.ctrlKey && pos > this.startPos) { if (event.keyCode === KEY_SPACE) { this.startPos = -1; } else if (event.keyCode === KEY_BACKSPACE && pos > 0) { pos--; if (pos == 0) { this.stopSearch = true; } this.searchList.hidden = this.stopSearch; } else if (!this.searchList.hidden) { if (event.keyCode === KEY_TAB || event.keyCode === KEY_ENTER) { this.stopEvent(event); this.searchList.hidden = true; // value is inserted without a trailing space for consistency // between element types (div and iframe do not preserve the space) let textValue = this.mentionSelect(this.searchList.activeItem); insertValue(nativeElement, this.startPos, pos, textValue, this.iframe); this.emitSelection(nativeElement); if (this.htmlStyling) { let quillElement = document.querySelector('.ql-editor'); let innerHtml = quillElement.innerHTML; let strings = innerHtml.split(textValue); if (strings.length === 2) { innerHtml = `${strings[0]}<span id="mention${textValue.substring(1)}${strings.length - 1}" style="color: #0065FF; background: rgba(0,101,255,.2)">${textValue}</span> ${strings[1]}`; } else { let openSpan = false; innerHtml = strings.reduce((total, current, currentIndex) => { if (current.indexOf(`mention${textValue.substring(1)}`) > 0) { return `${total}${openSpan ? '</span> ' : ''}${current}${textValue}`; } else if (openSpan) { return `${total}</span> ${currentIndex < strings.length - 1 ? current + textValue : current}`; } else { openSpan = true; return `${total}${current}<span id="mention${textValue.substring(1)}${strings.length - 1}" style="color: #0065FF; background: rgba(0,101,255,.2)">${textValue}`; } }, ''); } quillElement.innerHTML = innerHtml; // tslint:disable-next-line:no-angle-bracket-type-assertion let mentionElement: HTMLInputElement = document.getElementById(`mention${textValue.substring(1)}${strings.length - 1}`) as HTMLInputElement; // tslint:disable-next-line:no-angle-bracket-type-assertion setCaretPosition(mentionElement.nextSibling as HTMLInputElement, 1); } // fire input event so angular bindings are updated if ('createEvent' in document) { let evt = document.createEvent('HTMLEvents'); evt.initEvent('input', false, true); nativeElement.dispatchEvent(evt); } this.startPos = -1; return false; } else if (event.keyCode === KEY_ESCAPE) { this.stopEvent(event); this.searchList.hidden = true; this.stopSearch = true; return false; } else if (event.keyCode === KEY_DOWN) { this.stopEvent(event); this.searchList.activateNextItem(); return false; } else if (event.keyCode === KEY_UP) { this.stopEvent(event); this.searchList.activatePreviousItem(); return false; } } if (event.keyCode === KEY_LEFT || event.keyCode === KEY_RIGHT) { this.stopEvent(event); return false; } else { let mention = val.substring(this.startPos + 1, pos); if (event.keyCode !== KEY_BACKSPACE) { mention += charPressed; } this.searchString = mention; this.searchTerm.emit(this.searchString); this.updateSearchList(); } } } } 的用户需要使用@的组合,则EDGE只会先检测ALT + Q,然后检测ALT,结合使用Q的firefox和chrome,因此检测到ALT + Q的原因是列表不显示,因为字符从不匹配。

1 个答案:

答案 0 :(得分:0)

首先,我将事件keydown替换为keypress,然后将字符保存在变量charPress中,我创建了一个条件来检查浏览器是EDGE还是IE,并获取使用event.charCode的char代码,最后使用String.fromCharCode(event.charCode)将其转换成字符串。

  @HostListener('keypress', ['$event']) keyHandler(event: any, nativeElement: HTMLInputElement = this._element.nativeElement) {
    let val: string = getValue(nativeElement);
    let pos = getCaretPosition(nativeElement, this.iframe);
    let charPressed = this.keyCodeSpecified ? event.keyCode : event.key;
    if (this.configService.appConfig.platform.EDGE) {
      charPressed = String.fromCharCode(event.charCode);
    }
    ......