问题描述
我熟悉标准的基于 colspan 的方法,用于在 HTML 中显示(多周或月视图)日历以及跨越多天的事件.(Google 日历就是这样做的,这是众多示例之一.)
我很好奇是否有人知道实现相同目标的无表方法.也许它只是不重要,这是对表格元素的好"使用,但我认为它可能在这个响应式设计时代更相关.
这是一个响应式、无表格日历的示例.(不过,没有多日活动.)https://pittsburghkids.org/calendar 在其小视口版本中,它不再是一个表,语义上.同样,正如@ThinkingStiff 在下面提到的,如果您在客户端从月视图"切换到列表视图",则表格在语义上也并不真正适合.
日历 != 表格
日历是不是语义表.它们感觉就像表格,因为这是我们经常看到它们的方式,但是为了使数据语义为表格,每一行都必须包含一个唯一的实体,而它们没有.在日历中,day 是实体.
混淆之处在于我们还将天分组为几周.人们很自然地认为一个月是几个星期的集合,但事实并非如此,它是几天的集合.一个月平均有 4.3 周.表中的一行不能包含一个实体的部分或多个实体.
行 == 实体,列 == 属性
将其与在线购物车进行比较.您购物车中的物品是表格的.每 行 代表您购物车中的一种 item.每个列要么是项目的一个属性(名称、股票编号、价格),要么是一个属性的集合(数量、总量).您永远不会在一行中看到两种不同的商品类型(因为这没有意义),而且购物车不能包含 4.3 行.
解决方案
对于这个演示,我使用了 <divs>
,每天一个设置为 display: inline-block
,但您可能想要使用 >
- .在月/周/日视图之间更改时,天数流动良好(表格不可能).对于多日活动,Javascript可以做布局.
演示: http://jsfiddle.net/ThinkingStiff/XXm8y/一个>
输出:
脚本:
var events = [{ from: 3, to: 9 }, { from: 4, to: 4 }, { from: 9, to: 11 },{从:4,到:12}];for(var eventIndex = 0, event; event = events[eventIndex], eventIndex < events.length; eventIndex++) {for(var dayIndex = event.from;dayIndex <= event.to;dayIndex++){var dayElement = document.getElementById('day' + dayIndex),firstDay = document.getElementsByClassName('event' + eventIndex),最佳;如果(第一天.长度){top = firstDay[0].style.top;} 别的 {var eventCount = dayElement.getElementsByClassName('event').length;顶部 = ( 事件计数 * 20 ) + 'px';};var html = '<div'+ 'class="事件事件' + eventIndex + '" '+ 'style="top: ' + top + ';">'+ 事件索引+ '</div>';dayElement.insertAdjacentHTML('beforeEnd', html);};};
CSS:
#calendar {边框:1px纯黑色;高度:400px;宽度:504px;}.日 {显示:内联块;高度:80px;位置:相对;垂直对齐:顶部;宽度:72px;}.day:nth-child(偶数){背景颜色:粉红色;}.day:nth-child(奇数){背景颜色:浅蓝色;}.事件 {背景颜色:浅灰色;高度:20px;位置:绝对;文本对齐:居中;宽度:100%;}
HTML:
<div id="calendar"><div id="day1" class="day"></div><div id="day2" class="day"></div><div id="day3" class="day"></div><div id="day4" class="day"></div><div id="day5" class="day"></div><div id="day6" class="day"></div><div id="day7" class="day"></div><div id="day8" class="day"></div><div id="day9" class="day"></div><div id="day10" class="day"></div><div id="day11" class="day"></div><div id="day12" class="day"></div><div id="day13" class="day"></div><div id="day14" class="day"></div><div id="day15" class="day"></div><div id="day16" class="day"></div><div id="day17" class="day"></div><div id="day18" class="day"></div><div id="day19" class="day"></div><div id="day20" class="day"></div><div id="day21" class="day"></div><div id="day22" class="day"></div><div id="day23" class="day"></div><div id="day24" class="day"></div><div id="day25"class="day"></div><div id="day26" class="day"></div><div id="day27" class="day"></div><div id="day28" class="day"></div><div id="day29" class="day"></div><div id="day30"class="day"></div><div id="day31" class="day"></div></div>
I'm familiar with the standard colspan-based approach for displaying (multiweek or month view) calendars in HTML with events that span multiple days. (Google Calendar does this, as one of many examples.)
I'm curious if anyone knows of a table-less approach to achieve the same thing. Maybe it's just not important, and this is a "good" use of the table element, but I think it might be more relevant in this era of responsive design.
Here's an example of a responsive, table-less calendar. (No multi-day events, though.) https://pittsburghkids.org/calendar In its small-viewport version, it's no longer a table, semantically. Similarly, as @ThinkingStiff mentions below, if you're switching from "month view" to "list view" on the client side, a table doesn't really fit semantically either.
Calendars != Tables
Calendars are not semantically tables. They feel like tables because that is how we always see them, but for the data to be semantically tabular, each row would have to contain a unique entity, and they don't. In calendars the day is the entity.
The confusion lies in the fact that we also group days into weeks. People naturally think a month is a collection of weeks, but it is not, it's a collection of days. A month has, on average, 4.3 weeks. A row in a table can't contain part of an entity or multiple entities.
Row == Entity, Column == Property
Compare it to, say, a shopping cart online. The items in your cart are tabular. Each row represents one type of item in your cart. Each column is either a property of the item (name, stock number, price) or an aggregate (quantity, total amount) of a property. You never see two different item types in a single row (because it wouldn't make sense) and a cart can't contain 4.3 rows.
A Solution
For this demo I used <divs>
, one for each day set to display: inline-block
, but you'll probably want to use an <ol>
. Days flow well when changing between month/week/day views (not possible with tables). For multi-day events, Javascript can do the layout.
Demo: http://jsfiddle.net/ThinkingStiff/XXm8y/
Output:
Script:
var events = [{ from: 3, to: 9 }, { from: 4, to: 4 }, { from: 9, to: 11 },{ from: 4, to: 12 }];
for( var eventIndex = 0, event; event = events[eventIndex], eventIndex < events.length; eventIndex++ ) {
for( var dayIndex = event.from; dayIndex <= event.to; dayIndex++ ) {
var dayElement = document.getElementById( 'day' + dayIndex ),
firstDay = document.getElementsByClassName( 'event' + eventIndex ),
top;
if( firstDay.length ) {
top = firstDay[0].style.top;
} else {
var eventCount = dayElement.getElementsByClassName( 'event' ).length;
top = ( eventCount * 20 ) + 'px';
};
var html = '<div '
+ 'class="event event' + eventIndex + '" '
+ 'style="top: ' + top + ';">'
+ eventIndex
+ '</div>';
dayElement.insertAdjacentHTML( 'beforeEnd', html );
};
};
CSS:
#calendar {
border: 1px solid black;
height: 400px;
width: 504px;
}
.day {
display: inline-block;
height: 80px;
position: relative;
vertical-align: top;
width: 72px;
}
.day:nth-child( even ) {
background-color: pink;
}
.day:nth-child( odd ) {
background-color: lightblue;
}
.event {
background-color: lightgrey;
height: 20px;
position: absolute;
text-align: center;
width: 100%;
}
HTML:
<div id="calendar">
<div id="day1" class="day"></div><div id="day2" class="day"></div><div id="day3" class="day"></div><div id="day4" class="day"></div><div id="day5" class="day"></div><div id="day6" class="day"></div><div id="day7" class="day"></div><div id="day8" class="day"></div><div id="day9" class="day"></div><div id="day10" class="day"></div><div id="day11" class="day"></div><div id="day12" class="day"></div><div id="day13" class="day"></div><div id="day14" class="day"></div><div id="day15" class="day"></div><div id="day16" class="day"></div><div id="day17" class="day"></div><div id="day18" class="day"></div><div id="day19" class="day"></div><div id="day20" class="day"></div><div id="day21" class="day"></div><div id="day22" class="day"></div><div id="day23" class="day"></div><div id="day24" class="day"></div><div id="day25" class="day"></div><div id="day26" class="day"></div><div id="day27" class="day"></div><div id="day28" class="day"></div><div id="day29" class="day"></div><div id="day30" class="day"></div><div id="day31" class="day"></div>
</div>
这篇关于多日日历事件的 HTML 标记的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!