[CSS][Transition] 轉場效果

前言

轉場是從 A 狀態,轉變成 B 狀態,中間的過程,就叫轉場,在 CSS 中叫做 transition。適當的增加轉場效果,可以讓使用者的體驗更好,這是在 CSS3 中才有的新功能,目前大部份的主流瀏覽器也都支援了,這裡可看 transition 支援度

語法

底下這行的意思是,所有屬性(all)只要發生改變,等待 1 秒(1s),然後花 2 秒鐘(2s)的時間,轉場到新的樣式;ease-out 的意思是開始快,然後慢慢減速,是 timing-function 的其中一種。

transition: all 2s 1s ease-out;

// 等同於:
transition-property: all; // default: all
transition-duration: 2s;  // default: 0;2s 表示 2 秒;2ms 表示 2 毫秒。
transition-delay: 1s; // 開始進行轉場效果之前,所要等待的時間。
transition-timing-function: ease-out;

範例

範例 1:hover

A B

看原始碼:html css

範例 2:focus

看原始碼:html css

範例 3:多狀態

看原始碼:html css js

上面寫了三個範例,希望可以幫助大家瞭解 transition 的用途、用法。若有位何問題,可於底下留言。

參考資料

CSS3 Transitions

[Linux] 如何關閉 ping response

前言

有的時候你得知某個網域(以 uivacation.com 為例),然後你想使用 ping 的方式,然看看該網域所對應的 IP 是否有回應,這時你會想執行以下指令:

$ ping uivacation.com

// 會取得以下結果,表示該主機(139.59.241.74)有回應 ping 的訊息,並可得知 IP 以及封包來回傳送的時間:
PING uivacation.com (139.59.241.74): 56 data bytes
64 bytes from 139.59.241.74: icmp_seq=0 ttl=51 time=85.679 ms
64 bytes from 139.59.241.74: icmp_seq=1 ttl=51 time=104.005 ms
…

但身為系統管理者,有的時候其實我們並不想讓別人太輕易得知以上的結果,所以會想要將 ping 的 response 給關閉,那該如何做呢?

什麼是 ping?

ping 是一個指令,用來傳送一個 ICMP 封包至某主機,然後確認該主機的運作在網路上是否有正常啟動。

以 CentOS 7 為例,關閉 ping response

執行以下指令,即可完成:

// 將 icmp_echo_ignore_all 檔案,僅輸入 1 這個值。
$ echo 1 > /proc/sys/net/ipv4/icmp_echo_ignore_all

若要回復讓 server 可以對 ping 有所回應的話,就執行以下指令即可:

// 將 icmp_echo_ignore_all 檔案,僅輸入 0 這個值。
$ echo 0 > /proc/sys/net/ipv4/icmp_echo_ignore_all

若想讓以上的設定永久生效的話,開啟 /etc/sysctl.conf 檔案,並於檔案的最下方,新增以下這行並重新開機即可:

net.ipv4.conf.icmp_echo_ignore_all = 1

這時我再執行以下的 ping 指令,server 就不會再對 ping 指令有 response 了:

$ ping uivacation.com

// server 就不會對 ping 指令有 response 了。
PING uivacation.com (139.59.241.74): 56 data bytes
Request timeout for icmp_seq 0
Request timeout for icmp_seq 1
…

其它參考資料:

Disable ping response

UNIX ping Command Examples

[CSS] 滑鼠游標(Cursor)種類有哪些呢?

前言

為了方便看目前有哪些游標可以使用,所以這裡列出了目前可以使用的游標,在 CSS 的語法裡,例如我要將游標換成 text,則可以寫成:

.your_class{
  cursor: text;
}

上述的 text 可以直接換成以下方框的文字,滑鼠移過即可看到效果。

另外此篇文章也會告知你如何自訂游標。

CSS 2.1 游標

  • default
  • crosshair
  • help
  • move
  • pointer
  • progress
  • text
  • wait
  • e-resize
  • ne-resize
  • nw-resize
  • n-resize
  • se-resize
  • sw-resize
  • s-resize
  • w-resize

