新版 Safari 9 對於開發者的幾項要事

在 OS X El Capitan 的測試版中,也放入了下一版的 Safari。雖然 beta 1 裡面的其實是 Safari 8.1,不過已經具有跟官網上介紹的 Safari 9 同樣功能,預計應該再下一版 beta 就會提昇版號了。簡單玩過之後,有注意到幾件事情比較有趣,而且跟網頁開發者比較有關的:

ECMAScript 6

Safari 9 一次補齊了一堆缺很久的 ECMAScript 6 新標準實作,官方給出的清單有下列項目:

  • Classes
  • Computed Properties
  • Weak Set
  • Number Object
  • Octal and Binary Literals
  • Symbol Objects
  • Template Literals

而在 ECMAScript 6 compatibility table 上可以看到,新的 Safari 進度直接飆到 52%(Safari 8.0.6 只有 20%),差不多追上了最新的 Webkit build、甚至還超過了 Chrome 的 48%。

Screenshot of ECMAScript 6 compatibility table

瀏覽器語系偵測

Update (7/18): 安裝了 El Capitan DP 3 1.0 (15A216g) 之後,Safari 9 的 navigator.language 又變回 zh-tw 了。

在系統設定主要語言為繁體中文、且地區為台灣的情況下,打開 iCloud 網站竟然是出現簡體介面。所以我在 console 下面檢查了 navigator.language,發現新版的 Safari 9 吐出來的結果是 zh-hant、而不是以前的 zh-tw 了。

雖然某種程度上可以理解這是因為台灣不是唯一使用繁體中文的地區,因此 zh-hant 會比 zh-tw 更適合來描述「繁體中文」這件事,但是如果網站是透過比對這個來決定介面語言的話,就可能在這邊出錯而 fallback 成 zh ──然後就變成簡體中文了。

還不確定這個未來會不會修改,不過如果你的網站有偵測瀏覽器語言,就會需要留意這個問題。

Screenshot for Safari 9 console

Unprefixed CSS 屬性

同樣在《What's new in Safari 9.0》文件中,提供了一份正式脫離 vendor prefix 的 CSS 屬性清單。大致上來說是關於 Transition、Animation、CSS Flexbox 跟 CSS Columns 的相關屬性。不過如果平常開發時有在用 autoprefixer 之類的工具的話,其實也就不用太煩惱了,丟給它處理就好XD

釘選分頁的 icon

Safari 9 終於支援了「釘選分頁」的功能。不過被釘選的分頁上顯示的是單色的 icon,不支援現行彩色的 favicon。官方建議是使用前景為 100% 黑色、透明背景的 svg 作為 icon 本身,然後在 <head> 裡面加一行 <meta> 標籤來指定 icon 的顏色。

<!-- 這行要放在其他 <link rel="icon"> 的前面,才不會蓋掉彩色的 favicon -->
<link rel="icon" sizes="any" mask href="website_icon.svg">

<meta name="theme-color" content="#ff0000">

Update (6/11): 經過實測,<link rel="icon"> 那行必須放在 <link rel="apple-touch-icon"> 的後面,不然 Safari 會試圖用 apple-touch-icon 來作為釘選分頁的 icon(然後就會失敗。)

其他

其他還有蠻多沒有在發表會上宣布的新功能,建議有興趣的話可以逛一下《What's new in Safari 9.0》。

Enhance page speed for your Middleman websites on Heroku

Middleman is a great tool for developing static websites with a bunch of tools like template engine, SASS or CoffeeScript. Jordan Elver has a great post about how to deploy a Middleman to Heroku as a Rack app serving your static files.

If you want to follow the suggestions from Google's PageSpeed Insights to increase your website performance, you'll need some additional steps.

The most basic part will be minifying your CSS and JavaScript. You can even minify your HTML to make it smaller.

There are some more things you can do:

Read on

用 srcset 屬性做簡單的 Responsive Image

在 HTML5 的 Living Standard 中,為 <img> 增加了 srcset 的屬性。這個屬性允許你在不同條件下,為一張圖片指定不同版本的原始檔,以便讓支援的瀏覽器可以自動選擇最適合的版本,下載來顯示。適合的時機是「我有同一張圖片、但是幾個不同尺寸的版本想要替換使用」,例如在下圖中,如果我可以根據圖片顯示的實際需要,給他剛好大小的版本,就可以節省在行動裝置上的資源跟頻寬。

一張圖片、多種尺寸版本示意圖

srcset 並不是很新的東西,在 2012 年就被提出來了。Othree 這篇文章有蠻清楚的介紹。不過當時提出來的草稿經過翻修、並且併入 HTML 規格之後,現在已經簡化到剩下兩種用法:以裝置像素密度 (device pixel ratio) 為基準、或是以 Viewport 為基準。

Read on

Revised Batman.js all-views-cache hack

Batman.js works very well with Rails. However, when it comes to production environment, the way Batman request every view template via Ajax on demand will cause some inconvenience.

John Lynch and Ryan Funduk has an post about how to precompile all view templates into one json, and fetch it on App runs. This solves most issues, but has one drawback. When you're about to load the all-views json file, your App has actually became running already. It will look for the template of your root (or firtly-requested) view, and will be unable to find it in View Cache 'cause the Ajax is still running.

Eventually, Batman.js will try to download the view template almost at the same time your precompiled all-views json starts to be fetched. And this will generate one more HTTP request, and may occur some 404 errors if those template files are not served on the server.

Here's how I try to revise this hack and solve the above issue: prevent the Batman.App from running until the view caches are successfully loaded.

Read on

手動調整 Responsive 中日文斷行的實驗

