1. 程式人生 > >Bootstrap學習筆記-模態框

Bootstrap學習筆記-模態框

簡介

模態框經過了優化,更加靈活,以彈出對話方塊的形式出現,具有最小和最實用的功能集,參考modal

用法

HTML結構

  • div[class=modal[fade]][id]
    • div[class=modal-dialog[modal-lg|modal-md|modal-sm]]
      • div[class=modal-content]
        • div[class=modal-header]
          • h1/h2/h3/h4/h5/h6[class=modal-title]
        • div[class=modal-body]
        • div[class=modal-footer]

示例:

<div class
="modal fade" id="myModal"> <div class="modal-dialog" role="document"> <div class="modal-content"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal" aria-label="Close"> <span aria-hidden="true">&times
;</span> </button> <h4 class="modal-title">Modal title</h4> </div> <div class="modal-body"> ... </div> <div class="modal-footer"> <button type="button" class="btn btn-default" data-dismiss="modal">Close</button> <button type="button"
class="btn btn-primary">Save changes</button> </div> </div> </div> </div>

呼叫模態框

通過 data 屬性或 JavaScript 呼叫模態框外掛,可以根據需要動態展示隱藏的內容。模態框彈出時還會為 元素新增 .modal-open 類,從而覆蓋頁面預設的滾動行為,並且還會自動生成一個 .modal-backdrop 元素用於提供一個可點選的區域,點選此區域就即可關閉模態框。

通過 data 屬性

不需寫 JavaScript 程式碼也可啟用模態框。通過在一個起控制器作用的元素(例如:按鈕)上新增 data-toggle=”modal” 屬性和data-target=”#foo” 屬性,以及 href=”#foo” 屬性,用於指向被控制的模態框。例如:
<button type="button" data-toggle="modal" data-target="#myModal">Launch modal</button>
完整示例參考dynamic-demo.html.

通過 JavaScript 呼叫

需一行 JavaScript 程式碼,即可通過元素的 id myModal 呼叫模態框:$('#myModal').modal(options),完整示例參考dynamic-by-javascript-demo.html。modal引數:

  • backdrop boolean/’static’ 預設值為true,Includes a modal-backdrop element. Alternatively, specify static for a backdrop which doesn’t close the modal on click.
  • keyboard boolean 預設值為true,鍵盤上的 esc 鍵被按下時關閉模態框。
  • show boolean 預設值為true,模態框初始化之後就立即顯示出來。
  • remote path 預設值為false,如果提供的是 URL,將利用 jQuery 的 load 方法從此 URL 地址載入要展示的內容(只加載一次)並插入 .modal-content 內。如果使用的是 data 屬性 API,還可以利用 href 屬性指定內容來源地址。下面是一個例項:<a data-toggle="modal" href="remote.html" data-target="#modal">Click me</a>

modal方法的更多使用方式:

  • .modal(options): 將頁面中的某塊內容作為模態框啟用, 接受可選引數 object。
  • .modal(‘toggle’): 手動開啟或關閉模態框,在模態框顯示或隱藏之前返回到主調函式中(觸發 shown.bs.modal 或 hidden.bs.modal 事件之前)
  • .modal(‘show’): 手動開啟模態框, 在模態框顯示之前返回到主調函式中(也就是,在觸發 shown.bs.modal 事件之前)
  • .modal(‘hide’): 手動隱藏模態框, 在模態框隱藏之前返回到主調函式中(也就是,在觸發 hidden.bs.modal 事件之前)。
  • .modal(‘handleUpdate’): ???

模態框事件

Bootstrap 的模態框類提供了一些事件用於監聽並執行你自己的程式碼,具體如下所示:

  • show.bs.modal: show 方法呼叫之後立即觸發該事件。如果是通過點選某個作為觸發器的元素,則此元素可以通過事件的 relatedTarget 屬性進行訪問。
  • shown.bs.modal: 此事件在模態框已經顯示出來(並且同時在 CSS 過渡效果完成)之後被觸發。如果是通過點選某個作為觸發器的元素,則此元素可以通過事件的 relatedTarget 屬性進行訪問。
  • hide.bs.modal: hide 方法呼叫之後立即觸發該事件。
  • hidden.bs.modal: 此事件在模態框被隱藏(並且同時在 CSS 過渡效果完成)之後被觸發。
  • loaded.bs.modal: 從遠端的資料來源載入完資料之後觸發該事件。

