POC-以jQuery實作會議室登記狀況顯示
| | 3 | | 11,298 |
專案有個需求,要在網頁上呈現多間會議室一天的使用登記狀況。'傳統思維"可能會傾向用Table <td>模擬出時段區塊,然後將預約起迄時間範圍內的<td>用colspan併成一塊。不過如果要做到登記時間以10分鐘為單位,意味著每個小時要切割成6個<td>,即便沒有任何預約也是,讓Table充滿一堆無用又囉嗦的廢物Tag。加上計算哪幾個<td>要併在一起,得找出第一個<td>加colspan,並將後面<td>省略,演算法不怎麼單純。分析起來,這就是該用CSS取代Table做法實作Layout的經典情境。
寫了一段jQuery程式做出POC(Proof of Concept)供同事參考,示範使用DIV+CSS達成上述效果,並並盡可能簡化為呼叫函數就可以完成。一魚兩吃,PO出來供大家參考,順便蒐集諸位先進達人們的回饋指教。
排版顯示純文字
//輸入起/迄整點、寬、高及是否顯示時間標題列,傳回顯示全日時段狀態的<div>
function genTimeline(startHour, endHour, width, height, incHeader) {
$.Darkthread.tools.addDefaultStyles(".dttl_BookingBlock", {
".dttl_BookingBlock": {
float: "left", position: "absolute",
margin: "0px", padding: "0px", height: "100%",
"font-size": "9pt", "background-color": "#dddddd",
"border-left": "solid #444444 1px",
"border-right": "solid #444444 1px"
},
".dttl_Timeline": {
border: "solid black 1px", position: "relative"
},
".dttl_TimelineHeader": {
border: "solid black 1px",
backgroundColor: "#dddddd",
"font-size": "8pt", position: "relative"
},
".dttl_SplitLine": {
float: "left", position: "absolute",
"border-left": "solid gray 1px",
width: "1px", height: "100%"
}
});
var $tl = $("<div class='dttl_Timeline' />");
$tl.height(height).width(width);
var hourWidth = width / (endHour - startHour);
var $h = $("<div />");
if (incHeader)
$h.width(width).height(15).addClass("dttl_TimelineHeader");
for (var i = startHour; i < endHour; i++) {
var vLine =
"<div class='dttl_SplitLine' style='left:" +
hourWidth * (i - startHour) + "px;' />";
$tl.append(vLine);
if (incHeader)
$h.append("<div>" + i + "</div>").append(vLine);
}
if (incHeader) {
$h.find("div").css({
float: "left", margin: "0px", width: hourWidth + "px",
textAlign: "center"
});
}
var $container = $("<div class='dttl_Container' />");
$container.append($h).append($tl)
.data("hourWidth", hourWidth)
.data("startHour", startHour)
.data("endHour", endHour);
return $container;
}
//display會直接顯示在方格中,可支援HTML語法
//detail以title="..."方式處理,請給純文字
//cssOption可為css屬性物件,例如: { border:"...", color:"..." }或是className
//會傳回<div> jQuery物件供後續應用
function addBooking(timeline, startTime, endTime, display, detail, cssOption) {
if (cssOption == undefined || typeof cssOption == "string")
cssOption = { };
var $tl = $(timeline);
var sh = $tl.data("startHour"), eh = $tl.data("endHour");
//將時間先轉成小數
var p = startTime.split(':');
var st = parseInt(p[0]) + (parseFloat(p[1]) / 60);
//小於startHour, 以startHour為準
if (st < sh) st = sh;
p = endTime.split(':');
var et = parseInt(p[0]) + (parseFloat(p[1]) / 60);
//大於endHour, 以endHour為準
if (et > eh) et = eh;
//算出起始位置及寬度
var hw = $tl.data("hourWidth");
var w = (et - st) * hw;
var x = (st - sh) * hw;
//加入顯示元素
var $container = $tl.children("div:last");
var $dv = $("<div class=\"dttl_BookingBlock\"/>");
$dv.css(cssOption).css({
left: x + "px", width: w + "px",
opacity: 0.7
});
$dv.html("<span style='padding: 2px;'>" + display + "</span>")
.attr("title", startTime + "-" + endTime + "\n" + detail);
if (typeof cssOption == "string")
$dv.addClass(cssOption);
$container.append($dv);
return $dv;
}
以下是應用範例:
排版顯示純文字
<script src="jquery-1.4.2.js" type="text/javascript"></script>
<script src="jquery.darkthread.tools.js" type="text/javascript"></script>
<script src="TimelineUtil.js" type="text/javascript"></script>
<script type="text/javascript">
$(function() {
var $d = genTimeline(9, 21, 800, 30, true);
$("body").append($d);
var $booking;
//truncText可幫忙取前10個字
var longText = "超長文字測試,利用truncDetail()取前10個字元";
$booking = addBooking($d, "14:30", "17:00",
$.Darkthread.tools.truncText(longText, 10), longText);
//允許重疊顯示
$booking = addBooking($d, "16:30", "20:00", "來亂的", "咬我呀!");
//cssOption可指定CSS
var cssOption = { backgroundColor: "green", color: "yellow" };
$booking = addBooking($d, "09:30", "10:00", "Jeffrey",
"重要會議", cssOption);
//cssOption傳入字串時,視為className
$booking = addBooking($d, "10:30", "12:00",
"Meeting", "MouseOver特效", "booking");
//addBooking會傳回<div>的jQuery物件,可進行加上hover/click事件等操作
$booking.hover(function() {
$(this).addClass("inverse");
}, function() {
$(this).removeClass("inverse");
}).css("cursor", "pointer").click(function() {
alert("Hi!");
});
//產生100條時間軸各有12筆登錄,測試速度
var $tbl = $(
"<table cellspacing='0' cellpadding='0' style='margin-top: 10px;' />");
for (var i = 0; i < 100; i++) {
$tr = $("<tr><td width='10%' /><td width='90%' /></tr>");
$tr.find("td:first").text("Room" + i);
var $timeline = genTimeline(9, 21, 800, 30, i == 0);
$tr.find("td:last").append($timeline);
$tbl.append($tr);
for (var j = 9; j < 21; j++) {
$booking = addBooking($timeline, j + ":00", j + ":30",
"Test-" + i + "-" + j, "Test");
}
}
$("body").append($tbl);
});
</script>
<style type="text/css">
.booking
{
background-color: Green;
color: Yellow;
}
div.inverse
{
background-color: black;
color: White;
}
</style>
【註】只是POC,防呆、檢核及彈性都很薄弱,不足處請自理!
Comments
# by 大估
我就是用table拼<td>出來的... 寫那段演算法…花了快兩天… XD
# by Jquery新手
請問那個darkthread.tools.js有開放下載嗎:P
# by Jeffrey
to Jquery新手, darkthread.tools.js是我常用jQuery函數的大雜燴,還在不斷擴充修改中,也不敢確認有無重大Bug,計劃自己先用過一段時間確認穩定後,將來會再找黃道吉日Release。