CSS 3 游標

  • none
  • context-menu
  • cell
  • vertical-text
  • alias
  • copy
  • no-drop
  • not-allowed
  • ew-resize
  • ns-resize
  • nesw-resize
  • nwse-resize
  • col-resize
  • row-resize
  • all-scroll
  • zoom-in
  • zoom-out

其它

Chrome 和 Safari 瀏覽器並不支援以下兩個:

  • grab
  • grabbing

指定游標來源路徑

像 grab 和 grabbing 在 Chrome 和 Safari 瀏覽器中並不支援,那為了要保持一致性,我們就必須要自行指定游標的來源來徑,例如:

此路徑 https://ssl.gstatic.com/ui/v1/icons/mail/images/2/openhand.cur 會顯示

此路徑 https://ssl.gstatic.com/ui/v1/icons/mail/images/2/closedhand.cur 會顯示

另外的 png 圖路徑 http://notes.carlos-studio.com/images/1.png 會顯示

那麼就可以使用以下語法來讓 Chrome 和 Safari 也支援 grab 和 grabbing 的游標了,也可另外(another)指定客製的圖:

.grab_class{
  cursor: url(https://ssl.gstatic.com/ui/v1/icons/mail/images/2/openhand.cur), default !important;
}
.grabbing_class{
  cursor: url(https://ssl.gstatic.com/ui/v1/icons/mail/images/2/closedhand.cur), default !important;
}
.another{
  cursor: url(http://notes.carlos-studio.com/images/1.png), default !important;
}
  • grab
  • grabbing
  • another

這樣就可以很方便的查閱了。

如有任何問題,歡迎下方留言喔!

[Google Analytics] 如何正確地將 Referrer Spam 移除

前言

有鑑於有些朋友有 Google Analytics 被 Spam 污染資料的困擾,因此無法正確地解讀數據,因此想來寫一下關於如何讓 Spam 的資料,不要再在 Google Analytics 出現而影響數據分析。

簡述 Spam

首先,Spam 的種類其實滿多的,除了有 Referrer Spam、還有 Language Spam、Crawler Spam…其實真的沒有一個真的完美的方式來根除這些對數據分析來說的無效流量,我們只能儘可能使用有效的方式,降低我們常常要維護的頻率。

以 Referrer 為例,在 Google Analytics 報表中的 客戶開發 → 所有流量 → 參照連結網址,就可以看到所有的 Referrer 推薦網站(也就是在別人的網站有一個連結,是連到你的網站,那麼當有人點擊了此連結,這樣的流量,就會被歸為 Referrer了),如下圖:

上圖中,都是好的流量,當然上圖只是流量的一小部份,其它我自己判斷的可能無效流量有來自 ipv6.google.com、keywords-monitoring-success 等,就是所謂的 Referrer Spam,就要想辦法排除,那麼為什麼會有無效的流量呢?以 Referral Spam 為例,原因方法很多種,主要是因為有人(或網路機器人)可能取得你網站的 tracking ID(UA-XXXXXX-Y),然後透過 API 的方式,直接傳送資料(例:Pageview)至你的帳戶,進而擾亂了你的資料,但實際上跟本完全沒有實際造訪過你的網站。

Spam 流量的目的是什麼?

可以慶幸的是,這些 Spam 流量並不會影響我們的 SEO,但他們卻可以從中受益(金錢),也可能有某些特殊目的(例如選舉),來創造很多例如 Language Spam 流量,近期最有名的應該是 Secret.ɢoogle.com You are invited! Enter only with this ticket URL. Copy it. Vote for Trump!

我們非常難去阻止這些 Spam 的行為,但至少我們要避免這些數據在我們的 Google Analytics 報表中呈現進而汙染我們的資料。以下提供幾個方式:

方法一:開啟 Google 內建的「排除所有來自已知漫遊器和自動尋檢程式的匹配」

如下圖,Google 有內建收集一些已知的網路機器人或爬蟲或一些 Spam,在 管理 → 資料檢視 → 檢視設定 → 將漫遊器篩選項目勾選即可,這樣一來,就可以自動排除掉一些不必要的流量了。

方法二:使用 篩選器(Filters) 去排除 Referrer Spam

管理 → 資料檢視 → 篩選器 → 新增篩選器 ,直接建立一個排除參照網址的方式,如下圖:

在上圖中的 篩選器模式,可使用正規表示式,例如我輸入以下:

// 表示 spamsite1.com 的子網域或 spamsite2.com 子網域都會被過濾掉。
.*.spamsite1.com|.*.spamsite2.com

這個方法的缺點,就是只要你一有發現新的網域你想排除的話,都要來重建,也就是要不定期的來維護這個篩選器,算是比較人工的方式。

方法三:使用 篩選器(Filters) 去 Include 主機名稱(hostname)

讓我們先看下圖瞭解一下:一樣在 客戶開發 → 所有流量 → 參照連結網址 的報表中,只是我們多顯示了一個次要維度:主機名稱

會發現在 free-share-buttons.blogspot.com 的主機名稱是 (not set),為什麼?而我還看過來源是 website-analyzer.info,而它的主機名稱是 4webmasters.org,其實這些都不是正常的流量,以一般的情況來說,主機名稱都應該要是你的網址,以我的為例,應該就是 carlos-studio.com

至於為什麼會有 (not set) 的情況,其實是因為可能使用了 Google Analytics 的 Measurement Protocol 的方式來傳送資料,這種方式並不會有 hostname 的記錄,大部份的 Spam 都會過此種方式來汙染你的資料。

Measurement Protocol 可讓您透過任何連上網路的裝置將資料傳送至 Analytics (分析)。

所以這時我們就可以透過使用 篩選器(Filter) 中的 Include hostname 的方式,來確保在主機名稱中,僅包含我們所指定的網址,例如下圖以我的 blog 為例( 輸入任意的篩選器名稱 → 篩選器類型選預先定義 → 只包含 → 主機名稱獲得的流量 → 等於 → 輸入你自己的主機名稱 ):

此方法三雖然相較於方法二,比較自動化一點,但仍然無法根除,因為有的來源即使主機名稱沒有問題,但來源網址經查還是屬於 Spam,所以沒辦法,在你沒有其它資源可使用的情況下,就只能使用「方法一」、「方法二」、「方法三」合併一起使用,即設定兩個 Filter,然後定期的維護。

另外雖有第三方資源,可以自動化的幫你整合過濾掉 Spam,例如 Referrer Spam Blocker,但我沒用過,也不太建議,不是說不好,只是這種第三方資源,除非真的超重要,通常會擔心哪一天它要收費了、或它突然不支援了、而又要花時間研究…諸多考量之下,所以通常我不太用。

但難到沒辦法永久根除嗎?以下要介紹另一種長久之計,我參考了 how-can-handle-google-analytics-referrer-spam 這篇文章所使用的方式,是使用 Google Tag Manager 的方式,所以前提是你必須要透過 Google Tag Manager 的方式來載入 GA 的程式碼。這裡假設你已經有使用 Google Tag Manager 了。

方法四:建立 「自訂維度」,並在 Google Tag Manager 介面中設定

先闡述以下步驟的所有目的:當使用者有真正的造訪我們的網站的時候,我們要多傳送一個值(意義上有點像是"密碼")到 Google Analytics 中,之後我們就可以只要建立一個篩選器(Filter)來過濾只要包含此值(密碼)的流量即可,就可以確保在報表中所呈現的流量幾乎都是正常好的流量了。

因為像其它 Spam 所傳送的流量,有的可能是透過 Measurement Protocol 或並非真的造訪你的網站,所以不可能傳送你所設定的值(密碼),我自己實驗過,覺得是還滿好的方式。

以下是建立的流程:

Step 1:我們要建立一個自訂維度,而在此自訂維度中,設定一個值,在 Google Analytics 的「管理 → 資源 → 自訂定義 → 自訂維度」中,如下圖:

Step 2:按下「新增自訂維度」

Step 3:輸入以下資料,名稱可自行輸入自己可識別的名稱;範圍選 Hit, Hit 的意思是只要你每次傳送資料一次,即為一個 Hit,例如一個 Pageview,就會產生一次的 Hit;將「有效」勾選。按下"建立",如下圖:

Step 4:會產生下圖的程式碼,如果你沒有使用 Google Tag Manager ,那麼以下的程式碼,就要自行想辦法整合至自己的網站中了,如果有使用 Google Tag Manager,那麼可以直接按下「完成」按鈕。

Step 5:接下來一樣在「管理 → 資源 → 自訂定義 → 自訂維度」中,就可以看到所建立的自訂維度,以下圖為例,請記得所建的 索引編號,此例為 1,這個索引編號,會在 Google Tag Manager 中使用到:

Step 6:登入 Google Tag Manager 的後台介面,「Variables → User-Defined Variables → NEW」

Step 7:建立一個常數,值為 1 (這個數字,就是上一步的索引編號,這樣才可以對應。)。下圖的第2步,可輸入你自己可識別的名稱,第3步選常值,第4步就是該常數的值(1)

Step 8:再建立第二個常數,如下圖,名稱一樣可自己訂一個可識別的名稱,至於「值」的部份,在此我輸入 autospamfilter,你可以自行輸入任意的字串,如果想要複雜一點,可使用 Base 64 做 encode,讓那些 Spam不容易猜到。

Step 9:看下圖目前所建立的兩個常數:

Step 10:將上述所建立的兩個常數,加進自訂維度,分別是索引、維度值,如下圖:

Step 11:按下 Publish 按鈕,即可完成在 Google Tag Manager 中的設定。

Step 12:回到 Google Analytics 介面,新增 Filter 如下:主要在 篩選器欄位要選擇我們先前建立的自訂維度名稱,即 Analytics Key,而在 篩選器模式中直接輸入我們先前在 Google Tag Manager 中建立的常數值,即為 autospamfilter,如下圖:

以上整個的設定流程就算完成了。

我覺得這個方式還滿有效的,至少可以大幅降低你要時常維護篩選器(Filters)的頻率。

若有任何問題,歡迎在底下留言討論。

 

參考資料:

How can I handle Google Analytics referrer spam?

Ultimate Guide to Getting Rid of All the Spam in Google Analytics.

Common Google Analytics Spam Questions – Answered

[Google Analytics] 功勞歸屬模式 (Attribution Models)

什麼是功勞歸屬模式?

簡單來說,就是可以將訪客轉介過來的推薦網站 (referring websites),計算出貢獻多少收益,或是開發多少潛在客戶等。如果聯盟網站(affiliate)是行銷活動的重要部分,那麼此功能就很重要。

先看看下圖:

假設一位訪客在達成轉換(可以是成為顧客、訂閱用戶或潛在客戶)之前造訪了4次外部的網站,如果沒有功勞歸屬功能的話,所有推薦網站都會被視為有同等的貢獻:假設圖中顯示的路徑是先使用 Google 搜尋,接著抵達社群網站,然後點擊橫幅廣告到某個聯盟網站,最後點擊你的聯盟網站的某個連結到你的站內,最後完成轉換,那這四個網站會被視為同等重要。

功勞歸屬功能可以讓你決定各個推薦網站的不同比重,也就是網站為訪客最後的消費行為出了多少力,占總收益的比例又有多少。

而在 Google Analytics 的免費版與專業版(每年15萬美金)中,都可以自訂模式。只是專業版多了一個「數據導向」模式,讓你不必再手動比較或從不同模式中選擇,這個模式會替你自動計算各個管道的功勞。

參考

官網:歸屬模式總覽

書籍:透視數據下的商機 – 運用 Google Analytics 發掘商業洞見

[PHP] 介紹 htmlentities() 函式

htmlentities()  函式的一個主要用意,就是在將使用者輸入的資料,在傳送出去時,將它編碼成安全的字串,以免被惡意值入不必要的程式,也就是俗稱的 Sanitize Input (HTML 的部份)。

例如以下範例程式:

<?php
$input = "<p><script>alert('這是警告訊息!');</script></p>";
echo htmlentities($input);
echo "\n";
echo htmlentities($input, ENT_QUOTES, 'UTF-8');
echo "\n";

在後端會取得如下的資料:

htmlentities() 的輸出結果

有沒有發現第一行跟第二行不一樣,在於單引號在第一行並沒有被正確的編碼;
要使用第二行的方式才行。

原因是 htmlentities() 在預設上,是不會將單引號編碼的,而要加上第二個參數 ENT_QUOTES 才行。
在 PHP 的官網有說明 htmlentities(),第二個參數預設是 ENT_COMPAT,只會將雙引號編碼,而單引號不會。

所以以後在傳送有 html 的資料的時候,務必使用:
htmlentities($input, ENT_QUOTES, ‘UTF-8’);

[Linux] grep 指令使用方法

一、搜尋某檔案,找出"要搜尋的字串"的那行顯示出來:

$ grep "要搜尋的字串" 檔名

例如:

$ grep "name" composer.json composer.lock

或也可以使用萬用字元*,來搜尋多個檔案:

$ grep "name" *.md

 

二、使用 -r 來遞迴搜尋某資料夾裡的所有檔案,包含子資料夾,例如以下是搜尋當前目錄及其底下子資料夾裡的所有檔案:

$ grep -r "要搜尋的字串" .

 

三、find 指令找到當前目錄底下(包含子資料夾),檔名以 jsx 結尾的檔案,列出來:

$ find . -name "*jsx"

 

四、找出所有 .jsx 結尾的檔名,再 pipe 給後面的指令,透過 xargs 指令(eXtended ARGuments)搭配 grep 指令,找出那些檔名中,有出現 carlos 的各行:

$ find . -name "*.jsx" | xargs grep "carlos"
// 下方這行,與上方這行的結果會是一樣的,只是方式不同:
$ grep -r --include="*.jsx" "carlos" .

 

五、將所搜尋的字串,標出顏色:

$ grep -r --color uivacation .
// 如果是使用 git grep,可以排除被git忽略的檔案,如下:
$ git grep uivacation

 

六、也將搜尋到該行的行號( -n )給顯示出來:

$ grep -n -r --color uivacation resources/

 

七、將所搜尋到的那行,連同下一行也顯示出來(-A 1),如果要下兩行(-A 2),A代表的是 After;相反的,B是Before;C代表的是 Context,表示前後都會顯示:

$ grep -A 1 -n -r --color uivacation resources/
// -B 表示 Before,連同前一行也顯示出來
$ grep -B 1 -n -r --color uivacation resources/
// -C 表示 Context,連同前一行、後一行也顯示出來
$ grep -C 1 -n -r --color uivacation resources/

 

八、使用正規式,來找出某檔案的某字串:

// 下方的 "h." 是表示搜尋出 h 開頭,以及下一個字元是任意字元的字串:
$ grep --color -n "h." composer.json
// 使用 \ 來跳脫字元,以下例來說,就是一定要搜尋到 h. 才算符合:
$ grep --color -n "h\." composer.json
// 以下代表要搜尋到至少一個 # 字號,才算符合,因為後面的 #* 表示該 # 至少出現零次以上:
$ grep --color "##*" readme.md
// 以下代表在括號之間,可出現任意字元零次以上:
$ grep --color "(.*)" readme.md

 

九、使用進階的正規式:

// 在 readme.md 檔案中,搜尋出有 https 的所有行,並標示出顏色:
$ grep --color "https" readme.md
// 在 readme.md 檔案中,搜尋出有 http 開頭,後面搭配一個任意字元的所有行,並標示出顏色:
$ grep --color "http." readme.md
// 在 readme.md 檔案中,搜尋出有 http 開頭,後面的 s 可出現零次或一次,並標示出顏色:
$ grep --color "https\?" readme.md
// 在 readme.md 檔案中,搜尋出有 http 開頭,後面的 s 至少要出現一次以上,並標示出顏色:
$ grep --color "https\+" readme.md
// 如果不想加 \ 的話,那麼可改用 -E,例如上面這行,可改成以下這行,會是一樣的結果:
$ grep --color -E "https+" readme.md
// 下面這行,表示要搜尋的真的是 https+ 這樣的字串(也就是將 -E 移除):
$ grep --color "https+" readme.md

 

十、使用 | 這個代表或的運算

// 下面這個例子,會將 grey 及 gray 都標示出顏色:
$ echo "is it grey or gray?" | grep --color "grey\|gray"
// 或用以下語法也是可以的:
$ echo "is it grey or gray?" | grep --color -E "grey|gray"
// 以下例子為在 examples 資料夾底下(含子資料夾),搜尋出有 grey 或 gray 的所有行:
$ grep --color -rE "grey|gray" examples/

 

十一、使用 ^ 及 $ ,來表示那行的開頭跟結尾

// 表示在 app-spec.md 檔案中,要搜尋出以 # 字號開頭的行:
$ grep --color "^#" app-spec.md
// 表示在 app-spec.md 檔案中,要搜尋出以 , 字元結尾的行:
$ grep --color ",$" app-spec.md
// 表示在 examples 資料夾中(含子資料夾)的所有檔案,要搜尋出以 import 開頭,中間含有 from 的所有行:
$ grep --color -r "^import .* from" examples/

 

十二、使用 bracket 的表達式:[a-zA-Z]、[0-9]

// 以下是表示 a 和 b 會被搜尋出來並標示出顏色:
$ echo abc123 | grep --color "[ab]"
// 以下是表示 a 到 z 會被搜尋出來並標示出顏色:
$ echo abc123 | grep --color "[a-z]"
// 以下是表示 1 到 9 會被搜尋出來並標示出顏色:
$ echo abc123 | grep --color "[1-9]"
// 以下是表示 「de開頭,然後中間 a 到 z 的字元可任意出現多次,然後以 er 結尾」 會被搜尋出來並標示出顏色:
$ grep --color "de[a-z]*er" readme.md
// 以上的 [a-z] 可用以下方式來替代:
$ grep --color "de[[:alpha:]]*er" readme.md

$ find . -name "*.js" | grep --color "[sS]pec"

 

十三、group 例子:

// 找出 grey' 和 gray' 的所有行:
$ grep -rE --color "(grey|gray)\'" .
// 找出 grey' 和 gray'、grey"、gray" 的所有行:
$ grep -rE --color "(grey|gray)(\'|\")" .

 

十四、使用 find 找出所有的檔案列表,再透過 grep 將 node_modules 資料夾裡的排除

$ find examples/angularjs -name "*js" | grep -v "node_modules"

 

[Linux] vagrant 執行 vagrant box update 失敗

執行以下指令若失敗:

$ vagrant box update
==> default: Checking for updates to ‘laravel/homestead’
    default: Latest installed version: 0.5.0
    default: Version constraints:
    default: Provider: virtualbox
There was an error while downloading the metadata for this box.
The error message is shown below:

The requested URL returned error: 429 Too Many Requests

 

執行以下指令,就可以再重新執行 vagrant box update

$ rm -rf ~/.vagrant.d/tmp/

[Linux] 列出網卡

在 CentOS 7 中,使用以下指令,快速地列出網卡:

$ nmcli d
DEVICE  TYPE      STATE      CONNECTION  
eth0    ethernet  connected  System eth0 
lo      loopback  unmanaged  —