今天來看 Keyboard module 的章節。

Keyboard module 支援特定 context 中鍵盤事件的自訂行為。Quill 使用 Keyboard module 來綁定格式化快捷鍵並防止一些瀏覽器副作用。

Key Bindings

Keyboard handler 綁訂到特定的按鍵與修飾鍵。key 是 JavaScript event 的 key code,但也允許英文字母與數字鍵,以及常用的按鍵的字串縮寫設定。常見的修飾鍵例如:metaKeyctrlshift,以及 alt 等。另外 shortKey 是指特定平台的修飾鍵,像是 MacOS 上的 metaKey,以及 Linux 和 Windows 上的 ctrlKey

我們可以將指定的按鍵和修飾鍵綁定到一個 handler。當這個鍵被按下時,handler 就會被執行,並將使用者選擇的範圍傳入以及綁定到 keyboard module 當下的 instance:

quill.keyboard.addBinding({
  key: 'B',
  shortKey: true
}, function(range, context) {
  quill.formatText(range, 'bold', true);
});

// addBinding 也能只帶入一個參數,並加上 handler
quill.keyboard.addBinding({
  key: 'B',
  shortKey: true,
  handler: function(range, context) {
    quill.formatText(range, 'bold', true);
  }
});

這個範例是當使用者按下 B 鍵加上修飾鍵(Mac 上的 metaKey 或 Windows 和 Linux 上的 ctrlKey)時,選取的文字會變粗體。

Context

我們還可以設定更多的條件,讓 handler 只在特定的情境下被呼叫。例如,當使用者選擇的是一個空行或者是列表項目時,才會觸發相對應的 handler:

// 如果使用者在 list 或 blockquote 的開頭按了 ctrl + d,
// 則刪除 list 或 blockquote 的格式

quill.keyboard.addBinding(
  { key: 'd', shortKey: true },
  {
    collapsed: false,
    format: ['blockquote', 'list'],
    offset: 0,
  },
  function (range, context) {
    console.log('backspace pressed');
    if (context.format.list) {
      quill.format('list', false);
    } else {
      quill.format('blockquote', false);
    }
  }
);

不過需要注意的地方是,當編輯器初始化之後才加入的 keyboard binding,需要確認內建的部分是否也有監聽,否則會因為按鍵事件發生時逐條比對條件的關係,就被前面的規則代為執行了。例如 backspacekeycode8
被前面的規則代為執行

Context 的參數

collapsed

如果為 true 則當使用者的游標停在編輯器上,在沒有選擇任何文字的情況下觸發 handler。collapsed 翻成中文是收折的意思,但實際上就是指游標停在編輯器上並沒有選取任何文字的狀態。

empty

如果為 true,當使用者的游標在一行空白的時候會觸發。設為 false 則代表非空行,另外當 emptytrue 時,意思就是 collapsed 也要是 true,且 offset 必須是 0,這樣才是真正完全的一行空白。
例如當使用者換行的時候加上一個星星符號:

quill.keyboard.addBinding({ key: 'enter' }, {
  empty: true  // 只在空行觸發
}, function(range, context) {
  // 插入特殊符號的代碼
  this.editor.insertText(range.index, '★');
});

format

format 這個參數用來控制 handler 在哪些特定的格式條件下會被觸發。

  • format 是一個陣列時,如果當前活動(active)的格式中包含陣列裡面指定的任何一種格式,則會觸發 handler:
quill.keyboard.addBinding({ key: Keyboard.keys.ENTER }, {
  format: ['bold', 'italic'] // 只要文字是粗體或斜體,處理函數就會觸發
}, function(range, context) {
  // 插入特殊符號的代碼
  this.editor.insertText(range.index, '★');
});
  • format 是一個物件:所有指定的格式條件必須全部滿足,handler 才會觸發。
quill.keyboard.addBinding({ key: Keyboard.keys.ENTER }, {
  format: {
    bold: true,
    italic: true
  } // 當文字是粗體且斜體,處理函數才會觸發
}, function(range, context) {
  // 插入特殊符號的代碼
  this.editor.insertText(range.index, '★');
});

在任何情況下,context 參數的 format 屬性都會是一個物件,其中包含了所有當前活動的格式。這個物件的結構和 quill.getFormat() 回傳的結構是相同的。

小結

今天研究了 Quill 的 keyboard module,並了解如何加入自訂的 keyboard binding,也看到 context 的內容有哪些可以讓我們運用,明天接著看 context 其他的參數介紹。

雜記

今天下班前,不小心把弄了一陣子的 Git stash 給 drop 掉了,然後又因為是在 Git Graph 上執行,所以也沒有留意到 hash 的部分,當下真的有 BBQ 的感覺,不死心的我花了一點時間研究,總算找到解法,第一次使用 git fsck,搭配 sh 腳本執行,把碎片找回來從裡面去翻之前改過的程式片段,找到後來改的內容,趕快把 hash 記下來,接著 apply,逝去的青春終於又回來了(誤。這故事給了我一個教訓,以後還是乖乖建 commit 吧…Orz

Reference

文章同步發表於2023 iThome 鐵人賽