# 前言 不管在 mobile 還是 desktop 都有個困擾就是要處理用戶縮放頁面的問題
如果只是資料類型的頁面, 縮放的話大多都只是畫面 UI 跑版
但如果是複合功能型的頁面, 縮放的話大概率會讓功能壞掉
就得找一些方法處理
# 確認可行性 JavaScript 有一個 api window.devicePixelRatio 是顯示畫面解析度比率的
早期可以用這個是不是 1 來判斷
但是螢幕的解析度其實會影響這個值
所以這個 api 沒有辦法當作判斷的基準
resize 事件可以在頁面縮放時會觸發
搭配 window.outerWidth/window.innerWidth 的值的變化可以知道有沒有縮放
但是這在 mobile device 的兩指縮放是不會觸發
所以也沒用…
但是針對 mobile 兩指縮放
可以使用 window.visualViewport
window.visualViewport.scale 可以知道現在縮放比例
如果只是要判斷有沒有所放的話
可以使用 resize 事件 + mobile 判斷來拿取 window.visualViewport.scale 或是 let zoom = window.outerWidth/window.innerWidth; 的組合來處理
sample code
let zoom = window.outerWidth / window.innerWidth; function isMobileDevice() { return /Mobi/i.
...
Category: JavaScript
# Intro 在 JavaScript 中的日期時間是個當初沒有定義出良好設計的東西
這裡先舉幾個常見的問題
日期格式問題 日期呈現的語系問題 時區問題 12 小時 24 小時問題 … 以原生的 API 在處理日期時間大多得自己額外做許多事情或是套用一些第三方 libary 來協助達成目的
# 時區問題 這次主要是討論關於時區的問題
在早期只能用 getTimezoneOffset() 的方法搭配時區表去換算各地時區
現在倒是可以使用 Intl.DateTimeFormat
refer - Date.prototype.getTimezoneOffset()
refer - Intl.DateTimeFormat
其實上述的問題, 在使用 Intl.DateTimeFormat 基本上都可以解決掉
詳細方式可以參以下文件
refer - Intl.DateTimeFormat() constructor
在時區中又有一個常常被忽視的的問題就是夏令時間(daylight savings time) 這個在夏季時就得把時間提前一小時的問題
如果自己處理時區就得記得處理這問題
使用 Intl.DateTimeFormat 的話系統已經自動處理了
# Intl.DateTimeFormat 這邊簡單介紹一下 Intl.DateTimeFormat 的一些用法與注意事項
new Intl.DateTimeFormat(navigator.language, { timeZone: 'America/Los_Angeles', dateStyle: 'full', timeStyle: 'full' }).format(new Date()) 這個範例就表示了當前洛杉磯的時間
第一個參數是語系, 採用 BCP 47 標準, 基本上建議使用 navigator.
...
# 前言 距離上次使用 YouTube Player API 已經是 2014 年的事了
不知不覺也過了超久了
剛好最近公司有相關的需求需要在 App 中能夠播放 YouTube 的影片
原本想說 App 應該和我沒關係了
所以這次準備躺平(誤
結果還是被牽扯進來了…
# 2022 年當前如何使用 YouTube player SDK 沒想到不看還好, 一看就準備 GG
一開始把文件丟給 Android 和 iOS
Android 那邊說無法用
我當下????
文件都寫得好好的, 為何說無法用
和 Android 一起討論了一下, 才確認了一件事
原來 Android 為了統一 libary, 在 2018 年開始推行 Androidx 要取代 android.support
最大的改變是 namespace 的變動, 雖然官方有工具可以對第三方 lib 做轉換, 但也會是一個大換血, 而且對比較老舊的套件還會需要處理 activity 和 fragment 的處理, 因為現今大多的 Android 都以 fragment 實作 UI 了
...
# 前言 在 web 的世界中有一個需要處理的是文字排版的呈現
因為從電腦到整個計算機科學的領域都是在拉丁語系為主宗的國家發展的
所以在介面的文字排版上自然以從左到右為主
但是在這世界上的文字排版有從左到右, 上到下, 右到左等呈現方式
所以需要依照需求或不同語系的文字上有相對應的處理, 尤其是在多語系的情況下
上到下的排版大多是書面用的排版, 相對在資訊領域比較少呈現, 且因為上到下的排版方式也大多是亞洲地區的國家, 在標準化的話語權不高
但也漸漸在 web 領域中有開始支援上到下的排版(writing-mode)
且在資訊領域也大多是用左到右的呈現, 所以影響相對小
額外補充一下大部分的方塊文字像是中文、日文、韓文等其實左到右、右到左、上到下都可以書寫與呈現
但在部份語系像是
阿拉伯文 烏爾都文 庫德文 波斯文 希伯來文 上述文字排版就固定都是從右到左
除了希伯來文以外都是從阿拉伯文字延伸的, 就像是英文、德文、法文都是拉丁文延伸出來一樣
至於為何在世界各地的文字排版會有差異其實主要是起源於早期該文字書寫的方式與被書寫在什麼材質上面為主
右到左主要起源於早期是文字是刻在石板上面, 左手拿鑿子, 右手拿錘子, 這樣從右到左是相對順手的
中文早期大多從上到下從右到左的排列主要起源於以前是在竹片上捲成冊的(竹簡)
在單片竹片上面書寫自然是上到下, 那捲成冊之後在閱讀時為了方便持握, 會是左手拿著竹簡, 右手打開來看內容, 自然就變成了右到左來閱讀
不過現在大多也因為資訊科學的發展後在電子載體上就沿用左到右的排版(前面提到電腦乃至資訊科學都是在拉丁語系的國家發展出來的)
不過在亞洲地區的國家部分書面印刷還是有保留上到下右到左的排版
不過有點扯遠了
# 實作 RTL(Right To Left) 的方式 這次主要是要處理 RTL 的問題
但其實在實作上也很好解
HTML tag 有個屬性是 dir 只要設定是 rtl 或是 ltr 就可以了
那麼要在什麼情況下設定這個東西?
大致上會在兩種情況設定
## 1. 多語系且有右到左語系 網站是多語系的網站且有右到左語系提供切換呈現
...
# Intro 有時在看 GA 的 Web 數據時會發現在 Safari 的點擊 click 事件似乎會比較少
其實這背後是有原因的
主要是各個瀏覽器再處理新 direct 時的行為不一致所導致的
在 Safari 上面發生 direct 到新的 URL 的行為(超連結或是 JS 處理) 時
事件觸發過程中的任何請求會中斷甚至不會發出請求
所以這就是為何在 GA 中的 Safari 的 click 數量會有些異常的原因
雖然 GA 預設會做 setTimeout 處理
但是也不一定是百分之百處理成功
所以最佳處理方式還是自己在用個 settimeout 包起來後再 direct
像是以下範例
link.addEventListener('click', (e) => { e.preventDefault(); window.gtag('event', 'click', { event_category: 'link' }); setTimeout(() => { location.href = e.target.href }, 250) }) 如果真的要確保 GA 送完才做 direct
GA 也有提供事件發送的 callback 處理
...
因為工作上的需要
需要把使用者輸入的訊息中含有 url 的部分把它取出來轉成超連結
參照以下範例
https://gist.github.com/metafeather/202974/34c2d31bd82f59c2486f38790054bbbc0b10ca8b
不知為何他的正規有點問題
所以又做了修正
function urlParse(str) { var urlArray = []; var urlRegex = /((http[s]?|ftp):\/)\/?([^:\/\s]+)(?::([0-9]+))?((\/\w+)*\/)?([\w\-\.]*)?([#?\w\=]+)?([\&\w=\w]+.*)?([\w\+\-\/\%]*)?[A-Za-z0-9_\/]/g; var arr = str.split(/[\n,' ']+/gm); for (let u = 0; u < arr.length; u++) { const element = arr[u]; var validate = element.match(urlRegex); if (validate) { urlArray.push(validate[0]); } } return urlArray; } url 格式遵循 RFC3986
refer - rfc3986
這邊可以在實作一個白名單機制限制只有白名單中的域名所屬的 url 才可以轉成超連結
function urlWhitrList(url) { var list = [ 'www.instagram.com/', 'youtu.be/', 'www.youtube.com/', 'www.
...
# 在 Web 中的 emoji 處理 在普遍的字串計算長度的部分
一個字元是單位是一
但是因為 emoji 的 unicode 是比較後面定義的
這超出了原有 JavaScript 原有定義的範圍
可以參照網站的介紹
Unicode – The World Standard for Text and Emoji
所以 emoji 的字串長度在 JavaScript 一率都是從 2 起跳
這在 Web 中會造成有需要處理字串長度的地方就會出現問題
例如:
input 文字的長度限制的使用
<input type="text" maxlength="10"> 字串需要計算長度時
string.length; 尤其是在現在行動裝置的普及, 內建的鍵盤已經有 emoji 的輸入可以使用
更會大大的增加在需要的邏輯處理會出現問題
# 如何解決 有一個方便的套件 runes 會把 emoji 識別出來
所以就可以解決掉 emoji 的問題了
# 背後原理 其實背後的原理也不難
就是去比對 emoji 的 unicode 碼
比對該字串是不是 emoji 的 unicode 碼
...
常常會遇到用 JavaScript 處理一些資料結構的排序
這裡會列舉一些使用情境與案例
# 取出排名前幾名的資料(排名的值不重複) ## 資料 var data = { 123: { count: 123, type: "video", source: "", }, 345: { count: 345, type: "video", source: "", }, 99: { count: 99, type: "image", source: "", }, 1: { count: 1, type: "video", source: "", }, 9786: { count: 9786, type: "image", source: "", }, 347: { count: 347, type: "video", source: "", }, }; ## 處理方式 function topNine(data) { var arr = []; (tmp = Object.
...
# JavaScript - 半形 全形 轉換 因為一個奇怪的需求?
需要把使用者輸入的東西轉成可以方便驗證的格式(這應該後端做吧?)
反正因為以前也做過半形轉成全形(痛苦的回憶, 為啥政府的 opendata 各縣市格式不一致就算了, 竟然還有全形半形的問題…)
這邊就簡單的只針對最前面的基本拉丁字母字元符號集作轉換
因為大部分的需求應該這樣就可以應付了?
但是空白字元要特殊處理
那接下來只要知道需要轉換的字元範圍即可
全形從 U+FF01 到 U+FF5E
半形從 U+0021 到 U+007E
把 16 進制轉換回來就是
65281 到 65374
33 到 126
上述怎麼轉的?
就是這樣
parseInt('0xFF01', 16) 只要判斷輸入的字元這這些編碼區間就進行轉換
trans char
所以簡單做了一個 demo 頁面
程式檢視原始碼即可
Refer - Wiki
Refer - Unicode / UTF-8 字元編碼區間表 - 2013
...
# JavaScript - 計算網頁元件的曝光 因為某些需求需要精確計算某些網頁上的 UI 元件的曝光
沒錯
就是要像廣告計算 impression 一樣
之前只要確認有該元件的 request 就好了
但是為了精確追求計算曝光, 所以必須做到像 Google Ad 一樣
要到該網頁元件讓使用者看到後才能計算曝光
聽起來這要求不太容易
但是實作下去其實發現還好誒!!
## 概念 DOM 元件進入可視範圍觸發 impression
所以需要能夠釐清一些問題
如何確認可視範圍?
如何確認要記錄 impression 的 DOM 元件在可視範圍?
如何在進入可視範圍時觸發?
看似困難
但是如果熟悉 JavaScript Window 物件和 DOM 物件的話就會發現很好解
## 實作 ### 如何確認可視範圍? window.document.documentElement.clientHeight window.document.documentElement.clientWidth 完美解決
### 如何確認要記錄 impression 的 DOM 元件在可視範圍? <DOM Object>.getBoundingClientRect(); 完美解決
但是要取到對應可是範圍的位置建議使用(top, left), x y IE 和 Edge 不支援
還有一點要注意就是該 DOM 要先長在 browser 上面且不是 display: none 的狀態才能拿到值
...