鳥部製作所 廚房剪刀

九洲

最近在研究九州行程,然後去翻以前去過的照片,看到十年前(2015)年時去九州順便從 Amazon 買的:鳥部製作所的廚房剪刀,這隻剪刀其實我現在還在用,品質很好,以前好像推薦過一次,現在十週年了值得再推薦一次,也順便又研究了一下現在到底該怎樣買。

鳥部製作所其實是以金屬加工出名的燕三条地方的工廠之一,產品品項不多,其中這隻廚房剪刀一直以來評價都很高,設計簡單俐落,而我當初挑選的條件其中一個就是要可以拆開來清洗,然後加上看起來很好看,就買下去了,結果真的不負期待,品質極佳,用到現在十年過去也沒感覺到有什麼老化跡象,當然,我每次使用後都會拆開清潔。

現在鳥部製作所網站上的定價雖然是寫 ¥5500,不過在 Amazon 上是找不到這個價位的(在樂天也是),不確定是產地價和通路價差異,還是這兩年貨幣貶值加上通膨已經調價了但是網站沒更新,然後現在在 Amazon JP 上找到我判斷比較可靠的有兩個:

第一個賣 ¥7700 是標準版本,第二個賣 ¥8800 則是拋光過變亮面的版本,兩個賣家不一樣,第一個是村の鍛冶屋、第二個則是 NAGAO,兩家都是燕三条地方的公司經營的,看起來商譽都還 ok,至於我十年前買的時候,應該是 Amazon 自己的貨的樣子,價格則只有兩千多日圓,後悔當時沒多買幾把啊 🥲。

鳥部製作所廚房剪刀 價格歷史走勢

九洲



InnoDB 修復紀錄

前兩天意外發現 blog 的資料庫(MariaDB)死掉起不來了,加上我剛好沒有新的備份,所以這兩天就花了些時間慢慢修復,總之首先,我根據一開始的錯誤訊息大概搜尋了一下,發現說可以把/var/lib/mysql目錄下的ibdata1ib_logfile0ib_logfile1aria_log_control等檔案砍掉試試看(當時完全不知道是什麼),於是我簡單備份後就砍掉重啟試試看,結果 MariaDB 真的就復活了,只是我接著要跑mysqldump時就出現其他的錯誤:

mariadb-dump: Got error: 1932: "Table 'blog.mt_asset' doesn't exist in engine" when using LOCK TABLES

而且因為我的 shell script 太簡單,沒檢查結果,這錯誤還把我的本地備份覆蓋掉了😂,總之搜尋研究一陣子之後,發現這問題是因為mt_asset資料表是用 InnoDB,然後 InnoDB 有些資訊是集中在ibdata1的,不能只靠資料庫目錄下的mt_asset.*檔案來還原,結果我的作法就是把備份的ibdata1還原回來,試著在my.cnf裡加上:

[mysql]
innodb_force_recovery = 1

如果用 service 的話就要放到[mysqld]區段內,數值從1試到6,然後 su 到mysql這個帳號下手動執行mariadbd指令來啟動資料庫,其實第一次嘗試是失敗的,到第二次試到6時才成功,然後趕快跑mysqldump,結果有成功跑完,不過因為之前mt_asset有出過錯誤,我就認真檢查了一下 dump 出來的資料,結果果然,mt_asset只有結構沒有資料,於是又檢查其它的 InnoDB 資料表的 dump 的輸出,結果是有的有資料有的沒有,不過由於資料本身應該還在,所以我接著嘗試用mariadb命令列模式進去 DB 手動 SELECTmt_asset的資料,發現真的都還在,不知道為何 dump 會失敗,不過總之我就試試看死馬當活馬醫,用 mysqldump 匯出單一個資料表的資料:

mariadb-dump -u user_name -p db_name mt_asset > blog.mt_asset.sql

結果,竟然成功匯出了,於是就手工把每個有問題的 InnoDB 匯出,然後手工整合回去全資料庫的 dump 出來的 sql 檔案,有些資料表還是沒資料,不確定是不是本來就沒有的,不過看起來也不是重要資料,不影響 MovableType 運作,所以就不管。

