我有一个使用javascript和moment.js的日历功能,效果很好。尽管我想向包含eventName的字符串添加类似于带有href的href的链接,以便日历中显示的eventName是可单击的链接。我已经包含了函数和包括每个eventName的字符串。有什么建议吗?
!function() {
var today = moment();
function Calendar(selector, events) {
this.el = document.querySelector(selector);
this.events = events;
this.current = moment().date(1);
this.events.forEach(function(ev) {
ev.date = moment(ev.date);
});
this.draw();
var current = document.querySelector('.today');
}
Calendar.prototype.draw = function() {
//Create Header
this.drawHeader();
//Draw Month
this.drawMonth();
this.drawLegend();
}
Calendar.prototype.drawHeader = function() {
var self = this;
if(!this.header) {
//Create the header elements
this.header = createElement('div', 'header');
this.header.className = 'header';
this.title = createElement('h1');
var right = createElement('div', 'right');
right.addEventListener('click', function() { self.nextMonth(); });
var left = createElement('div', 'left');
left.addEventListener('click', function() { self.prevMonth(); });
//Append the Elements
this.header.appendChild(this.title);
this.header.appendChild(right);
this.header.appendChild(left);
this.el.appendChild(this.header);
}
this.title.innerHTML = this.current.format('MMMM YYYY');
}
Calendar.prototype.drawMonth = function() {
var self = this;
if(this.month) {
this.oldMonth = this.month;
this.oldMonth.className = 'month out ' + (self.next ? 'next' : 'prev');
this.oldMonth.addEventListener('webkitAnimationEnd', function() {
self.oldMonth.parentNode.removeChild(self.oldMonth);
self.month = createElement('div', 'month');
self.backFill();
self.currentMonth();
self.fowardFill();
self.el.appendChild(self.month);
window.setTimeout(function() {
self.month.className = 'month in ' + (self.next ? 'next' : 'prev');
}, 16);
});
} else {
this.month = createElement('div', 'month');
this.el.appendChild(this.month);
this.backFill();
this.currentMonth();
this.fowardFill();
this.month.className = 'month new';
}
}
Calendar.prototype.backFill = function() {
var clone = this.current.clone();
var dayOfWeek = clone.day();
if(!dayOfWeek) { return; }
clone.subtract('days', dayOfWeek+1);
for(var i = dayOfWeek; i > 0 ; i--) {
this.drawDay(clone.add('days', 1));
}
}
Calendar.prototype.fowardFill = function() {
var clone = this.current.clone().add('months', 1).subtract('days', 1);
var dayOfWeek = clone.day();
if(dayOfWeek === 6) { return; }
for(var i = dayOfWeek; i < 6 ; i++) {
this.drawDay(clone.add('days', 1));
}
}
Calendar.prototype.currentMonth = function() {
var clone = this.current.clone();
while(clone.month() === this.current.month()) {
this.drawDay(clone);
clone.add('days', 1);
}
}
Calendar.prototype.getWeek = function(day) {
if(!this.week || day.day() === 0) {
this.week = createElement('div', 'week');
this.month.appendChild(this.week);
}
}
Calendar.prototype.drawDay = function(day) {
var self = this;
this.getWeek(day);
//Outer Day
var outer = createElement('div', this.getDayClass(day));
outer.addEventListener('click', function() {
self.openDay(this);
});
//Day Name
var name = createElement('div', 'day-name', day.format('ddd'));
//Day Number
var number = createElement('div', 'day-number', day.format('DD'));
//Events
var events = createElement('div', 'day-events');
this.drawEvents(day, events);
outer.appendChild(name);
outer.appendChild(number);
outer.appendChild(events);
this.week.appendChild(outer);
}
Calendar.prototype.drawEvents = function(day, element) {
if(day.month() === this.current.month()) {
var todaysEvents = this.events.reduce(function(memo, ev) {
if(ev.date.isSame(day, 'day')) {
memo.push(ev);
}
return memo;
}, []);
todaysEvents.forEach(function(ev) {
var evSpan = createElement('span', ev.color);
element.appendChild(evSpan);
});
}
}
Calendar.prototype.getDayClass = function(day) {
classes = ['day'];
if(day.month() !== this.current.month()) {
classes.push('other');
} else if (today.isSame(day, 'day')) {
classes.push('today');
}
return classes.join(' ');
}
Calendar.prototype.openDay = function(el) {
var details, arrow;
var dayNumber = +el.querySelectorAll('.day-number')[0].innerText || +el.querySelectorAll('.day-number')[0].textContent;
var day = this.current.clone().date(dayNumber);
var currentOpened = document.querySelector('.details');
//Check to see if there is an open detais box on the current row
if(currentOpened && currentOpened.parentNode === el.parentNode) {
details = currentOpened;
arrow = document.querySelector('.arrow');
} else {
//Close the open events on differnt week row
//currentOpened && currentOpened.parentNode.removeChild(currentOpened);
if(currentOpened) {
currentOpened.addEventListener('webkitAnimationEnd', function() {
currentOpened.parentNode.removeChild(currentOpened);
});
currentOpened.addEventListener('oanimationend', function() {
currentOpened.parentNode.removeChild(currentOpened);
});
currentOpened.addEventListener('msAnimationEnd', function() {
currentOpened.parentNode.removeChild(currentOpened);
});
currentOpened.addEventListener('animationend', function() {
currentOpened.parentNode.removeChild(currentOpened);
});
currentOpened.className = 'details out';
}
//Create the Details Container
details = createElement('div', 'details in');
//Create the arrow
var arrow = createElement('div', 'arrow');
//Create the event wrapper
details.appendChild(arrow);
el.parentNode.appendChild(details);
}
var todaysEvents = this.events.reduce(function(memo, ev) {
if(ev.date.isSame(day, 'day')) {
memo.push(ev);
}
return memo;
}, []);
this.renderEvents(todaysEvents, details);
arrow.style.left = el.offsetLeft - el.parentNode.offsetLeft + 27 + 'px';
}
Calendar.prototype.renderEvents = function(events, ele) {
//Remove any events in the current details element
var currentWrapper = ele.querySelector('.events');
var wrapper = createElement('div', 'events in' + (currentWrapper ? ' new' : ''));
events.forEach(function(ev) {
var div = createElement('div', 'event');
var square = createElement('div', 'event-category ' + ev.color);
var span = createElement('span', '', ev.eventName);
div.appendChild(square);
div.appendChild(span);
wrapper.appendChild(div);
});
if(!events.length) {
var div = createElement('div', 'event empty');
var span = createElement('span', '', 'No Events');
div.appendChild(span);
wrapper.appendChild(div);
}
if(currentWrapper) {
currentWrapper.className = 'events out';
currentWrapper.addEventListener('webkitAnimationEnd', function() {
currentWrapper.parentNode.removeChild(currentWrapper);
ele.appendChild(wrapper);
});
currentWrapper.addEventListener('oanimationend', function() {
currentWrapper.parentNode.removeChild(currentWrapper);
ele.appendChild(wrapper);
});
currentWrapper.addEventListener('msAnimationEnd', function() {
currentWrapper.parentNode.removeChild(currentWrapper);
ele.appendChild(wrapper);
});
currentWrapper.addEventListener('animationend', function() {
currentWrapper.parentNode.removeChild(currentWrapper);
ele.appendChild(wrapper);
});
} else {
ele.appendChild(wrapper);
}
}
Calendar.prototype.drawLegend = function() {
var legend = createElement('div', 'legend');
var calendars = this.events.map(function(e) {
return e.calendar + '|' + e.color;
}).reduce(function(memo, e) {
if(memo.indexOf(e) === -1) {
memo.push(e);
}
return memo;
}, []).forEach(function(e) {
var parts = e.split('|');
var entry = createElement('span', 'entry ' + parts[1], parts[0]);
legend.appendChild(entry);
});
this.el.appendChild(legend);
}
Calendar.prototype.nextMonth = function() {
this.current.add('months', 1);
this.next = true;
this.draw();
}
Calendar.prototype.prevMonth = function() {
this.current.subtract('months', 1);
this.next = false;
this.draw();
}
window.Calendar = Calendar;
function createElement(tagName, className, innerText) {
var ele = document.createElement(tagName);
if(className) {
ele.className = className;
}
if(innerText) {
ele.innderText = ele.textContent = innerText;
}
return ele;
}
}();
!function() {
var data = [
{ eventName: 'Dinner under the stars', calendar: 'Food/Beverage', color: 'orange', date: '2019-03-10' },
{ eventName: 'Wine tasting', calendar: 'Food/Beverage', color: 'orange', date: '2019-03-08' },
{ eventName: 'BBQ Festival', calendar: 'Food/Beverage', color: 'orange', date: '2019-03-10' },
{ eventName: 'Food Event', calendar: 'Food/Beverage', color: 'orange', date: '2019-03-10' },
{ eventName: 'Wine Event', calendar: 'Food/Beverage', color: 'orange', date: '2019-03-12' },
{ eventName: 'Wine Event', calendar: 'Food/Beverage', color: 'orange', date: '2019-03-18' },
{ eventName: 'Food Event', calendar: 'Food/Beverage', color: 'orange', date: '2019-03-20' },
{ eventName: 'Team vs Team', calendar: 'Sports', color: 'blue', date: '2019-03-01' },
{ eventName: 'Team vs Team', calendar: 'Sports', color: 'blue', date: '2019-03-02' },
{ eventName: 'Kickball Event', calendar: 'Sports', color: 'blue', date: '2019-04-04' },
{ eventName: 'Team vs Team', calendar: 'Sports', color: 'blue', date: '2019-04-01' },
{ eventName: 'Haunted tour', calendar: 'History', color: 'yellow', date: '2019-03-04' },
{ eventName: 'Art museum', calendar: 'History', color: 'yellow', date: '2019-03-19' },
{ eventName: 'Civil War tour', calendar: 'History', color: 'yellow', date: '2019-03-20' },
{ eventName: 'History Event', calendar: 'History', color: 'yellow', date: '2019-03-31' },
{ eventName: 'Outdoor movie', calendar: 'Outdoors', color: 'green', date: '2019-03-02' },
{ eventName: 'Nature walk', calendar: 'Outdoors', color: 'green', date: '2019-03-10' },
{ eventName: 'White water rafting', calendar: 'Outdoors', color: 'green', date: '2019-03-14' },
{ eventName: 'Nature Event', calendar: 'Outdoors', color: 'green', date: '2019-03-17' }
];
var calendar = new Calendar('#calendar', data);
}();
<body>
<div id="calendar"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.5.1/moment.min.js"></script>
<script src="script.js"></script>
</body>
答案 0 :(得分:0)
要实现日历点击的重定向,您必须选择操作方式,这是没有最好的方法,尤其是因为我们不知道您的日历构造函数是如何工作的。我会回答你的问题:
要添加到javascript字符串的链接吗?
如果您不知道链接将在哪里预先指向,那么您别无选择,只能自己添加一个字段。
如果您确实有某种确定href的方法,请在声明数组后执行以下操作:
const linkMaker = (string) => {
const href="/path/to/determine/somehow";
return `<a href={href}>{string}</a>`;
}
dataWithLinks = data.map(dataObject => ({...dataObject, eventName: linkMaker(dataObject.eventName)}));