簡單示例:

$('#myModal').on('hidden.bs.modal', function (e) {
  // do something...
})
  • 觸發視窗開啟事件
    $("#id").modal(...) => 執行show.bs.modal事件繫結的回撥函式=>執行$("#id").modal(...)之後的程式碼=>如果有設定remote和loaded.bs.modal事件的監聽函式,則執行該函式=>執行shown.bs.modal事件繫結的回撥函式
  • 觸發視窗關閉事件
    $("#id").modal("close")=>執行hide.bs.modal事件繫結的回撥函式=>執行$("#id").modal("close")之後的程式碼=>執行hidden.bs.modal事件繫結的回撥函式

樣式

  • 可選尺寸
    • div.modal-dialog.modal-lg
    • div.modal-dialog.modal-md,預設
    • div.modal-dialog.modal-sm
  • 動畫
    • div.modal.fade
    • div.modal

高階配置

  • 增強模態框的可訪問性
    .modal 新增 role=”dialog” 和 aria-labelledby=”…” 屬性,用於指向模態框的標題欄;為 .modal-dialog 新增 aria-hidden=”true” 屬性。另外,還應該通過 aria-describedby屬性為模態框 .modal 新增描述性資訊。示例如下:
<div class="modal fade" id="myModal" role="dialog" aria-labelledby="myModalLabel" aria-describedby="this is a modal!">
  <div class="modal-dialog" role="document" aria-hidden="true">
    <div class="modal-content">
      <div class="modal-header">
        <h4 class="modal-title" id="myModalLabel">Modal title</h4>
      </div>
      <div class="modal-body">
        ...
      </div>
      <div class="modal-footer">
        ...
      </div>
    </div>
  </div>
</div>

混合組件

使用柵格系統

<div class="modal fade" role="dialog" aria-labelledby="gridSystemModalLabel">
  <div class="modal-dialog" role="document">
    <div class="modal-content">
      <div class="modal-header">
        <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
        <h4 class="modal-title" id="gridSystemModalLabel">Modal title</h4>
      </div>
      <div class="modal-body">
        <div class="container-fluid">
          <div class="row">
            <div class="col-md-4">.col-md-4</div>
            <div class="col-md-4 col-md-offset-4">.col-md-4 .col-md-offset-4</div>
          </div>
          <div class="row">
            <div class="col-md-3 col-md-offset-3">.col-md-3 .col-md-offset-3</div>
            <div class="col-md-2 col-md-offset-4">.col-md-2 .col-md-offset-4</div>
          </div>
          <div class="row">
            <div class="col-md-6 col-md-offset-3">.col-md-6 .col-md-offset-3</div>
          </div>
          <div class="row">
            <div class="col-sm-9">
              Level 1: .col-sm-9
              <div class="row">
                <div class="col-xs-8 col-sm-6">
                  Level 2: .col-xs-8 .col-sm-6
                </div>
                <div class="col-xs-4 col-sm-6">
                  Level 2: .col-xs-4 .col-sm-6
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
        <button type="button" class="btn btn-primary">Save changes</button>
      </div>
    </div><!-- /.modal-content -->
  </div><!-- /.modal-dialog -->
</div><!-- /.modal -->

原始碼分析

CSS原始碼

body