然後因為我好像用不太到 InnoDB 的優點,加上發生過一次這種事情,冷備份比較簡單的 MyISAM 還是比較適合我,就順手都改成 MyISAM 資料表;同時,又想到因為我的 CHARSET 還是用 utf8,所以一直都還不能用 emoji,之前也有想過要換到 utf8mb4,只是一直沒動手,就趁機一起手工改了mt_entry表下的幾個相關的欄位:

`entry_title` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`entry_excerpt` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`entry_text` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`entry_text_more` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL,

這樣大致上就把 sql 檔案準備好了,回到這次發生問題的原因,我推測是用 pacman 更新套件時,更新到 MariaDB 後,不知道為何造成ibdata1檔案損毀,一開始的錯誤訊息試有看到說某個檔案是 MariaDB 10.4.8 建立的,所以我是先退回 10.4.8 然後才進行上述的修正,還好上次已經操作過一次了,之後為了避免再次有太久沒更新出事,就決定也要把 MariaDB 更新一下,所以其實是先更新最後才把 sql 檔案匯入的。

更新完把/var/lib/mysql目錄下的ibdata1ib_logfile0ib_logfile1都砍掉,重新建立資料庫後才匯入,還好一切順利,詳細的說明其實在 MariaDB 的 Knowledge Base 也都有,最後就補上兩個我覺得很有幫助的文件:

  • Cold Backup: 一樣是 MariaDB 的 Knowledge Base 的官方文件,有提到 InnoDB 要冷備份時要備份哪些檔案;
  • Tag: InnoDB: Error: tablespace id in file: 一篇說明如果這時候要直接還原 InnoDB 資料表的話要怎樣弄,非常麻煩(網站已死,所以是 Internet Archive 的)。

另外補充,如果要在 MovableType 4.x 使用 emoji,除了資料庫欄位的設定外,還需要修改一點程式碼,詳見我的修改紀錄 🥳。


onAutofill

Credit Card autofill

在現在這個網路標準橫行的時代,要遇到還沒廣泛標準化的東西其實是越來越難了,不過我最近還是遇到了一個,那就是 autofill 的偵測。

首先要說的是,autofill(自動填入)和 autocomplete(自動補完)嚴格定義下是不一樣的,雖然都可以透過autocomplete來控制相關的行為,但是 autocomplete 其實只能算是 autofill 的一種,而我遇到的就是非 autocomplete 的,信用卡資料的自動填入,那問題在哪呢?

問題就是這種 autofill 發生時,瀏覽器不一定會觸發change/input事件,如果表單設計成自動檢查表單輸入,然後輸入都正確才讓人送出的話就會有使用體驗的問題發生,因為這種設計的欄位檢查通常就是綁在<input>change/input事件上,結果就是如果瀏覽器自動填入,然後又沒觸發change/input事件,於是就不會執行到欄位檢查,表單也就會一直維持在無法送出的狀態,產生的副作用就是使用者體驗反而比按下送出按鈕才作表單檢查還要來的差。

那麼在 Web 標準中,change事件應該何時觸發的定義是為何呢?在 HTML 4.01 是這樣寫的:

The onchange event occurs when a control loses the input focus and its value has been modified since gaining focus. This attribute applies to the following elements: INPUT, SELECT, and TEXTAREA.

按照古時候網路標準的規範,autofill 不是使用者和 DOM 之間的互動,沒有經過 focus blur,所以沒有觸發 change 事件也是合理,事實上也就是現在部分瀏覽器的行為;不過在現在的 HTML Living Standard 是這樣寫的:

Thechangeevent fires when the value is committed, if that makes sense for the control, or else when the control loses focus.

觸發的時機除了失去 focus 時之外,還多了資料 commit(提交)時,變成兩種時機,而這邊的提交主要指的是像type=color或是type=date那種,瀏覽器有支援,有提供另外頁面內的小工具讓使用者方便挑選值的時候,使用者選好,瀏覽器更新值進入<input>的 value 的動作,那 autofill 更新值該算是 commit 嗎?其實文件內也是有講到的,就在同個章節的後面:

When the user agent is to change an input element's value on behalf of the user (e.g. as part of a form prefilling feature), the user agent must queue an element task on the user interaction task source given the input element to first update the value accordingly, then fire an event namedinputat theinputelement, with thebubblesandcomposedattributes initialized to true, then fire an event namedchangeat theinputelement, with thebubblesattribute initialized to true.

