CINXE.COM
A4版で印刷して使える万年卓上予定表/カレンダー【みんなの知識 ちょっと便利帳】
<!doctype html> <html lang="ja"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width,initial-scale=1.0"> <title>A4版で印刷して使える万年卓上予定表/カレンダー【みんなの知識 ちょっと便利帳】</title> <!--[if lt IE 9]> <script src="/common_js/ie-html5/html5shiv.js"></script> <![endif]--> <meta name="description" content="A4版で印刷して使える万年卓上予定表/カレンダーです。『みんなの知識 ちょっと便利帳』の一部です。" /> <meta name="keywords" content="カレンダー,A4版,印刷,万年卓上予定表,万年卓上カレンダー,万年予定表,万年カレンダー,予定表,みんなの知識,ちょっと便利帳" /> <meta name="robots" content="INDEX,FOLLOW"> <link rel="shortcut icon" href="/favicon.ico"> <link rel='stylesheet' href='/2017css/responsive-style.css' type='text/css' media='all' /> <link rel='stylesheet' href='/2017css/responsive-page.css' type='text/css' media='all' /> <link rel='stylesheet' id='responsive-mode-style-css' href='/2017css/responsive.css' type='text/css' media='all' /> <link rel='stylesheet' href='/2017css/print.css' type='text/css' media='print' /> <!-- 必須:WebFont-Awesome --> <link href="/2017css/font-awesome.css" rel="stylesheet" /> <!-- 数字の電話番号自動リンク機能制御-iOS_Safari向け --> <meta name="format-detection" content="telephone=no"> <!-- 必須:jQuery --> <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script> <!-- 必須:FlashRun --> <script src="/Scripts/AC_RunActiveContent.js"></script> <!-- カレンダーに関するCSS <link rel="stylesheet" type="text/css" href="css/styles-site.css" />--> <link rel="stylesheet" type="text/css" href="css/fullcalendar_today.css" /> <!-- カレンダーに関するスクリプト JS --> <!--<script type="text/javascript" src="js/fullcalendar.js">--> <script type="text/javascript"> /*! * FullCalendar v1.4.1 * http://arshaw.com/fullcalendar/ * * Use fullcalendar.css for basic styling. * For event drag & drop, required jQuery UI draggable. * For event resizing, requires jQuery UI resizable. * * Copyright (c) 2009 Adam Shaw * Dual licensed under the MIT and GPL licenses: * http://www.opensource.org/licenses/mit-license.php * http://www.gnu.org/licenses/gpl.html * */ (function($) { var fc = $.fullCalendar = {}; var views = fc.views = {}; /* Defaults -----------------------------------------------------------------------------*/ var defaults = { // display defaultView: 'month', aspectRatio: 1.35, header: { left: 'title', center: '', right: 'today prev,next' }, weekends: true, // editing //editable: false, //disableDragging: false, //disableResizing: false, allDayDefault: true, // event ajax startParam: 'start', endParam: 'end', cacheParam: '_', // time formats titleFormat: { month: 'yyyy年 MMMM', week: "yyyy年 MMM d[ yyyy]日{ '—'[ MMM] d日}", day: 'yyyy年 MMM d月 dddd' }, columnFormat: { month: 'ddd', week: 'M/d ddd', day: 'M/d dddd' }, timeFormat: { // for event elements '': 'h(:mm)t' // default }, /* // time formats titleFormat: { month: 'MMMM yyyy', week: "MMM d[ yyyy]{ '—'[ MMM] d yyyy}", day: 'dddd, MMM d, yyyy' }, columnFormat: { month: 'ddd', week: 'ddd M/d', day: 'dddd M/d' }, timeFormat: { // for event elements '': 'h(:mm)t' // default }, */ // locale isRTL: false, firstDay: 0, monthNames: ['1月[January]','2月[February]','3月[March]','4月[April]','5月[May]','6月[June]','7月[July]','8月[August]','9月[September]','10月[October]','11月[November]','12月[December]'], monthNamesShort: ['1月','2月','3月','4月','5月','6月','7月','8月','9月','10月','11月','12月'], dayNames: ['日曜[Sunday]','月曜[Monday]','火曜[Tuesday]','水曜[Wednesday]','木曜[Thursday]','金曜[Friday]','土曜[Saturday]'], dayNamesShort: ['日','月','火','水','木','金','土'], /* monthNames: ['January','February','March','April','May','June','July','August','September','October','November','December'], monthNamesShort: ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'], dayNames: ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'], dayNamesShort: ['Sun','Mon','Tue','Wed','Thu','Fri','Sat'], */ buttonText: { prev: ' << ', next: ' >> ', prevYear: ' << ', nextYear: ' >> ', today: '今月', today: '今月', month: '', week: '', day: '' }, // jquery-ui theming theme: false, buttonIcons: { prev: 'circle-triangle-w', next: 'circle-triangle-e' } }; // right-to-left defaults var rtlDefaults = { header: { left: 'next,prev today', center: '', right: 'title' }, buttonText: { prev: ' ► ', next: ' ◄ ', prevYear: ' >> ', nextYear: ' << ' }, buttonIcons: { prev: 'circle-triangle-e', next: 'circle-triangle-w' } }; // function for adding/overriding defaults var setDefaults = fc.setDefaults = function(d) { $.extend(true, defaults, d); } /* .fullCalendar jQuery function -----------------------------------------------------------------------------*/ $.fn.fullCalendar = function(options) { // method calling if (typeof options == 'string') { var args = Array.prototype.slice.call(arguments, 1), res; this.each(function() { var r = $.data(this, 'fullCalendar')[options].apply(this, args); if (res == undefined) { res = r; } }); if (res != undefined) { return res; } return this; } // pluck the 'events' and 'eventSources' options var eventSources = options.eventSources || []; delete options.eventSources; if (options.events) { eventSources.push(options.events); delete options.events; } // first event source reserved for 'sticky' events eventSources.unshift([]); // initialize options options = $.extend(true, {}, defaults, (options.isRTL || options.isRTL==undefined && defaults.isRTL) ? rtlDefaults : {}, options ); var tm = options.theme ? 'ui' : 'fc'; // for making theme classes this.each(function() { /* Instance Initialization -----------------------------------------------------------------------------*/ // element var _element = this, element = $(this).addClass('fc'), content = $("<div class='fc-content " + tm + "-widget-content' style='position:relative'/>").appendTo(this); // relative for ie6 if (options.isRTL) { element.addClass('fc-rtl'); } if (options.theme) { element.addClass('ui-widget'); } // view managing var date = new Date(), viewName, view, // the current view viewInstances = {}; if (options.year != undefined && options.year != date.getFullYear()) { date.setDate(1); date.setMonth(0); date.setFullYear(options.year); } if (options.month != undefined && options.month != date.getMonth()) { date.setDate(1); date.setMonth(options.month); } if (options.date != undefined) { date.setDate(options.date); } /* View Rendering -----------------------------------------------------------------------------*/ function changeView(v) { if (v != viewName) { fixContentSize(); if (view) { if (view.eventsChanged) { eventsDirtyExcept(view); view.eventsChanged = false; } view.element.hide(); } if (viewInstances[v]) { (view = viewInstances[v]).element.show(); if (view.shown) { view.shown(); } }else{ view = viewInstances[v] = $.fullCalendar.views[v]( $("<div class='fc-view fc-view-" + v + "'/>").appendTo(content), options); } if (header) { // update 'active' view button header.find('div.fc-button-' + viewName).removeClass(tm + '-state-active'); header.find('div.fc-button-' + v).addClass(tm + '-state-active'); } view.name = viewName = v; render(); unfixContentSize(); } } function render(inc) { if (_element.offsetWidth !== 0) { // visible on the screen if (inc || !view.date || +view.date != +date) { // !view.date means it hasn't been rendered yet fixContentSize(); view.render(date, inc || 0, function(callback) { // dont refetch if new view contains the same events (or a subset) if (!eventStart || view.visStart < eventStart || view.visEnd > eventEnd) { fetchEvents(callback); }else{ callback(events); // no refetching } }); unfixContentSize(); view.date = cloneDate(date); } else if (view.sizeDirty) { view.updateSize(); view.rerenderEvents(); } else if (view.eventsDirty) { // ensure events are rerendered if another view messed with them // pass in 'events' b/c event might have been added/removed view.clearEvents(); view.renderEvents(events); } if (header) { // update title text header.find('h2.fc-header-title').html(view.title); // enable/disable 'today' button var today = new Date(); if (today >= view.start && today < view.end) { header.find('div.fc-button-today').addClass(tm + '-state-disabled'); }else{ header.find('div.fc-button-today').removeClass(tm + '-state-disabled'); } } view.sizeDirty = false; view.eventsDirty = false; view.trigger('viewDisplay', _element); } } // marks other views' events as dirty function eventsDirtyExcept(exceptView) { $.each(viewInstances, function() { if (this != exceptView) { this.eventsDirty = true; } }); } // marks other views' sizes as dirty function sizesDirtyExcept(exceptView) { $.each(viewInstances, function() { if (this != exceptView) { this.sizeDirty = true; } }); } // called when any event objects have been added/removed/changed, rerenders function eventsChanged() { view.clearEvents(); view.renderEvents(events); eventsDirtyExcept(view); } /* Event Sources and Fetching -----------------------------------------------------------------------------*/ var events = [], eventStart, eventEnd; // Fetch from ALL sources. Clear 'events' array and populate function fetchEvents(callback) { events = []; eventStart = cloneDate(view.visStart); eventEnd = cloneDate(view.visEnd); var queued = eventSources.length, sourceDone = function() { if (--queued == 0) { if (callback) { callback(events); } } }, i=0; for (; i<eventSources.length; i++) { fetchEventSource(eventSources[i], sourceDone); } } // Fetch from a particular source. Append to the 'events' array function fetchEventSource(src, callback) { var prevViewName = view.name, prevDate = cloneDate(date), reportEvents = function(a) { if (prevViewName == view.name && +prevDate == +date) { // protects from fast switching for (var i=0; i<a.length; i++) { normalizeEvent(a[i], options); a[i].source = src; } events = events.concat(a); if (callback) { callback(a); } } }, reportEventsAndPop = function(a) { reportEvents(a); popLoading(); }; if (typeof src == 'string') { var params = {}; params[options.startParam] = Math.round(eventStart.getTime() / 1000); params[options.endParam] = Math.round(eventEnd.getTime() / 1000); params[options.cacheParam] = (new Date()).getTime(); pushLoading(); $.getJSON(src, params, reportEventsAndPop); } else if ($.isFunction(src)) { pushLoading(); src(cloneDate(eventStart), cloneDate(eventEnd), reportEventsAndPop); } else { reportEvents(src); // src is an array } } /* Loading State -----------------------------------------------------------------------------*/ var loadingLevel = 0; function pushLoading() { if (!loadingLevel++) { view.trigger('loading', _element, true); } } function popLoading() { if (!--loadingLevel) { view.trigger('loading', _element, false); } } /* Public Methods -----------------------------------------------------------------------------*/ var publicMethods = { render: render, changeView: changeView, // // Navigation // prev: function() { render(-1); }, next: function() { render(1); }, prevYear: function() { addYears(date, -1); render(); }, nextYear: function() { addYears(date, 1); render(); }, today: function() { date = new Date(); render(); }, gotoDate: function(year, month, dateNum) { if (typeof year == 'object') { date = cloneDate(year); // provided 1 argument, a Date }else{ if (year != undefined) { date.setFullYear(year); } if (month != undefined) { date.setMonth(month); } if (dateNum != undefined) { date.setDate(dateNum); } } render(); }, incrementDate: function(years, months, days) { if (years != undefined) { addYears(date, years); } if (months != undefined) { addMonths(date, months); } if (days != undefined) { addDays(date, days); } render(); }, // // Event Manipulation // updateEvent: function(event) { // update an existing event var i, len = events.length, e, startDelta = event.start - event._start, endDelta = event.end ? (event.end - (event._end || view.defaultEventEnd(event))) // event._end would be null if event.end : 0; // was null and event was just resized for (i=0; i<len; i++) { e = events[i]; if (e._id == event._id && e != event) { e.start = new Date(+e.start + startDelta); if (event.end) { if (e.end) { e.end = new Date(+e.end + endDelta); }else{ e.end = new Date(+view.defaultEventEnd(e) + endDelta); } }else{ e.end = null; } e.title = event.title; e.url = event.url; e.allDay = event.allDay; e.className = event.className; e.editable = event.editable; normalizeEvent(e, options); } } normalizeEvent(event, options); eventsChanged(); }, renderEvent: function(event, stick) { // render a new event normalizeEvent(event, options); if (!event.source) { if (stick) { (event.source = eventSources[0]).push(event); } events.push(event); } eventsChanged(); }, removeEvents: function(filter) { if (!filter) { // remove all events = []; // clear all array sources for (var i=0; i<eventSources.length; i++) { if (typeof eventSources[i] == 'object') { eventSources[i] = []; } } }else{ if (!$.isFunction(filter)) { // an event ID var id = filter + ''; filter = function(e) { return e._id == id; }; } events = $.grep(events, filter, true); // remove events from array sources for (var i=0; i<eventSources.length; i++) { if (typeof eventSources[i] == 'object') { eventSources[i] = $.grep(eventSources[i], filter, true); } } } eventsChanged(); }, clientEvents: function(filter) { if ($.isFunction(filter)) { return $.grep(events, filter); } else if (filter) { // an event ID filter += ''; return $.grep(events, function(e) { return e._id == filter; }); } return events; // else, return all }, rerenderEvents: function() { view.rerenderEvents(); }, // // Event Source // addEventSource: function(source) { eventSources.push(source); fetchEventSource(source, function() { eventsChanged(); }); }, removeEventSource: function(source) { eventSources = $.grep(eventSources, function(src) { return src != source; }); // remove all client events from that source events = $.grep(events, function(e) { return e.source != source; }); eventsChanged(); }, refetchEvents: function() { fetchEvents(eventsChanged); } }; $.data(this, 'fullCalendar', publicMethods); /* Header -----------------------------------------------------------------------------*/ var header, sections = options.header; if (sections) { header = $("<table class='fc-header'/>") .append($("<tr/>") .append($("<td class='fc-header-left'/>").append(buildSection(sections.left))) .append($("<td class='fc-header-center'/>").append(buildSection(sections.center))) .append($("<td class='fc-header-right'/>").append(buildSection(sections.right)))) .prependTo(element); } function buildSection(buttonStr) { if (buttonStr) { var tr = $("<tr/>"); $.each(buttonStr.split(' '), function(i) { if (i > 0) { tr.append("<td><span class='fc-header-space'/></td>"); } var prevButton; $.each(this.split(','), function(j, buttonName) { if (buttonName == 'title') { tr.append("<td><h2 class='fc-header-title'/></td>"); if (prevButton) { prevButton.addClass(tm + '-corner-right'); } prevButton = null; }else{ var buttonClick; if (publicMethods[buttonName]) { buttonClick = publicMethods[buttonName]; } else if (views[buttonName]) { buttonClick = function() { button.removeClass(tm + '-state-hover'); changeView(buttonName) }; } if (buttonClick) { if (prevButton) { prevButton.addClass(tm + '-no-right'); } var button, icon = options.theme ? smartProperty(options.buttonIcons, buttonName) : null, text = smartProperty(options.buttonText, buttonName); if (icon) { button = $("<div class='fc-button-" + buttonName + " ui-state-default'>" + "<a><span class='ui-icon ui-icon-" + icon + "'/></a></div>"); } else if (text) { button = $("<div class='fc-button-" + buttonName + " " + tm + "-state-default'>" + "<a><span>" + text + "</span></a></div>"); } if (button) { button .click(function() { if (!button.hasClass(tm + '-state-disabled')) { buttonClick(); } }) .mousedown(function() { button .not('.' + tm + '-state-active') .not('.' + tm + '-state-disabled') .addClass(tm + '-state-down'); }) .mouseup(function() { button.removeClass(tm + '-state-down'); }) .hover( function() { button .not('.' + tm + '-state-active') .not('.' + tm + '-state-disabled') .addClass(tm + '-state-hover'); }, function() { button .removeClass(tm + '-state-hover') .removeClass(tm + '-state-down'); } ) .appendTo($("<td/>").appendTo(tr)); if (prevButton) { prevButton.addClass(tm + '-no-right'); }else{ button.addClass(tm + '-corner-left'); } prevButton = button; } } } }); if (prevButton) { prevButton.addClass(tm + '-corner-right'); } }); return $("<table/>").append(tr); } } /* Resizing -----------------------------------------------------------------------------*/ var elementWidth, contentSizeFixed = false, resizeCnt = 0; function fixContentSize() { if (!contentSizeFixed) { contentSizeFixed = true; content.css({ overflow: 'hidden', height: Math.round(content.width() / options.aspectRatio) }); // TODO: previous action might have caused scrollbars // which will make the window width more narrow, possibly changing the aspect ratio } } function unfixContentSize() { if (contentSizeFixed) { content.css({ overflow: 'visible', height: '' }); if ($.browser.msie && ($.browser.version=='6.0' || $.browser.version=='7.0')) { // in IE6/7 the inside of the content div was invisible // bizarre hack to get this work... need both lines content[0].clientHeight; content.hide().show(); } contentSizeFixed = false; } } $(window).resize(function() { if (!contentSizeFixed && view.date) { // view.date means the view has been rendered var rcnt = ++resizeCnt; // add a delay setTimeout(function() { if (rcnt == resizeCnt && !contentSizeFixed) { var newWidth = element.width(); if (newWidth != elementWidth) { elementWidth = newWidth; fixContentSize(); view.updateSize(); unfixContentSize(); view.rerenderEvents(true); sizesDirtyExcept(view); view.trigger('windowResize', _element); } } }, 200); } }); // let's begin... changeView(options.defaultView); elementWidth = element.width(); }); return this; }; /* Important Event Utilities -----------------------------------------------------------------------------*/ var fakeID = 0; function normalizeEvent(event, options) { event._id = event._id || (event.id == undefined ? '_fc' + fakeID++ : event.id + ''); if (event.date) { if (!event.start) { event.start = event.date; } delete event.date; } event._start = cloneDate(event.start = parseDate(event.start)); event.end = parseDate(event.end); if (event.end && event.end <= event.start) { event.end = null; } event._end = event.end ? cloneDate(event.end) : null; if (event.allDay == undefined) { event.allDay = options.allDayDefault; } if (event.className) { if (typeof event.className == 'string') { event.className = event.className.split(/\s+/); } }else{ event.className = []; } } /* Grid-based Views: month, basicWeek, basicDay -----------------------------------------------------------------------------*/ setDefaults({ weekMode: 'fixed' }); views.month = function(element, options) { return new Grid(element, options, { render: function(date, delta, fetchEvents) { if (delta) { addMonths(date, delta); date.setDate(1); } // start/end var start = this.start = cloneDate(date, true); start.setDate(1); this.end = addMonths(cloneDate(start), 1); // visStart/visEnd var visStart = this.visStart = cloneDate(start), visEnd = this.visEnd = cloneDate(this.end), nwe = options.weekends ? 0 : 1; if (nwe) { skipWeekend(visStart); skipWeekend(visEnd, -1, true); } addDays(visStart, -((visStart.getDay() - Math.max(options.firstDay, nwe) + 7) % 7)); addDays(visEnd, (7 - visEnd.getDay() + Math.max(options.firstDay, nwe)) % 7); // row count var rowCnt = Math.round((visEnd - visStart) / (DAY_MS * 7)); if (options.weekMode == 'fixed') { addDays(visEnd, (6 - rowCnt) * 7); rowCnt = 6; } // title this.title = formatDate( start, this.option('titleFormat'), options ); // render this.renderGrid( rowCnt, options.weekends ? 7 : 5, this.option('columnFormat'), true, fetchEvents ); } }); } views.basicWeek = function(element, options) { return new Grid(element, options, { render: function(date, delta, fetchEvents) { if (delta) { addDays(date, delta * 7); } var visStart = this.visStart = cloneDate( this.start = addDays(cloneDate(date), -((date.getDay() - options.firstDay + 7) % 7)) ), visEnd = this.visEnd = cloneDate( this.end = addDays(cloneDate(visStart), 7) ); if (!options.weekends) { skipWeekend(visStart); skipWeekend(visEnd, -1, true); } this.title = formatDates( visStart, addDays(cloneDate(visEnd), -1), this.option('titleFormat'), options ); this.renderGrid( 1, options.weekends ? 7 : 5, this.option('columnFormat'), false, fetchEvents ); } }); }; views.basicDay = function(element, options) { return new Grid(element, options, { render: function(date, delta, fetchEvents) { if (delta) { addDays(date, delta); if (!options.weekends) { skipWeekend(date, delta < 0 ? -1 : 1); } } this.title = formatDate(date, this.option('titleFormat'), options); this.start = this.visStart = cloneDate(date, true); this.end = this.visEnd = addDays(cloneDate(this.start), 1); this.renderGrid(1, 1, this.option('columnFormat'), false, fetchEvents); } }); } // rendering bugs var tdHeightBug, rtlLeftDiff; function Grid(element, options, methods) { var tm, firstDay, nwe, // no weekends (int) rtl, dis, dit, // day index sign / translate rowCnt, colCnt, colWidth, thead, tbody, cachedSegs, //... // initialize superclass view = $.extend(this, viewMethods, methods, { renderGrid: renderGrid, renderEvents: renderEvents, rerenderEvents: rerenderEvents, updateSize: updateSize, defaultEventEnd: function(event) { // calculates an end if event doesnt have one, mostly for resizing return cloneDate(event.start); }, visEventEnd: function(event) { // returns exclusive 'visible' end, for rendering if (event.end) { var end = cloneDate(event.end); return (event.allDay || end.getHours() || end.getMinutes()) ? addDays(end, 1) : end; }else{ return addDays(cloneDate(event.start), 1); } } }); view.init(element, options); /* Grid Rendering -----------------------------------------------------------------------------*/ element.addClass('fc-grid').css('position', 'relative'); if (element.disableSelection) { element.disableSelection(); } function renderGrid(r, c, colFormat, showNumbers, fetchEvents) { rowCnt = r; colCnt = c; // update option-derived variables tm = options.theme ? 'ui' : 'fc'; nwe = options.weekends ? 0 : 1; firstDay = options.firstDay; if (rtl = options.isRTL) { dis = -1; dit = colCnt - 1; }else{ dis = 1; dit = 0; } var month = view.start.getMonth(), today = clearTime(new Date()), s, i, j, d = cloneDate(view.visStart); if (!tbody) { // first time, build all cells from scratch var table = $("<table/>").appendTo(element); s = "<thead><tr>"; for (i=0; i<colCnt; i++) { s += "<th width='15%' class='fc-" + dayIDs[d.getDay()] + ' ' + // needs to be first tm + '-state-default' + (i==dit ? ' fc-leftmost' : '') + "'>" + formatDate(d, colFormat, options) + "</th>"; addDays(d, 1); if (nwe) { skipWeekend(d); } } thead = $(s + "</tr></thead>").appendTo(table); s = "<tbody>"; d = cloneDate(view.visStart); for (i=0; i<rowCnt; i++) { s += "<tr class='fc-week" + i + "'>"; for (j=0; j<colCnt; j++) { s += "<td class='fc-" + dayIDs[d.getDay()] + ' ' + // needs to be first tm + '-state-default fc-day' + (i*colCnt+j) + (j==dit ? ' fc-leftmost' : '') + (rowCnt>1 && d.getMonth() != month ? ' fc-other-month' : '') + (+d == +today ? ' fc-today '+tm+'-state-highlight' : ' fc-not-today') + "'>" + (showNumbers ? "<div class='fc-day-number'>" + d.getDate() + "</div>" : '') + "<div class='fc-day-content'><div> </div></div></td>"; addDays(d, 1); if (nwe) { skipWeekend(d); } } s += "</tr>"; } tbody = $(s + "</tbody>").appendTo(table); tbody.find('td').click(dayClick); }else{ // NOT first time, reuse as many cells as possible view.clearEvents(); var prevRowCnt = tbody.find('tr').length; if (rowCnt < prevRowCnt) { tbody.find('tr:gt(' + (rowCnt-1) + ')').remove(); // remove extra rows } else if (rowCnt > prevRowCnt) { // needs to create new rows... s = ''; for (i=prevRowCnt; i<rowCnt; i++) { s += "<tr class='fc-week" + i + "'>"; for (j=0; j<colCnt; j++) { s += "<td class='fc-" + dayIDs[d.getDay()] + ' ' + // needs to be first tm + '-state-default fc-new fc-day' + (i*colCnt+j) + (j==dit ? ' fc-leftmost' : '') + "'>" + (showNumbers ? "<div class='fc-day-number'></div>" : '') + "<div class='fc-day-content'><div> </div></div>" + "</td>"; addDays(d, 1); if (nwe) { skipWeekend(d); } } s += "</tr>"; } tbody.append(s); } tbody.find('td.fc-new').removeClass('fc-new').click(dayClick); // re-label and re-class existing cells d = cloneDate(view.visStart); tbody.find('td').each(function() { var td = $(this); if (rowCnt > 1) { if (d.getMonth() == month) { td.removeClass('fc-other-month'); }else{ td.addClass('fc-other-month'); } } if (+d == +today) { td.removeClass('fc-not-today') .addClass('fc-today') .addClass(tm + '-state-highlight'); }else{ td.addClass('fc-not-today') .removeClass('fc-today') .removeClass(tm + '-state-highlight'); } td.find('div.fc-day-number').text(d.getDate()); addDays(d, 1); if (nwe) { skipWeekend(d); } }); if (rowCnt == 1) { // more changes likely (week or day view) // redo column header text and class d = cloneDate(view.visStart); thead.find('th').each(function() { $(this).text(formatDate(d, colFormat, options)); this.className = this.className.replace(/^fc-\w+(?= )/, 'fc-' + dayIDs[d.getDay()]); addDays(d, 1); if (nwe) { skipWeekend(d); } }); // redo cell day-of-weeks d = cloneDate(view.visStart); tbody.find('td').each(function() { this.className = this.className.replace(/^fc-\w+(?= )/, 'fc-' + dayIDs[d.getDay()]); addDays(d, 1); if (nwe) { skipWeekend(d); } }); } } updateSize(); fetchEvents(renderEvents); }; function dayClick(ev) { var n = parseInt(this.className.match(/fc\-day(\d+)/)[1]), date = addDays( cloneDate(view.visStart), Math.floor(n/colCnt) * 7 + n % colCnt ); view.trigger('dayClick', this, date, true, ev); } function updateSize() { var height = Math.round(element.width() / options.aspectRatio), leftTDs = tbody.find('tr td:first-child'), tbodyHeight = height - thead.height(), rowHeight1, rowHeight2; if (options.weekMode == 'variable') { rowHeight1 = rowHeight2 = Math.floor(tbodyHeight / (rowCnt==1 ? 2 : 6)); }else{ rowHeight1 = Math.floor(tbodyHeight / rowCnt); rowHeight2 = tbodyHeight - rowHeight1*(rowCnt-1); } reportTBody(tbody); if (tdHeightBug == undefined) { // bug in firefox where cell height includes padding var tr = tbody.find('tr:first'), td = tr.find('td:first'); td.height(rowHeight1); tdHeightBug = rowHeight1 != td.height(); } if (tdHeightBug) { leftTDs.slice(0, -1).height(rowHeight1); leftTDs.slice(-1).height(rowHeight2); }else{ setOuterHeight(leftTDs.slice(0, -1), rowHeight1); setOuterHeight(leftTDs.slice(-1), rowHeight2); } setOuterWidth( thead.find('th').slice(0, -1), colWidth = Math.floor(element.width() / colCnt) ); } /* Event Rendering -----------------------------------------------------------------------------*/ function renderEvents(events) { view.reportEvents(events); renderSegs(cachedSegs = compileSegs(events)); } function rerenderEvents(skipCompile) { view.clearEvents(); if (skipCompile) { renderSegs(cachedSegs); }else{ renderEvents(view.cachedEvents); } } function compileSegs(events) { var d1 = cloneDate(view.visStart), d2 = addDays(cloneDate(d1), colCnt), rows = [], i=0; for (; i<rowCnt; i++) { rows.push(stackSegs(view.sliceSegs(events, d1, d2))); addDays(d1, 7); addDays(d2, 7); } return rows; } function renderSegs(segRows) { var i, len = segRows.length, levels, tr, td, innerDiv, top, rowContentHeight, j, segs, levelHeight, k, seg, event, className, startElm, endElm, left, right, eventElement, eventAnchor, triggerRes; for (i=0; i<len; i++) { levels = segRows[i]; tr = tbody.find('tr:eq('+i+')'); td = tr.find('td:first'); innerDiv = td.find('div.fc-day-content div').css('position', 'relative'); top = safePosition(innerDiv, td, tr, tbody).top; rowContentHeight = 0; for (j=0; j<levels.length; j++) { segs = levels[j]; levelHeight = 0; for (k=0; k<segs.length; k++) { seg = segs[k]; event = seg.event; className = 'fc-event fc-event-hori '; startElm = seg.isStart ? tr.find('td:eq('+((seg.start.getDay()-Math.max(firstDay,nwe)+colCnt)%colCnt)+') div div') : tbody; endElm = seg.isEnd ? tr.find('td:eq('+((seg.end.getDay()-Math.max(firstDay,nwe)+colCnt-1)%colCnt)+') div div') : tbody; if (rtl) { left = endElm.position().left; right = startElm.position().left + startElm.width(); if (seg.isStart) { className += 'fc-corner-right '; } if (seg.isEnd) { className += 'fc-corner-left '; } }else{ left = startElm.position().left; right = endElm.position().left + endElm.width(); if (seg.isStart) { className += 'fc-corner-left '; } if (seg.isEnd) { className += 'fc-corner-right '; } } eventElement = $("<div class='" + className + event.className.join(' ') + "'/>") .append(eventAnchor = $("<a/>") .append(event.allDay || !seg.isStart ? null : $("<span class='fc-event-time'/>") .html(formatDates(event.start, event.end, view.option('timeFormat'), options))) .append($("<span class='fc-event-title'/>") .text(event.title))); if (event.url) { eventAnchor.attr('href', event.url); } triggerRes = view.trigger('eventRender', event, event, eventElement); if (triggerRes !== false) { if (triggerRes && typeof triggerRes != 'boolean') { eventElement = $(triggerRes); } eventElement .css({ position: 'absolute', top: top, left: left + (rtlLeftDiff||0), zIndex: 8 }) .appendTo(element); setOuterWidth(eventElement, right-left, true); if (rtl && rtlLeftDiff == undefined) { // bug in IE6 where offsets are miscalculated with direction:rtl rtlLeftDiff = left - eventElement.position().left; if (rtlLeftDiff) { eventElement.css('left', left + rtlLeftDiff); } } view.eventElementHandlers(event, eventElement); if (event.editable || event.editable == undefined && options.editable) { draggableEvent(event, eventElement); if (seg.isEnd) { view.resizableDayEvent(event, eventElement, colWidth); } } view.reportEventElement(event, eventElement); levelHeight = Math.max(levelHeight, eventElement.outerHeight(true)); } } rowContentHeight += levelHeight; top += levelHeight; } innerDiv.height(rowContentHeight); } } /* Event Dragging -----------------------------------------------------------------------------*/ function draggableEvent(event, eventElement) { if (!options.disableDragging && eventElement.draggable) { var matrix; eventElement.draggable({ zIndex: 9, delay: 50, opacity: view.option('dragOpacity'), revertDuration: options.dragRevertDuration, start: function(ev, ui) { view.hideEvents(event, eventElement); view.trigger('eventDragStart', eventElement, event, ev, ui); matrix = new HoverMatrix(function(cell) { eventElement.draggable('option', 'revert', !cell || !cell.rowDelta && !cell.colDelta); if (cell) { view.showOverlay(cell); }else{ view.hideOverlay(); } }); tbody.find('tr').each(function() { matrix.row(this); }); var tds = tbody.find('tr:first td'); if (rtl) { tds = $(tds.get().reverse()); } tds.each(function() { matrix.col(this); }); matrix.mouse(ev.pageX, ev.pageY); }, drag: function(ev) { matrix.mouse(ev.pageX, ev.pageY); }, stop: function(ev, ui) { view.hideOverlay(); view.trigger('eventDragStop', eventElement, event, ev, ui); var cell = matrix.cell; if (!cell || !cell.rowDelta && !cell.colDelta) { if ($.browser.msie) { eventElement.css('filter', ''); // clear IE opacity side-effects } view.showEvents(event, eventElement); }else{ eventElement.find('a').removeAttr('href'); // prevents safari from visiting the link view.eventDrop(this, event, cell.rowDelta*7+cell.colDelta*dis, 0, event.allDay, ev, ui); } } }); } } // event resizing w/ 'view' methods... }; /* Agenda Views: agendaWeek/agendaDay -----------------------------------------------------------------------------*/ setDefaults({ allDaySlot: true, allDayText: 'all-day', firstHour: 6, slotMinutes: 30, defaultEventMinutes: 120, axisFormat: 'h(:mm)tt', timeFormat: { agenda: 'h:mm{ - h:mm}' }, dragOpacity: { agenda: .5 } }); views.agendaWeek = function(element, options) { return new Agenda(element, options, { render: function(date, delta, fetchEvents) { if (delta) { addDays(date, delta * 7); } var visStart = this.visStart = cloneDate( this.start = addDays(cloneDate(date), -((date.getDay() - options.firstDay + 7) % 7)) ), visEnd = this.visEnd = cloneDate( this.end = addDays(cloneDate(visStart), 7) ); if (!options.weekends) { skipWeekend(visStart); skipWeekend(visEnd, -1, true); } this.title = formatDates( visStart, addDays(cloneDate(visEnd), -1), this.option('titleFormat'), options ); this.renderAgenda(options.weekends ? 7 : 5, this.option('columnFormat'), fetchEvents); } }); }; views.agendaDay = function(element, options) { return new Agenda(element, options, { render: function(date, delta, fetchEvents) { if (delta) { addDays(date, delta); if (!options.weekends) { skipWeekend(date, delta < 0 ? -1 : 1); } } this.title = formatDate(date, this.option('titleFormat'), options); this.start = this.visStart = cloneDate(date, true); this.end = this.visEnd = addDays(cloneDate(this.start), 1); this.renderAgenda(1, this.option('columnFormat'), fetchEvents); } }); }; function Agenda(element, options, methods) { var head, body, bodyContent, bodyTable, bg, colCnt, axisWidth, colWidth, slotHeight, cachedDaySegs, cachedSlotSegs, tm, firstDay, nwe, // no weekends (int) rtl, dis, dit, // day index sign / translate // ... view = $.extend(this, viewMethods, methods, { renderAgenda: renderAgenda, renderEvents: renderEvents, rerenderEvents: rerenderEvents, updateSize: updateSize, shown: resetScroll, defaultEventEnd: function(event) { var start = cloneDate(event.start); if (event.allDay) { return start; } return addMinutes(start, options.defaultEventMinutes); }, visEventEnd: function(event) { if (event.allDay) { if (event.end) { var end = cloneDate(event.end); return (event.allDay || end.getHours() || end.getMinutes()) ? addDays(end, 1) : end; }else{ return addDays(cloneDate(event.start), 1); } } if (event.end) { return cloneDate(event.end); }else{ return addMinutes(cloneDate(event.start), options.defaultEventMinutes); } } }); view.init(element, options); /* Time-slot rendering -----------------------------------------------------------------------------*/ element.addClass('fc-agenda').css('position', 'relative'); if (element.disableSelection) { element.disableSelection(); } function renderAgenda(c, colFormat, fetchEvents) { colCnt = c; // update option-derived variables tm = options.theme ? 'ui' : 'fc'; nwe = options.weekends ? 0 : 1; firstDay = options.firstDay; if (rtl = options.isRTL) { dis = -1; dit = colCnt - 1; }else{ dis = 1; dit = 0; } var d0 = rtl ? addDays(cloneDate(view.visEnd), -1) : cloneDate(view.visStart), d = cloneDate(d0), today = clearTime(new Date()); if (!head) { // first time rendering, build from scratch var i, minutes, slotNormal = options.slotMinutes % 15 == 0, //... // head s = "<div class='fc-agenda-head' style='position:relative;z-index:4'>" + "<table style='width:100%'>" + "<tr class='fc-first" + (options.allDaySlot ? '' : ' fc-last') + "'>" + "<th width='14%' class='fc-leftmost " + tm + "-state-default'> </th>"; for (i=0; i<colCnt; i++) { s += "<th width='15%' class='fc-" + dayIDs[d.getDay()] + ' ' + // needs to be first tm + '-state-default' + "'>" + formatDate(d, colFormat, options) + "</th>"; addDays(d, dis); if (nwe) { skipWeekend(d, dis); } } s += "<th width='14%' class='" + tm + "-state-default'> </th></tr>"; if (options.allDaySlot) { s += "<tr class='fc-all-day'>" + "<th width='14%' class='fc-axis fc-leftmost " + tm + "-state-default'>" + options.allDayText + "</th>" + "<td colspan='" + colCnt + "' class='" + tm + "-state-default'>" + "<div class='fc-day-content'><div> </div></div></td>" + "<th width='14%' class='" + tm + "-state-default'> </th>" + "</tr><tr class='fc-divider fc-last'><th width='14%' colspan='" + (colCnt+2) + "' class='" + tm + "-state-default fc-leftmost'><div/></th></tr>"; } s+= "</table></div>"; head = $(s).appendTo(element); head.find('td').click(slotClick); // body d = zeroDate(); s = "<table>"; for (i=0; d.getDate() != 2; i++) { minutes = d.getMinutes(); s += "<tr class='" + (i==0 ? 'fc-first' : (minutes==0 ? '' : 'fc-minor')) + "'><th width='14%' class='fc-axis fc-leftmost " + tm + "-state-default'>" + ((!slotNormal || minutes==0) ? formatDate(d, options.axisFormat) : ' ') + "</th><td class='fc-slot" + i + ' ' + tm + "-state-default'><div> </div></td></tr>"; addMinutes(d, options.slotMinutes); } s += "</table>"; body = $("<div class='fc-agenda-body' style='position:relative;z-index:2;overflow:auto'/>") .append(bodyContent = $("<div style='position:relative;overflow:hidden'>") .append(bodyTable = $(s))) .appendTo(element); body.find('td').click(slotClick); // background stripes d = cloneDate(d0); s = "<div class='fc-agenda-bg' style='position:absolute;z-index:1'>" + "<table style='width:100%;height:100%'><tr class='fc-first'>"; for (i=0; i<colCnt; i++) { s += "<td class='fc-" + dayIDs[i] + ' ' + // needs to be first tm + '-state-default ' + (i==0 ? 'fc-leftmost ' : '') + (+d == +today ? tm + '-state-highlight fc-today' : 'fc-not-today') + "'><div class='fc-day-content'><div> </div></div></td>"; addDays(d, dis); if (nwe) { skipWeekend(d, dis); } } s += "</tr></table></div>"; bg = $(s).appendTo(element); }else{ // skeleton already built, just modify it view.clearEvents(); // redo column header text and class head.find('tr:first th').slice(1, -1).each(function() { $(this).text(formatDate(d, colFormat, options)); this.className = this.className.replace(/^fc-\w+(?= )/, 'fc-' + dayIDs[d.getDay()]); addDays(d, dis); if (nwe) { skipWeekend(d, dis); } }); // change classes of background stripes d = cloneDate(d0); bg.find('td').each(function() { this.className = this.className.replace(/^fc-\w+(?= )/, 'fc-' + dayIDs[d.getDay()]); if (+d == +today) { $(this) .removeClass('fc-not-today') .addClass('fc-today') .addClass(tm + '-state-highlight'); }else{ $(this) .addClass('fc-not-today') .removeClass('fc-today') .removeClass(tm + '-state-highlight'); } addDays(d, dis); if (nwe) { skipWeekend(d, dis); } }); } updateSize(); resetScroll(); fetchEvents(renderEvents); }; function resetScroll() { var d0 = zeroDate(), scrollDate = cloneDate(d0); scrollDate.setHours(options.firstHour); var go = function() { body.scrollTop(timePosition(d0, scrollDate) + 1); // +1 for the border // TODO: +1 doesn't apply when firstHour=0 } if ($.browser.opera) { setTimeout(go, 0); // opera 10 (and earlier?) needs this }else{ go(); } } function updateSize() { bodyTable.width(''); body.height(Math.round(body.width() / options.aspectRatio) - head.height()); // need this for IE6/7. triggers clientWidth to be calculated for // later user in this function. this is ridiculous body[0].clientWidth; var topTDs = head.find('tr:first th'), stripeTDs = bg.find('td'), contentWidth = body[0].clientWidth; bodyTable.width(contentWidth); // time-axis width axisWidth = 0; setOuterWidth( head.find('tr:lt(2) th:first').add(body.find('tr:first th')) .width('') .each(function() { axisWidth = Math.max(axisWidth, $(this).outerWidth()); }), axisWidth ); // column width colWidth = Math.floor((contentWidth - axisWidth) / colCnt); setOuterWidth(stripeTDs.slice(0, -1), colWidth); setOuterWidth(topTDs.slice(1, -2), colWidth); setOuterWidth(topTDs.slice(-2, -1), contentWidth - axisWidth - colWidth*(colCnt-1)); bg.css({ top: head.find('tr').height(), left: axisWidth, width: contentWidth - axisWidth, height: element.height() }); slotHeight = body.find('tr:first div').height() + 1; // TODO: //reportTBody(bodyTable.find('tbody')); // Opera 9.25 doesn't detect the bug when called from agenda } function slotClick(ev) { var col = Math.floor((ev.pageX - bg.offset().left) / colWidth), date = addDays(cloneDate(view.visStart), dit + dis*col), rowMatch = this.className.match(/fc-slot(\d+)/); if (rowMatch) { var mins = parseInt(rowMatch[1]) * options.slotMinutes, hours = Math.floor(mins/60); date.setHours(hours); date.setMinutes(mins % 60); view.trigger('dayClick', this, date, false, ev); }else{ view.trigger('dayClick', this, date, true, ev); } } /* Event Rendering -----------------------------------------------------------------------------*/ function renderEvents(events) { view.reportEvents(events); var i, len=events.length, dayEvents=[], slotEvents=[]; for (i=0; i<len; i++) { if (events[i].allDay) { dayEvents.push(events[i]); }else{ slotEvents.push(events[i]); } } renderDaySegs(cachedDaySegs = stackSegs(view.sliceSegs(dayEvents, view.visStart, view.visEnd))); renderSlotSegs(cachedSlotSegs = compileSlotSegs(slotEvents)); } function rerenderEvents(skipCompile) { view.clearEvents(); if (skipCompile) { renderDaySegs(cachedDaySegs); renderSlotSegs(cachedSlotSegs); }else{ renderEvents(view.cachedEvents); } } function compileSlotSegs(events) { var d1 = cloneDate(view.visStart), d2 = addDays(cloneDate(d1), 1), levels, segCols = [], i=0; for (; i<colCnt; i++) { levels = stackSegs(view.sliceSegs(events, d1, d2)); countForwardSegs(levels); segCols.push(levels); addDays(d1, 1); addDays(d2, 1); } return segCols; } // renders 'all-day' events at the top function renderDaySegs(segRow) { if (options.allDaySlot) { var td = head.find('td'), tdInner = td.find('div div'), tr = td.parent(), top = safePosition(tdInner, td, tr, tr.parent()).top, rowContentHeight = 0, i, len=segRow.length, level, levelHeight, j, seg, event, className, leftDay, leftRounded, rightDay, rightRounded, left, right, eventElement, anchorElement, triggerRes; for (i=0; i<len; i++) { level = segRow[i]; levelHeight = 0; for (j=0; j<level.length; j++) { seg = level[j]; event = seg.event; className = 'fc-event fc-event-hori '; if (rtl) { leftDay = seg.end.getDay() - 1; leftRounded = seg.isEnd; rightDay = seg.start.getDay(); rightRounded = seg.isStart; }else{ leftDay = seg.start.getDay(); leftRounded = seg.isStart; rightDay = seg.end.getDay() - 1; rightRounded = seg.isEnd; } if (leftRounded) { className += 'fc-corner-left '; left = bg.find('td:eq('+(((leftDay-Math.max(firstDay,nwe)+colCnt)%colCnt)*dis+dit)+') div div').position().left + axisWidth; }else{ left = axisWidth; } if (rightRounded) { className += 'fc-corner-right '; right = bg.find('td:eq('+(((rightDay-Math.max(firstDay,nwe)+colCnt)%colCnt)*dis+dit)+') div div'); right = right.position().left + right.width() + axisWidth; }else{ right = axisWidth + bg.width(); } eventElement = $("<div class='" + className + event.className.join(' ') + "'/>") .append(anchorElement = $("<a/>") .append($("<span class='fc-event-title' />") .text(event.title))); if (event.url) { anchorElement.attr('href', event.url); } triggerRes = view.trigger('eventRender', event, event, eventElement); if (triggerRes !== false) { if (triggerRes && typeof triggerRes != 'boolean') { eventElement = $(triggerRes); } eventElement .css({ position: 'absolute', top: top, left: left, zIndex: 8 }) .appendTo(head); setOuterWidth(eventElement, right-left, true); view.eventElementHandlers(event, eventElement); if (event.editable || event.editable == undefined && options.editable) { draggableDayEvent(event, eventElement, seg.isStart); if (seg.isEnd) { view.resizableDayEvent(event, eventElement, colWidth); } } view.reportEventElement(event, eventElement); levelHeight = Math.max(levelHeight, eventElement.outerHeight(true)); } } top += levelHeight; rowContentHeight += levelHeight; } tdInner.height(rowContentHeight); updateSize(); // tdInner might have pushed the body down, so resize } } // renders events in the 'time slots' at the bottom function renderSlotSegs(segCols) { var colI, colLen=segCols.length, col, levelI, level, segI, seg, forward, event, top, bottom, tdInner, width, left, className, eventElement, anchorElement, timeElement, titleElement, triggerRes; for (colI=0; colI<colLen; colI++) { col = segCols[colI]; for (levelI=0; levelI<col.length; levelI++) { level = col[levelI]; for (segI=0; segI<level.length; segI++) { seg = level[segI]; forward = seg.forward || 0; event = seg.event; top = timePosition(seg.start, seg.start); bottom = timePosition(seg.start, seg.end); tdInner = bg.find('td:eq(' + (colI*dis + dit) + ') div div'); availWidth = tdInner.width(); if (levelI) { // indented and thin width = availWidth / (levelI + forward + 1); }else{ if (forward) { // moderately wide, aligned left still width = ((availWidth / (forward + 1)) - (12/2)) * 2; // 12 is the predicted width of resizer = }else{ // can be entire width, aligned left width = availWidth * .96; } } left = axisWidth + tdInner.position().left + // leftmost possible (availWidth / (levelI + forward + 1) * levelI) // indentation * dis + (rtl ? availWidth - width : 0); // rtl className = 'fc-event fc-event-vert '; if (seg.isStart) { className += 'fc-corner-top '; } if (seg.isEnd) { className += 'fc-corner-bottom '; } eventElement = $("<div class='" + className + event.className.join(' ') + "' />") .append(anchorElement = $("<a><span class='fc-event-bg'/></a>") .append(timeElement = $("<span class='fc-event-time'/>") .text(formatDates(event.start, event.end, view.option('timeFormat')))) .append(titleElement = $("<span class='fc-event-title'/>") .text(event.title))) if (event.url) { anchorElement.attr('href', event.url); } triggerRes = view.trigger('eventRender', event, event, eventElement); if (triggerRes !== false) { if (triggerRes && typeof triggerRes != 'boolean') { eventElement = $(triggerRes); } eventElement .css({ position: 'absolute', zIndex: 8, top: top, left: left }) .appendTo(bodyContent); setOuterWidth(eventElement, width, true); setOuterHeight(eventElement, bottom-top, true); if (eventElement.height() - titleElement.position().top < 10) { // event title doesn't have enough room, put next to the time timeElement.text(formatDate(event.start, view.option('timeFormat')) + ' - ' + event.title); titleElement.remove(); } view.eventElementHandlers(event, eventElement); if (event.editable || event.editable == undefined && options.editable) { draggableSlotEvent(event, eventElement, timeElement); if (seg.isEnd) { resizableSlotEvent(event, eventElement, timeElement); } } } view.reportEventElement(event, eventElement); } } } } /* Event Dragging -----------------------------------------------------------------------------*/ // when event starts out FULL-DAY function draggableDayEvent(event, eventElement, isStart) { if (!options.disableDragging && eventElement.draggable) { var origPosition, origWidth, resetElement, allDay=true, matrix; eventElement.draggable({ zIndex: 9, opacity: view.option('dragOpacity', 'month'), // use whatever the month view was using revertDuration: options.dragRevertDuration, start: function(ev, ui) { view.hideEvents(event, eventElement); view.trigger('eventDragStart', eventElement, event, ev, ui); origPosition = eventElement.position(); origWidth = eventElement.width(); resetElement = function() { if (!allDay) { eventElement .width(origWidth) .height('') .draggable('option', 'grid', null); allDay = true; } }; matrix = new HoverMatrix(function(cell) { eventElement.draggable('option', 'revert', !cell || !cell.rowDelta && !cell.colDelta); if (cell) { if (!cell.row) { // on full-days resetElement(); view.showOverlay(cell); }else{ // mouse is over bottom slots if (isStart && allDay) { // convert event to temporary slot-event setOuterHeight( eventElement.width(colWidth - 10), // don't use entire width slotHeight * Math.round( (event.end ? ((event.end - event.start)/MINUTE_MS) : options.defaultEventMinutes) /options.slotMinutes) ); eventElement.draggable('option', 'grid', [colWidth, 1]); allDay = false; } view.hideOverlay(); } }else{ // mouse is outside of everything view.hideOverlay(); } }); matrix.row(head.find('td')); bg.find('td').each(function() { matrix.col(this); }); matrix.row(body); matrix.mouse(ev.pageX, ev.pageY); }, drag: function(ev, ui) { matrix.mouse(ev.pageX, ev.pageY); }, stop: function(ev, ui) { view.hideOverlay(); view.trigger('eventDragStop', eventElement, event, ev, ui); var cell = matrix.cell, dayDelta = dis * ( allDay ? // can't trust cell.colDelta when using slot grid (cell ? cell.colDelta : 0) : Math.floor((ui.position.left - origPosition.left) / colWidth) ); if (!cell || !dayDelta && !cell.rowDelta) { // over nothing (has reverted) resetElement(); if ($.browser.msie) { eventElement.css('filter', ''); // clear IE opacity side-effects } view.showEvents(event, eventElement); }else{ eventElement.find('a').removeAttr('href'); // prevents safari from visiting the link view.eventDrop( this, event, dayDelta, allDay ? 0 : // minute delta Math.round((eventElement.offset().top - bodyContent.offset().top) / slotHeight) * options.slotMinutes - (event.start.getHours() * 60 + event.start.getMinutes()), allDay, ev, ui ); } } }); } } // when event starts out IN TIMESLOTS function draggableSlotEvent(event, eventElement, timeElement) { if (!options.disableDragging && eventElement.draggable) { var origPosition, resetElement, prevSlotDelta, slotDelta, allDay=false, matrix; eventElement.draggable({ zIndex: 9, scroll: false, grid: [colWidth, slotHeight], axis: colCnt==1 ? 'y' : false, opacity: view.option('dragOpacity'), revertDuration: options.dragRevertDuration, start: function(ev, ui) { view.hideEvents(event, eventElement); view.trigger('eventDragStart', eventElement, event, ev, ui); if ($.browser.msie) { eventElement.find('span.fc-event-bg').hide(); // nested opacities mess up in IE, just hide } origPosition = eventElement.position(); resetElement = function() { // convert back to original slot-event if (allDay) { timeElement.css('display', ''); // show() was causing display=inline eventElement.draggable('option', 'grid', [colWidth, slotHeight]); allDay = false; } }; prevSlotDelta = 0; matrix = new HoverMatrix(function(cell) { eventElement.draggable('option', 'revert', !cell); if (cell) { if (!cell.row && options.allDaySlot) { // over full days if (!allDay) { // convert to temporary all-day event allDay = true; timeElement.hide(); eventElement.draggable('option', 'grid', null); } view.showOverlay(cell); }else{ // on slots resetElement(); view.hideOverlay(); } }else{ view.hideOverlay(); } }); if (options.allDaySlot) { matrix.row(head.find('td')); } bg.find('td').each(function() { matrix.col(this); }); matrix.row(body); matrix.mouse(ev.pageX, ev.pageY); }, drag: function(ev, ui) { slotDelta = Math.round((ui.position.top - origPosition.top) / slotHeight); if (slotDelta != prevSlotDelta) { if (!allDay) { // update time header var minuteDelta = slotDelta*options.slotMinutes, newStart = addMinutes(cloneDate(event.start), minuteDelta), newEnd; if (event.end) { newEnd = addMinutes(cloneDate(event.end), minuteDelta); } timeElement.text(formatDates(newStart, newEnd, view.option('timeFormat'))); } prevSlotDelta = slotDelta; } matrix.mouse(ev.pageX, ev.pageY); }, stop: function(ev, ui) { view.hideOverlay(); view.trigger('eventDragStop', eventElement, event, ev, ui); var cell = matrix.cell, dayDelta = dis * ( allDay ? // can't trust cell.colDelta when using slot grid (cell ? cell.colDelta : 0) : Math.floor((ui.position.left - origPosition.left) / colWidth) ); if (!cell || !slotDelta && !dayDelta) { resetElement(); if ($.browser.msie) { eventElement .css('filter', '') // clear IE opacity side-effects .find('span.fc-event-bg').css('display', ''); // .show() made display=inline } eventElement.css(origPosition); // sometimes fast drags make event revert to wrong position view.showEvents(event, eventElement); }else{ view.eventDrop( this, event, dayDelta, allDay ? 0 : slotDelta * options.slotMinutes, // minute delta allDay, ev, ui ); } } }); } } /* Event Resizing -----------------------------------------------------------------------------*/ // for TIMESLOT events function resizableSlotEvent(event, eventElement, timeElement) { if (!options.disableResizing && eventElement.resizable) { var slotDelta, prevSlotDelta; eventElement .resizable({ handles: 's', grid: slotHeight, start: function(ev, ui) { slotDelta = prevSlotDelta = 0; view.hideEvents(event, eventElement); if ($.browser.msie && $.browser.version == '6.0') { eventElement.css('overflow', 'hidden'); } eventElement.css('z-index', 9); view.trigger('eventResizeStart', this, event, ev, ui); }, resize: function(ev, ui) { // don't rely on ui.size.height, doesn't take grid into account slotDelta = Math.round((Math.max(slotHeight, eventElement.height()) - ui.originalSize.height) / slotHeight); if (slotDelta != prevSlotDelta) { timeElement.text( formatDates( event.start, (!slotDelta && !event.end) ? null : // no change, so don't display time range addMinutes(view.eventEnd(event), options.slotMinutes*slotDelta), view.option('timeFormat') ) ); prevSlotDelta = slotDelta; } }, stop: function(ev, ui) { view.trigger('eventResizeStop', this, event, ev, ui); if (slotDelta) { view.eventResize(this, event, 0, options.slotMinutes*slotDelta, ev, ui); }else{ eventElement.css('z-index', 8); view.showEvents(event, eventElement); // BUG: if event was really short, need to put title back in span } } }) .find('div.ui-resizable-s').text('='); } } // ALL-DAY event resizing w/ 'view' methods... /* Misc -----------------------------------------------------------------------------*/ // get the Y coordinate of the given time on the given day (both Date objects) function timePosition(day, time) { if (time > day && time.getDay() != day.getDay()) { return bodyContent.height(); } var slotMinutes = options.slotMinutes, minutes = time.getHours()*60 + time.getMinutes(), slotI = Math.floor(minutes / slotMinutes), tr = body.find('tr:eq(' + slotI + ')'), td = tr.find('td'), innerDiv = td.find('div'); return Math.max(0, Math.round( safePosition(innerDiv, td, tr, tr.parent()).top - 1 + slotHeight * ((minutes % slotMinutes) / slotMinutes) )); } } // count the number of colliding, higher-level segments (for event squishing) function countForwardSegs(levels) { var i, j, k, level, segForward, segBack; for (i=levels.length-1; i>0; i--) { level = levels[i]; for (j=0; j<level.length; j++) { segForward = level[j]; for (k=0; k<levels[i-1].length; k++) { segBack = levels[i-1][k]; if (segsCollide(segForward, segBack)) { segBack.forward = Math.max(segBack.forward||0, (segForward.forward||0)+1); } } } } } /* Methods & Utilities for All Views -----------------------------------------------------------------------------*/ var viewMethods = { // TODO: maybe change the 'vis' variables to 'excl' /* * Objects inheriting these methods must implement the following properties/methods: * - title * - start * - end * - visStart * - visEnd * - defaultEventEnd(event) * - visEventEnd(event) * - render(events) * - rerenderEvents() * * * z-index reservations: * 3 - day-overlay * 8 - events * 9 - dragging/resizing events * */ init: function(element, options) { this.element = element; this.options = options; this.cachedEvents = []; this.eventsByID = {}; this.eventElements = []; this.eventElementsByID = {}; }, // triggers an event handler, always append view as last arg trigger: function(name, thisObj) { if (this.options[name]) { return this.options[name].apply(thisObj || this, Array.prototype.slice.call(arguments, 2).concat([this])); } }, // returns a Date object for an event's end eventEnd: function(event) { return event.end ? cloneDate(event.end) : this.defaultEventEnd(event); // TODO: make sure always using copies }, // report when view receives new events reportEvents: function(events) { // events are already normalized at this point var i, len=events.length, event, eventsByID = this.eventsByID = {}, cachedEvents = this.cachedEvents = []; for (i=0; i<len; i++) { event = events[i]; if (eventsByID[event._id]) { eventsByID[event._id].push(event); }else{ eventsByID[event._id] = [event]; } cachedEvents.push(event); } }, // report when view creates an element for an event reportEventElement: function(event, element) { this.eventElements.push(element); var eventElementsByID = this.eventElementsByID; if (eventElementsByID[event._id]) { eventElementsByID[event._id].push(element); }else{ eventElementsByID[event._id] = [element]; } }, // event element manipulation clearEvents: function() { // only remove ELEMENTS $.each(this.eventElements, function() { this.remove(); }); this.eventElements = []; this.eventElementsByID = {}; }, showEvents: function(event, exceptElement) { this._eee(event, exceptElement, 'show'); }, hideEvents: function(event, exceptElement) { this._eee(event, exceptElement, 'hide'); }, _eee: function(event, exceptElement, funcName) { // event-element-each var elements = this.eventElementsByID[event._id], i, len = elements.length; for (i=0; i<len; i++) { if (elements[i] != exceptElement) { elements[i][funcName](); } } }, // event modification reporting eventDrop: function(e, event, dayDelta, minuteDelta, allDay, ev, ui) { var view = this, oldAllDay = event.allDay; view.moveEvents(view.eventsByID[event._id], dayDelta, minuteDelta, allDay); view.trigger('eventDrop', e, event, dayDelta, minuteDelta, allDay, function() { // TODO: change docs // TODO: investigate cases where this inverse technique might not work view.moveEvents(view.eventsByID[event._id], -dayDelta, -minuteDelta, oldAllDay); view.rerenderEvents(); }, ev, ui); view.eventsChanged = true; view.rerenderEvents(); }, eventResize: function(e, event, dayDelta, minuteDelta, ev, ui) { var view = this; view.elongateEvents(view.eventsByID[event._id], dayDelta, minuteDelta); view.trigger('eventResize', e, event, dayDelta, minuteDelta, function() { // TODO: investigate cases where this inverse technique might not work view.elongateEvents(view.eventsByID[event._id], -dayDelta, -minuteDelta); view.rerenderEvents(); }, ev, ui); view.eventsChanged = true; view.rerenderEvents(); }, // event modification moveEvents: function(events, dayDelta, minuteDelta, allDay) { minuteDelta = minuteDelta || 0; for (var e, len=events.length, i=0; i<len; i++) { e = events[i]; if (allDay != undefined) { e.allDay = allDay; } addMinutes(addDays(e.start, dayDelta, true), minuteDelta); if (e.end) { e.end = addMinutes(addDays(e.end, dayDelta, true), minuteDelta); } normalizeEvent(e, this.options); } }, elongateEvents: function(events, dayDelta, minuteDelta) { minuteDelta = minuteDelta || 0; for (var e, len=events.length, i=0; i<len; i++) { e = events[i]; e.end = addMinutes(addDays(this.eventEnd(e), dayDelta, true), minuteDelta); normalizeEvent(e, this.options); } }, // semi-transparent overlay (while dragging) showOverlay: function(props) { if (!this.dayOverlay) { this.dayOverlay = $("<div class='fc-cell-overlay' style='position:absolute;z-index:3;display:none'/>") .appendTo(this.element); } var o = this.element.offset(); this.dayOverlay .css({ top: props.top - o.top, left: props.left - o.left, width: props.width, height: props.height }) .show(); }, hideOverlay: function() { if (this.dayOverlay) { this.dayOverlay.hide(); } }, // common horizontal event resizing resizableDayEvent: function(event, eventElement, colWidth) { var view = this; if (!view.options.disableResizing && eventElement.resizable) { eventElement.resizable({ handles: view.options.isRTL ? 'w' : 'e', grid: colWidth, minWidth: colWidth/2, // need this or else IE throws errors when too small containment: view.element.parent().parent(), // the main element... // ... a fix. wouldn't allow extending to last column in agenda views (jq ui bug?) start: function(ev, ui) { eventElement.css('z-index', 9); view.hideEvents(event, eventElement); view.trigger('eventResizeStart', this, event, ev, ui); }, stop: function(ev, ui) { view.trigger('eventResizeStop', this, event, ev, ui); // ui.size.width wasn't working with grid correctly, use .width() var dayDelta = Math.round((eventElement.width() - ui.originalSize.width) / colWidth); if (dayDelta) { view.eventResize(this, event, dayDelta, 0, ev, ui); }else{ eventElement.css('z-index', 8); view.showEvents(event, eventElement); } } }); } }, // attaches eventClick, eventMouseover, eventMouseout eventElementHandlers: function(event, eventElement) { var view = this; eventElement .click(function(ev) { if (!eventElement.hasClass('ui-draggable-dragging') && !eventElement.hasClass('ui-resizable-resizing')) { return view.trigger('eventClick', this, event, ev); } }) .hover( function(ev) { view.trigger('eventMouseover', this, event, ev); }, function(ev) { view.trigger('eventMouseout', this, event, ev); } ); }, // get a property from the 'options' object, using smart view naming option: function(name, viewName) { var v = this.options[name]; if (typeof v == 'object') { return smartProperty(v, viewName || this.name); } return v; }, // event rendering utilities sliceSegs: function(events, start, end) { var segs = [], i, len=events.length, event, eventStart, eventEnd, segStart, segEnd, isStart, isEnd; for (i=0; i<len; i++) { event = events[i]; eventStart = event.start; eventEnd = this.visEventEnd(event); if (eventEnd > start && eventStart < end) { if (eventStart < start) { segStart = cloneDate(start); isStart = false; }else{ segStart = eventStart; isStart = true; } if (eventEnd > end) { segEnd = cloneDate(end); isEnd = false; }else{ segEnd = eventEnd; isEnd = true; } segs.push({ event: event, start: segStart, end: segEnd, isStart: isStart, isEnd: isEnd, msLength: segEnd - segStart }); } } return segs.sort(segCmp); } }; // event rendering calculation utilities function stackSegs(segs) { var levels = [], i, len = segs.length, seg, j, collide, k; for (i=0; i<len; i++) { seg = segs[i]; j = 0; // the level index where seg should belong while (true) { collide = false; if (levels[j]) { for (k=0; k<levels[j].length; k++) { if (segsCollide(levels[j][k], seg)) { collide = true; break; } } } if (collide) { j++; }else{ break; } } if (levels[j]) { levels[j].push(seg); }else{ levels[j] = [seg]; } } return levels; } function segCmp(a, b) { return (b.msLength - a.msLength) * 100 + (a.event.start - b.event.start); } function segsCollide(seg1, seg2) { return seg1.end > seg2.start && seg1.start < seg2.end; } /* Date Math -----------------------------------------------------------------------------*/ var DAY_MS = 86400000, HOUR_MS = 3600000, MINUTE_MS = 60000; function addYears(d, n, keepTime) { d.setFullYear(d.getFullYear() + n); if (!keepTime) { clearTime(d); } return d; } function addMonths(d, n, keepTime) { // prevents day overflow/underflow if (+d) { // prevent infinite looping on invalid dates var m = d.getMonth() + n, check = cloneDate(d); check.setDate(1); check.setMonth(m); d.setMonth(m); if (!keepTime) { clearTime(d); } while (d.getMonth() != check.getMonth()) { d.setDate(d.getDate() + (d < check ? 1 : -1)); } } return d; } function addDays(d, n, keepTime) { // deals with daylight savings if (+d) { // prevent infinite looping on invalid dates var dd = d.getDate() + n, check = cloneDate(d); check.setHours(12); // set to middle of day check.setDate(dd); d.setDate(dd); if (!keepTime) { clearTime(d); } while (d.getDate() != check.getDate()) { d.setTime(+d + (d < check ? 1 : -1) * HOUR_MS); } } return d; } fc.addDays = addDays; function addMinutes(d, n) { d.setMinutes(d.getMinutes() + n); return d; } function clearTime(d) { d.setHours(0); d.setMinutes(0); d.setSeconds(0); d.setMilliseconds(0); return d; } function cloneDate(d, dontKeepTime) { if (dontKeepTime) { return clearTime(new Date(+d)); } return new Date(+d); } function zeroDate() { // returns a Date with time 00:00:00 and dateOfMonth=1 var i=0, d; do { d = new Date(1970, i++, 1); } while (d.getHours() != 0); return d; } function skipWeekend(date, inc, excl) { inc = inc || 1; while (date.getDay()==0 || (excl && date.getDay()==1 || !excl && date.getDay()==6)) { addDays(date, inc); } return date; } /* Date Parsing -----------------------------------------------------------------------------*/ var parseDate = fc.parseDate = function(s) { if (typeof s == 'object') { // already a Date object return s; } if (typeof s == 'number') { // a UNIX timestamp return new Date(s * 1000); } if (typeof s == 'string') { if (s.match(/^\d+$/)) { // a UNIX timestamp return new Date(parseInt(s) * 1000); } return parseISO8601(s, true) || new Date(s) || null; } return null; } var parseISO8601 = fc.parseISO8601 = function(s, ignoreTimezone) { // derived from http://delete.me.uk/2005/03/iso8601.html var d = s.match(/^([0-9]{4})(-([0-9]{2})(-([0-9]{2})(T([0-9]{2}):([0-9]{2})(:([0-9]{2})(\.([0-9]+))?)?(Z|(([-+])([0-9]{2}):([0-9]{2})))?)?)?)?$/); if (!d) return null; var offset = 0; var date = new Date(d[1], 0, 1); if (d[3]) { date.setMonth(d[3] - 1); } if (d[5]) { date.setDate(d[5]); } if (d[7]) { date.setHours(d[7]); } if (d[8]) { date.setMinutes(d[8]); } if (d[10]) { date.setSeconds(d[10]); } if (d[12]) { date.setMilliseconds(Number("0." + d[12]) * 1000); } if (!ignoreTimezone) { if (d[14]) { offset = (Number(d[16]) * 60) + Number(d[17]); offset *= ((d[15] == '-') ? 1 : -1); } offset -= date.getTimezoneOffset(); } return new Date(Number(date) + (offset * 60 * 1000)); } /* Date Formatting -----------------------------------------------------------------------------*/ var formatDate = fc.formatDate = function(date, format, options) { return formatDates(date, null, format, options); } var formatDates = fc.formatDates = function(date1, date2, format, options) { options = options || defaults; var date = date1, otherDate = date2, i, len = format.length, c, i2, formatter, res = ''; for (i=0; i<len; i++) { c = format.charAt(i); if (c == "'") { for (i2=i+1; i2<len; i2++) { if (format.charAt(i2) == "'") { if (date) { if (i2 == i+1) { res += "'"; }else{ res += format.substring(i+1, i2); } i = i2; } break; } } } else if (c == '(') { for (i2=i+1; i2<len; i2++) { if (format.charAt(i2) == ')') { var subres = formatDate(date, format.substring(i+1, i2), options); if (parseInt(subres.replace(/\D/, ''))) { res += subres; } i = i2; break; } } } else if (c == '[') { for (i2=i+1; i2<len; i2++) { if (format.charAt(i2) == ']') { var subformat = format.substring(i+1, i2); var subres = formatDate(date, subformat, options); if (subres != formatDate(otherDate, subformat, options)) { res += subres; } i = i2; break; } } } else if (c == '{') { date = date2; otherDate = date1; } else if (c == '}') { date = date1; otherDate = date2; } else { for (i2=len; i2>i; i2--) { if (formatter = dateFormatters[format.substring(i, i2)]) { if (date) { res += formatter(date, options); } i = i2 - 1; break; } } if (i2 == i) { if (date) { res += c; } } } } return res; } var dateFormatters = { s : function(d) { return d.getSeconds() }, ss : function(d) { return zeroPad(d.getSeconds()) }, m : function(d) { return d.getMinutes() }, mm : function(d) { return zeroPad(d.getMinutes()) }, h : function(d) { return d.getHours() % 12 || 12 }, hh : function(d) { return zeroPad(d.getHours() % 12 || 12) }, H : function(d) { return d.getHours() }, HH : function(d) { return zeroPad(d.getHours()) }, d : function(d) { return d.getDate() }, dd : function(d) { return zeroPad(d.getDate()) }, ddd : function(d,o) { return o.dayNamesShort[d.getDay()] }, dddd: function(d,o) { return o.dayNames[d.getDay()] }, M : function(d) { return d.getMonth() + 1 }, MM : function(d) { return zeroPad(d.getMonth() + 1) }, MMM : function(d,o) { return o.monthNamesShort[d.getMonth()] }, MMMM: function(d,o) { return o.monthNames[d.getMonth()] }, yy : function(d) { return (d.getFullYear()+'').substring(2) }, yyyy: function(d) { return d.getFullYear() }, t : function(d) { return d.getHours() < 12 ? 'a' : 'p' }, tt : function(d) { return d.getHours() < 12 ? 'am' : 'pm' }, T : function(d) { return d.getHours() < 12 ? 'A' : 'P' }, TT : function(d) { return d.getHours() < 12 ? 'AM' : 'PM' }, u : function(d) { return formatDate(d, "yyyy-MM-dd'T'HH:mm:ss'Z'") }, S : function(d) { var date = d.getDate(); if (date > 10 && date < 20) return 'th'; return ['st', 'nd', 'rd'][date%10-1] || 'th'; } }; /* Element Dimensions -----------------------------------------------------------------------------*/ function setOuterWidth(element, width, includeMargins) { element.each(function() { var e = $(this); var w = width - ( (parseInt(e.css('border-left-width')) || 0) + (parseInt(e.css('padding-left')) || 0) + (parseInt(e.css('padding-right')) || 0) + (parseInt(e.css('border-right-width')) || 0)); if (includeMargins) { w -= (parseInt(e.css('margin-left')) || 0) + (parseInt(e.css('margin-right')) || 0); } e.width(w); }); } function setOuterHeight(element, height, includeMargins) { element.each(function() { var e = $(this); var h = height - ( (parseInt(e.css('border-top-width')) || 0) + (parseInt(e.css('padding-top')) || 0) + (parseInt(e.css('padding-bottom')) || 0) + (parseInt(e.css('border-bottom-width')) || 0)); if (includeMargins) { h -= (parseInt(e.css('margin-top')) || 0) + (parseInt(e.css('margin-bottom')) || 0); } e.height(h); }); } /* Position Calculation -----------------------------------------------------------------------------*/ // nasty bugs in opera 9.25 // position() returning relative to direct parent var operaPositionBug; function reportTBody(tbody) { if (operaPositionBug == undefined) { operaPositionBug = tbody.position().top != tbody.find('tr').position().top; } } function safePosition(element, td, tr, tbody) { var position = element.position(); if (operaPositionBug) { position.top += tbody.position().top + tr.position().top - td.position().top; } return position; } /* Hover Matrix -----------------------------------------------------------------------------*/ function HoverMatrix(changeCallback) { var tops=[], lefts=[], prevRowE, prevColE, origRow, origCol, currRow, currCol; this.row = function(e, topBug) { prevRowE = $(e); tops.push(prevRowE.offset().top + ( (operaPositionBug && prevRowE.is('tr')) ? prevRowE.parent().position().top : 0 )); }; this.col = function(e) { prevColE = $(e); lefts.push(prevColE.offset().left); }; this.mouse = function(x, y) { if (origRow == undefined) { tops.push(tops[tops.length-1] + prevRowE.outerHeight()); lefts.push(lefts[lefts.length-1] + prevColE.outerWidth()); currRow = currCol = -1; } var r, c; for (r=0; r<tops.length && y>=tops[r]; r++) ; for (c=0; c<lefts.length && x>=lefts[c]; c++) ; r = r >= tops.length ? -1 : r - 1; c = c >= lefts.length ? -1 : c - 1; if (r != currRow || c != currCol) { currRow = r; currCol = c; if (r == -1 || c == -1) { this.cell = null; }else{ if (origRow == undefined) { origRow = r; origCol = c; } this.cell = { row: r, col: c, top: tops[r], left: lefts[c], width: lefts[c+1] - lefts[c], height: tops[r+1] - tops[r], isOrig: r==origRow && c==origCol, rowDelta: r-origRow, colDelta: c-origCol }; } changeCallback(this.cell); } }; } /* Misc Utils -----------------------------------------------------------------------------*/ var undefined, dayIDs = ['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat']; function zeroPad(n) { return (n < 10 ? '0' : '') + n; } function smartProperty(obj, name) { // get a camel-cased/namespaced property if (obj[name] != undefined) { return obj[name]; } var parts = name.split(/(?=[A-Z])/), i=parts.length-1, res; for (; i>=0; i--) { res = obj[parts[i].toLowerCase()]; if (res != undefined) { return res; } } return obj['']; } })(jQuery); </script> <script type="text/javascript" src="js/function.js"></script> </head> <body class="single" itemscope itemtype="http://schema.org/WebPage" onLoad="setToday()"> <!-- User Local --> <script type="text/javascript" src="/AD_Tag/UserLocal/userlocal.js"></script> <div id="container"> <!-- header--> <header itemscope itemtype="http://schema.org/WPHeader"> <div id="header" class="clearfix"> <div id="header-in"> <div id="site-title"><a href="https://www.benricho.org/"><img src="/benri_img/title-1070_110.jpg" alt="みんなの知識 ちょっと便利帳" title="みんなの知識 ちょっと便利帳"></a></div> <div class="subtitle_box"> <h1 class="sub_h1">万年卓上予定表/カレンダー<span>= A4版で印刷して使えます。半永久的に作成できます =</span></h1> </div> <!-- 概要 --> <!-- <div class="clear"></div> <div class="titleunder_gaiyo">ここにページ概要を記載しコメントアウトを外す。</div> <div class="clear"></div> --> <!-- /#概要 --> </div> </div> </header> <div id="body"> <div id="body-in"> <main itemscope itemprop="mainContentOfPage"> <div id="main" itemscope itemtype="http://schema.org/Blog"> <div class="post"> <article class="article"> <!-- 上部 Ad --> <div class="no_print mt10"> <div class="mt10 mb10 ml15"> <script type="text/javascript" src="/2017js/ad_upper01.js"></script> </div> <div align="center"> <script type="text/javascript" src="/2017js/ad_upper02.js"></script> <div class="mt20 mb20"> <script type="text/javascript" src="/2017js/ad_upper03_linkunit.js"></script> </div> <!-- CriteoABP-728X90HEADER_ABP --> <script type='text/javascript' src='//static.criteo.net/js/ld/publishertag.js'></script> <div id='crt-1408243' style="width:728px;height:90px;"></div> <script type='text/javascript'> Criteo.DisplayAcceptableAdIfAdblocked( {'zoneid' : 1408243, 'containerid' : 'crt-1408243' }); </script> </div> </div> <div class="clear"></div> <!-- ページ内インデックス --> <a href="/clock/year_calendar.html"> <div class="squarebutton_lightgrey_nofontcolor"> <i class="fa fa-chevron-circle-right fa-1x" aria-hidden="true"></i> カレンダーを見る・カレンダーを作る </div></a> <a href="/calender_printable/"><div class="squarebutton_Pumpkin_BoderColor" style=" border:#c0392b 1px solid;background-color: #c0392b;color: #FFF"> <i class="fa fa-chevron-circle-down fa-1x" aria-hidden="true"></i> 万年卓上予定表 </div></a> <a href="/calender_printable/year-calender.html"><div class="squarebutton_lightgrey_nofontcolor"> <i class="fa fa-chevron-circle-right fa-1x" aria-hidden="true"></i> 年間カレンダーを作る </div></a> <a href="/clock/calendar.html"><div class="squarebutton_lightgrey_nofontcolor"> <i class="fa fa-chevron-circle-right fa-1x" aria-hidden="true"></i> 万年カレンダーを見る(275759 年位まで) </div></a> <div class="clear"></div> <div class="no_print" style="margin:25px 0 5px 0;border:#CCC solid 1px; border-radius:4px;background-color:#FFFBD4;"> <table width="99%" border="0" align="center" cellpadding="0" cellspacing="0"> <tr> <td align="center" class="textbgcolor02"><h2 style="padding: 20px 0; text-align: center">万年卓上予定表/カレンダー <div style="margin-top:8px; font-size:18px">= A4版で印刷して使えます。半永久的に作成できます =</div> </h2></td> </tr> </table> </div> <div id="container-calender" style="width:97%; border:solid #CCCCCC 1px; padding:10px;"> <div id="content"> <a href="calender.html" rel="clearbox[tnhrf=nopreview,,width=1000,,height=800,,title= 【みんなの知識 ちょっと便利帳】 A4版で印刷して使える万年卓上予定表/カレンダー]"> <div style="background-color:#FFFBD4; padding:5px;"><img src="../benri_img/arrow_right.gif" width="16" height="16" align="absmiddle" />・ここをクリックすると下のようなカレンダーが開きます。<br /> ・A4版 で印刷することができ、卓上予定表として利用することができます。<br /> ・[翌月][前月]をクリックして将来・過去のカレンダーを作ることもできます。<br /> ・印刷用では、「きょう」の枠に色は付きません。</div> </a><br /> <div align="center"><div id="calendar"></div></div> </p> </div> </div> <div class="clear"></div> <!-- 記事下Ad --> <div class="ad-article-bottom ad-space no_print"> <!-- Ad (1) --> <div class="ad-left ad-pc adsense-336"> <script type="text/javascript" src="/2017js/ad_under_01.js"></script> </div> <!-- Ad (2) --> <div class="ad-right ad-pc adsense-336"> <script type="text/javascript" src="/2017js/ad_under_02.js"></script> </div> </div> <br clear="all"> <div class="ad-article-bottom ad-space no_print"> <!-- Google関連コンテンツ --> <div class="no_print mt15 cb"> <h2 class="toph2_06"><span class="subtitle6c"><i class="fa fa-book fa-1x" aria-hidden="true"></i> おすすめサイト・関連サイト…</span></h2> <script type="text/javascript" src="/2017js/ad_kanren_osusume.js"></script> </div> <!-- Ad (3) --> <div class="ad-left ad-pc adsense-336"> <script type="text/javascript" src="/2017js/ad_under_03.js"></script> </div> <!-- Ad (4) --> <div class="ad-right ad-pc adsense-336"> <script type="text/javascript" src="/2017js/ad_under_04.js"></script> </div> </div> <!-- CriteoABP-750X280_ABP --> <div align="center" class="no_print"> <script type='text/javascript' src='//static.criteo.net/js/ld/publishertag.js'></script> <div id='crt-1408242' style="width:750px;height:280px;"></div> <script type='text/javascript'> Criteo.DisplayAcceptableAdIfAdblocked( {'zoneid' : 1408242, 'containerid' : 'crt-1408242' }); </script> </div> <!-- /記事下Ad --> </article><!-- .article --> </div><!-- .post --> </div><!-- /#main --> </main> <!-- sidebar --> <div id="sidebar" role="complementary" class="no_print"> <div id="sidebar-widget"> <aside id="search-2" class="widget widget_search"> <!-- サイドバー | GoogleSearch --> <script type="text/javascript" src="/2017js/sidebar01-GoogleSearch.js"></script> <!-- サイドバー | 時計・カレンダー --> <div id="sidebar-Clock-Calender"> <script type="text/javascript" src="/2017js/sidebar02-Clock-Calender.js"></script> </div> <!-- CriteoABP-300_600GOOGLE_ABP --> <div class="no_print" style="margin-left:-2.5px"> <script type='text/javascript' src='//static.criteo.net/js/ld/publishertag.js'></script> <div id='crt-1408241' style="width:300px;height:600px;"></div> <script type='text/javascript'> Criteo.DisplayAcceptableAdIfAdblocked( {'zoneid' : 1408241, 'containerid' : 'crt-1408241' }); </script> </div> <!-- サイドバー | Twitter・Facebook・はてなブックマーク・Google +1 --> <script type="text/javascript" src="/2017js/sidebar03-twitter-facebook.js"></script> <!-- サイドバー | お知らせ --> <script type="text/javascript" src="/2017js/information_sidebar.js"></script> <hr> <div class="side_link"><a href="/"> <i class="fa fa-chevron-circle-right fa-1x" aria-hidden="true"></i> トップページ・<i class="fa fa-home" aria-hidden="true"></i> Home </a></div> <hr> <!-- サイドバー主な項目リンク --> <script type="text/javascript" src="/2017js/sidebar-maincontents_link.js"></script> <div class="side_adarea1"> <hr> <!-- サイドバーAmazon --> <script type="text/javascript" src="/2017js/sidebar-amazon.js"></script> <!-- サイドバーGoogleAd --> <script type="text/javascript" src="/2017js/sidebar_googlead.js"></script> </div> </aside> </div> </div><!-- /#sidebar --> </div><!-- /#body-in --> <!-- footer_copyright --> <script type="text/javascript" src="/2017js/footer.js"></script> <div class="clear"></div> <!-- LastModified --> <div class='lastmodified-new'> Last updated : 2024/06/28 </div> <!-- Page-toTop --> <div id="page-top" class="no_print"><a id="move-page-top"><i class="fa fa-angle-up fa-2x" aria-hidden="true"></i></a></div> <!-- Mobile_Ad - Bottom_Ad --> <script type="text/javascript" src="/2017js/mobile_ad-bottom_ad.js"></script> </div><!-- /#body --> </div><!-- /#container --> <!-- Copyright印刷用テキスト--> <div class="footer-sitetitle-print copyright2">© みんなの知識 ちょっと便利帳 - <script type="text/javascript">document.write(location.href);</script></div> <!-- CommonJavaScript--> <script src="/2017js/javascript.js" defer></script> <!-- Ad-Smartphone-fluct --> <script type="text/javascript" src="https://cdn-fluct.sh.adingo.jp/f.js?G=1000042041"></script> <!-- fluct_320×50_Web_iOS --> <script type="text/javascript"> //<![CDATA[ if(typeof(adingoFluct)!="undefined") adingoFluct.showAd('1000064514'); //]]> </script> <!-- fluct_320×50_Web_Android --> <script type="text/javascript"> //<![CDATA[ if(typeof(adingoFluct)!="undefined") adingoFluct.showAd('1000064515'); //]]> </script> <!-- End Ad-Smartphone-fluct --> <!-- Google-Analytics --> <script type="text/javascript"> var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www."); document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E")); </script> <script type="text/javascript"> try { var pageTracker = _gat._getTracker("UA-1594968-1"); pageTracker._trackPageview(); } catch(err) {}</script> </body> </html>