連假的第一天,今天繼續看 Keyboard module 的 context 剩下的參數以及設定相關的介紹。

offset

當使用者的游標從開始移動到 offset 指定的特定的位置則觸發 handler,例如:當 offset3 時,只有使用者選擇的文字或是游標是在同一行的第三個字元位置開始,才會執行對應的 handler。另外執行的時機點是在使用者輸入內容的時候就已經判定的,因此使用者如果在第 3 個字元時按下按鍵輸入文字,則 handler 會在文字輸入之前就被執行。

quill.keyboard.addBinding(
  { key: 'o' },
  { offset: 2 }, // 當游標在第3個字元前面時觸發
  (range, context) => {
    // 插入特殊符號的代碼
    quill.insertText(range.index, '★★★');
  }
);

prefix

一個正則表達式(Regex)屬性,用於指定必須與使用者選擇的區域或游標開始位置之前的文字比對的模式。換句話說,當該正則表達式匹配到使用者選擇開始位置前方的文字時,相關的處理函數(handler)才會被觸發。例如,當使用者輸入一個 @ 符號,然後按下 k 時,這個 handler 會被觸發。prefix: /@$/ 確保了只有當游標(或選取範圍)前方是 @ 符號時,這個 handler 才會執行:

quill.keyboard.addBinding({ key: 'k' }, {
  prefix: /@$/, // 前置文本必須是 @
}, (range, context) => {
  // 這裡實現你的自定義邏輯,例如彈出一個用戶列表以供選擇
  console.log("觸發了 @ 符號的自定義行為");
});

context.prefix 在這個例子中會是 @,因為它包含了選擇開始位置之前的整個文字區塊。如此一來,我們就可以在使用者輸入 @ 符號後進行特定操作,像是顯示一個下拉清單讓使用者選擇名稱。

suffix

prefix 的概念相同,只是比對的位置是使用者選擇的內容或游標的位置的後面開始。

配置

預設的情況下,Quill 內建幾個實用的按鍵綁定,例如使用 Tab 鍵進行縮排。我們可以在初始化時加入自訂的按鍵綁定。

有些綁定對於防止瀏覽器的危險預設行為(如 Enter 鍵和 Backspace 鍵)是必要的。不能移除這些綁定以恢復到瀏覽器的原生行為。然而,由於在配置中指定的綁定會在 Quill 的預設綁定之前運行,您可以處理特殊情況並將其傳播給 Quill。

使用 quill.keyboard.addBinding 加入綁定不會在 Quill 的預設綁定之前運行,因為到那時預設綁定已經被加入。

每個綁定配置必須包含鍵(key)和處理器(handler)選項,並且可以選擇性地包括任何 context 選項。

const bindings = {
  // 這將覆蓋名為 'tab' 的預設綁定
  tab: {
    key: 9,
    handler: function() {
      // 處理 Tab 鍵
    }
  },

  // 沒有名為 'custom' 的預設綁定,
  // 因此這將會被新增,而不會覆蓋任何內容
  custom: {
    key: 'B',
    shiftKey: true,
    handler: (range, context) => {
      // 處理 Shift + B
    }
  },

  // 當按 Backspace 鍵並且格式為 list 時
  list: {
    key: 'backspace',
    format: ['list'],
    handler: (range, context) => {
      if (context.offset === 0) {
        // 若在 list 的第一個字元上按 Backspace,
        // 則移除該列表
        this.quill.format('list', false, Quill.sources.USER);
      } else {
        // 否則,傳給 Quill 做預設處理
        return true;
      }
    }
  }
};

// 初始化 Quill,並指定 keyboard module 的綁定
var quill = new Quill('#editor', {
  modules: {
    keyboard: {
      bindings: bindings
    }
  }
});

性能考量

和 DOM event 相同,Quill key binding 在每次比對時都會阻擋呼叫,因此為一個非常普通的按鍵綁定一個複雜的 handler 不是一個好的實現方式。在套用像是滑鼠移動或卷軸滾動的 DOM 事件時,盡可能的套用性能較好的實現以確保一定品質的使用者體驗。

小結

這兩天探討了 Quill 的 Keyboard module,讓我們可以自定義鍵盤事件的處理。Quill 的 keyboard module 主要有兩種用途:

  1. 綁定格式化快捷鍵:比如 “Ctrl + B” 可以讓選中的文字變粗。
  2. 防止瀏覽器的一些預設行為:這樣可以確保應用程式的穩定性與使用者體驗。

我們也了解如何使用不同的 context 參數來更精細的控制 handler 的觸發時機,包含游標的位置、目前使用中的格式、以及前後緊鄰的文本內容等。

此外,keyboard module 也提供了豐富的設定選項,讓我們可以在初始化時加入自訂的綁定,或是覆蓋Quill 的預設綁定。

雜記

今天午餐後整理一下文章,晚一點就要出發去載朋友來宜蘭玩了,希望不要塞車塞得太嚴中 XD。昨天看了同事的分享會 Feedback,看到很多有趣的回應。其中還有提到下班後學習這件事,我認為學習是屬於個人的事情,至於有沒有要求下班後學習這件事,最終決定權還是在自己手上。若真的有興趣的而且學到之後能讓自己在上班的過程更順暢也能克服一些挑戰,我想這個學習過程應該是相當精彩的,儘管最後發現也許是個坑,但這都是成長的一部分。

Reference

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