adjusting the way the data URIs are handled since most browsers are not able to download the link without “save as” command. this resolves #8

This commit is contained in:
Jason Salzman
2017-05-22 03:27:32 -07:00
parent 6b18fc020b
commit 49ba1238a1
2 changed files with 102 additions and 93 deletions
+19 -7
View File
@@ -46,9 +46,25 @@ export default class ReactAddToCalendar extends React.Component {
e.preventDefault();
let url = e.currentTarget.getAttribute("href");
if (url.startsWith("data") || url.startsWith("BEGIN")) {
let filename = "download.ics";
let blob = new Blob([url], { type: "text/calendar;charset=utf-8" });
if (this.state.isCrappyIE) {
let blob = new Blob([url], { type: "text/calendar" });
window.navigator.msSaveOrOpenBlob(blob, "download.ics");
window.navigator.msSaveOrOpenBlob(blob, filename);
} else {
/****************************************************************
// many browsers do not properly support downloading data URIs
// (even with "download" attribute in use) so this solution
// ensures the event will download cross-browser
****************************************************************/
let link = document.createElement("a");
link.href = window.URL.createObjectURL(blob);
link.setAttribute("download", filename);
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
} else {
window.open(url, "_blank");
}
@@ -77,11 +93,7 @@ export default class ReactAddToCalendar extends React.Component {
<a
className={currentItem + "-link"}
onClick={self.handleDropdownLinkClick}
href={helpers.buildUrl(
self.props.event,
currentItem,
self.state.isCrappyIE
)}
href={helpers.buildUrl(self.props.event, currentItem)}
target="_blank"
>
{icon}
+45 -48
View File
@@ -1,59 +1,60 @@
import moment from 'moment';
import moment from "moment";
export default class helpers {
getRandomKey () {
getRandomKey() {
let n = Math.floor(Math.random() * 999999999999).toString();
return new Date().getTime().toString() + '_' + n;
return new Date().getTime().toString() + "_" + n;
}
formatTime (date) {
let formattedDate = moment.utc(date).format('YYYYMMDDTHHmmssZ');
return formattedDate.replace('+00:00', 'Z');
formatTime(date) {
let formattedDate = moment.utc(date).format("YYYYMMDDTHHmmssZ");
return formattedDate.replace("+00:00", "Z");
}
calculateDuration (startTime, endTime) {
calculateDuration(startTime, endTime) {
// snag parameters and format properly in UTC
let end = moment.utc(endTime).format('DD/MM/YYYY HH:mm:ss');
let start = moment.utc(startTime).format('DD/MM/YYYY HH:mm:ss');
let end = moment.utc(endTime).format("DD/MM/YYYY HH:mm:ss");
let start = moment.utc(startTime).format("DD/MM/YYYY HH:mm:ss");
// calculate the difference in milliseconds between the start and end times
let difference = moment(end, 'DD/MM/YYYY HH:mm:ss').diff(moment(start, 'DD/MM/YYYY HH:mm:ss'));
let difference = moment(end, "DD/MM/YYYY HH:mm:ss").diff(
moment(start, "DD/MM/YYYY HH:mm:ss")
);
// convert difference from above to a proper momentJs duration object
let duration = moment.duration(difference);
return Math.floor(duration.asHours()) + moment.utc(difference).format(':mm');
return (
Math.floor(duration.asHours()) + moment.utc(difference).format(":mm")
);
}
buildUrl (event, type, isCrappyIE) {
let calendarUrl = '';
buildUrl(event, type) {
let calendarUrl = "";
switch (type) {
case 'google':
// This is all I changed, there were 2 problems,
// first, the root URL of Google calendar changed, and second,
// somehow the order of the params creates a bad request so I fixed that too
calendarUrl = 'https://calendar.google.com/calendar/render';
calendarUrl += '?action=TEMPLATE';
calendarUrl += '&dates=' + this.formatTime(event.startTime);
calendarUrl += '/' + this.formatTime(event.endTime);
calendarUrl += '&location=' + encodeURIComponent(event.location);
calendarUrl += '&text=' + encodeURIComponent(event.title);
calendarUrl += '&details=' + encodeURIComponent(event.description);
case "google":
calendarUrl = "https://calendar.google.com/calendar/render";
calendarUrl += "?action=TEMPLATE";
calendarUrl += "&dates=" + this.formatTime(event.startTime);
calendarUrl += "/" + this.formatTime(event.endTime);
calendarUrl += "&location=" + encodeURIComponent(event.location);
calendarUrl += "&text=" + encodeURIComponent(event.title);
calendarUrl += "&details=" + encodeURIComponent(event.description);
break;
case 'yahoo':
case "yahoo":
// yahoo doesn't utilize endTime so we need to calulate duration
let duration = this.calculateDuration(event.startTime, event.endTime);
calendarUrl = 'https://calendar.yahoo.com/?v=60&view=d&type=20';
calendarUrl += '&title=' + encodeURIComponent(event.title);
calendarUrl += '&st=' + this.formatTime(event.startTime);
calendarUrl += '&dur=' + duration;
calendarUrl += '&desc=' + encodeURIComponent(event.description);
calendarUrl += '&in_loc=' + encodeURIComponent(event.location);
calendarUrl = "https://calendar.yahoo.com/?v=60&view=d&type=20";
calendarUrl += "&title=" + encodeURIComponent(event.title);
calendarUrl += "&st=" + this.formatTime(event.startTime);
calendarUrl += "&dur=" + duration;
calendarUrl += "&desc=" + encodeURIComponent(event.description);
calendarUrl += "&in_loc=" + encodeURIComponent(event.location);
break;
case 'outlookcom':
case "outlookcom":
calendarUrl = "https://outlook.live.com/owa/?rru=addevent";
calendarUrl += "&startdt=" + this.formatTime(event.startTime);
calendarUrl += "&enddt=" + this.formatTime(event.endTime);
@@ -67,22 +68,18 @@ export default class helpers {
default:
calendarUrl = [
'BEGIN:VCALENDAR',
'VERSION:2.0',
'BEGIN:VEVENT',
'URL:' + document.URL,
'DTSTART:' + this.formatTime(event.startTime),
'DTEND:' + this.formatTime(event.endTime),
'SUMMARY:' + event.title,
'DESCRIPTION:' + event.description,
'LOCATION:' + event.location,
'END:VEVENT',
'END:VCALENDAR'
].join('\n');
if (!isCrappyIE) {
calendarUrl = encodeURI('data:text/calendar;charset=utf8,' + calendarUrl);
}
"BEGIN:VCALENDAR",
"VERSION:2.0",
"BEGIN:VEVENT",
"URL:" + document.URL,
"DTSTART:" + this.formatTime(event.startTime),
"DTEND:" + this.formatTime(event.endTime),
"SUMMARY:" + event.title,
"DESCRIPTION:" + event.description,
"LOCATION:" + event.location,
"END:VEVENT",
"END:VCALENDAR"
].join("\n");
}
return calendarUrl;