前幾天,敝社的產品 Logdown 上了新翻譯完成的日文 Landing 首頁。這版 Landing 頁,我有做 Responsive Web Design1,讓網頁能稍微有點彈性地適應各種瀏覽寬度、而不至於看起來活像是壞掉。不過在日文的大標題填上去之後,稍微遇到了一個問題──他實際上佔的長度蠻寬的,比一開始的英文大標還要寬──而這讓他在小螢幕上面會產生斷行。

當然我可以透過 Media Query 的方法,確保他的字體在每個寬度都縮小到不致於斷到下一行,不過字體太小的標題顯然很難看起來像是「大標題」。試著實際拉了一下瀏覽器視窗,覺得還是讓他保留一定的字體大小而斷行比較好。不過在這邊引發我的興趣:要怎麼斷行,可以讓他盡量斷在「詞」的邊緣,而不是斷在「詞」的中間?

Read on

用 Composition Event 改進 CodeMirror 對輸入法的支援

CodeMirror 是一套相當熱門的編輯器套件,除了 WebKit 跟 Chromium 裡面的 Inspector 採用以外,Logdown 的編輯器也是用 CodeMirror 做成的。恰如其名,CodeMirror 用來處理程式碼片段非常適合;但是用來處理「文字」倒是有個缺點:沒辦法好好的處理「輸入法」。

對於要編寫非英語文章的使用者來說,多半需要使用輸入法 (Input Method Editor, IME) 來輸入不同語言的文字。大部分的輸入法(例如注音、倉頡、日文拼音輸入法)在打字的時候,會進入一個「組字模式」,把你鍵盤上的輸入,經過對應後轉換為非 ASCII 的文字。

以注音輸入法來說,就是你會看到打出來的字,最後面一小段下面會有底線,然後你可以把游標移動到有底線的文字上、按下「↓」或是空白鍵之類的來改變選字,好讓你可以把「 放棄 」改成「 放氣 」。

但是如果你試過在 CodeMirror(現在是 v3.18)的編輯器裡面使用輸入法打字,你會發現:

Read on

Infinite Scroll 自動捲動換頁的客製化選項

Infinite ScrollPaul Irish 編寫維護的一套自動換頁 plugin。他的運作原理是透過 JS 去讀取網頁上的分頁連結 (Pagination)、然後在網頁捲動到接近分頁連結位置的時候自動去抓下一頁的內容、然後插入到目前內容的結尾處。像是 Pinterest 這類的 UI 用的就是類似的概念。

基本用法

Infite Scroll 的基本用法是,你先指定好用來包內容的元件 (Content Container),然後告訴他分頁連結在哪裡、網頁裡面要抓什麼元件回來,剩下的他就會幫你搞定。甚至還幫你準備好了 loading 的提示動畫,會幫你插在目前內容的尾端。假設我是一個公告系統,想要讓我的公告可以一直無限捲動的話,可以這樣寫:

Read on

Web Speech API (I): 使用 SpeechSynthesis 讓瀏覽器講話

Google 在去年以 Community Group 的方式,向 W3C 提交了 Web Speech API 的規格書。該 API 主要分為兩部分:

  1. 語音轉文字 (Speech Recoginition)
  2. 文字轉語音 (Speech Synthesis)

其中 Chrome 實作語音轉文字的語音辨識功能很久了,不過似乎並沒有急著實作文字轉語音的部份;反倒是回歸 Apple 掌握的 WebKit 最近實作了無 vender prefix 的 Speech Synthesis 相關 API,目前 WebKit Nightly 就玩得到,所以來玩玩看。下一版的 Safari (6.1/7.0) 也預計會支援此 API。

本篇之前於 HappyDesigner Mini 分享會 #2 分享,實際效果可參考 Demo 影片 或是 Demo Page

Read on

在 Rails 下模組化整理 CoffeeScript

在 Rails 下面寫 JavaScript 跟 CSS 很方便,因為你可以把 .js.css 以模組化的方式拆成很多小檔案、然後以階層目錄之類的方式來整理檔案。反正最終上 Production 後、AssetPipeline 會幫你把眾多小檔案,以你指定的順序結合成一包大檔案一起載入──例如 application.jsapplication.css

對 CSS 來說這樣整理的方式沒有問題,因為 CSS rules 是只要宣告過就會留在那邊;只有先後順序跟優先層級問題,沒有跨檔案問題。對純 JavaScript 來說其實也蠻好解決,例如 CSS-Tricks 的《How Do You Structure JavaScript? The Module Pattern Edition》 就建議你可以把 script 以模組化的方式包成一個個物件、就可以一個模組一個檔案拆下去整理;最後再依序包回來使用即可。CSS-Tricks 的範例大概如下:

Read on

HTML5 File API 筆記 (1) 基本名詞解釋

HTML5 多了 File API,可以透過 JavaScript 來處理到本機的檔案。下面有幾個 Interface,稍微筆記一下:

FileList

HTML5 的檔案欄位支援選取多個檔案一次上傳,只需要加上 "multiple" 屬性。要拿到檔案欄位目前選取的檔案清單,可以直接跟該欄位要 files 屬性:

<input id="fileField" name="files[]" type="file" multiple />
var fileList  = document.querySelector('#fileField').files;

這樣會回傳一個 FIleList 物件回來,結構上類似陣列,有 length 屬性、也可以用 item(n) 的方法要到清單中的第 n 個檔案。其實也可以直接像陣列一樣直接跟他要 fileList[n]。這份檔案清單裡面放的是 File 物件的集合,下面會提到這個類別,但總之就是一個個檔案。

Read on