繁体   English   中英

Javascript keydown 事件没有给我 EDGE 中的字符 @

[英]Javascript keydown event doesn´t give me the char @ in EDGE

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

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

主机监听器

  @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()

基本上是要显示的提到选项列表,当且仅当用户按下@即触发CHAR( 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();
        }
      }
    }
  }

现在这里的问题是,如果用户插入字符@需要使用ALT + Q EDGE 的组合仅检测ALT然后Q ,与ALT + Q组合检测@ firefox 和 chrome 相比,出于这个原因列表不显示,因为字符永远不匹配。

首先,我将事件keydown替换为keypress ,然后将字符保存在变量charPress我创建一个条件来检查浏览器是 EDGE 还是 IE,并使用event.charCode获取字符代码并使用String.fromCharCode(event.charCode)将其转换为字符串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);
    }
    ......

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM