2016年9月8日 星期四

BS3 datetimepicker

BS3 datetimepicker

簡介

在基本的 BS3 中並沒有提供圖形的日曆介面以供選取日期,必須使用額外的插件 (plug-in)。在網路上可以找到很多 BS3 的日期選取插件, https://eonasdan.github.io/bootstrap-datetimepicker/ 這個插件可說是廣受歡迎。這個插件除了架構於 jQuery 及 Bootstrap 3 之上,還另需一個 Moment.js 的 JavaScript 程式館,可由 http://momentjs.com/ 下載。如果必須客製顯示日期時使用的語言,則下載 moment-with-locales.js 程式館。

datetimepicker 這個插件,並沒有定義容器類別,必須透過 JavaScript 在程式中建立。建立 datatimepicker 時,常用的傳入參數略述如下:

viewMode
允許值為 'decades','years','months','days',預設為 'days'。指定日期選取插件顯示時的內容格式。
locale
指定顯示日期時所要使用的語言,正體中文為 'zh-TW'。
daysOfWeekDisabled
允許值為一陣列,內中包含 0 到 6 的數值,0 代表週日,其它數值則代表一週中對應的日子。日期選取插件顯示時,會將陣列中數值對應的日子,顯示為無法選取。
format
設定日期及時間的格式,只設定日期格式時,會隱藏時間的選取介面; 只設定時間格式時,會隱藏日期的選取介面。也就是說這個參數的值,也同時用來設定輸入時只能選取日期,或只能選取時間。
toolbarPlacement
允許值為 'top', 'bottom',預設為 'bottom'。用來設定工具列出現的位置。
showTodayButton
允許值為 true/false,預設為 false。在工具列中顯示「今日」按鈕,圖像為「準星」;點按時會自行輸入當日日期及時間。
showClear
允許值為 true/false,預設為 false。在工具列中顯示「清除」按鈕,圖像為「拉圾」;點按時會清除日期輸入值。
showClose
允許值為 true/false,預設為 false。在工具列中顯示「關閉」按鈕,圖像為 "X";點按時會隱藏日期選取介面。

以下為 datetimepicker.css 樣式表的內容。

<style>
/*!
 * Datetimepicker for Bootstrap 3
 * version : 4.17.42
 * https://github.com/Eonasdan/bootstrap-datetimepicker/
 */
.bootstrap-datetimepicker-widget {
    list-style: none;
}
.bootstrap-datetimepicker-widget.dropdown-menu {
    margin: 2px 0;
    padding: 4px;
    width: 19em;
}
@media (min-width: 768px) {
    .bootstrap-datetimepicker-widget.dropdown-menu.timepicker-sbs {
        width: 38em;
    }
}
@media (min-width: 992px) {
    .bootstrap-datetimepicker-widget.dropdown-menu.timepicker-sbs {
        width: 38em;
    }
}
@media (min-width: 1200px) {
    .bootstrap-datetimepicker-widget.dropdown-menu.timepicker-sbs {
        width: 38em;
    }
}
.bootstrap-datetimepicker-widget.dropdown-menu:before,
.bootstrap-datetimepicker-widget.dropdown-menu:after {
    content: '';
    display: inline-block;
    position: absolute;
}
.bootstrap-datetimepicker-widget.dropdown-menu.bottom:before {
    border-left: 7px solid transparent;
    border-right: 7px solid transparent;
    border-bottom: 7px solid #ccc;
    border-bottom-color: rgba(0, 0, 0, 0.2);
    top: -7px;
    left: 7px;
}
.bootstrap-datetimepicker-widget.dropdown-menu.bottom:after {
    border-left: 6px solid transparent;
    border-right: 6px solid transparent;
    border-bottom: 6px solid white;
    top: -6px;
    left: 8px;
}
.bootstrap-datetimepicker-widget.dropdown-menu.top:before {
    border-left: 7px solid transparent;
    border-right: 7px solid transparent;
    border-top: 7px solid #ccc;
    border-top-color: rgba(0, 0, 0, 0.2);
    bottom: -7px;
    left: 6px;
}
.bootstrap-datetimepicker-widget.dropdown-menu.top:after {
    border-left: 6px solid transparent;
    border-right: 6px solid transparent;
    border-top: 6px solid white;
    bottom: -6px;
    left: 7px;
}
.bootstrap-datetimepicker-widget.dropdown-menu.pull-right:before {
    left: auto;
    right: 6px;
}
.bootstrap-datetimepicker-widget.dropdown-menu.pull-right:after {
    left: auto;
    right: 7px;
}
.bootstrap-datetimepicker-widget .list-unstyled {
    margin: 0;
}
.bootstrap-datetimepicker-widget a[data-action] {
    padding: 6px 0;
}
.bootstrap-datetimepicker-widget a[data-action]:active {
    box-shadow: none;
}
.bootstrap-datetimepicker-widget .timepicker-hour,
.bootstrap-datetimepicker-widget .timepicker-minute,
.bootstrap-datetimepicker-widget .timepicker-second {
    width: 54px;
    font-weight: bold;
    font-size: 1.2em;
    margin: 0;
}
.bootstrap-datetimepicker-widget button[data-action] {
    padding: 6px;
}
.bootstrap-datetimepicker-widget .btn[data-action="incrementHours"]::after {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    border: 0;
    content: "Increment Hours";
}
.bootstrap-datetimepicker-widget .btn[data-action="incrementMinutes"]::after {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    border: 0;
    content: "Increment Minutes";
}
.bootstrap-datetimepicker-widget .btn[data-action="decrementHours"]::after {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    border: 0;
    content: "Decrement Hours";
}
.bootstrap-datetimepicker-widget .btn[data-action="decrementMinutes"]::after {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    border: 0;
    content: "Decrement Minutes";
}
.bootstrap-datetimepicker-widget .btn[data-action="showHours"]::after {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    border: 0;
    content: "Show Hours";
}
.bootstrap-datetimepicker-widget .btn[data-action="showMinutes"]::after {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    border: 0;
    content: "Show Minutes";
}
.bootstrap-datetimepicker-widget .btn[data-action="togglePeriod"]::after {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    border: 0;
    content: "Toggle AM/PM";
}
.bootstrap-datetimepicker-widget .btn[data-action="clear"]::after {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    border: 0;
    content: "Clear the picker";
}
.bootstrap-datetimepicker-widget .btn[data-action="today"]::after {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    border: 0;
    content: "Set the date to today";
}
.bootstrap-datetimepicker-widget .picker-switch {
    text-align: center;
}
.bootstrap-datetimepicker-widget .picker-switch::after {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    border: 0;
    content: "Toggle Date and Time Screens";
}
.bootstrap-datetimepicker-widget .picker-switch td {
    padding: 0;
    margin: 0;
    height: auto;
    width: auto;
    line-height: inherit;
}
.bootstrap-datetimepicker-widget .picker-switch td span {
    line-height: 2.5;
    height: 2.5em;
    width: 100%;
}
.bootstrap-datetimepicker-widget table {
    width: 100%;
    margin: 0;
}
.bootstrap-datetimepicker-widget table td,
.bootstrap-datetimepicker-widget table th {
    text-align: center;
    border-radius: 4px;
}
.bootstrap-datetimepicker-widget table th {
    height: 20px;
    line-height: 20px;
    width: 20px;
}
.bootstrap-datetimepicker-widget table th.picker-switch {
    width: 145px;
}
.bootstrap-datetimepicker-widget table th.disabled,
.bootstrap-datetimepicker-widget table th.disabled:hover {
    background: none;
    color: #777777;
    cursor: not-allowed;
}
.bootstrap-datetimepicker-widget table th.prev::after {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    border: 0;
    content: "Previous Month";
}
.bootstrap-datetimepicker-widget table th.next::after {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    border: 0;
    content: "Next Month";
}
.bootstrap-datetimepicker-widget table thead tr:first-child th {
    cursor: pointer;
}
.bootstrap-datetimepicker-widget table thead tr:first-child th:hover {
    background: #eeeeee;
}
.bootstrap-datetimepicker-widget table td {
    height: 54px;
    line-height: 54px;
    width: 54px;
}
.bootstrap-datetimepicker-widget table td.cw {
    font-size: .8em;
    height: 20px;
    line-height: 20px;
    color: #777777;
}
.bootstrap-datetimepicker-widget table td.day {
    height: 20px;
    line-height: 20px;
    width: 20px;
}
.bootstrap-datetimepicker-widget table td.day:hover,
.bootstrap-datetimepicker-widget table td.hour:hover,
.bootstrap-datetimepicker-widget table td.minute:hover,
.bootstrap-datetimepicker-widget table td.second:hover {
    background: #eeeeee;
    cursor: pointer;
}
.bootstrap-datetimepicker-widget table td.old,
.bootstrap-datetimepicker-widget table td.new {
    color: #777777;
}
.bootstrap-datetimepicker-widget table td.today {
    position: relative;
}
.bootstrap-datetimepicker-widget table td.today:before {
    content: '';
    display: inline-block;
    border: solid transparent;
    border-width: 0 0 7px 7px;
    border-bottom-color: #337ab7;
    border-top-color: rgba(0, 0, 0, 0.2);
    position: absolute;
    bottom: 4px;
    right: 4px;
}
.bootstrap-datetimepicker-widget table td.active,
.bootstrap-datetimepicker-widget table td.active:hover {
    background-color: #337ab7;
    color: #fff;
    text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
}
.bootstrap-datetimepicker-widget table td.active.today:before {
    border-bottom-color: #fff;
}
.bootstrap-datetimepicker-widget table td.disabled,
.bootstrap-datetimepicker-widget table td.disabled:hover {
    background: none;
    color: #777777;
    cursor: not-allowed;
}
.bootstrap-datetimepicker-widget table td span {
    display: inline-block;
    width: 54px;
    height: 54px;
    line-height: 54px;
    margin: 2px 1.5px;
    cursor: pointer;
    border-radius: 4px;
}
.bootstrap-datetimepicker-widget table td span:hover {
    background: #eeeeee;
}
.bootstrap-datetimepicker-widget table td span.active {
    background-color: #337ab7;
    color: #fff;
    text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
}
.bootstrap-datetimepicker-widget table td span.old {
    color: #777777;
}
.bootstrap-datetimepicker-widget table td span.disabled,
.bootstrap-datetimepicker-widget table td span.disabled:hover {
    background: none;
    color: #777777;
    cursor: not-allowed;
}
.bootstrap-datetimepicker-widget.usetwentyfour td.hour {
    height: 27px;
    line-height: 27px;
}
.bootstrap-datetimepicker-widget.wider {
    width: 21em;
}
.bootstrap-datetimepicker-widget .datepicker-decades .decade {
    line-height: 1.8em !important;
}
.input-group.date .input-group-addon {
    cursor: pointer;
}
.sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    border: 0;
}
</style>

範例

範例中建立了三個日期/時間的輸入選取介面。由左至右,第一個不具圖像,當輸入欄位獲得焦點時,自動顯示日期選取介面。點選工具列中的時鐘圖像則顯示時間選取介面。第二個具有圖像,當輸人欄位獲得焦點時,並不會顯示日期選取介面,必須點按「日曆」圖像才能顯示日期選取介面,工具列中具有「今日」、「清除」及「關閉」三個圖像。第三個具有「時鐘」圖像,用來點按以顯示時間的選取介面。在實務上運作時,三個介面在一個時間點只會出現一個介面,其它的會被隱藏,圖例中的示意圖有經過剪貼。

CSS

<style>
html {
    width:100%;
    height:100%;
}
body {
    margin: 0 auto;
    max-width: 1000px;
    padding: 20px;
}
</style>

在 CSS 中沒有特別的樣式需要設定。但要在 <head> 標記中加上下列程式碼,以納入 datetimepicker 的樣式表。請自行修改路徑位置。
<link rel="stylesheet" href="libs/bootstrap-datetimepicker/css/bootstrap-datetimepicker.min.css">

HTML

<body>
    
</body>

第 5 行建立一個不具圖像的日期和時間輸入欄位的掛載點,因為不具圖像,所以用不到 .form-group 及 .input-group 樣式類別。搜尋用的 id 設在 <input> 之中。
第 8~15 行及 18~26 行各建立一個具有圖像的日期和時間輸入欄位,因為具有圖像,所以用到 .form-group 及 .input-group 等樣式類別。搜尋用的 id 設在 .input-group 的 <div> 標記中,注意 .input-group 伴隨一個 .date 樣式類別,這是程式碼中唯一定義於 datetimepicker.css 中的樣式類別,.input-group.date{}樣式中設定了游標形狀。
第 22 行用 glyphicon-time 將圖像設成「時鐘」的圖像。
剩下的工作都得靠 JavaScript 程式來完成了。

Script

記得加上下列程式碼,以納入 datetimepicker 的 JavaScript 程式碼。請自行修改路徑位置。
<script src="libs/bootstrap-datetimepicker/js/bootstrap-datetimepicker.min.js"></script>

<script>
$(function(){
    $('#datetimepicker1').datetimepicker({
        daysOfWeekDisabled: [0, 6]
    });
    $('#datetimepicker2').datetimepicker({
        locale: 'zh-TW',
        format: 'YYYY-MM-DD',   // this will only display date selector
        toolbarPlacement: 'bottom',
        showTodayButton : true,
        showClear: true,
        showClose: true
    }).on('dp.change', function(){
        let picked = $('#datetimepicker2').datetimepicker('date');
        alert(picked);
    });
    $('#datetimepicker3').datetimepicker({
        format: 'LT'          // this will only display time selector
    });
});
</script>

第 4 行將所有週六及週日的日子,都設定為不可選取。
第 7 行設定顯示時使用正體中文。
第 8 行設定日期格式,因為只設定了日期格式,所以不會出現時間的選取介面。
第 9 行設定工具列在選取介面中的位置。
第 10~12 行則分別顯示「今日」、「清除」及「關閉」三個工具列的圖像鈕。
第 13~15 行於資料改變時,處理 dp.change 事件,讀取輸入值,並顯示在螢幕上。
第 20 行將格式設定為 LT (Local Time),因此只會出現時間選取介面。format 屬性的值,得去參考 Moment.js 的文件。