哈瑪星共通平台 前端規範 ======================= 前端介面版本 2.0 [oka Li](mailto:okaoka0709@gmail.com) ## 目錄 --- :::warning - [簡介](#簡介) 1. [前言](#前言) 2. [定義](#定義) 3. [工具](#環境與工具) - [哲學](#哲學) 1. [模塊:模組與群組](#模塊:模組與群組) 2. [CSS 選擇器與範圍](#css-selector) 3. [Javascript 優化](#javascript-optimize) - [HTML 實作](#HTML) 1. [專案目錄結構](#project-directory) 2. [參數與意義](#HTML-parameter) 3. [底層、框架與內容](#base-layout) 4. [模塊基礎結構](#module-and-group-structure) 5. [群組類別與結構](#group-structure) 6. [模組類別與結構](#module-structure) 7. [組件](#component) 8. [以 class name 表示狀態](#use-class-name-to-show-status) - [erb 實作](#erb) 1. [erb 目錄結構](#erb-directory) 2. [erb 樣板語言](#erb-script) 3. [erb 運作方式](#erb-run) 4. [關於 layout 樣板](#erb-layout) 5. [關於 index 樣板](#erb-index-layout) 6. [關於 sys/variable](#erb-variable) 7. [假字與圖片](#lorem-ipsum-and-picture) - [CSS/SCSS 實作](#scss) 1. [SCSS 目錄結構](#scss-directory) 2. [SCSS](#scss-script) 3. [格線系統](#grid) 4. [類別](#scss-type) 5. [選擇器邏輯](#selector-logic) 6. [base/variable、base/function 與 sys/function](#function-and-variable) 7. [關於 sys/variable](#scss-sys-variable) 8. [noscript 方法](#scss-noscript) 9. [hack 方法](#scss-hack) 10. [rwd 方法](#scss-rwd) 11. [在 pc、pad、phone 寬度隱藏模塊](#rwd-hide) 12. [隱藏模塊 header 的方法](#hide-header) 13. [admin 方法](#scss-admin) 14. [文字圖示](#scss-font-icon) 15. [sprite 圖示](#scss-sprite-picture) 16. [關於設定數量的方法](#scss-len-function) - [javascript/requireJS 實作](#js) 1. [Script 目錄結構](#js-directory) 2. [requireJS 運作方式](#js-require) 3. [以 node 呼叫 javascript 檔案](#node-and-files) 4. [關於 lib/app 與 lib/main](#app-and-main) 5. [關於 jquery.js](#js-jquery) 6. [關於 cookie.js](#js-cookie) 7. [關於 getNode.js](#js-getNode) 8. [關於 fix.js](#js-fix) ::: ## 簡介 --- ### 前言 共通平台是一套商用 cms 系統,本文解說其前端規範。 共通平台定義了**模塊**的概念,每個具有內容的模塊都是**模組模塊**,而**群組模塊**沒有任何內容,僅用以輔助排版。 群組模塊可以作為主選單、跑馬燈、輪播等複合模塊的載體,例如我們將數個選單模組放入群組模塊,該群組模塊就可做為雙層選單使用。 其他特點如下: 1. HTML 有標準格式,降低工程師、設計師維護的複雜度。 2. 各個模塊可以使用彼此的樣式,甚至 javascript 程式。 3. 讓使用者可定參數以控制顯示寬度比例。 4. javascript 動態載入,增進效能與維護性。 5. 引進樣板語言,提高建立靜態頁面、網頁測試的效率。 ### 定義 本文規範包括前台 HTML、CSS、javascript,無關後端資料處理。 ### 環境與工具 我們支援 IE8 以上的瀏覽器,使用 HTML5 宣告與 HTML4.2 的標籤。語意標籤被轉化為 class name,便於日後轉換(如 nav 標籤)。 唯二的例外是視訊與音訊模組,使用 HTML 5 原生撥放器,但也提供了相應的外掛給 IE8、IE9 使用。 開發環境推薦使用 Fire.app。以下是使用到的工具: <table> <tr> <th>開發環境</th> <td>Ruby(erb)、Java(Fire.app)、Scss、Compass</td> </tr> <tr> <th>工具</th> <td>Fire.app、requireJS、normalize、jquery</td> </tr> </table> ## 哲學 --- ### 模塊:模組與群組 平台基於兩種**模塊**:**群組模塊**與**模組模塊**。 > 共通平台定義了模塊的概念,每個具有內容的模塊都是模組模塊,而群組模塊沒有任何內容,僅用以輔助排版。 共通平台網頁的構成,應由模塊堆砌而成,不應有例外,當我們需要一個複合模組,應該使用現有模塊堆砌出來。 例如把日曆模組與選單模組加入到群組裡,該群組就成為帶選單的日曆模組。 模組有兩種命名法,一是依照模組的內容命名,例如:logo(標誌)。 另一種是依照模組的樣式命名,例如:pic-block(圖片區塊)。 一般來說,首頁模組使用內容命名法,內頁模組使用樣式命名法。 更多模塊的規範,可參閱 [模塊基礎結構](#module-and-group-structure) 章節。 ### CSS 選擇器與範圍 將平台 HTML 整理之後,大致可以歸類出數種結構,相同/相似結構的模塊,樣式設定會被寫在同一份檔案裡。 由於同類別的結構趨於相似,因此可以很方便的套用同類別的其他樣式。 如 group-list、 list-text 與 list-pic 這三個類別,相當程度上可以套用彼此的樣式,但群組與模組指定選擇器的方式稍有不同,需多加注意,可參閱 [選擇器邏輯](#selector-logic) 章節。 樣式可依所在位置有所變更,例如指定主選單在手機側欄、側邊欄與內頁時呈現不同的樣式,更多框架區塊可參閱 [底層、框架與內容](#base-layout) 章節,樣式的指定可參閱 [選擇器邏輯](#selector-logic) 章節。。 平台提供了許多指定寬度的方法,例如讓使用者透過參數來調整顯示的項目,可參閱 [關於設定數量的方法](#scss-len-function) 章節。 ### Javascript 優化 以往新增/修改 javascript 程式,必須在 head 標籤中引入,時間一久往往會造成維護上的問題,也載入不少沒有用到的程式,浪費資源。 平台使用 requireJS 解決這些問題,動態載入執行的檔案,解決相依性、套件衝突的問題,可參閱 [requireJS 運作方式](#js-require) 章節。 由於 HTML 有可依循的結構,因此許多模塊能夠共享程式。 如輪播模組可被 group-list、list-text 與 list-pic 這三個類別所使用,減少客製化。 ## HTML 實作</h2> --- ### 專案目錄結構與其他檔案 以下是專案目錄結構圖及說明。 - 專案目錄 |- .git |- .sass-cache |- audio |- Css |- Document |- erb |- images |- Prototype |- Sample |- Sass |- Script |- video |- .gitignore |- _index_layout.html.erb |- _layout.html.erb |- apple-touch-icon.png |- config.rb |- favicon.ico |- index.html.erb |- index.HTML.layout |- README.md <table> <tr> <th>文件、目錄</th> <th>說明</th> </tr> <tr> <td>.git</td> <td>存放 git 版本管理庫的目錄</td> </tr> <tr> <td>.sass-cache</td> <td>存放 Sass 編譯暫存檔案的目錄</td> </tr> <tr> <td>audio</td> <td>存放音訊檔案的目錄</td> </tr> <tr> <td>Css</td> <td>存放 css 文件的目錄</td> </tr> <tr> <td>Document</td> <td>存放其他相關文件的目錄</td> </tr> <tr> <td>erb</td> <td>存放 erb 樣板與模組的目錄</td> </tr> <tr> <td>images</td> <td>存放圖片、圖示的目錄(包含文字圖示)</td> </tr> <tr> <td>Prototype</td> <td>存放專案雛形、原始圖檔的目錄</td> </tr> <tr> <td>Sample</td> <td>DEMO 頁面</td> </tr> <tr> <td>Sass</td> <td>存放 Scss 文件</td> </tr> <tr> <td>Script</td> <td>存放 javascript 文件</td> </tr> <tr> <td>video</td> <td>存放視訊檔案</td> </tr> <tr> <td>.gitignore</td> <td>紀錄 Git 排除名單的文件</td> </tr> <tr> <td>_index_layout.html.erb</td> <td>index.html.erb 的樣板</td> </tr> <tr> <td>_layout.html.erb</td> <td>所有內頁的樣板</td> </tr> <tr> <td>apple-touch-icon.png</td> <td>iOS、OSX 使用較大的 icon 圖片</td> </tr> <tr> <td>config.rb</td> <td>compass、sass 的設定文件</td> </tr> <tr> <td>favicon.ico</th> <td>網頁 icon 圖示</td> </tr> <tr> <td>index.html.erb</td> <td>以 erb 撰寫的首頁</td> </tr> <tr> <td>index.HTML.layout</td> <td>指定 _index_layout.html.erb 為 index.html.erb 樣板的設定文件</td> </tr> <tr> <td>README.md</td> <td>說明文件,即本文</td> </tr> </table> ### 參數與意義 平台使用 data- 前輟屬性為 css 及 javascript 做一些事,強化整體規範與便利性。 一般的模塊具有屬性 data-type、data-index、data-child、data-func、data-setlen,而 body 則有屬性 data-js、data-admin, 項目(li)屬性有 data-width 等等,以下將這幾種屬性的用途、意義等一一說明。 <table> <tr> <th>屬性</th> <th>意義</th> <th>說明</th> <th>歸屬</th> </tr> <tr> <td>data-type</td> <td>模塊類型</td> <td>標示該模塊的類型,0 代表該模塊為模組,1到4分別為不同類別的群組,更多說明請至 <a href="#group-structure">群組類別與結構</a> 章節</td> <td>模塊</td> </tr> <tr> <td>data-index</td> <td>模塊或項目順序</td> <td>標示模塊的順序、標示項目的順序、標示 tr 的順序、標示 td 的順序</td> <td>模塊、項目(li)、thead、tbody、tfoot、tr、td</td> </tr> <tr> <td>data-child</td> <td>子模塊或子項目數量</td> <td>標示該模塊包含的子模塊數量、標示該清單的子項目數量,標示 thead、tbody、tfoot 中的 tr 數量,標示 tr 中的 td 與 th 數量</td> <td>群組、清單(ul)、thead、tbody、tfoot、tr</td> </tr> <tr> <td>data-func</td> <td>呼叫模塊程式</td> <td>提供一組 javascript 物件字串,用以呼叫程式模塊,更多說明請至 <a href="#node-and-files">以 node 呼叫 javascript 檔案</a> 章節</td> <td>模塊、body</td> </tr> <tr> <td>data-setlen</td> <td>設定模塊顯示項目</td> <td>設定內容項目顯示的數量,更多說明請至 <a href="#scss-len-function">關於設定數量的方法</a> 章節</td> <td>模塊</td> </tr> <tr> <td>data-js</td> <td>javascript 提示</td> <td>標示用戶是否開啟 javascript</td> <td>body</td> </tr> <tr> <td>data-admin</td> <td>管理者提示</td> <td>標示目前用戶是否為系統管理者</td> <td>body</td> </tr> <tr> <td>data-width</td> <td>選單寬度</td> <td>設定子模塊的 content 選單寬度,主要用於主選單,單位是基本寬度的倍數</td> <td>項目(li)</td> </tr> </table> ### 底層、框架與內容 底層與框架是一些**固定存在**的群組模塊。以 sys(系統級) 與 base(基礎級) 前輟區分。 前輟 sys 是系統級節點,內容由此節點開始堆砌,而樣式也應由此節點開始撰寫,**不應在 HTML、body、form 寫入任何樣式**。 前輟 base 是基礎級節點,是區分網頁層級的重要區塊,以下將一層一層的介紹它們的意義。 sys-root 是一組群組,是平台版面根節點,所有網頁的內容由它開始: <body> <div class="sys-root"> 網頁內容由此開始 </div> </body> 在 sys-root 之下有 base-mobile、base-extend 與 base-wrapper 三個主要區塊: base-mobile: 行動側欄。通常會放置主選單、分享模組等。 base-extend: 漂浮在瀏覽器上的物件層。通常會放置回到最頂按鈕等等。 base-wrapper: 網頁頁面框架。 <body> <div class="sys-root"> <div class="base-mobile"> 行動版側欄 </div> <div class="base-extend"> 漂浮物件層 </div> <div class="base-wrapper"> 網頁頁面框架 </div> </div> </body> base-wrapper 中分 base-header、base-content、base-footer 三個次要區塊: base-header: 網頁頁首。通常放置主選單、LOGO模組等。 base-content: 網頁主要內容。 base-footer: 網頁頁尾。通常放置一些網站資訊。 <body> <div class="sys-root"> <div class="base-mobile"> </div> <div class="base-extend"> </div> <div class="base-wrapper"> <div class="base-header"> 網頁頁首 </div> <div class="base-content"> 網頁主要內容 </div> <div class="base-footer"> 網頁頁尾 </div> </div> </div> </body> 依據首頁/內頁框架區塊的不同,可區分 base-module-area 與 base-page-area: base-module-area: 模組區塊。可放置各種模組。在內頁時該區塊會顯示在 base-page-area 之上。 base-page-area: 內頁框架。 <body> <div class="sys-root"> <div class="base-mobile"> </div> <div class="base-extend"> </div> <div class="base-wrapper"> <div class="base-header"> </div> <div class="base-content"> <div class="base-module-area"> 模組 </div> <div class="base-page-area"> 內頁 </div> </div> <div class="base-footer"> </div> </div> </div> </body> base-page-area 分為 base-aside 與 base-section: base-aside: 內頁側欄。通常放置選單或其他內容。 base-section: 內頁內容。 <HTML> <body> <div class="sys-root"> <div class="base-mobile"> </div> <div class="base-extend"> </div> <div class="base-wrapper"> <div class="base-header"> </div> <div class="base-content"> <div class="base-module-area"> </div> <div class="base-page-area"> <div class="base-aside"> 內頁側欄 </div> <div class="base-section"> 內頁內容 </div> </div> </div> <div class="base-footer"> </div> </div> </div> </body> </HTML> 若內頁內容中包含文章區塊,base-section 區塊會包含固定框架 base-article: base-article: 內頁文章區塊。 <body> <div class="sys-root"> <div class="base-mobile"> </div> <div class="base-extend"> </div> <div class="base-wrapper"> <div class="base-header"> </div> <div class="base-content"> <div class="base-module-area"> </div> <div class="base-page-area"> <div class="base-aside"> </div> <div class="base-section"> <div class="base-article"> 內頁文章 </div> </div> </div> </div> <div class="base-footer"> </div> </div> </div> </body> 以下以列表說明各框架具體內容與說明: <table> <tr> <th>框架</th> <th>意義</th> <th>說明</th> <th>層級</th> </tr> <tr> <td>.sys-root</td> <td>平台版面根節點</td> <td>內容由此節點開始堆砌,而樣式也應由此節點開始撰寫,不應在 HTML、body、form 寫入任何樣式</td> <td>1</td> </tr> <tr> <td>.base-mobile</td> <td>行動版側欄</td> <td>行動側欄框架。通常會放置主選單、分享模組等</td> <td>2</td> </tr> <tr> <td>.base-extend</td> <td>漂浮物件層</td> <td>漂浮在瀏覽器上的物件層。通常會放置回到最頂按鈕等等</td> <td>2</td> </tr> <tr> <td>.base-wrapper</td> <td>網頁頁面框架</td> <td>網頁頁面框架</td> <td>2</td> </tr> <tr> <td>.base-header</td> <td>網頁頁首</td> <td>通常放置主選單、LOGO模組等</td> <td>3</td> </tr> <tr> <td>.base-content</td> <td>網頁主要內容</td> <td>網頁主要內容</td> <td>3</td> </tr> <tr> <td>.base-footer</td> <td>網頁頁尾</td> <td>通常放置一些網站資訊</td> <td>3</td> </tr> <tr> <td>.base-module-area</td> <td>模組區塊</td> <td>可放置各種模組。在內頁時該區塊會顯示在 base-page-area 之上</td> <td>4</td> </tr> <tr> <td>.base-page-area</td> <td>內頁區塊</td> <td>內頁框架</td> <td>4</td> </tr> <tr> <td>.base-aside</td> <td>內頁側欄</td> <td>通常放置主選單或次選單</td> <td>5</td> </tr> <tr> <td>.base-section</td> <td>內頁內容</td> <td>內頁內容</td> <td>5</td> </tr> <tr> <td>.base-article</td> <td>內頁文章</td> <td>內頁文章區塊</td> <td>6</td> </tr> </table> 每一層框架都是一個群組,群組有其特定的結構,以上僅是結構示意,關於群組結構請參閱 [模塊基礎結構](#module-and-group-structure) 章節。 ### 模塊基礎結構 模塊是平台網頁的基礎單位,分為**群組模塊**與**模組模塊**。 只要該模組同時含有屬性 data-index 與 data-type,該節點就是一個模塊節點。 模塊由 header、content、footer 三個區塊組成,以下將列表說明他們的意義: <table> <tr> <th>區塊</th> <th>意義</th> <th>說明</th> </tr> <tr> <td>hd(header)</td> <td>標頭</td> <td>該模組的標題。若該模塊不須標題,那麼該模塊將沒有 hd 區塊</td> </tr> <tr> <td>ct(content)</td> <td>內容</td> <td>模組表達的意義</td> </tr> <tr> <td>ft(footer)</td> <td>附加資訊</td> <td>通常用來放置上一則、下一則、更多、RSS等附加操作或補充說明。若該模塊不須附加操作,那麼該模塊將沒有 ft 區塊</td> </tr> </table> 模塊、hd、ct、ft 都有一個 .in(inner) 區塊, in 用來輔助排版。 以下列出模塊基本結構: <data-index data-type> <div class="in"> <div class="hd"> <div class="in"> 標頭 </div> </div> <div class="ct"> <div class="in"> 內容 </div> </div> <div class="ft"> <div class="in"> 附加資訊 </div> </div> </div> </div> 模塊的 data-type 屬性指明了該模塊是群組還是模組,以下列舉 data-type 屬性的5個類別。 <table> <tr> <th>值</th> <th>說明</th> </tr> <tr> <td>0</td> <td>標示該模塊為模組</td> </tr> <tr> <td>1</td> <td>標示該模塊為分割群組</td> </tr> <tr> <td>2</td> <td>標示該模塊為頁籤群組</td> </tr> <tr> <td>3</td> <td>標示該模塊為單欄群組</td> </tr> <tr> <td>4</td> <td>標示該模塊為清單群組</td> </tr> </table> 關於更多群組類別的分別,請參閱 [群組類別與結構](#group-structure) 章節。 ### 群組類別與結構 群組是一個無內容的模塊,主要用於裝載其他的模塊,因此常利用它構成版面需要的框架。 群組分為**分割**、**頁籤**、**單欄**與**清單**,以下針對這四種模組的意義作說明。 #### 分割群組 分割群組會依照 [格線系統](#grid) 均分子模塊,如分割模組裡有兩個模塊,那麼子模塊的寬度則各為 50% (100% / 2),不過**該規則可被 data-setlen 屬性覆蓋**,可參閱 [關於設定數量的方法](#scss-len-function) 章節。 以下是分割群組的 HTML 格式: <data-index class="group" data-type="0"> <div class="in"> <div class="hd"> <div class="in"> <h3><span><a>標題</a></span> </div> </div> <div class="ct"> <div class="in"> 子模塊 </div> </div> </div> </div> #### 頁籤群組 提供切換頁籤功能的群組。 該模塊 content 具有一個列表,**第一個項目是頁籤模組、第二個項目以後依序放入其他子模塊**。 頁籤模組的 content 具有一個列表,依序為此頁籤群組的子模塊 header 文字。 一般情況下,頁籤群組的子模塊 hd 區塊應被隱藏。**若客戶沒有開啟 javascript,應隱藏頁籤模組,而顯示其他子模塊的 hd**。 以下是頁籤群組的 HTML 格式: <data-index class="group-tab" data-type="2"> <div class="in"> <div class="hd"> <div class="in"> <h3><span><a>標題</a></span> </div> </div> <div class="ct"> <div class="in"> <ul data-index data-child> <li data-index="1"> <data-index data-type="0"> <div class="in"> <div class="hd"> <div class="in"> <h4><span><a>頁籤模組</a></span></h4> </div> </div> <div class="ct"> <div class="in"> <ul data-child> <li data-index="1"><span><a>依序加入子模塊 header文字...</a></span><li> </ul> </div> </div> </div> </div> </li> <li data-index="2">依序加入子模塊...</li> </ul> </div> </div> </div> </div> #### 單欄群組 相對於分割群組,單欄群組並不分割子模塊,而是依順序由上而下排列。 以下是單欄群組的 HTML 格式: <data-index class="group" data-type="3"> <div class="in"> <div class="hd"> <div class="in"> <h3><span><a>標題</a></span> </div> </div> <div class="ct"> <div class="in"> 子模塊 </div> </div> </div> </div> #### 清單群組 清單群組的 ct 具有一個清單,而子模塊會被依序放入該清單的項目(li)中。 此模塊的結構與 list-text、 list-pic 的結構相似,因此可共用 javascript 與 css,惟選擇器的指定方法稍有不同,請參閱 [選擇器邏輯](#selector-logic) 章節。 以下是清單群組的 HTML 格式: <data-index class="group-list" data-type="3"> <div class="in"> <div class="hd"> <div class="in"> <h3><span><a>標題</a></span> </div> </div> <div class="ct"> <div class="in"> <ul data-child> <li>依序加入子模塊...</li> </ul> </div> </div> </div> </div> ### 模組類別與結構 與群組類別相仿,模組也分為11種類別。但不論屬於何種類別,模組的 data-type 都是 0。 類別區分模組的結構,如該模組是一個圖片列表,則屬於 list-pic 類別。 模組使用 class name 區別類別,每個模組都同時包含類別 class 與自定義 class,例如選單模組: <div calss="list-text nav" data-type="0" data-index="1"> list-text 是類別 class,而 nav 是自定義 class。 以下列舉出12種類別的意義、說明與參考格式: #### area-customize 客製的模組,如 google map 模組、iframe 框架模組、vedia 視訊模組、audio 音訊模組等等。以下是 area-customize 類別的 HTML 參考格式: <class="area-customize" data-index data-type="0"> <div class="in"> <div class="hd"> <div class="in"> <h4><span><a>標題</a></span></h4> </div> </div> <div class="ct"> <div class="in"> ... </div> </div> </div> </div> #### area-editor 意指客戶可以使用編輯器編輯內文的模組,如使用者發佈文章區塊。 以下是 area-editor 類別的 HTML 參考格式: <class="area-editor" data-index data-type="0"> <div class="in"> <div class="hd"> <div class="in"> <h4><span><a>標題</a></span></h4> </div> </div> <div class="ct"> <div class="in"> 使用者編輯文字 </div> </div> </div> </div> #### area-essay 參雜文字與圖片,以文字為主體的模組,如最新消息。 以下是 area-essay 類別的 HTML 參考格式,**area-essay 的內標標題 class 應為 .caption**: <class="area-essay" data-index data-type="0"> <div class="in"> <div class="hd"> <div class="in"> <h4><span><a>標題</a></span></h4> </div> </div> <div class="ct"> <div class="in"> <a href="#" class="div"> <div class="img"><span style="background-image: url('#')"><img src="#" alt=""></span></div> <div class="essay"> <div class="caption"><span>內容標題</span></div> <div class="label"> <ul> <li><span><i class="mark">標籤</i></span></li> </ul> </div> <div class="p"> <p><span>內容簡介</span></p> </div> </div> </a> </div> </div> </div> </div> #### area-figure 參雜文字與圖片,以圖片為主體的模組,如相簿。 以下是 area-figure 類別的 HTML 參考格式,**area-figure 的內標標題 class 應為 .figcaption**: <class="area-figure" data-index data-type="0"> <div class="in"> <div class="hd"> <div class="in"> <h4><span><a>標題</a></span></h4> </div> </div> <div class="ct"> <div class="in"> <a href="#" class="div"> <div class="img"><span style="background-image: url('#')"><img src="#" alt=""></span></div> <div class="essay"> <div class="figcaption"><span>內容標題</span></div> <div class="label"> <ul> <li><span><i class="mark">標籤</i></span></li> </ul> </div> <div class="p"> <p><span>內容簡介</span></p> </div> </div> </a> </div> </div> </div> </div> #### area-form 以表單為主體的模組,如搜尋。 以下是 area-form 類別的 HTML 參考格式: <class="area-form" data-index data-type="0"> <div class="in"> <div class="hd"> <div class="in"> <h4><span><a>標題</a></span></h4> </div> </div> <div class="ct"> <div class="in"> <div class="fieldset"> <span class="text"><input type="text"></span> <span class="submit"><a href="#">送出</a></span> </div> </div> </div> </div> </div> #### area-table 以表格為主體的模組。 以下是 area-table 類別的 HTML 參考格式: <class="area-table" data-index data-type="0"> <div class="in"> <div class="hd"> <div class="in"> <h4><span><a>標題</a></span></h4> </div> </div> <div class="ct"> <div class="in"> <table> <thead data-index data-child> <tr data-index data-child> <th data-index><span>標頭</span></th> </tr> </thead> <tbody data-index data-child> <tr data-index data-child> <td data-index><span>內容</span></td> </tr> </tbody> <tfoot data-index data-child> <tr data-index data-child> <th data-index><span>附加資訊</span></th> </tr> </foot> </table> </div> </div> </div> </div> #### list-multiple 多重清單模組,如頁次導航列。 以下是 area-audio 類別的 list-multiple 參考格式: <class="list-multiple" data-index data-type="0"> <div class="in"> <div class="hd"> <div class="in"> <h4><span><a>標題</a></span></h4> </div> </div> <div class="ct"> <div class="in"> <ul data-index data-child><li><span>1</span></li></ul> <ul data-index data-child><li><span>1</span></li></ul> </div> </div> </div> </div> #### list-pic 圖片清單模組,如標章。 以下是 list-pic 類別的 HTML 參考格式: <class="list-text" data-index data-type="0"> <div class="in"> <div class="hd"> <div class="in"> <h4><span><a>標題</a></span></h4> </div> </div> <div class="ct"> <div class="in"> <ul data-index data-child> <li data-index><span style="background-image: url('#');"><a href="#"><img src="#" alt=""></a></span></li> </ul> </div> </div> </div> </div> #### list-text 文字清單模組,如選單。 以下是 list-text 類別的 HTML 參考格式: <class="list-text" data-index data-type="0"> <div class="in"> <div class="hd"> <div class="in"> <h4><span><a>標題</a></span></h4> </div> </div> <div class="ct"> <div class="in"> <ul data-index data-child> <li data-index><span><a><i class="mark">標籤</i>依序加入文字項目...</a></span></li> </ul> </div> </div> </div> </div> #### simple-pic 顯示一張圖片的模組,如圖片模組。 以下是 simple-pic 類別的 HTML 參考格式: <class="simple-pic" data-index data-type="0"> <div class="in"> <div class="hd"> <div class="in"> <h4><span><a>標題</a></span></h4> </div> </div> <div class="ct"> <div class="in"> <span style="background-image: url('#');"><a href="#"><img src="#" alt=""></a></span> </div> </div> </div> </div> #### simple-text 只敘述一行文字的文字模組,如LOGO 模組。 以下是 simple-text 類別的 HTML 參考格式: <class="simple-text" data-index data-type="0"> <div class="in"> <div class="hd"> <div class="in"> <h4><span><a>標題</a></span></h4> </div> </div> <div class="ct"> <div class="in"> <span><a>文字</a></span> </div> </div> </div> </div> 若想參閱所有模組列表,可以參閱 [模組盤點](https://docs.google.com/document/d/15XokVf-KISYmoEm7otdGADsnAHNIpbIypbBoaRkbMrE/edit)。 ### 組件 模組的 ct 是一塊有意義的內容,ct 由組件組成,有規則可依循。 組件依模組需求,由小區塊到大區塊堆砌,盡可能以簡潔為主, 例如使用 div.paragraph>p>span 即可滿足排版需求,則不需用到 div.essay>div.paragraph>p>span。 以下列出可用的組件(emmet 格式): <table> <tr> <th colspan="2">表單類</th> </tr> <tr> <td>表單主題區塊</td> <td>div.form></td> </tr> <tr> <td>表單區塊</td> <td>.fieldset></td> </tr> <tr> <td>表單標題組件</td> <td>.legend>a{可選}>span>{標題文字}</td> </tr> <tr> <td>輸入框組件</td> <td>span.button>input[type='button']</td> </tr> <tr> <td></td> <td>span.checkbox>input[type='checkbox']</td> </tr> <tr> <td></td> <td>span.color>input[type='color']</td> </tr> <tr> <td></td> <td>span.date>input[type='date']</td> </tr> <tr> <td></td> <td>span.datetime>input[type='datetime']</td> </tr> <tr> <td></td> <td>span.datetime_local>input[type='datetime-local']</td> </tr> <tr> <td></td> <td>span.email>input[type='email']</td> </tr> <tr> <td></td> <td>span.file>input[type='file']</td> </tr> <tr> <td></td> <td>span.hidden>input[type='hidden']</td> </tr> <tr> <td></td> <td>span.input_image>input[type='image']</td> </tr> <tr> <td></td> <td>span.month>input[type='month']</td> </tr> <tr> <td></td> <td>span.number>input[type='number']</td> </tr> <tr> <td></td> <td>span.input>input[type='password']</td> </tr> <tr> <td></td> <td>span.radio>input[type='radio']</td> </tr> <tr> <td></td> <td>span.range>input[type='range']</td> </tr> <tr> <td></td> <td>span.reset>input[type='reset']</td> </tr> <tr> <td></td> <td>span.search>input[type='search']</td> </tr> <tr> <td></td> <td>span.submit>input[type='submit']</td> </tr> <tr> <td></td> <td>span.tel>input[type='tel']</td> </tr> <tr> <td></td> <td>span.text>input[type='text']</td> </tr> <tr> <td></td> <td>span.time>input[type='time']</td> </tr> <tr> <td></td> <td>span.url>input[type='url']</td> </tr> <tr> <td></td> <td>span.week>input[type='week']</td> </tr> <tr> <td>標籤組件</td> <td>span.label>label{可選}</td> </tr> <tr> <td>勾選框組件</td> <td>span.checkbox>(input[type='checkbox'])+(span.label>label)</td> </tr> <tr> <td>單選框組件</td> <td>span.checkbox>(input[type='radio'])+(span.label>label)</td> </tr> <tr> <td>文字輸入框組件</td> <td>div.textarea>textarea</td> </tr> <tr> <td></td> <td>span.textarea>textarea</td> </tr> <tr> <td>選擇框組件</td> <td>div.select>select>option>{文字}</td> </tr> <tr> <td></td> <td>span.select>select>option>{文字}</td> </tr> <tr> <th colspan="2">表格類</th> </tr> <tr> <td>表格主題區塊</td> <td>div.table></td> </tr> <tr> <td>表格區塊</td> <td>table></td> </tr> <tr> <td>表格標題區塊</td> <td>thead></td> </tr> <tr> <td>表格內容區塊</td> <td>tbody></td> </tr> <tr> <td>表格附加資訊區塊</td> <td>tfoot></td> </tr> <tr> <td>表格內容組件</td> <td>tr>td>span>a{可選}</td> </tr> <tr> <td></td> <td>tr>th>span>a{可選}</td> </tr> <tr> <th colspan="2">清單類</th> </tr> <tr> <td>清單主題區塊</td> <td>div.list></td> </tr> <tr> <td></td> <td>a.list></td> </tr> <tr> <td>清單區塊</td> <td>ul></td> </tr> <tr> <td></td> <td>ol></td> </tr> <tr> <td>項目</td> <td>li>span>a{可選}</td> </tr> <tr> <th colspan="2">標籤類</th> </tr> <tr> <td>標籤主題區塊</td> <td>div.label></td> </tr> <tr> <td>標籤區塊</td> <td>ul></td> </tr> <tr> <td>項目</td> <td>li>span>a{可選}</td> </tr> <tr> <th colspan="2">內文類</th> </tr> <tr> <td>內文主題區塊</td> <td>div.essay></td> </tr> <tr> <td></td> <td>a.essay></td> </tr> <tr> <td>內文區塊</td> <td>div.paragraph</td> </tr> <tr> <td></td> <td>a.paragraph></td> </tr> <tr> <td>標題組件</td> <td>div.caption>span>a{可選}>{標題文字}</td> </tr> <tr> <td>標題內文組件</td> <td>h1>span>a{可選}</td> </tr> <tr> <td></td> <td>h2>span>a{可選}</td> </tr> <tr> <td></td> <td>h3>span>a{可選}</td> </tr> <tr> <td></td> <td>h4>span>a{可選}</td> </tr> <tr> <td></td> <td>h5>span>a{可選}</td> </tr> <tr> <td></td> <td>h6>span>a{可選}</td> </tr> <tr> <td>段落文字組件</td> <td>p>span>a{可選}>{文字}</td> </tr> <tr> <td>簡單文字組件</td> <td>span>a{可選}>{文字}</td> </tr> <tr> <th colspan="2">圖片類</th> </tr> <tr> <td>圖片主題區塊</td> <td>div.figure></td> </tr> <tr> <td></td> <td>a.figure></td> </tr> <tr> <td>圖片區塊</td> <td>div.images></td> </tr> <tr> <td></td> <td>a.images></td> </tr> <tr> <td>標題組件</td> <td>div.figcaption>span>a{可選}>{標題文字}</td> </tr> <tr> <td>複數圖片組件</td> <td>div.image>span>a{可選}>img</td> </tr> <tr> <td>簡單圖片組件</td> <td>span>a{可選}>img</td> </tr> <tr> <th colspan="2">標題類</th> </tr> <tr> <td>標題主題區塊</td> <td>div.heading></td> </tr> <tr> <td></td> <td>a.heading></td> </tr> <tr> <td>標題區塊</td> <td>div.caption></td> </tr> <tr> <td></td> <td>a.caption></td> </tr> <tr> <td>標題組件</td> <td>span>a{可選}>{標題文字}</td> </tr> <tr> <th colspan="2">區塊類</th> </tr> <tr> <td>區塊</td> <td>div.division></td> </tr> <tr> <td></td> <td>a.division></td> </tr> <tr> <th colspan="2">視訊類</th> </tr> <tr> <td>視訊主題區塊</td> <td>.video></td> </tr> <tr> <td>視訊區塊</td> <td>video></td> </tr> <tr> <td>視訊</td> <td>source</td> </tr> <tr> <td>註解</td> <td>span>a{可選}>{標題文字}</td> </tr> <tr> <th colspan="2">音訊類</th> </tr> <tr> <td>音訊主題區塊</td> <td>.audio></td> </tr> <tr> <td>音訊區塊</td> <td>audio></td> </tr> <tr> <td>音訊</td> <td>source</td> </tr> <tr> <td>註解</td> <td>span>a{可選}>{標題文字}</td> </tr> </table> ### 以 class name 表示狀態 在撰寫動態切換時,我們經常使用 class name 切換,class name 應使用**相對自然狀態命名**。 例如手機側欄的自然狀態是關閉,當它被打開,切換的 class name 應取名為:is-open。 反之, fat footer 的自然狀態是開啟,當它要關閉,使用的 class name 應取名為:is-close。 注意,切換狀態的 class name 只應出現在模塊、項目(li) 或 表單(input、select、textarea)項目的父 span (.text、.select、.radio...etc),不應出現在其他地方。 **假如切換狀態的行為是發生在清單群組上,那麼切換的狀態應寫在清單群組的 li 上。** **若切換狀態的行為是發生在該模組中,那麼切換的狀態應寫在模組上。** ## erb 實作 --- ### erb 目錄結構 以下是 erb 目錄結構圖及說明。 - 專案目錄 |- erb | |- base | | |- _base-article.html.erb | | |- _base-aside.html.erb | | |- _base-content_index.html.erb | | |- _base-content_page.html.erb | | |- _base-extend.html.erb | | |- _base-footer.html.erb | | |- _base-header.html.erb | | |- _base-mobile.html.erb | | |- _base-module-area_index.html.erb | | |- _base-module-area_page.html.erb | | |- _base-page-area.html.erb | | |- _base-section.html.erb | | |- _base-wrapper.html.erb | |- group | | |- 群組模塊... | |- module | | |- 模組模塊... | |- sys | | |- _icon.html.erb | | |- _meta.html.erb | | |- _script.html.erb | | |- _style.html.erb | | |- _test.html.erb | | |- _title.html.erb | | |- _variable.html.erb <table> <tr> <th>文件、目錄</th> <th>說明</th> </tr> <tr> <td>base</td> <td>存放 base 框架樣板的目錄</td> </tr> <tr> <td>base/_base-article.html.erb</td> <td>編輯 base-article 樣板的文件</td> </tr> <tr> <td>base/_base-aside.html.erb</td> <td>編輯 base-aside 樣板的文件</td> </tr> <tr> <td>base/_base-content_index.html.erb</td> <td>編輯 base-content 樣板的文件,供首頁使用</td> </tr> <tr> <td>base/_base-content_page.html.erb</td> <td>編輯 base-content 樣板的文件,供內頁使用</td> </tr> <tr> <td>base/_base-extend.html.erb</td> <td>編輯 base-extend 樣板的文件</td> </tr> <tr> <td>base/_base-footer.html.erb</td> <td>編輯 base-footer 樣板的文件</td> </tr> <tr> <td>base/_base-header.html.erb</td> <td>編輯 base-header 樣板的文件</td> </tr> <tr> <td>base/_base-mobile.html.erb</td> <td>編輯 base-mobile 樣板的文件</td> </tr> <tr> <td>base/_base-module-area_index.html.erb</td> <td>編輯 base-module-area 樣板的文件,供首頁使用</td> </tr> <tr> <td>base/_base-module-area_page.html.erb</td> <td>編輯 base-module-area 樣板的文件,供內頁使用</td> </tr> <tr> <td>base/_base-page-area.html.erb</td> <td>編輯 base-page-area 樣板的文件</td> </tr> <tr> <td>base/_base-section.html.erb</td> <td>編輯 base-section 樣板的文件</td> </tr> <tr> <td>base/_base-wrapper.html.erb</td> <td>編輯 base-wrapper 樣板的文件</td> </tr> <tr> <td>group</td> <td>存放 group 樣板的目錄</td> </tr> <tr> <td>module</td> <td>存放 module 樣板的目錄</td> </tr> <tr> <td>sys</td> <td>存放 head 設定的樣板如:icon、meta、script、style、title,另有測試用的 test 與全域變數設定檔 variable</td> </tr> <tr> <td>sys/_icon.html.erb</td> <td>設定 ico 引入的文件</td> </tr> <tr> <td>sys/_meta.html.erb</td> <td>設定 meta 設定的文件</td> </tr> <tr> <td>sys/_script.html.erb</td> <td>設定網頁 script 引入的文件</td> </tr> <tr> <td>sys/_style.html.erb</td> <td>設定網頁樣式引入的文件</td> </tr> <tr> <td>sys/_test.html.erb</td> <td>測試用的文件</td> </tr> <tr> <td>sys/_title.html.erb</td> <td>設定網頁 title 的文件</td> </tr> <tr> <td>sys/_variable.html.erb</td> <td>設定 erb 全域變數的文件</td> </tr> </table> ### erb 樣板語言 erb 幫助我們把 HTML 模組化,並提供隨機的內容與字元長度,幫助我們測試版型。 我們可以將個頁面一致的 HTML 存成一個檔案,在檢視時自動嵌套,簡化維護的難度。 erb 主要基於 Ruby 語言,因此可以在裡面使用 Ruby。 更多 erb 樣板語言請參閱 [fire.app erb 樣板語言簡介](http://fireapp.kkbox.com/doc/tw/tutorial_1.HTML)、[Ruby on Rails 實戰聖經 Action View - 樣板設計](https://ihower.tw/rails4/actionview.HTML)。 ### erb 運作方式 樣板是一段 HTML,在樣板中,我們可以輕易嵌入另一塊樣板,達成 HTML 模組化,以下我將示範如何嵌套一個 .html.erb 檔。 <div class="base-article" data-index="1" data-type="3" data-child="4"><div class="in"> <div class="hd"><div class="in"> </div><h3><span><a>嵌套範本</a></span></div> <div class="ct"><div class="in"> <!--嵌套 /erb/sample --> <%= render partial: "/erb/sample" %> </div></div> </div></div> 我們可藉由演示的語法嵌入 /erb/_sample.html.erb,以下將演示如何傳參數進 erb 檔案。 <div class="base-article" data-index="1" data-type="3" data-child="4"><div class="in"> <div class="hd"><div class="in"> </div><h3><span><a>嵌套範本</a></span></div> <div class="ct"><div class="in"> <!--嵌套 /erb/sample --> <%= render partial: "/erb/sample", locals: set({ index: 4, header_text: '模塊標頭' }) %> </div></div> </div></div> 使用一個 locals: set({ }) 的形式傳遞兩個區域變數 index 與 header_text 進去,index 的參數為 4。 接著演示 /erb/_sample.html.erb 如何接受這個參數。 <div class="sample" data-index="<%= index %>"> </div> 我們可以在 _sample.html.erb 檔案中,將 <% %> 中間放入區域變數名,此例即是 index 關鍵字,若要打印在 HTML 裡,則必須加上等號 <%= index %> ,更多教學請參閱 [局部樣板 Partials](https://ihower.tw/rails4/actionview.HTML#partials)。 以下列出幾個平台 erb 樣板常用的區域變數與其意義: <table> <tr> <th>變數</th> <th>說明</th> </tr> <tr> <td>index</td> <td>對應模塊的 data-index 屬性</td> </tr> <tr> <td>class_set</td> <td>新增 class name (框架群組無此功能)</td> </tr> <tr> <td>func_set</td> <td>對應模塊的 data-func 屬性 (框架群組無此功能)</td> </tr> <tr> <td>header_text</td> <td>設定模塊的 header 文字</td> </tr> <tr> <td>show_footer</td> <td>設定是否顯示 footer 區塊</td> </tr> <tr> <td>show_mark</td> <td>設定是否顯示標籤</td> </tr> <tr> <td>access_key</td> <td>設定導盲磚按鍵</td> </tr> <tr> <td>access_title</td> <td>設定導盲磚標頭</td> </tr> <tr> <td>inner</td> <td>若模塊內鑲嵌其他模塊,可指定鑲入檔案</td> </tr> </table> 關於所有的變數,可參閱 erb/module/_simple-text_test-require.html.erb 的內容。 ### 關於 layout 樣板 layout.html.erb 是所有網頁的預設樣板,會將專案中的 html.erb 與 .HTML 檔案嵌入指定的框架裡。 ### 關於 index樣板 但首頁的樣板有別於一般內頁,因此必需另外編輯樣板 _index_layout.html.erb 供 index.html.erb 使用。 index.html.layout 指明 _index_layout.html.erb 為 index.html.erb 的樣板。 ### 關於 sys/variable 在 [erb 運作方式](#erb-run) 曾提及區域變數的使用方式,另有全域變數設定在 /erb/sys__variable.html.erb。 全域變數以 $ 前輟命名,使用方式如同區域變數一般。 <div class="sample" data-type="<%= $module %>"> </div> ### 假字與圖片 erb 提供了假字及假圖的功能,使用方式請參閱 [更新更強大的網頁設計師好幫手 Fire.app 進階篇](http://demo.tc/post/758)。 ## CSS/SCSS 實作 ### SCSS 目錄結構 以下是 Scss 目錄結構圖及說明。 - 專案目錄 |- SCSS | |- base | | |- _function.scss | | |- _icon-font.scss | | |- _layout.scss | | |- _variable.scss | |- group | | |- _group.scss | | |- _group_list.scss | | |- _group_tab.scss | |- module | | |- _area-customize.scss | | |- _area-editor.scss | | |- _area-essay.scss | | |- _area-figure.scss | | |- _area-form.scss | | |- _area-table.scss | | |- _list-multiple.scss | | |- _list-pic.scss | | |- _list-text.scss | | |- _simple-pic.scss | | |- _simple-text.scss | |- sys | | |- _function.scss | | |- _global.scss | | |- _grid.scss | | |- _icon-font.scss | | |- _icon-pic.scss | | |- _normalize.scss | | |- _variable.scss | |- global.scss | |- page.scss | |- print.scss <table> <tr> <th>文件、目錄</th> <th>說明</th> </tr> <tr> <td>base</td> <td>存放 Scss 基本設定的目錄</td> </tr> <tr> <td>base/_function.scss</td> <td>基礎級方法,可依切板需求修改文件</td> </tr> <tr> <td>base/_icon-font.scss</td> <td>文字 icon 基礎級設定</td> </tr> <tr> <td>base/_layout.scss</td> <td>版面 Scss 設定</td> </tr> <tr> <td>base/_variable.scss</td> <td>基礎級變數,可依切板需求修改文件</td> </tr> <tr> <td>group</td> <td>存放群組樣式目錄</td> </tr> <tr> <td>group/_group.scss</td> <td>分割、單欄群組樣式設定</td> </tr> <tr> <td>group/_group_list.scss</td> <td>清單群組樣式設定</td> </tr> <tr> <td>group/_group_tab.scss</td> <td>頁籤群組樣式設定</td> </tr> <tr> <td>module</td> <td>存放模組樣式目錄</td> </tr> <tr> <td>module/_area-customize.scss</td> <td>對應模組 area-customize 類別的樣式設定</td> </tr> <tr> <td>module/_area-editor.scss</td> <td>對應模組 area-editor 類別的樣式設定</td> </tr> <tr> <td>module/_area-essay.scss</td> <td>對應模組 area-essay 類別的樣式設定</td> </tr> <tr> <td>module/_area-figure.scss</td> <td>對應模組 area-figure 類別的樣式設定</td> </tr> <tr> <td>module/_area-form.scss</td> <td>對應模組 area-form 類別的樣式設定</td> </tr> <tr> <td>module/_area-table.scss</td> <td>對應模組 area-table 類別的樣式設定</td> </tr> <tr> <td>module/_list-multiple.scss</td> <td>對應模組 list-multiple 類別的樣式設定</td> </tr> <tr> <td>module/_list-pic.scss</td> <td>對應模組 list-pic 類別的樣式設定</td> </tr> <tr> <td>module/_list-text.scss</td> <td>對應模組 list-text 類別的樣式設定</td> </tr> <tr> <td>module/_simple-pic.scss</td> <td>對應模組 simple-pic 類別的樣式設定</td> </tr> <tr> <td>module/_simple-text.scss</td> <td>對應模組 simple-text 類別的樣式設定</td> </tr> <tr> <td>sys</td> <td>存放系統級設定的目錄</td> </tr> <tr> <td>sys/_function.scss</td> <td>系統級方法,非必要請勿修改文件</td> </tr> <tr> <td>sys/_global.scss</td> <td>整合 sys/variable、base/variable、sys/function、base/function、sys/icon-font、base/icon-font、sys/icon-pic 的基本 Scss 檔</td> </tr> <tr> <td>sys/_grid.scss</td> <td>格線系統,更多資訊請參閱 [格線系統](#grid) 章節。 </td> </tr> <tr> <td>sys/_icon-font.scss</td> <td>文字 icon 系統級設定,更多資訊請參閱 [文字圖示](#scss-font-icon) 章節</td> </tr> <tr> <td>sys/_icon-pic.scss</td> <td>sprite 圖的系統級設定,更多資訊請參閱 [sprite 圖示](#scss-sprite-picture) 章節</td> </tr> <tr> <td>sys/_normalize.scss</td> <td>normalize.css,相關資訊請參閱 (normalize.css)[https://necolas.github.io/normalize.css/]</td> </tr> <tr> <td>sys/_variable.scss</td> <td>系統級變數,非必要請勿修改文件</td> </tr> <tr> <td>global.scss</td> <td>整合 sys/normalize、sys/grid、base/layout 與所有群組與模組的檔案,將會匯出 global.css</td> </tr> <tr> <td>page.scss</td> <td>內頁將會額外引入的樣式設定檔案,將會匯出 page.css</td> </tr> <tr> <td>print.scss</td> <td>列印將會被應用的樣式設定檔案,將會匯出 print.css</td> </tr> </table> ### SCSS Sass 是為了增強 CSS 而設計的語言,Scss 則是 Sass 另一種寫法。 它讓 CSS 可以使用變數、函式,提升撰寫 CSS 的效率,更多教學請參閱 [Sass 用法指南](http://www.ruanyifeng.com/blog/2012/06/sass.HTML)。 ### 格線系統 平台格線系統分為**自然分割**與**設定分割**。 分割群組均分子模塊寬度,是**依據 [data-child] 的值作判斷**。 例如分割模組([data-type="1"])具有兩個子模塊([data-child="2"]),那麼就會自然均分子模塊(具有 [data-index][data-type] 的節點),稱為自然分割: [data-type="1"][data-child="2] > .inner > .content > .inner > [data-index][data-type] { width: 50%; //100% / 2 } 設定分割是依據 [data-setLen] 的值作為 CSS 判斷,將會覆蓋自然分割的設定。 例如分割模組([data-type="1"])設定2排均分([data-setLen="2"]),那麼就會均分子模塊([data-index][data-type]): [data-type="1"][data-setLen="2] > .inner > .content > .inner > [data-index][data-type] { width: 50%; //100% / 2 } 更多關於 [data-setLen] 的說明,請連結說明至 [關於設定數量的方法](#scss-len-function) 章節。 ### 類別 相同類別的模塊樣式,都撰寫在同一支 SCSS 檔案中。如: <div class="list-text nav" data-type="0"></div> <div class="list-text font-size" data-type="0"></div> 以上兩個模塊的樣式,都在 /Sass/module/list-text.scss 中,便於快速的參考、交換、複製其他相同類別的模塊樣式。 .list-text { &.nav { ... } &.font-size { ... } } ### 選擇器邏輯 模組與群組的結構十分相似,.group-list 與 .list-text、.list-pic 的結構也十分相似,甚至所有模塊的 footer 與 header 長得幾乎相同,因此樣式的交換上十分便利,但還是要注意權重指定的問題。 一般來說,在設定樣式的時候,應盡可能減少指定的層數: .list-text { &.nav { .ct { ... } } } 一個模組只會有一個 ct,因此可以用這種選取方法指定到唯一的 ct。 **但群組下可能會有許多模塊,每個模塊都有自己的 ct**,因此若要指明群組自己的的 ct,必須如下指定: [data-index][data-type="1"] { &.group { > .in { > .ct { ... } } } } 此外,**行為必須寫在發生行為的模塊上**,如主選單群組的子模塊觸發 :hover,秀出該模塊的 content,這個行為應該寫在 主選單群組,而非子模塊(群組行為)。 我們也可以指定同一模塊在不同框架下的樣式,例如: .nav { .base-header & { color: #000; } .base-footer & { color: #555; } } 那麼 nav 模塊就會在 base-header 框架下被設為 color: #000,在 base-footer框架下被設為 color: #555。 更多框架區塊可參閱 [底層、框架與內容](#base-layout)。 ### base/variable、base/function 與 sys/function base/function 與 base/variable 將常用的變數與功能定義在一起,sys/function 則負責定義一些底層方法。 以下首先說明 base/variable 的一些常用內容: <table> <tr> <th colspan="3">$ 變數</th> </tr> <tr> <td>設定</td> <td>$debug</td> <td>是否啟用除錯模式(會提示掉圖、掉文字圖示)</td> </tr> <tr> <td></td> <td>$rwd</td> <td>是否啟用 rwd(如不啟用,將忽略 RWD 樣式設定)</td> </tr> <tr> <td>灰階</td> <td>$white</td> <td>非常淺</td> </tr> <tr> <td></td> <td>$light</td> <td>白色</td> </tr> <tr> <td></td> <td>$light-gray</td> <td>淺灰</td> </tr> <tr> <td></td> <td>$gray</td> <td>灰色</td> </tr> <tr> <td></td> <td>$deep-gray</td> <td>深灰</td> </tr> <tr> <td></td> <td>$deep</td> <td>深色</td> </tr> <tr> <td></td> <td>$black</td> <td>黑色</td> </tr> <tr> <td>主要版面顏色</td> <td>$major-color</td> <td>主色</td> </tr> <tr> <td></td> <td>$minor-color</td> <td>次色</td> </tr> <tr> <td>其他版面顏色</td> <td>$lesser1-color</td> <td>更次色(設定多個為 $lesser2-color、$lesser3-color...)</td> </tr> <tr> <td>文字顏色</td> <td>$title-color</td> <td>標題色</td> </tr> <tr> <td></td> <td>$span-color</td> <td>附註色</td> </tr> <tr> </tr> <tr> <td>文字大小(建議使用 em)</td> <td>$font-size-xs</td> <td>極小字</td> </tr> <tr> <td></td> <td>$font-size-s</td> <td>小字</td> </tr> <tr> <td></td> <td>$font-size-m</td> <td>一般字</td> </tr> <tr> <td></td> <td>$font-size-l</td> <td>大字</td> </tr> <tr> <td></td> <td>$font-size-xl</td> <td>極大字</td> </tr> <tr> <td>文字厚度</td> <td>$font-weight-n</td> <td>一般字體</td> </tr> <tr> <td></td> <td>$font-weight-b</td> <td>粗字體</td> </tr> <tr> <td>文字行高</td> <td>$line-height-xs</td> <td>極小行高</td> </tr> <tr> <td></td> <td>$line-height-s</td> <td>小行高</td> </tr> <tr> <td></td> <td>$line-height-m</td> <td>一般行高</td> </tr> <tr> <td></td> <td>$line-height-l</td> <td>高行高</td> </tr> <tr> <td></td> <td>$line-height-xl</td> <td>極高行高</td> </tr> <tr> <td>文字間格</td> <td>$letter-spacing-xs</td> <td>極小文字間隔</td> </tr> <tr> <td></td> <td>$letter-spacing-s</td> <td>小文字間隔</td> </tr> <tr> <td></td> <td>$letter-spacing-m</td> <td>中文字間隔</td> </tr> <tr> <td></td> <td>$letter-spacing-l</td> <td>寬字間隔</td> </tr> <tr> <td></td> <td>$letter-spacing-xl</td> <td>極寬文字間隔</td> </tr> <tr> <td>透明度</td> <td>$opacity-vl</td> <td>極低透明度</td> </tr> <tr> <td></td> <td>$opacity-l</td> <td>低透明度</td> </tr> <tr> <td></td> <td>$opacity-m</td> <td>中等透明度</td> </tr> <tr> <td></td> <td>$opacity-h</td> <td>高透明度</td> </tr> <tr> <td></td> <td>$opacity-vh</td> <td>極高透明度</td> </tr> <tr> <td>間隔設定</td> <td>$interval-xs</td> <td>極窄間隔</td> </tr> <tr> <td></td> <td>$interval-s</td> <td>窄間隔</td> </tr> <tr> <td></td> <td>$interval-m</td> <td>中等間隔</td> </tr> <tr> <td></td> <td>$interval-l</td> <td>寬間隔</td> </tr> <tr> <td></td> <td>$interval-xl</td> <td>極寬間隔</td> </tr> <tr> <td>基本動畫速度</td> <td>$transition</td> <td>動畫速度</td> </tr> <tr> <td>RWD設定</td> <td>$pc-width</td> <td>PC 版寬度</td> </tr> <tr> <td></td> <td>$pad-width</td> <td>Pad 版寬度</td> </tr> <tr> <td></td> <td>$phone-width</td> <td>手機版寬度</td> </tr> <tr> <td></td> <td>$rwd-btn-size</td> <td>手機側欄按鈕大小</td> </tr> <tr> <td>grid 框架設定</td> <td>$min-child</td> <td>最少的child數量</td> </tr> <tr> <td></td> <td>$max-child</td> <td>最多的child數量</td> </tr> <tr> <td></td> <td>$min-setLen</td> <td>最少的單行數量</td> </tr> <tr> <td></td> <td>$max-setLen</td> <td>最多的單行數量</td> </tr> <tr> <td>預設空文字</td> <td>$content</td> <td>空偽類的字元</td> </tr> <tr> <td>預設陰影</td> <td>$box-shadow</td> <td>區塊陰影</td> </tr> <tr> <td></td> <td>$text-shadow</td> <td>文字陰影</td> </tr> <tr> <td>文字圖示</td> <td>$icon-font-size</td> <td>文字圖示大小</td> </tr> <tr> <td></td> <td>$icon-font-color</td> <td>文字圖示顏色</td> </tr> <tr> <td>全頁文字</td> <td>$body-font-color</td> <td>網站文字顏色</td> </tr> <tr> <td></td> <td>$body-font-size-s</td> <td>"小"字級文字設定</td> </tr> <tr> <td></td> <td>$body-font-size-m</td> <td>"中"字級文字設定</td> </tr> <tr> <td></td> <td>$body-font-size-l</td> <td>"大"字級文字設定</td> </tr> <tr> <td>預設線條</td> <td>$border-style</td> <td>預設線條樣式</td> </tr> <tr> <td></td> <td>$border-width</td> <td>預設線條寬度</td> </tr> <tr> <td></td> <td>$border-color</td> <td>預設線條顏色</td> </tr> <tr> <td></td> <td>$border</td> <td>預設線條設定</td> </tr> <tr> <td>預設圓角</td> <td>$border-radius</td> <td>預設圓角設定</td> </tr> <tr> <td>連結顏色</td> <td>$link-color</td> <td>連結顏色</td> </tr> <tr> <td></td> <td>$visited-color</td> <td>造訪過連結顏色</td> </tr> <tr> <td></td> <td>$hover-color</td> <td>指標移入連結顏色,不可與任何底色重疊</td> </tr> <tr> <td></td> <td>$active-color</td> <td>點擊連結顏色</td> </tr> <tr> <td>按鈕樣式</td> <td>$btn-bg-color</td> <td>按鈕背景色</td> </tr> <tr> <td></td> <td>$btn-hover-bg-color</td> <td>按鈕滑入顏色</td> </tr> <tr> <td></td> <td>$btn-text-color</td> <td>按鈕文字顏色</td> </tr> <tr> <td></td> <td>$btn-padding</td> <td>按鈕內邊距,決定按鈕大小</td> </tr> <tr> <td></td> <td>$btn-padding-xs</td> <td>按鈕內邊距,決定按鈕大小</td> </tr> <tr> <td></td> <td>$btn-border</td> <td>按鈕線框</td> </tr> <tr> <td>輸入框樣式</td> <td>$input-border</td> <td>輸入框線框</td> </tr> <tr> <td></td> <td>$input-padding</td> <td>輸入框內邊距,決定輸入框大小</td> </tr> <tr> <td></td> <td>$input-bg-color</td> <td>輸入框背景色</td> </tr> <tr> <td>特殊字元"\"</td> <td>$backslash</td> <td>逃逸字元\</td> </tr> <tr> <td>分享</td> <td>$share-map</td> <td>圖片 & 顏色物件</td> </tr> <tr> <td>檔案類型</td> <td>$file-type-map</td> <td>圖片 & 顏色物件,下載項目的類型</td> </tr> <tr> <td>瀏覽器媒體</td> <td>$hack</td> <td>提供 @mixin hack() 方法使用,用 hack</td> </tr> <tr> <td></td> <td>$media</td> <td>提供 @mixin media() 方法使用,用於 RWD</td> </tr> <tr> <td>瀏覽器支持</td> <td>$supports</td> <td>提供 @mixin supports() 方法使用,用於 hack</td> </tr> </table> 以下說明 base/function 的內容: <table> <tr> <th colspan="2">%extend 樣式</th> </tr> <tr> <td>%reset-outer</td> <td>重新設定外部樣式</td> </tr> <tr> <td>%reset-inner</td> <td>重新設定內部樣式</td> </tr> <tr> <td>%reset</td> <td>重新設定全部樣式</td> </tr> <tr> <td>%clear-inner-module</td> <td>清除內部模塊的 margin</td> </tr> <tr> <td>%clear</td> <td>偽類清除浮動的方法</td> </tr> <tr> <td>%hide-text</td> <td>隱藏文字的方法</td> </tr> <tr> <td>%ellipsis</td> <td>超過範圍文字變成'...'的方法</td> </tr> <tr> <td>%cover-bg</td> <td>cover 底圖</td> </tr> <tr> <td>%contain-bg</td> <td>contain 底圖</td> </tr> <tr> <td>%icon</td> <td>偽類作為行內icon的方法</td> </tr> <tr> <td>%icon-pic</td> <td>偽類作為行內icon-pic的方法,請參閱 /bace/icon-pic</td> </tr> <tr> <td>%icon-font</td> <td>偽類作為行內icon-font的方法,請參閱 /bace/icon-font</td> </tr> <tr> <td>%center</td> <td>齊中寬度</td> </tr> <tr> <td>%title</td> <td>模組、內頁 title</td> </tr> <tr> <td>%module</td> <td>模組</td> </tr> <tr> <td>%module-area</td> <td>首頁模組</td> </tr> <tr> <td>%page</td> <td>內頁</td> </tr> <tr> <td>%page-area</td> <td>內頁模組</td> </tr> <tr> <td>%mobile</td> <td>手機側欄模組</td> </tr> <tr> <td>%mobile-area</td> <td>手機側欄模組</td> </tr> <tr> <td>%caption</td> <td>標題組件</td> </tr> <tr> <td>%label</td> <td>標籤組件</td> </tr> <tr> <td>%mark</td> <td>標籤元件</td> </tr> <tr> <td>%paragraph</td> <td>第二種標籤元件</td> </tr> <tr> <td>%btn</td> <td>按鈕樣式</td> </tr> <tr> <td>%btn-s</td> <td>小按鈕</td> </tr> <tr> <td>%btn-imp</td> <td>important 重要的按鈕</td> </tr> <tr> <td>%input</td> <td>輸入框樣式</td> </tr> <tr> <td>%article</td> <td>內文文章樣式</td> </tr> <tr> <td>%list</td> <td>列表樣式</td> </tr> <tr> <td>%list-hover</td> <td>列表 :hover 樣式</td> </tr> <tr> <td>%mask</td> <td>圖片遮罩</td> </tr> <tr> <td>%footer-btns</td> <td>更多按鈕</td> </tr> <tr> <td>%table</td> <td>表單樣式</td> </tr> <tr> <td>%table-hover</td> <td>表單 :hover 樣式</td> </tr> </table> <table> <tr> <th colspan="3">@mixin 涵式</th> </tr> <tr> <td>re-ellipsis()</td> <td>無參數</td> <td>反 %ellipsis 的方法</td> </tr> <tr> <td>bg-to-pic($img-src, $size, $height)</td> <td>$img-src:圖片路徑(字串), $size(可選):是否匯出圖片寬高(布林), 匯出指定倍數大小(數字), $height(可選):指定高度(數字)</td> <td>依圖改變大小並置中</td> </tr> <tr> <td>icon-pic($img-src, $size, $height)</td> <td>$img-src:圖片路徑(字串), $size(可選):是否匯出圖片寬高(布林) 匯出指定倍數大小(數字), $height(可選):指定高度(數字)</td> <td>取雪碧圖icon</td> </tr> <tr> <td>icon-font($font)</td> <td>$font:文字圖示名稱(字串)</td> <td>文字圖示,列表請參閱 https://icomoon.io</td> </tr> <tr> <td>icon-pic-btn($img-src, $size, $height)</td> <td>$img-src: 圖片路徑(字串), $size(可選):是否匯出圖片寬高(布林) 匯出指定倍數大小(數字), $height(可選):指定高度(數字)</td> <td>只有icon圖片的按鈕,隱含 佔用了:before</td> </tr> <tr> <td>default-min-len($type, $default-len, $max-len)</td> <td>$type:使用模塊類別(數字), $default-len:預設的項目數量(數字), $max-child(可選):最大的項目數量(數字)</td> <td>設定預設的最小單行數量</td> </tr> <tr> <td>default-len($type, $len)</td> <td>$type:使用模塊類別(數字), len:預設的項目數量(數字)</td> <td>設定預設的單行數量</td> </tr> <tr> <td>default-len-hide($type, $len)</td> <td>$type:使用模塊類別(數字), len:預設的項目數量(數字)</td> <td>設定預設的單行數量,並且隱藏超過的</td> </tr> <tr> <td>set-len($type, $len)</td> <td>$type:使用模塊類別(數字), len:預設的項目數量(數字)</td> <td>手動設定單行數量</td> </tr> <tr> <td>set-len-hide($type, $len)</td> <td>$type:使用模塊類別(數字), len:預設的項目數量(數字)</td> <td>手動設定單行數量,並且隱藏超過的</td> </tr> <tr> <td>len-rwd($key, $len, $int)</td> <td>$key:$media 物件中的 $key(字串), len:預設的項目數量(數字), int(可選):被計算的基數(數字)</td> <td>手動設定 rwd 數量</td> </tr> <tr> <td>rwd($max, $min)</td> <td>$max:最大寬度設定(數字), $min(可選):最小寬度設定(數字)</td> <td>自訂 RWD 寬度</td> </tr> <tr> <td>at($selector)</td> <td>$selector:選擇器(字串)</td> <td>在某個選擇器下的樣式</td> </tr> <tr> <td>hack($key)</td> <td>$key:$hack 物件中的 $key(字串)</td> <td>查詢瀏覽器媒體,給 hack 用</td> </tr> <tr> <td>media($key)</td> <td>$key:$media 物件中的 $key(字串)</td> <td>查詢瀏覽器媒體,給 rwd 用</td> </tr> <tr> <td>supports($key)</td> <td>$key:$supports 物件中的 $key(字串) 或是供判斷式使用的字串</td> <td>查詢瀏覽器媒體與瀏覽器支持,在不同情況下呈現不同樣式,是 CSS3 正式規範的判斷工具 @supports</td> </tr> <tr> <td>js($boolean)</td> <td>$boolean:瀏覽器是否有開啟 js(布林)</td> <td>有/無 js下的樣式表現</td> </tr> <tr> <td>admin($boolean)</td> <td>$boolean:瀏覽者是否為管理員(布林)</td> <td>管理員/一般使用者 登入的樣式</td> </tr> </table> 以下說明 sys/function 的內容: <table> <tr> <th colspan="3">@function 方法</th> </tr> <tr> <td>lighter($color, $int, $base)</td> <td>$color:顏色(字串), $int: 變亮的倍數(數字), $base(可選):變亮倍數的基數(數字)</td> <td>顏色變亮方法</td> </tr> <tr> <td>deeper($color,$int,$base)</td> <td>$color:顏色(字串), $int:變暗的倍數(數字), $base(可選):變暗倍數的基數(數字)</td> <td>顏色變暗方法</td> </tr> </table> ### 關於 sys/variable 我們可以開放一些變數,讓共通平台後臺覆蓋設定。但在命名變數時,**必須後輟 !default** 如: $major-color: #0088cc !default; 接著在 sys/variable 加入相應的註解,並依序加入 ,解釋 ,input type,格式如: // $major-color,主色,color ### noscript 方法 為了盡量避免使用 noscript 標籤,推薦使用平台提供的 @mixin js() 方法,以下將示範如何撰寫無 js 的樣式: .sys-root { color: #000; @include js(false) { color: #555; } } 在一般的的狀況下,.sys-root 的 color 是 #000,一但關閉了 js,.sys-root 的 color 就變成了 #555。 我們也可以透過 :before 或 :after 來插入引導文字。 具體的實作方法是在 body 加入 data-js 的屬性,在網站開始渲染之前,透過 javascript 把 data-js 設為 true,並將選擇器放在 [data-js="false"] 中。 ### hack 方法 平台設計了兩種 hack 方法,分別是 @mixin hack() 與 @mixin supports(),都是透過 @media query 的方式實作。 $hack 物件中彙整了一些針對瀏覽器設定的 @media query,只有特定的瀏覽器才能閱讀,以下示範將如何利用 @mixin hack(): .sys-root { color: #000; @include hack('ie6-7-8') { color: #555; } } 在一般的瀏覽器中,.sys-root 的 color 是 #000,在 ie6-7-8 的版本裡,.sys-root 的 color 就變成了 #555。 更多的瀏覽器選擇請參閱 $hack 物件。 另一個方法是透過 @mixin supports() 方法,我們一樣在 $supports 中整理了一些方法以判別瀏覽器,我們可以像使用 @mixin hack() 的方法去使用 @mixin supports(): .sys-root { color: #000; @include supports('gc28+') { color: #555; } } @mixin supports() 同時也是 CSS3 正式規範的判斷工具 @supports,例如我們可以判斷瀏覽器有沒有支援 display: flex,如果有,就設定 color: #555;: .sys-root { color: #000; @include supports('display: flex') { color: #555; } } 但一些較老舊的瀏覽器沒有提供 @supports 方法,需特別注意。 ### rwd 方法 平台提供了兩種 rwd 方法分別是 @mixin media() 與 @mixin rwd(),注意,當 $rwd 變數為 true 時,這些方法才能被使用。 @mixin media() 可以使用 $media 物件裡的項目設定,分別是 center、pc、mobile、pad 與 phone,以下列表說明: <table> <tr> <td>center</td> <td>當瀏覽器尺寸小於 $pc-width</td> </tr> <tr> <td>pc</td> <td>當瀏覽器尺寸介於 $pc-width 與 $pad-width 之間。</td> </tr> <tr> <td>mobile</td> <td>當瀏覽器尺寸小於 $pad-width</td> </tr> <tr> <td>pad</td> <td>當瀏覽器尺寸介於 $pad-width 與 $phone-width 之間。</td> </tr> <tr> <td>phone</td> <td>當瀏覽器尺寸小於 $phone-width</td> </tr> </table> 以下示範如何使用 @mixin media() 方法: .sys-root { color: #000; @include media('phone') { color: #555; } } 在預設的樣式設定中,.sys-root 的 color 是 #000 ,在 phone 的尺寸中,.sys-root 的 color 就變成了 #555。 另外,@mixin rwd() 方法允許我們設定兩個數字參數(第二個參數可選用),當瀏覽器尺寸介於兩個尺寸之間,網頁就會引用該樣式: .sys-root { color: #000; @include rwd(800, 300) { color: #555; } } .sys-root 的 color 是 #000 ,當瀏覽器尺寸介於 800px 與 300px 之間,.sys-root 的 color 就變成了 #555。 若第二個參數沒有值,表示在第一個尺寸以下的解析度都會引入該樣式: .sys-root { font-size: 1em; @include rwd(600) { font-size: 1.2em; } } .sys-root 的 font-size 是 1em ,當瀏覽器尺寸小於 600px,.sys-root 的 font-size 就變成了 1.2em。 ### admin 方法 為了讓 管理者/一般使用者 能取用不同樣式,請使用平台提供的 @mixin admin() 方法,以下將示範如何使用 @mixin admin(): .sys-root { color: #000; @include admin(true) { color: #555; } } 在一般使用者的狀況下,.sys-root 的 color 是 #000,如果是管理者,.sys-root 的 color 就變成了 #555。 ### 在 pc、pad、phone 寬度隱藏模塊 我們可以指定模塊在 pc、pad、phone 尺寸中隱藏,只要在欲隱藏的區塊加入 .is-pc-hide .is-pad-hide .is-phone-hide 相應的 class 即可。該方法的設定存在 base/_layout.scss 中。 ### 隱藏模塊 header 的方法 許多模塊都帶有 .header,但有時候我們希望把 .header 隱藏起來,這時候只需要在模塊加上 .is-hide-header 即可。 ### 文字圖示 文字圖示是一種字型,可以用 font-size 控制大小,color 控制顏色。 本平台引入 icomoon 圖示字型,以作為文字圖示來源,詳細資訊請參閱 [icomoon.io](https://icomoon.io)。 新增字型步驟如下: 1. 將 icon 包下載回來後,將包裡的 fonts 目錄檔案 .eot .svg .ttf .woff 檔案複製到 /images/icon-font 2. 開啟 style.css 3. 將 @font-face 與 [class^="icon-"], [class*=" icon-"] 樣式刪除 4. ":before" 字串全數刪除 5. 將 ".icon-" 取代成 "%icon-font-" 6. 將修改的內容複製至 /Sass/bace/icon-font.scss ### sprite 圖示 spriting 圖旨在減少HTTP的請求數。將多張小圖合併成一張大圖,再用 css 把小圖取出。 SCSS 能夠自動將指定資料夾中的圖片彙整成大圖,並自動產生 class name 取出。 我們將這個方法彙整進 @mixin icon-pic 方法,以下我們解說 spriting 圖應用的流程: 1. 將 a.png 圖片放入 images/icon-pic 2. 在某個選擇器中使用 @include icon-pic('a'); ### 關於設定數量的方法 在格線系統,我們依據 [data-child] 參數去設定顯示的寬度,也能使用 [data-setLen] 去覆蓋 [格線系統](#grid) 所定的寬度。 在 .group-list、list-text 與 list-pic 這三種模塊中,我們通常會設定 li 的寬度,但我們也希望使用 [data-setLen] 的方法去覆蓋我們編寫的寬度, 因此有了 @mixin default-len、@mixin default-len-hide、@mixin set-len、@mixin set-len-hide 這四個方法,以下演示使用的方式。 我們會這麼設定 li 的寬度。 .link { .content { ul { &:after { content: ''; display: block; height: 0; clear: both; visibility: hidden; } } li { width: 50%; float: left; } } } 但有了 @mixin default-len,我們可以這麼寫: .link { @include default-len(0, 2); .content { ul { } li { } } } 第一個參數是模塊類型是0,第二個參數是2,表示設定為兩排。 如果使用 default-len-hide,那麼超過設定值(第二個參數)以後的 li 都會被隱藏。 假使我們希望使用 @mixin default-len 的模塊可以使用 [data-setLen] 參數,則須加上 @mixin set-len,若使用 @mixin default-len-hide,則必須搭配 @mixin set-len-hide: .link { @include default-len(0, 2); @include set-len(0); .content { ul { } li { } } } 當我們使用這些方法時,就不能用一般的方法設定 li 的 rwd 的寬度,必須用到 @mixin len-rwd 方法: .link { @include default-len(0, 2); @include set-len(0); .content { ul { } li { @include len-rwd('pad', 2); @include len-rwd('phone', 1); } } } ## javascript/requireJS 實作 ### Script 目錄結構 以下是 Script 目錄結構圖及說明。 - 專案目錄 |- Script | |- app.js | |- js 模塊... | |- lib | | |- cookie.js | | |- domReady.js | | |- getNode.js | | |- jqueryPrivate.js | | |- main.js | | |- plugin.js | | |- fix.js <table> <tr> <th>文件、目錄</th> <th>說明</th> </tr> <tr> <td>app.js</td> <td>設定套件縮寫,執行 main.js 的檔案</td> </tr> <tr> <td>lib</td> <td>存放套件目錄</td> </tr> <tr> <td>lib/cookie.js</td> <td>操作 cookie 的方法套件</td> </tr> <tr> <td>lib/domReady.js</td> <td>延遲執行 require.js 的方法套件</td> </tr> <tr> <td>lib/getNode.js</td> <td>操作模塊的套件</td> </tr> <tr> <td>lib/jqueryPrivate.js</td> <td>引用私有 jquery 的套件</td> </tr> <tr> <td>lib/main.js</td> <td>執行 data-func 方法的套件</td> </tr> <tr> <td>lib/plugin.js</td> <td>擴充方法</td> </tr> <tr> <td>lib/fix.js</td> <td>修正瀏覽器錯誤</td> </tr> </table> ### requireJS 運作方式 requireJS 能動態插入頁面需要的 script,並解決相依性、套件衝突等問題,並提供模組化管理。 更多有關 requireJS 的介紹,請參閱 [require 官網](http://requirejs.org)。 ### 以 node 呼叫 javascript 檔案 先前曾在 [參數與意義](#HTML-parameter) 章節討論過 data-func 屬性的用途。 data-func 可藉由傳入一個字串化物件,來啟動指定的 js 模塊。 js 模塊應存在 /Script 目錄中(可在 app.js 改變基礎路徑),以下示範一個模組 nav ,啟動一個名為 hud 的 js 模塊: <div class="nav" data-type="0" data-func="{'hud':{}}"> data-func 的值為一個物件,{'hud':{}} 中的 hud 為 js 模塊,啟動一個 /Script/hud.js 的檔案。 hud 後面對應的物件為參數物件,你將可以在 hud.js 檔案中接收到這組參數: define(function(){ function main(env, opt, file){ do something... } return main; }); 在 hud.js 中的涵式 main 中會有三個參數,env 表示當前執行節點、opt 就是傳遞進去的參數、file 則是執行的 js 檔案名稱。以此例來說 file 即是 hud。 hud.js 最終回傳一個涵式給 main.js 並執行。 同一個模塊中也可以一次執行多個 js 模塊: <div class="nav" data-type="0" data-func="{'hud':{},'slider':{'auto':true}}"> 以此例來說,nav 同時啟用了 hud.js、slider.js 兩個 js 模塊,且 slider 傳送了一組參數 'auto':true,我們可以從 opt 取出參數。 define(function(){ function main(env, opt, file){ console.log(opt.auto) //true } return main; }); ### 關於 app.js 與 lib/main 先前曾在 [Script 目錄結構](#js-directory) 章節討論過 app.js 與 main.js。 app.js 的 requirejs.config 設定了套件的短名與命名配置,以下是 app.js 的程式部分內容: requirejs.config({ baseUrl: '/Scripts', paths: { 'jquery': ['//ajax.googleapis.com/ajax/libs/jquery/1/jquery.min', 'lib/jquery-1.11.3.min'] }, map: { '*': { 'jquery': 'lib/jqueryPrivate' }, 'lib/jqueryPrivate': { 'jquery': 'jquery' } } }); 以下以列表說明參數意義: <table> <tr> <th>baseUrl</th> <td>設定 js 模塊的路徑</td> </tr> <tr> <th>paths</th> <td>配置套件與相應的關鍵字</td> </tr> <tr> <th>map</th> <td>配置關鍵字在各個檔案的意義</td> </tr> </table> 關鍵字的作用在引用套件時,可用關鍵字取出套件內容。引用的方式是利用陣列包含關鍵字,例如某個 js 模塊需要取用 jquery 與 google map: define(['jquery','googleMaps'],function(){ function main(env, opt, file){ youu can use jquery and google map api here. } return main; }); 執行完 require.config 的設定後,接著 app.js 會執行 main.js requirejs(['main']); main.js 會抓出所有設有 data-func 的模塊,接著一一解析 data-func 的內容,接著如果有此 js 檔案,就執行該檔案。 以下是簡化過的 main.js 結構: requirejs(['domReady!'], function(dom){ var $nodes = document.querySelectorAll('[data-func]'); //抓出所有設有 data-func 的模塊 for( var i = 0; i < $nodes.length; i++ ) { //一一解析模塊的 data-func 的內容 var $env = $nodes[i], //存節點 $func = JSON.parse(($env.getAttribute('data-func')).replace(/\'/g,'"')); //轉成物件 for( var _file in $func ) { //取 function name 與設定參數 var $opt = $func[_file]; requirejs([_file], function(func){ //如果有此 js 檔案,就執行該檔案 func($env, $opt, _file); }); } } }); ### 關於 jquery.js 我們在 app.js 中設定了一個 jquery 關鍵字,該值是一個陣列: 'jquery': ['//ajax.googleapis.com/ajax/libs/jquery/1/jquery.min', 'lib/jquery-1.11.3.min'] 第一個字串是 google CDN 來源的 jquery,第二個是來自本地的 jquery 作為備援。當第一項資源失效時會立即啟用備援。 jquery 會污染全域變數 $,因此需要一個私有 jquery 對象的方法,jqueryPrivate 實作了這個方法。 先來看看 app.js 中 map 的設定: map: { '*': { 'jquery': 'lib/jqueryPrivate' }, 'lib/jqueryPrivate': { 'jquery': 'jquery' } } *代表所有的 js 模塊,在所有 js 模塊中,jquery 關鍵字代表 Script/lib/jqueryPrivate 這個模塊,而在 Script/lib/jqueryPrivate.js 中的 jquery 關鍵字則指向 //ajax.googleapis.com/ajax/libs/jquery/1/jquery.min 位置與 Script/lib/jquery.js 模塊。 以下示範如何在模塊中使用 jquery: define(['jquery'], function($){ function main(env, opt, file){ you can use $('body') jquery here... } return main; }); ### 關於 cookie.js cookie.js 定義了幾種方法來操控網頁 cookie,以下將列舉一些它的 api: <table> <tr> <td>set(_key, _value, _life)</td> <td>設定 cookie。_key 為 cookie 名稱, _value 為 cookie 內容, _life 為生命週期(天)</td> </tr> <tr> <td>get(_key)</td> <td>取 cookie 值。_key 為 cookie 名稱</td> </tr> <tr> <td>remove(_key)</td> <td>刪除 cookie。_key 為 cookie 名稱</td> </tr> </table> 以下示範如何在模塊中使用 cookie: define(['cookie'], function(cookie){ function main(env, opt, file){ cookie.set('sample', 'true', 1); } return main; }); ### 關於 getNode.js 因為我們統一了 HTML 結構,因此我們可更便捷、快速的取出想要的節點內容,getNode.js 就是為此而生。 getNode.js 定義了許多取得節點的方法。 getNode.js 的核心程式叫做 getChild,會抓取子節點並比對關鍵字,並把所有子節點展開、並回傳一個真正的陣列。 ### 關於 fix.js fix.js 主要是修補瀏覽器的錯誤,例如 IE8 在接受到 console.log 即會拋出錯誤,我們使用這支 js 修改類似的錯誤。