這段就是說當瀏覽器代表使用者改變 input 的值時,也是要發一個 input 一個 change 事件,這段文字的重點在於 "on behalf of the user",就是「代表使用者做事」,後面舉的例是 prefill 時,prefill 通常發生在 帳號/密碼 欄位,發生時間點又不太一樣,可能是在 render DOM 時就發生;不過根據文字解釋其實 autofill 應該也符合 "on behalf of the user"。

雖然 HTML 標準有規範了,但是現實世界總是不會這麼美好,不然也不會有這篇文章了,那麼現實世界是怎樣呢?我遇到的狀況就是有些瀏覽器是照著舊的規範,完全沒有事件,發現問題後我就上網搜尋一番之後發現,這問題其實已經很久了,早在 2010 年,@avernet 就寫了一篇 Autocomplete and JavaScript Change Event,紀錄了當年的這個問題,根據不同欄位、不同瀏覽器會有不同的行為,即使到了今天,也還是同樣情形,文章最後建議的解法也是很無奈的:

  1. 關掉相關功能autocomplete=off
  2. 定時檢查

總之就是讓人不喜歡的解法,那麼時至今日,有沒有比較好的方法呢?其實還真的有,而且蠻聰明的,Klarna 的 Tommy Brunn 在 2016 年寫了 Detecting autofilled fields in Javascript 一文介紹了這種方法,透過 CSS pseudo-class:autofill和 CSS animation 配上animationStart事件,首先 CSS 這樣:

input:autofill {  
  animation-name: autofill;
  animation-duration: 500ms;
  animation-fill-mode: both;
}

@keyframes autofill {
  from {
    background: var(--color1);
  }
  to {
    background: var(--color2);
  }
}

然後 JS 監聽事件並確定動畫名稱沒錯,就可以做事了:

inputNode.addEventListener('animationstart', (event) => {  
  const { currentTarget, animationName } = event;
  
  if (animationName === 'autofill') {
    // do what ever you want, or
    // trigger `change` event
    currentTarget.dispatchEvent(new Event('change'));
    // trigger custom event
    currentTarget.dispatchEvent(new Event('autofill'));
  }  
}, false);

完全成為真的 event based,不用定時檢查了,不過缺點是要 CSS 搭配,不是純 JS 的方案,維護上比較麻煩一些,另外就是 Tommy Brunn 文章內用的是:--webkit-autofill,但是現在完全可以用沒有 prefix 的 pseudo class 了。

以上的程式碼範例就可以處理好瀏覽器內建的自動填入事件,不過現實世界除了瀏覽器內建的自動填入,還有很多的第三方工具支援,像是各種 password manager: 1Password, LastPass, Dashlane 等,這些工具自動填入的行為又不太一樣,我確實有發現有其中一兩家的行為也是 value 會改變,但是不會有 input 和 change 事件,幸好這些工具都會加上各自自訂的 attribute,所以可以另外透過 observer 監看 attribute 的變化來判斷是否有相關的事件,目前我所知道有以下的 attributeName 可以檢查:

  • data-dashlane-autofilledDashlane 的
  • data-com-onepassword-filled1Password 的
  • chrome-autofillediOS Chrome,超容易漏掉

至於 LastPass 目前測試結果是不會有自訂的 attribute,但是會有 change 事件,所以也可以照常運作(不過相對的就完全沒有提供給使用者的視覺提示好像怪怪的)。

這篇內容大概就到這邊,雖然沒有提供很完整的程式碼,不過這些資訊應該很夠幫助其他人完成 autofill 事件的偵測了,其實這次弄信用卡資訊的輸入欄位真是費了不少心力,很多細節可以弄,也很多 domain knowledge(都靠 lib 搞定就是),真是想不到只是信用卡欄位也這麼多眉角。


Oklab Color Space

2019 年的時候,寫過一篇文章介紹了 Lab Gradient,然後就沒特別關注相關發展,直到前幾天看到勞哥的推文提到 Oklab 這個色彩空間,而且瀏覽器已經原生支援了,我才發現原來網路標準的發展有跟上來,我也趁機多惡補了一些相關的知識。

