aboutsummaryrefslogtreecommitdiffstats
path: root/tiddlers/journal-calendar-widget.tid
diff options
context:
space:
mode:
Diffstat (limited to 'tiddlers/journal-calendar-widget.tid')
-rw-r--r--tiddlers/journal-calendar-widget.tid333
1 files changed, 0 insertions, 333 deletions
diff --git a/tiddlers/journal-calendar-widget.tid b/tiddlers/journal-calendar-widget.tid
deleted file mode 100644
index cd54724..0000000
--- a/tiddlers/journal-calendar-widget.tid
+++ /dev/null
@@ -1,333 +0,0 @@
-title: $:/plugins/local/journal-calendar/widget.js
-type: application/javascript
-module-type: widget
-
-/*\
-title: $:/plugins/local/journal-calendar/widget.js
-type: application/javascript
-module-type: widget
-
-Renders journal tiddlers as monthly calendars.
-\*/
-(function() {
-"use strict";
-
-var Widget = require("$:/core/modules/widgets/widget.js").widget,
- VIEW_STATE_TITLE = "$:/state/journal-calendar/view",
- MONTH_STATE_TITLE = "$:/state/journal-calendar/month";
-
-var JournalCalendarWidget = function(parseTreeNode,options) {
- this.initialise(parseTreeNode,options);
-};
-
-JournalCalendarWidget.prototype = new Widget();
-JournalCalendarWidget.prototype.constructor = JournalCalendarWidget;
-
-function pad(value) {
- return value < 10 ? "0" + value : "" + value;
-}
-
-function dateKey(year,month,day) {
- return year + "-" + pad(month) + "-" + pad(day);
-}
-
-function monthKey(year,month) {
- return year + "-" + pad(month);
-}
-
-function isValidMonth(value) {
- var match = /^(\d{4})-(\d{2})$/.exec(value || "");
- return !!match && Number(match[2]) >= 1 && Number(match[2]) <= 12;
-}
-
-function parseMonth(value) {
- var parts = value.split("-");
- return {
- year: Number(parts[0]),
- month: Number(parts[1])
- };
-}
-
-JournalCalendarWidget.prototype.render = function(parent,nextSibling) {
- this.parentDomNode = parent;
- this.computeAttributes();
- this.execute();
-
- var container = this.document.createElement("div");
- container.className = "tc-journal-calendar";
- parent.insertBefore(container,nextSibling);
- this.domNodes.push(container);
- this.containerNode = container;
-
- this.renderCalendar();
-};
-
-JournalCalendarWidget.prototype.execute = function() {
- this.tag = this.getAttribute("tag","日志");
- this.view = this.getAttribute("view","switchable");
- this.month = this.getAttribute("month","");
-};
-
-JournalCalendarWidget.prototype.getJournalDate = function(tiddler) {
- var titleMatch = /^(\d{4})年(\d{2})月(\d{2})日$/.exec(tiddler.fields.title),
- date;
-
- if(titleMatch) {
- date = new Date(Number(titleMatch[1]),Number(titleMatch[2]) - 1,Number(titleMatch[3]));
- if(date.getFullYear() === Number(titleMatch[1]) && date.getMonth() === Number(titleMatch[2]) - 1 && date.getDate() === Number(titleMatch[3])) {
- return date;
- }
- }
- return null;
-};
-
-JournalCalendarWidget.prototype.getJournalData = function() {
- var titles = this.wiki.getTiddlersWithTag(this.tag),
- byDate = Object.create(null),
- months = Object.create(null),
- self = this;
-
- titles.forEach(function(title) {
- var tiddler = self.wiki.getTiddler(title);
- if(!tiddler || tiddler.fields["draft.of"]) {
- return;
- }
-
- var date = self.getJournalDate(tiddler);
- if(!date) {
- return;
- }
-
- var day = dateKey(date.getFullYear(),date.getMonth() + 1,date.getDate()),
- month = day.substring(0,7);
- byDate[day] = {
- title: title,
- tags: (tiddler.fields.tags || []).filter(function(tag) {
- return tag !== self.tag;
- })
- };
- months[month] = true;
- });
-
- return {
- byDate: byDate,
- months: Object.keys(months).sort().reverse()
- };
-};
-
-JournalCalendarWidget.prototype.getCurrentMonth = function() {
- if(isValidMonth(this.month)) {
- return this.month;
- }
-
- var stateMonth = this.wiki.getTiddlerText(MONTH_STATE_TITLE,"");
- if(isValidMonth(stateMonth)) {
- return stateMonth;
- }
-
- var now = new Date();
- return monthKey(now.getFullYear(),now.getMonth() + 1);
-};
-
-JournalCalendarWidget.prototype.getCurrentView = function() {
- if(this.view === "month" || this.view === "all") {
- return this.view;
- }
- return this.wiki.getTiddlerText(VIEW_STATE_TITLE,"month") === "all" ? "all" : "month";
-};
-
-JournalCalendarWidget.prototype.setState = function(title,value) {
- this.wiki.addTiddler({
- title: title,
- text: value
- });
-};
-
-JournalCalendarWidget.prototype.createButton = function(label,className,handler) {
- var button = this.document.createElement("button");
- button.setAttribute("type","button");
- button.className = className;
- button.textContent = label;
- button.addEventListener("click",handler);
- return button;
-};
-
-JournalCalendarWidget.prototype.renderViewSwitcher = function(currentView) {
- if(this.view !== "switchable") {
- return;
- }
-
- var self = this,
- controls = this.document.createElement("div");
- controls.className = "tc-journal-calendar-view-switcher";
-
- controls.appendChild(this.createButton("单月视图","tc-btn-invisible tc-journal-calendar-switch" + (currentView === "month" ? " tc-selected" : ""),function() {
- self.setState(VIEW_STATE_TITLE,"month");
- }));
- controls.appendChild(this.createButton("全部月份","tc-btn-invisible tc-journal-calendar-switch" + (currentView === "all" ? " tc-selected" : ""),function() {
- self.setState(VIEW_STATE_TITLE,"all");
- }));
- this.containerNode.appendChild(controls);
-};
-
-JournalCalendarWidget.prototype.renderMonthControls = function(selectedMonth) {
- if(isValidMonth(this.month)) {
- return;
- }
-
- var self = this,
- selected = parseMonth(selectedMonth),
- controls = this.document.createElement("div");
- controls.className = "tc-journal-calendar-month-controls";
-
- function setOffset(offset) {
- var date = new Date(selected.year,selected.month - 1 + offset,1);
- self.setState(MONTH_STATE_TITLE,monthKey(date.getFullYear(),date.getMonth() + 1));
- }
-
- controls.appendChild(this.createButton("上个月","tc-btn-invisible tc-journal-calendar-nav",function() {
- setOffset(-1);
- }));
- controls.appendChild(this.createButton("本月","tc-btn-invisible tc-journal-calendar-nav",function() {
- var now = new Date();
- self.setState(MONTH_STATE_TITLE,monthKey(now.getFullYear(),now.getMonth() + 1));
- }));
- controls.appendChild(this.createButton("下个月","tc-btn-invisible tc-journal-calendar-nav",function() {
- setOffset(1);
- }));
- this.containerNode.appendChild(controls);
-};
-
-JournalCalendarWidget.prototype.navigateTo = function(title,node,event) {
- var bounds = node.getBoundingClientRect();
- this.dispatchEvent({
- type: "tm-navigate",
- navigateTo: title,
- navigateFromTitle: this.getVariable("storyTiddler"),
- navigateFromNode: this,
- navigateFromClientRect: {
- top: bounds.top,
- left: bounds.left,
- width: bounds.width,
- right: bounds.right,
- bottom: bounds.bottom,
- height: bounds.height
- },
- navigateSuppressNavigation: event.metaKey || event.ctrlKey || event.button === 1
- });
-};
-
-JournalCalendarWidget.prototype.renderMonth = function(value,byDate) {
- var self = this,
- selected = parseMonth(value),
- section = this.document.createElement("section"),
- heading = this.document.createElement("h2"),
- viewport = this.document.createElement("div"),
- grid = this.document.createElement("div"),
- weekdays = ["一","二","三","四","五","六","日"],
- firstWeekday = (new Date(selected.year,selected.month - 1,1).getDay() + 6) % 7,
- daysInMonth = new Date(selected.year,selected.month,0).getDate(),
- today = new Date(),
- index;
-
- section.className = "tc-journal-calendar-month";
- heading.className = "tc-journal-calendar-month-title";
- heading.textContent = selected.year + "年" + selected.month + "月";
- section.appendChild(heading);
- viewport.className = "tc-journal-calendar-viewport";
- grid.className = "tc-journal-calendar-grid";
-
- weekdays.forEach(function(weekday) {
- var weekdayNode = self.document.createElement("div");
- weekdayNode.className = "tc-journal-calendar-weekday";
- weekdayNode.textContent = weekday;
- grid.appendChild(weekdayNode);
- });
-
- for(index = 0; index < firstWeekday; index++) {
- var blank = this.document.createElement("div");
- blank.className = "tc-journal-calendar-day tc-journal-calendar-day-empty";
- grid.appendChild(blank);
- }
-
- for(var day = 1; day <= daysInMonth; day++) {
- var key = dateKey(selected.year,selected.month,day),
- journal = byDate[key],
- dayNode = this.document.createElement("div"),
- numberNode;
-
- dayNode.className = "tc-journal-calendar-day" + (journal ? " tc-journal-calendar-day-has-journal" : "");
- if(selected.year === today.getFullYear() && selected.month === today.getMonth() + 1 && day === today.getDate()) {
- dayNode.className += " tc-journal-calendar-day-today";
- }
-
- if(journal) {
- numberNode = this.createButton(day,"tc-btn-invisible tc-journal-calendar-day-number tc-journal-calendar-day-link",function(title) {
- return function(event) {
- self.navigateTo(title,event.currentTarget,event);
- };
- }(journal.title));
- numberNode.title = "打开日志:" + journal.title;
- numberNode.setAttribute("aria-label","打开日志:" + journal.title);
- } else {
- numberNode = this.document.createElement("div");
- numberNode.className = "tc-journal-calendar-day-number";
- numberNode.textContent = day;
- }
- dayNode.appendChild(numberNode);
-
- if(journal) {
- journal.tags.forEach(function(tag) {
- var tagButton = self.createButton(tag,"tc-btn-invisible tc-tag-label tc-journal-calendar-tag",function(event) {
- self.navigateTo(tag,event.currentTarget,event);
- });
- tagButton.title = "打开标签:" + tag;
- tagButton.setAttribute("aria-label","打开标签:" + tag);
- dayNode.appendChild(tagButton);
- });
- }
- grid.appendChild(dayNode);
- }
-
- viewport.appendChild(grid);
- section.appendChild(viewport);
- this.containerNode.appendChild(section);
-};
-
-JournalCalendarWidget.prototype.renderCalendar = function() {
- var data = this.getJournalData(),
- currentView = this.getCurrentView();
-
- this.renderViewSwitcher(currentView);
-
- if(currentView === "all") {
- if(!data.months.length) {
- var empty = this.document.createElement("div");
- empty.className = "tc-journal-calendar-empty";
- empty.textContent = "目前没有日志。";
- this.containerNode.appendChild(empty);
- return;
- }
- data.months.forEach(function(month) {
- this.renderMonth(month,data.byDate);
- },this);
- return;
- }
-
- var selectedMonth = this.getCurrentMonth();
- this.renderMonthControls(selectedMonth);
- this.renderMonth(selectedMonth,data.byDate);
-};
-
-JournalCalendarWidget.prototype.refresh = function(changedTiddlers) {
- var changedAttributes = this.computeAttributes();
- if(Object.keys(changedAttributes).length || Object.keys(changedTiddlers).length) {
- this.refreshSelf();
- return true;
- }
- return false;
-};
-
-exports["journal-calendar"] = JournalCalendarWidget;
-
-})();