.modal-open {
  overflow: hidden;
}
.modal {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  z-index: 1050;
  display: none;
  overflow: hidden;
  -webkit-overflow-scrolling: touch;
  outline: 0;
}
.modal.fade .modal-dialog {
  -webkit-transition: -webkit-transform .3s ease-out;
       -o-transition:      -o-transform .3s ease-out;
          transition:         transform .3s ease-out;
  -webkit-transform: translate(0, -25%);
      -ms-transform: translate(0, -25%);
       -o-transform: translate(0, -25%);
          transform: translate(0, -25%);
}
.modal.in .modal-dialog {
  -webkit-transform: translate(0, 0);
      -ms-transform: translate(0, 0);
       -o-transform: translate(0, 0);
          transform: translate(0, 0);
}
.modal-open .modal {
  overflow-x: hidden;
  overflow-y: auto;
}
.modal-dialog {
  position: relative;
  width: auto;
  margin: 10px;
}
.modal-content {
  position: relative;
  background-color: #fff;
  -webkit-background-clip: padding-box;
          background-clip: padding-box;
  border: 1px solid #999;
  border: 1px solid rgba(0, 0, 0, .2);
  border-radius: 6px;
  outline: 0;
  -webkit-box-shadow: 0 3px 9px rgba(0, 0, 0, .5);
          box-shadow: 0 3px 9px rgba(0, 0, 0, .5);
}
.modal-backdrop {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  z-index: 1040;
  background-color: #000;
}
.modal-backdrop.fade {
  filter: alpha(opacity=0);
  opacity: 0;
}
.modal-backdrop.in {
  filter: alpha(opacity=50);
  opacity: .5;
}
.modal-header {
  min-height: 16.42857143px;
  padding: 15px;
  border-bottom: 1px solid #e5e5e5;
}
.modal-header .close {
  margin-top: -2px;
}
.modal-title {
  margin: 0;
  line-height: 1.42857143;
}
.modal-body {
  position: relative;
  padding: 15px;
}
.modal-footer {
  padding: 15px;
  text-align: right;
  border-top: 1px solid #e5e5e5;
}
.modal-footer .btn + .btn {
  margin-bottom: 0;
  margin-left: 5px;
}
.modal-footer .btn-group .btn + .btn {
  margin-left: -1px;
}
.modal-footer .btn-block + .btn-block {
  margin-left: 0;
}
.modal-footer:before,
.modal-footer:after {
  display: table;
  content: " ";
}

.modal-footer:after {
  clear: both;
}

響應式

@media (min-width: 768px) {
  .modal-dialog {
    width: 600px;
    margin: 30px auto;
  }
  .modal-content {
    -webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, .5);
            box-shadow: 0 5px 15px rgba(0, 0, 0, .5);
  }
  .modal-sm {
    width: 300px;
  }
}
@media (min-width: 992px) {
  .modal-lg {
    width: 900px;
  }
}

其他

.modal-scrollbar-measure {
  position: absolute;
  top: -9999px;
  width: 50px;
  height: 50px;
  overflow: scroll;
}

Javascript原始碼

分析總結

在模態框被開啟的時候,bootstrap做了如下處理:

  1. 給body元素新增class=modal-open,表示模態框開啟
  2. 給body新增子元素<div class="modal-backdrop fade in"></div>,用於遮擋底層的元素,且提供一個可點選的區域,點選此區域就即可關閉模態框。
  3. 修改.modal元素的display屬性,由none設定為block

問題

  1. 模態框的HTML程式碼放置的位置
    務必將模態框的 HTML 程式碼放在文件的最高層級內(也就是說,儘量作為 body 標籤的直接子元素),以避免其他元件影響模態框的展現和/或功能,參考例項wrong-multi-modal-demo.html

  2. Due to how HTML5 defines its semantics, the autofocus HTML attribute has no effect in Bootstrap modals. To achieve the same effect, use some custom JavaScript:

$('#myModal').on('shown.bs.modal', function () {
  $('#myInput').focus()
})
  1. 嵌入視訊
    在模態框中嵌入 YouTube 視訊需要增加一些額外的 JavaScript 程式碼,用於自動停止重放等功能,這些程式碼並沒有在 Bootstrap 中提供。請參考這份釋出在 Stack Overflow 上的文章

Todo

  1. bootstrap是如何通過data屬性開閉模態框的?
  2. “增強模態框的可訪問性 ”是做什麼用的?