在介紹 Oklab 前,先來介紹以前提到的 Lab 吧,其實它是國際照明委員會(International Commission on Illumination,簡稱 CIE)在 1976 年提出的色彩空間定義,全名是 CIELAB color space,或是簡寫為 L*a*b*,多加*為了避免混淆,Lab 其實是不正確的縮寫,不過這三個字母其實就是該顏色空間的三個軸:L 代表亮度、a 代表紅色到綠色間的位置、b 代表藍色到黃色間的位置,也就是 opponent color theory(又稱對比色理論或色覺對向論)的顏色組成,這個色彩空間的重點在它的座標比較符合人類對色彩的感知。

Oklab 又是什麼呢?它是 Björn Ottosson 在 2020 年底發表的一個新的色彩空間定義,他在文章內有詳細的說明為什麼會想要定義一個新的色彩空間,文內也列舉了現存的色彩空間的主要問題,其中 CIELAB 的問題就是在 predict hue (預測色相)有些問題,尤其是藍色附近,其實我一開始對於這個 predict 感到很疑惑,想說到底是什麼意思,後來看到另外一篇文章 An interactive review of Oklab,文章一開始放的互動工具預設的漸層設定就是藍色到白色,然後一看就很明顯, CIELAB 的漸層色相跑一下就歪掉了變成偏紫色去了(random 按鈕可以按按看看其他色相都沒這樣嚴重),才了解到因為 CIELAB 是屬於人類感知的色彩空間,意思就是它的依歸其實是人類的感覺,所以需要從三維座標去推測人類實際上看到感覺到的顏色,數值上一樣的話就應該讓人感覺一致,而 Oklab 則是結構和 CIELAB 一樣,但是透過新的資料集來調整並解決前面提到的問題,而後在 2023,Oklab 進了 CSS Color Level 4 的草稿,主流瀏覽器現在也都已經支援。

CIELAB

進 CSS Color 代表什麼意思呢?第一個當然就是可以用 oklab() 函數來定義顏色了:

oklab(40.1% 0.1143 0.045);
oklab(59.69% 0.1007 0.1191);
oklab(59.69% 0.1007 0.1191 / 0.5);

除了直接定義顏色之外,現在 CSS 也支援相對顏色(relative color)了:

/* Relative values */
oklab(from green l a b / 0.5)
oklab(from #0000FF calc(l + 0.1) a b / calc(alpha * 0.9))
oklab(from hsl(180 100% 50%) calc(l - 0.1) a b)

這樣要只調整色相或是亮度都變得很簡單,或是也可以用 oklch(),這樣色相(Hue)就更好挑選。

然後就是漸層了,現在的 CSS 漸層也支援使用不同的顏色內差方式,也就是用不同色彩空間來算中間的顏色變化:

linear-gradient(in oklab, blue, red)
linear-gradient(in lab to right, #44C, #795)

在最前面加上in <color-space>就可以,支援的色彩空間其實不少,如果是線性漸層,那支援 srgb、srgb-linear、display-p3、a98-rgb、prophoto-rgb、rec2020、lab、oklab、xyz、xyz-d50、xyz-d65,如果是 polar 漸層,那支援 hsl、hwb、lch、oklch,其實相當夠用,而這段語法其實是叫 color-interpolate(顏色內插),除了漸層之外,會用到的地方還包括 filter、animation、transition 和color-mix()函數等。

前面也已經提到,現在主流瀏覽器都已經支援了,不過還是來看一下 caniuse 上的細節,Chrome 是 2022 就支援了,但是 Firefox 是到去年的 2023 才支援,如果要抓兩年的時間的話就還要再等等,當然現在也還是可以直接用,多加一組 fallback 就可以。

除了瀏覽器原生支援外,其實也不少其它開發相關的工具支援,也有不少文章在介紹,像是 Smashing Magazine 的 Falling For Oklch: A Love Story Of Color Spaces, Gamuts, And CSS 和 Evil Martians 的 OKLCH in CSS: why we moved from RGB and HSL,兩篇文章就介紹了不少工具和一些延伸的文章,工具部分像是 Figma 的 plugin OkColor 和 npm 上的 convert-to-oklch,Evil Martians 還做了一個 oklch.com ,是針對 Oklch 的 color picker 還蠻厲害的。

oklch.com


➡ 看看其它文章