diff --git a/README.md b/README.md index 2ee3587..9714759 100644 --- a/README.md +++ b/README.md @@ -1,24 +1,27 @@ -# OuiCal +# OuiCal2 A simple JS library that enables you to add an "add to calendar" button for your upcoming events. ## Inspiration -This project was inspired by [Eventbrite's](http://www.eventbrite.com/) add to calendar feature (which should have been open sourced #justSayin). +This project was inspired by [Eventbrite's](http://www.eventbrite.com/) add to calendar feature (which should have been open sourced #justSayin). + +Later, it was adjusted to look and behave more like [AddToCalendar](https://addtocalendar.com), which suddenly became a commercial tool, and very expensive too #justSayin. ## How to use it? -Call 'createCalendar' with your event info, pass in any optional parameters such as a class and/ or id and boom! Insert your add-to-calendar div wherever you'd like. +### Method 1 + +Call 'addToCalendar' with your event info, pass in any optional parameters such as a class and/ or id and boom! Insert your add-to-calendar div wherever you'd like. The only fields that are mandatory are: - Event title - Start time - - Event duration, in minutes -## Example +#### Example - var myCalendar = createCalendar({ + var myCalendar = addToCalendar({ options: { class: 'my-class', @@ -32,12 +35,19 @@ The only fields that are mandatory are: // Event start date start: new Date('June 15, 2013 19:00'), + // Event timezone. Will convert the given time to that zone + timezone: America/Los_Angeles, + // Event duration (IN MINUTES) duration: 120, // You can also choose to set an end time // If an end time is set, this will take precedence over duration - end: new Date('June 15, 2013 23:00'), + // end: new Date('June 15, 2013 23:00'), + + // You can also choose to set 'all day' + // If this is set, this will override end time, duration and timezone + // allday:true, // Event Address address: 'The internet', @@ -49,23 +59,62 @@ The only fields that are mandatory are: document.querySelector('#place-where-I-want-this-calendar').appendChild(myCalendar); -[Here is a live example](http://carlsednaoui.github.io/add-to-calendar-buttons/example.html) +### Method 2 + +Write your events data in several hidden HTML tags with the right classnames, and wrap them in a div. Then call 'createCalendar' with the outer div and boom! The calendar is appended to your wrapping div. +The only fields that are mandatory are: + + - Event title + - Start time + + +#### Example + +
+ 12/18/2018 08:00 AM + America/Los_Angeles + + + + Summary of the event + Description of the event + Location of the event +
+ + +### method 3 + +If you are ony interested in the data, call 'addToCalendarData' with your event info, pass in any optional parameters as described in method #1. An object with some html links is returned. + + +#### Example + + var caldata = addToCalendarData({ + data: { + // Event title + title: 'Get on the front page of HN', + + // Event start date + start: new Date('June 15, 2013 19:00'), + + //.. and the rest was optional. + + } + }); + console.log(caldata); -## Looking for Instant Gratification? -[Copy OuiCal into Chrome's JS console](https://raw.github.com/carlsednaoui/ouical/master/ouical.js) (or whatever browser you're using). +## Demo -Then call this: +[Here is a live example](https://commonpike.github.io/add-to-calendar-buttons/example.html) - document.getElementsByTagName('body')[0].appendChild(createCalendar({data:{title:"this is the title of my event", start: new Date(), duration: 90}})); -\#winning! ## Calendar Generator -Need to generate an add-to-calendar widget on the fly? No problem, [go here](http://carlsednaoui.github.io/add-to-calendar-buttons/generator/generator.html). +Need to generate an add-to-calendar widget on the fly? No problem, [go here](https://commonpike.github.io/add-to-calendar-buttons/generator/generator.html). ## GitHub Project Page -[Official Project Page](http://carlsednaoui.github.io/ouical/) +[Official Project Page](http://commonpike.github.io/ouical/) ## License [MIT](http://opensource.org/licenses/MIT) diff --git a/main.css b/add-to-calendar.css similarity index 60% rename from main.css rename to add-to-calendar.css index f9d318f..a5f882c 100644 --- a/main.css +++ b/add-to-calendar.css @@ -1,24 +1,46 @@ -#add-to-calendar-checkbox-label { +/* -------------------- + this css is embedded in the script in + minified version. it is here for reference + only +-------------------- */ + +.add-to-calendar { + position: relative; + text-align: left; +} + +.add-to-calendar > * { + display:none; +} + +.add-to-calendar > .add-to-calendar-widget { + display:block; +} + +.add-to-calendar-label { cursor: pointer; } -.add-to-calendar-checkbox ~ a { +.add-to-calendar-checkbox + div.add-to-calendar-dropdown { display: none; + margin-left: 20px; } -.add-to-calendar-checkbox:checked ~ a { +.add-to-calendar-checkbox:checked + div.add-to-calendar-dropdown { display: block; - width: 150px; - margin-left: 20px; } input[type=checkbox].add-to-calendar-checkbox { position: absolute; - top: -9999px; - left: -9999px; + visibility:hidden; +} + +.add-to-calendar-checkbox + div.add-to-calendar-dropdown a { + cursor:pointer; + display:block; } -.add-to-calendar-checkbox ~ a:before { +.add-to-calendar-checkbox + div.add-to-calendar-dropdown a:before { width: 16px; height: 16px; display: inline-block; @@ -35,10 +57,70 @@ input[type=checkbox].add-to-calendar-checkbox { /*this is the default icon*/ } +.icon-off365:before { + /*this is the default icon*/ +} + .icon-yahoo:before { background-position: -36px +4px; } .icon-google:before { background-position: -52px 0; -} \ No newline at end of file +} + +/* -------------------- + prettify +-------------------- */ + +.add-to-calendar-widget { + font-family:sans-serif; + margin: 1em 0; + position:relative; +} + +.add-to-calendar-label { + display: inline-block; + background-color: white; + background-image: url(data:image/vndmicrosofticon;base64,AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVlZW/1ZWVv9WVlb/VlZW/1ZWVv9WVlb/VlZW/1ZWVv9WVlb/VlZW/1ZWVv9WVlb/VlZW/wAAAAAAAAAAVlZW/1ZWVv9WVlb/VlZW/1ZWVv9WVlb/VlZW/1ZWVv9WVlb/VlZW/1ZWVv9WVlb/VlZW/1ZWVv9WVlb/AAAAAFZWVv9WVlb///////////9WVlb///////////9WVlb///////////9WVlb///////////9WVlb/VlZW/wAAAABWVlb/VlZW////////////VlZW////////////VlZW////////////VlZW////////////VlZW/1ZWVv8AAAAAVlZW/1ZWVv9WVlb/VlZW/1ZWVv9WVlb/VlZW/1ZWVv9WVlb/VlZW/1ZWVv9WVlb/VlZW/1ZWVv9WVlb/AAAAAFZWVv9WVlb///////////9WVlb///////////9WVlb///////////9WVlb///////////9WVlb/VlZW/wAAAABWVlb/VlZW////////////VlZW////////////VlZW////////////VlZW////////////VlZW/1ZWVv8AAAAAVlZW/1ZWVv9WVlb/VlZW/1ZWVv9WVlb/VlZW/1ZWVv9WVlb/VlZW/1ZWVv9WVlb/VlZW/1ZWVv9WVlb/AAAAAFZWVv9WVlb///////////9WVlb///////////9WVlb///////////9WVlb///////////9WVlb/VlZW/wAAAABWVlb/VlZW////////////VlZW////////////VlZW////////////VlZW////////////VlZW/1ZWVv8AAAAAVlZW/1ZWVv9WVlb/VlZW/1ZWVv9WVlb/VlZW/1ZWVv9WVlb/VlZW/1ZWVv9WVlb/VlZW/1ZWVv9WVlb/AAAAAFZWVv9WVlb/VlZW/1ZWVv9WVlb/VlZW/1ZWVv9WVlb/VlZW/1ZWVv9WVlb/VlZW/1ZWVv9WVlb/VlZW/wAAAAAAAAAAVlZW/1ZWVv///////////1ZWVv9WVlb/VlZW/1ZWVv9WVlb///////////9WVlb/VlZW/wAAAAAAAAAAAAAAAAAAAABWVlb///////////9WVlb/AAAAAAAAAAAAAAAAVlZW////////////VlZW/wAAAAAAAAAAAAAAAAAAAAAAAAAAVlZW/1ZWVv9WVlb/VlZW/wAAAAAAAAAAAAAAAFZWVv9WVlb/VlZW/1ZWVv8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==); + background-position: 10px 45%; + background-repeat:no-repeat; + padding: 1em 1em 1em 40px; + background-size: 20px 20px; + border-radius: 3px; + box-shadow: 0 0 0 0.5px rgba(50, 50, 93, .17), + 0 2px 5px 0 rgba(50, 50, 93, .1), + 0 1px 1.5px 0 rgba(0, 0, 0, .07), + 0 1px 2px 0 rgba(0, 0, 0, .08), + 0 0 0 0 transparent!important; +} + +.add-to-calendar-dropdown { + position: absolute; + z-index: 99; + background-color: white; + top: 0; + left:0; + padding: 1em; + margin:0!important; + border-radius: 3px; + box-shadow: 0 0 0 0.5px rgba(50, 50, 93, .17), + 0 2px 5px 0 rgba(50, 50, 93, .1), + 0 1px 1.5px 0 rgba(0, 0, 0, .07), + 0 1px 2px 0 rgba(0, 0, 0, .08), + 0 0 0 0 transparent!important; +} + +.add-to-calendar-dropdown a { + display: block; + line-height: 1.75em; + text-decoration: none; + color: inherit; + opacity:.7; +} + +.add-to-calendar-dropdown a:hover { + opacity:1; +} + + diff --git a/add-to-calendar.js b/add-to-calendar.js new file mode 100644 index 0000000..97b6051 --- /dev/null +++ b/add-to-calendar.js @@ -0,0 +1,486 @@ +;(function(exports) { + + /* -------------- + config + --------------- */ + + var MS_IN_MINUTES = 60 * 1000; + + var CONFIG = { + selector : ".add-to-calendar", + duration : 60, + texts : { + label : "Add to Calendar", + title : "New event", + download : "Calendar-event.ics", + google : "Google Calendar", + yahoo : "Yahoo! Calendar", + off365 : "Office 365", + ical : "Download iCal", + outlook : "Download Outlook", + ienoblob : "Sorry, your browser does not support downloading Calendar events." + } + }; + + if (typeof ADDTOCAL_CONFIG != "undefined") { + CONFIG = ADDTOCAL_CONFIG; + } + + /* -------------- + browser sniffing + --------------- */ + + // ie < edg (=chromium) doesnt support data-uri:text/calendar + var ieCanDownload = ('msSaveOrOpenBlob' in window.navigator); + var ieMustDownload = /\b(MSIE |Trident.*?rv:|Edge\/)(\d+)/.exec(navigator.userAgent); + + + /* -------------- + generators + --------------- */ + + var calendarGenerators = { + + google: function(event) { + var startTime,endTime; + + if (event.allday) { + // google wants 2 consecutive days at 00:00 + startTime = formatTime(event.tzstart); + endTime = formatTime(getEndDate(event.tzstart,60*24)); + startTime = stripISOTime(startTime); + endTime = stripISOTime(endTime); + } else { + if (event.timezone) { + // google is somehow weird with timezones. + // it works better when giving the local + // time in the given timezone without the zulu, + // and pass timezone as argument. + // but then the dates we have loaded + // need to shift inverse with tzoffset the + // browser gave us. + // so + var shiftstart, shiftend; + shiftstart = new Date(event.start.getTime()-event.start.getTimezoneOffset()*MS_IN_MINUTES); + if (event.end) { + shiftend = new Date(event.end.getTime()-event.end.getTimezoneOffset()*MS_IN_MINUTES); + } + startTime = formatTime(shiftstart); + endTime = formatTime(shiftend); + // strip the zulu and pass the tz as argument later + startTime = startTime.substring(0,startTime.length-1); + endTime = endTime.substring(0,endTime.length-1); + } else { + // use regular times + startTime = formatTime(event.start); + endTime = formatTime(event.end); + } + } + + var href = encodeURI([ + 'https://www.google.com/calendar/render', + '?action=TEMPLATE', + '&text=' + (event.title || ''), + '&dates=' + (startTime || ''), + '/' + (endTime || ''), + (event.timezone)?'&ctz='+event.timezone:'', + '&details=' + (event.description || ''), + '&location=' + (event.address || ''), + '&sprop=&sprop=name:' + ].join('')); + + + return ''+CONFIG.texts.google+''; + }, + + yahoo: function(event) { + + + if (event.allday) { + var yahooEventDuration = 'allday'; + } else { + + var eventDuration = event.tzend ? + ((event.tzend.getTime() - event.tzstart.getTime())/ MS_IN_MINUTES) : + event.duration; + + // Yahoo dates are crazy, we need to convert the duration from minutes to hh:mm + + + var yahooHourDuration = eventDuration < 600 ? + '0' + Math.floor((eventDuration / 60)) : + Math.floor((eventDuration / 60)) + ''; + + var yahooMinuteDuration = eventDuration % 60 < 10 ? + '0' + eventDuration % 60 : + eventDuration % 60 + ''; + + var yahooEventDuration = yahooHourDuration + yahooMinuteDuration; + } + + // Remove timezone from event time + // var st = formatTime(new Date(event.start - (event.start.getTimezoneOffset() * MS_IN_MINUTES))) || ''; + + var st = formatTime(event.tzstart) || ''; + + var href = encodeURI([ + 'http://calendar.yahoo.com/?v=60&view=d&type=20', + '&title=' + (event.title || ''), + '&st=' + st, + '&dur=' + (yahooEventDuration || ''), + '&desc=' + (event.description || ''), + '&in_loc=' + (event.address || '') + ].join('')); + + return ''+CONFIG.texts.yahoo+''; + }, + + off365: function(event) { + var startTime = formatTime(event.tzstart); + var endTime = formatTime(event.tzend); + + var href = encodeURI([ + 'https://outlook.office365.com/owa/', + '?path=/calendar/action/compose', + '&rru=addevent', + '&subject=' + (event.title || ''), + '&startdt=' + (startTime || ''), + '&enddt=' + (endTime || ''), + '&body=' + (event.description || ''), + '&location=' + (event.address || ''), + '&allday=' + (event.allday)?'true':'false' + ].join('')); + return ''+CONFIG.texts.off365+''; + }, + + ics: function(event, eClass, calendarName) { + var startTime,endTime; + + if (event.allday) { + // DTSTART and DTEND need to be equal and 0 + startTime = formatTime(event.tzstart); + endTime = startTime = stripISOTime(startTime)+'T000000'; + } else { + startTime = formatTime(event.tzstart); + endTime = formatTime(event.tzend); + } + + var cal = [ + 'BEGIN:VCALENDAR', + 'VERSION:2.0', + 'BEGIN:VEVENT', + 'URL:' + document.URL, + 'DTSTART:' + (startTime || ''), + 'DTEND:' + (endTime || ''), + 'SUMMARY:' + (event.title || ''), + 'DESCRIPTION:' + (event.description || ''), + 'LOCATION:' + (event.address || ''), + 'UID:' + (event.id || '') + '-' + document.URL, + 'END:VEVENT', + 'END:VCALENDAR'].join('\n'); + + if (ieMustDownload) { + return '' + calendarName + ''; + } + + var href = encodeURI('data:text/calendar;charset=utf8,' + cal); + + return '' + calendarName + ''; + + + }, + + ical: function(event) { + return this.ics(event, 'icon-ical', CONFIG.texts.ical); + }, + + outlook: function(event) { + return this.ics(event, 'icon-outlook', CONFIG.texts.outlook); + } + }; + + /* -------------- + helpers + --------------- */ + + var changeTimezone = function(date,timezone) { + if (date) { + if (timezone) { + var invdate = new Date(date.toLocaleString('en-US', { + timeZone: timezone + })); + var diff = date.getTime()-invdate.getTime(); + return new Date(date.getTime()+diff); + } + return date; + } + return; + } + + var formatTime = function(date) { + return date?date.toISOString().replace(/-|:|\.\d+/g, ''):''; + }; + + var getEndDate = function(start,duration) { + return new Date(start.getTime() + duration * MS_IN_MINUTES); + }; + + var stripISOTime = function(isodatestr) { + return isodatestr.substr(0,isodatestr.indexOf('T')); + }; + + var escapeJSValue = function(text) { + return text + .replace(/&/g, '&') + .replace(//g, '>') + .replace(/\"/g, '"') + .replace(/\'/g, '\\\'') + .replace(/(\r?\n|\r)/gm, '\\n'); + }; + + /* -------------- + output handling + --------------- */ + + var generateMarkup = function(calendars, clazz, calendarId) { + var result = document.createElement('div'); + + result.innerHTML = ''; + result.innerHTML += ''; + + var dropdown = document.createElement('div'); + dropdown.className = 'add-to-calendar-dropdown'; + + Object.keys(calendars).forEach(function(services) { + dropdown.innerHTML += calendars[services]; + }); + + result.appendChild(dropdown); + + result.className = 'add-to-calendar-widget'; + if (clazz !== undefined) { + result.className += (' ' + clazz); + } + + addCSS(); + + result.id = calendarId; + return result; + }; + + var generateCalendars = function(event) { + return { + google: calendarGenerators.google(event), + yahoo: calendarGenerators.yahoo(event), + off365: calendarGenerators.off365(event), + ical: calendarGenerators.ical(event), + outlook: calendarGenerators.outlook(event) + }; + }; + + var addCSS = function() { + if (!document.getElementById('add-to-calendar-css')) { + document.getElementsByTagName('head')[0].appendChild(generateCSS()); + } + }; + + var generateCSS = function() { + var styles = document.createElement('style'); + styles.id = 'add-to-calendar-css'; + + styles.innerHTML = ".add-to-calendar{position:relative;text-align:left}.add-to-calendar>*{display:none}.add-to-calendar>.add-to-calendar-widget{display:block}.add-to-calendar-label{cursor:pointer}.add-to-calendar-checkbox+div.add-to-calendar-dropdown{display:none;margin-left:20px}.add-to-calendar-checkbox:checked+div.add-to-calendar-dropdown{display:block}input[type=checkbox].add-to-calendar-checkbox{position:absolute;visibility:hidden}.add-to-calendar-checkbox+div.add-to-calendar-dropdown a{cursor:pointer;display:block}.add-to-calendar-checkbox+div.add-to-calendar-dropdown a:before{width:16px;height:16px;display:inline-block;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFQAAAAQCAYAAACIoli7AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoTWFjaW50b3NoKSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDo0MzJCRDU2NUE1MDIxMUUyOTY1Q0EwNTkxNEJDOUIwNCIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDo0MzJCRDU2NkE1MDIxMUUyOTY1Q0EwNTkxNEJDOUIwNCI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjQzMkJENTYzQTUwMjExRTI5NjVDQTA1OTE0QkM5QjA0IiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjQzMkJENTY0QTUwMjExRTI5NjVDQTA1OTE0QkM5QjA0Ii8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+1Gcb3QAACh1JREFUeNrEWAtw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);margin-right:.5em;content:' '}.icon-ical:before{background-position:-68px 0}.icon-yahoo:before{background-position:-36px +4px}.icon-google:before{background-position:-52px 0}.add-to-calendar-widget{font-family:sans-serif;margin:1em 0;position:relative}.add-to-calendar-label{display:inline-block;background-color:#fff;background-image:url(data:image/vndmicrosofticon;base64,AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVlZW/1ZWVv9WVlb/VlZW/1ZWVv9WVlb/VlZW/1ZWVv9WVlb/VlZW/1ZWVv9WVlb/VlZW/wAAAAAAAAAAVlZW/1ZWVv9WVlb/VlZW/1ZWVv9WVlb/VlZW/1ZWVv9WVlb/VlZW/1ZWVv9WVlb/VlZW/1ZWVv9WVlb/AAAAAFZWVv9WVlb///////////9WVlb///////////9WVlb///////////9WVlb///////////9WVlb/VlZW/wAAAABWVlb/VlZW////////////VlZW////////////VlZW////////////VlZW////////////VlZW/1ZWVv8AAAAAVlZW/1ZWVv9WVlb/VlZW/1ZWVv9WVlb/VlZW/1ZWVv9WVlb/VlZW/1ZWVv9WVlb/VlZW/1ZWVv9WVlb/AAAAAFZWVv9WVlb///////////9WVlb///////////9WVlb///////////9WVlb///////////9WVlb/VlZW/wAAAABWVlb/VlZW////////////VlZW////////////VlZW////////////VlZW////////////VlZW/1ZWVv8AAAAAVlZW/1ZWVv9WVlb/VlZW/1ZWVv9WVlb/VlZW/1ZWVv9WVlb/VlZW/1ZWVv9WVlb/VlZW/1ZWVv9WVlb/AAAAAFZWVv9WVlb///////////9WVlb///////////9WVlb///////////9WVlb///////////9WVlb/VlZW/wAAAABWVlb/VlZW////////////VlZW////////////VlZW////////////VlZW////////////VlZW/1ZWVv8AAAAAVlZW/1ZWVv9WVlb/VlZW/1ZWVv9WVlb/VlZW/1ZWVv9WVlb/VlZW/1ZWVv9WVlb/VlZW/1ZWVv9WVlb/AAAAAFZWVv9WVlb/VlZW/1ZWVv9WVlb/VlZW/1ZWVv9WVlb/VlZW/1ZWVv9WVlb/VlZW/1ZWVv9WVlb/VlZW/wAAAAAAAAAAVlZW/1ZWVv///////////1ZWVv9WVlb/VlZW/1ZWVv9WVlb///////////9WVlb/VlZW/wAAAAAAAAAAAAAAAAAAAABWVlb///////////9WVlb/AAAAAAAAAAAAAAAAVlZW////////////VlZW/wAAAAAAAAAAAAAAAAAAAAAAAAAAVlZW/1ZWVv9WVlb/VlZW/wAAAAAAAAAAAAAAAFZWVv9WVlb/VlZW/1ZWVv8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==);background-position:10px 45%;background-repeat:no-repeat;padding:1em 1em 1em 40px;background-size:20px 20px;border-radius:3px;box-shadow:0 0 0 .5px rgba(50,50,93,.17),0 2px 5px 0 rgba(50,50,93,.1),0 1px 1.5px 0 rgba(0,0,0,.07),0 1px 2px 0 rgba(0,0,0,.08),0 0 0 0 transparent!important}.add-to-calendar-dropdown{position:absolute;z-index:99;background-color:#fff;top:0;left:0;padding:1em;margin:0!important;border-radius:3px;box-shadow:0 0 0 .5px rgba(50,50,93,.17),0 2px 5px 0 rgba(50,50,93,.1),0 1px 1.5px 0 rgba(0,0,0,.07),0 1px 2px 0 rgba(0,0,0,.08),0 0 0 0 transparent!important}.add-to-calendar-dropdown a{display:block;line-height:1.75em;text-decoration:none;color:inherit;opacity:.7}.add-to-calendar-dropdown a:hover{opacity:1}"; + return styles; + }; + + + /* -------------- + input handling + --------------- */ + + var sanitizeParams = function(params) { + if (!params.options) { + params.options = {} + } + if (!params.options.id) { + params.options.id = Math.floor(Math.random() * 1000000); + } + if (!params.options.class) { + params.options.class = ''; + } + if (!params.data) { + params.data = {}; + } + if (!params.data.start) { + params.data.start=new Date(); + } + if (params.data.allday) { + delete params.data.end; // may be set later + delete params.data.duration; + } + if (params.data.end) { + delete params.data.duration; + } else { + if (!params.data.duration) { + params.data.duration = CONFIG.duration; + } + } + if (params.data.duration) { + params.data.end = getEndDate(params.data.start,params.data.duration); + } + + if (params.data.timezone) { + params.data.tzstart = changeTimezone(params.data.start,params.data.timezone); + params.data.tzend = changeTimezone(params.data.end,params.data.timezone); + } else { + params.data.tzstart = params.data.start; + params.data.tzend = params.data.end; + } + if (!params.data.title) { + params.data.title = CONFIG.texts.title; + } + + + }; + + var validParams = function(params) { + return params.data !== undefined && params.data.start !== undefined && + (params.data.end !== undefined || params.data.allday !== undefined); + }; + + var parseCalendar = function(elm) { + + /* +
+ 12/18/2018 08:00 AM + 12/18/2018 10:00 AM + 45 + true + America/Los_Angeles + Summary of the event + Description of the event + Location of the event +
+ */ + + var data = {}, node; + + node = elm.querySelector('.start'); + if (node) data.start = new Date(node.textContent); + + node = elm.querySelector('.end'); + if (node) data.end = new Date(node.textContent); + + node = elm.querySelector('.duration'); + if (node) data.duration = 1*node.textContent; + + node = elm.querySelector('.allday'); + if (node) data.allday = true; + + node = elm.querySelector('.title'); + if (node) data.title = node.textContent; + + node = elm.querySelector('.description'); + if (node) data.description = node.textContent; + + node = elm.querySelector('.address'); + if (node) data.address = node.textContent; + if (!data.address) { + node = elm.querySelector('.location'); + if (node) data.address = node.textContent; + } + + node = elm.querySelector('.timezone'); + if (node) data.timezone = node.textContent; + + cal = createCalendar({data:data}); + if (cal) elm.appendChild(cal); + return cal; + + } + + /* -------------- + exports + --------------- */ + + exports.ieDownloadCalendar = function(cal) { + if (ieCanDownload) { + var blob = new Blob([cal], { type: 'text/calendar' }); + window.navigator.msSaveOrOpenBlob(blob, CONFIG.texts.download); + } else { + alert(CONFIG.texts.ienoblob); + } + }; + + exports.closeCalenderOnMouseDown = function(checkbox) { + //console.log('check'); + var closeCalendar = function() { + //console.log('click'); + setTimeout(function() { checkbox.checked=false; }, 750); + document.removeEventListener("mousedown",closeCalendar); + }; + document.addEventListener("mousedown",closeCalendar); + } + + exports.addToCalendarData = function(params) { + if (!params) params = {}; + sanitizeParams(params); + if (!validParams(params)) { + console.error('Event details missing.'); + return; + } + return generateCalendars(params.data); + } + + // bwc + exports.createCalendar = function(params) { + return addToCalendar(params); + }; + + exports.addToCalendar = function(params) { + + if (!params) params = {}; + + if (params instanceof HTMLElement) { + //console.log('HTMLElement'); + return parseCalendar(params); + } + + if (params instanceof NodeList) { + //console.log('NodeList'); + var success = (params.length>0); + Array.prototype.forEach.call(params, function(node) { + success = success && addToCalendar(node); + }); + return success; + } + + sanitizeParams(params); + + if (!validParams(params)) { + console.error('Event details missing.'); + return; + } + + return generateMarkup( + generateCalendars(params.data), + params.options.class, + params.options.id + ); + + }; + + // document.ready + + document.addEventListener("DOMContentLoaded", function(event) { + addToCalendar(document.querySelectorAll(CONFIG.selector)); + }); + +})(this); \ No newline at end of file diff --git a/add-to-calendar.min.js b/add-to-calendar.min.js new file mode 100644 index 0000000..ec92423 --- /dev/null +++ b/add-to-calendar.min.js @@ -0,0 +1 @@ +!function(e){var n=6e4,l={selector:".add-to-calendar",duration:60,texts:{label:"Add to Calendar",title:"New event",download:"Calendar-event.ics",google:"Google Calendar",yahoo:"Yahoo! Calendar",off365:"Office 365",ical:"Download iCal",outlook:"Download Outlook",ienoblob:"Sorry, your browser does not support downloading Calendar events."}};"undefined"!=typeof ADDTOCAL_CONFIG&&(l=ADDTOCAL_CONFIG);function t(e,t){if(e){if(t){var a=new Date(e.toLocaleString("en-US",{timeZone:t})),A=e.getTime()-a.getTime();return new Date(e.getTime()+A)}return e}}function a(e){return{google:i.google(e),yahoo:i.yahoo(e),off365:i.off365(e),ical:i.ical(e),outlook:i.outlook(e)}}function A(e){e.options||(e.options={}),e.options.id||(e.options.id=Math.floor(1e6*Math.random())),e.options.class||(e.options.class=""),e.data||(e.data={}),e.data.start||(e.data.start=new Date),e.data.allday&&(delete e.data.end,delete e.data.duration),e.data.end?delete e.data.duration:e.data.duration||(e.data.duration=l.duration),e.data.duration&&(e.data.end=s(e.data.start,e.data.duration)),e.data.timezone?(e.data.tzstart=t(e.data.start,e.data.timezone),e.data.tzend=t(e.data.end,e.data.timezone)):(e.data.tzstart=e.data.start,e.data.tzend=e.data.end),e.data.title||(e.data.title=l.texts.title)}function o(e){return void 0!==e.data&&void 0!==e.data.start&&(void 0!==e.data.end||void 0!==e.data.allday)}var d="msSaveOrOpenBlob"in window.navigator,r=/\b(MSIE |Trident.*?rv:|Edge\/)(\d+)/.exec(navigator.userAgent),i={google:function(e){var t,a,A,o;e.allday?(t=c(e.tzstart),a=c(s(e.tzstart,1440)),t=W(t),a=W(a)):a=e.timezone?(A=new Date(e.start.getTime()-e.start.getTimezoneOffset()*n),e.end&&(o=new Date(e.end.getTime()-e.end.getTimezoneOffset()*n)),t=c(A),a=c(o),t=t.substring(0,t.length-1),a.substring(0,a.length-1)):(t=c(e.start),c(e.end));return''+l.texts.google+""},yahoo:function(e){if(e.allday)var t="allday";else{var a=e.tzend?(e.tzend.getTime()-e.tzstart.getTime())/n:e.duration;t=(a<600?"0"+Math.floor(a/60):Math.floor(a/60)+"")+(a%60<10?"0"+a%60:a%60+"")}var A=c(e.tzstart)||"";return''+l.texts.yahoo+""},off365:function(e){var t=c(e.tzstart),a=c(e.tzend);return''+l.texts.off365+""},ics:function(e,t,a){var A,o;o=e.allday?(A=c(e.tzstart),A=W(A)+"T000000"):(A=c(e.tzstart),c(e.tzend));var n=["BEGIN:VCALENDAR","VERSION:2.0","BEGIN:VEVENT","URL:"+document.URL,"DTSTART:"+(A||""),"DTEND:"+(o||""),"SUMMARY:"+(e.title||""),"DESCRIPTION:"+(e.description||""),"LOCATION:"+(e.address||""),"UID:"+(e.id||"")+"-"+document.URL,"END:VEVENT","END:VCALENDAR"].join("\n");if(r)return'"+a+"";var d=encodeURI("data:text/calendar;charset=utf8,"+n);return''+a+""},ical:function(e){return this.ics(e,"icon-ical",l.texts.ical)},outlook:function(e){return this.ics(e,"icon-outlook",l.texts.outlook)}},c=function(e){return e?e.toISOString().replace(/-|:|\.\d+/g,""):""},s=function(e,t){return new Date(e.getTime()+t*n)},W=function(e){return e.substr(0,e.indexOf("T"))},V=function(e){return e.replace(/&/g,"&").replace(//g,">").replace(/\"/g,""").replace(/\'/g,"\\'").replace(/(\r?\n|\r)/gm,"\\n")},u=function(){document.getElementById("add-to-calendar-css")||document.getElementsByTagName("head")[0].appendChild(b())},b=function(){var e=document.createElement("style");return e.id="add-to-calendar-css",e.innerHTML=".add-to-calendar{position:relative;text-align:left}.add-to-calendar>*{display:none}.add-to-calendar>.add-to-calendar-widget{display:block}.add-to-calendar-label{cursor:pointer}.add-to-calendar-checkbox+div.add-to-calendar-dropdown{display:none;margin-left:20px}.add-to-calendar-checkbox:checked+div.add-to-calendar-dropdown{display:block}input[type=checkbox].add-to-calendar-checkbox{position:absolute;visibility:hidden}.add-to-calendar-checkbox+div.add-to-calendar-dropdown a{cursor:pointer;display:block}.add-to-calendar-checkbox+div.add-to-calendar-dropdown a:before{width:16px;height:16px;display:inline-block;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFQAAAAQCAYAAACIoli7AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoTWFjaW50b3NoKSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDo0MzJCRDU2NUE1MDIxMUUyOTY1Q0EwNTkxNEJDOUIwNCIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDo0MzJCRDU2NkE1MDIxMUUyOTY1Q0EwNTkxNEJDOUIwNCI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjQzMkJENTYzQTUwMjExRTI5NjVDQTA1OTE0QkM5QjA0IiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjQzMkJENTY0QTUwMjExRTI5NjVDQTA1OTE0QkM5QjA0Ii8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+1Gcb3QAACh1JREFUeNrEWAtw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);margin-right:.5em;content:' '}.icon-ical:before{background-position:-68px 0}.icon-yahoo:before{background-position:-36px +4px}.icon-google:before{background-position:-52px 0}.add-to-calendar-widget{font-family:sans-serif;margin:1em 0;position:relative}.add-to-calendar-label{display:inline-block;background-color:#fff;background-image:url(data:image/vndmicrosofticon;base64,AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVlZW/1ZWVv9WVlb/VlZW/1ZWVv9WVlb/VlZW/1ZWVv9WVlb/VlZW/1ZWVv9WVlb/VlZW/wAAAAAAAAAAVlZW/1ZWVv9WVlb/VlZW/1ZWVv9WVlb/VlZW/1ZWVv9WVlb/VlZW/1ZWVv9WVlb/VlZW/1ZWVv9WVlb/AAAAAFZWVv9WVlb///////////9WVlb///////////9WVlb///////////9WVlb///////////9WVlb/VlZW/wAAAABWVlb/VlZW////////////VlZW////////////VlZW////////////VlZW////////////VlZW/1ZWVv8AAAAAVlZW/1ZWVv9WVlb/VlZW/1ZWVv9WVlb/VlZW/1ZWVv9WVlb/VlZW/1ZWVv9WVlb/VlZW/1ZWVv9WVlb/AAAAAFZWVv9WVlb///////////9WVlb///////////9WVlb///////////9WVlb///////////9WVlb/VlZW/wAAAABWVlb/VlZW////////////VlZW////////////VlZW////////////VlZW////////////VlZW/1ZWVv8AAAAAVlZW/1ZWVv9WVlb/VlZW/1ZWVv9WVlb/VlZW/1ZWVv9WVlb/VlZW/1ZWVv9WVlb/VlZW/1ZWVv9WVlb/AAAAAFZWVv9WVlb///////////9WVlb///////////9WVlb///////////9WVlb///////////9WVlb/VlZW/wAAAABWVlb/VlZW////////////VlZW////////////VlZW////////////VlZW////////////VlZW/1ZWVv8AAAAAVlZW/1ZWVv9WVlb/VlZW/1ZWVv9WVlb/VlZW/1ZWVv9WVlb/VlZW/1ZWVv9WVlb/VlZW/1ZWVv9WVlb/AAAAAFZWVv9WVlb/VlZW/1ZWVv9WVlb/VlZW/1ZWVv9WVlb/VlZW/1ZWVv9WVlb/VlZW/1ZWVv9WVlb/VlZW/wAAAAAAAAAAVlZW/1ZWVv///////////1ZWVv9WVlb/VlZW/1ZWVv9WVlb///////////9WVlb/VlZW/wAAAAAAAAAAAAAAAAAAAABWVlb///////////9WVlb/AAAAAAAAAAAAAAAAVlZW////////////VlZW/wAAAAAAAAAAAAAAAAAAAAAAAAAAVlZW/1ZWVv9WVlb/VlZW/wAAAAAAAAAAAAAAAFZWVv9WVlb/VlZW/1ZWVv8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==);background-position:10px 45%;background-repeat:no-repeat;padding:1em 1em 1em 40px;background-size:20px 20px;border-radius:3px;box-shadow:0 0 0 .5px rgba(50,50,93,.17),0 2px 5px 0 rgba(50,50,93,.1),0 1px 1.5px 0 rgba(0,0,0,.07),0 1px 2px 0 rgba(0,0,0,.08),0 0 0 0 transparent!important}.add-to-calendar-dropdown{position:absolute;z-index:99;background-color:#fff;top:0;left:0;padding:1em;margin:0!important;border-radius:3px;box-shadow:0 0 0 .5px rgba(50,50,93,.17),0 2px 5px 0 rgba(50,50,93,.1),0 1px 1.5px 0 rgba(0,0,0,.07),0 1px 2px 0 rgba(0,0,0,.08),0 0 0 0 transparent!important}.add-to-calendar-dropdown a{display:block;line-height:1.75em;text-decoration:none;color:inherit;opacity:.7}.add-to-calendar-dropdown a:hover{opacity:1}",e};e.ieDownloadCalendar=function(e){if(d){var t=new Blob([e],{type:"text/calendar"});window.navigator.msSaveOrOpenBlob(t,l.texts.download)}else alert(l.texts.ienoblob)},e.closeCalenderOnMouseDown=function(e){var t=function(){setTimeout(function(){e.checked=!1},750),document.removeEventListener("mousedown",t)};document.addEventListener("mousedown",t)},e.addToCalendarData=function(e){if(A(e=e||{}),o(e))return a(e.data);console.error("Event details missing.")},e.createCalendar=function(e){return addToCalendar(e)},e.addToCalendar=function(e){if((e=e||{})instanceof HTMLElement)return function(e){var t,a={};return(t=e.querySelector(".start"))&&(a.start=new Date(t.textContent)),(t=e.querySelector(".end"))&&(a.end=new Date(t.textContent)),(t=e.querySelector(".duration"))&&(a.duration=1*t.textContent),(t=e.querySelector(".allday"))&&(a.allday=!0),(t=e.querySelector(".title"))&&(a.title=t.textContent),(t=e.querySelector(".description"))&&(a.description=t.textContent),(t=e.querySelector(".address"))&&(a.address=t.textContent),a.address||(t=e.querySelector(".location"))&&(a.address=t.textContent),(t=e.querySelector(".timezone"))&&(a.timezone=t.textContent),cal=createCalendar({data:a}),cal&&e.appendChild(cal),cal}(e);if(e instanceof NodeList){var t=0'+l.texts.label+"",A.innerHTML+='';var o=document.createElement("div");return o.className="add-to-calendar-dropdown",Object.keys(t).forEach(function(e){o.innerHTML+=t[e]}),A.appendChild(o),A.className="add-to-calendar-widget",void 0!==e&&(A.className+=" "+e),u(),A.id=a,A}(a(e.data),e.options.class,e.options.id);console.error("Event details missing.")},document.addEventListener("DOMContentLoaded",function(e){addToCalendar(document.querySelectorAll(l.selector))})}(this); \ No newline at end of file diff --git a/example.html b/example.html index fa82ccb..361e8e6 100644 --- a/example.html +++ b/example.html @@ -1,45 +1,114 @@ - - - OuiCal Example + + + OUICal2 Add to Calendar Example -
-
- + document.querySelector('.ouical-button').appendChild(ouical); + + + +
+ +

Widget from HTML input

+

+ The example below created a calendar from html content. Check the source to see how that's done. +

+ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. + + +

+ 12/18/2018 08:00 AM + America/Los_Angeles + + + + Summary of the event + Description of the event + Location of the event +
+ +

+ +
+ +

Generating javascript data as output

+

+ The example below created the calendar links from javascript data + and returned it as a javascript object. Check the source to see how that's done. +

+

+ + + + diff --git a/generator/ouical_generator.css b/generator/generator.css similarity index 91% rename from generator/ouical_generator.css rename to generator/generator.css index 5b655fc..d46b53d 100644 --- a/generator/ouical_generator.css +++ b/generator/generator.css @@ -13,11 +13,10 @@ body { } header { - background: #3e73f8; - height: 50px; + background: #3E73B8; color: #fdfaff; text-align: center; - padding-top: 20px; + padding: 20px 0; } h1 { @@ -56,7 +55,7 @@ label + input { input[type=submit] { padding: 10px; - background-color: #3e73f8; + background-color: #3E73B8; color: #fdfaff; font-size: 1.1em; border: none; diff --git a/generator/generator.html b/generator/generator.html index c015565..ed3e60e 100644 --- a/generator/generator.html +++ b/generator/generator.html @@ -1,16 +1,15 @@ - - + - - OuiCal - Calendar Embed Code Generator + + Oui2 - AddToCalendar Embed Code Generator
-

Add To Calendar Generator

+

OUI2 Add To Calendar - Embed Code Generator

@@ -47,6 +46,6 @@

Your result will appear below

- + \ No newline at end of file diff --git a/generator/generator.js b/generator/generator.js new file mode 100644 index 0000000..26592ea --- /dev/null +++ b/generator/generator.js @@ -0,0 +1,54 @@ +document.getElementById('calendar-generator').onsubmit = function() { + + // Get values for the calendar + var title = document.getElementById('event-title').value; + var startString = document.getElementById('start-time').value; + var start = new Date(startString.replace(/-/g, ",").replace(/T/, " ")); + var endString = document.getElementById('end-time').value; + var end = new Date(endString.replace(/-/g, ",").replace(/T/, " ")); + var address = document.getElementById('event-address').value; + var description = document.getElementById('event-description').value; + + var eventId = document.getElementById('event-id').value; + var eventClass = document.getElementById('event-class').value; + + // Make sure basic info is passed in + if (!(title && start)) { + console.log('Add some details'); + return false; + } + + // Create the calendar + var myCalendar = addToCalendar({ + options: { + class: eventClass, + id: eventId + }, + data: { + title: title, + start: start, + end: end, + address: address, + description: description + } + }); + + // Add the calendar result and an example + document.getElementById('live-example').appendChild(myCalendar); + + var embedTextArea = document.createElement('textarea'); + embedTextArea.setAttribute('rows', 10); + embedTextArea.setAttribute('cols', 80); + document.getElementById('html-result').innerHTML += '

Copy and paste this code:

'; + + + var calendarStyleNode = document.getElementById('add-to-calendar-css'); + var calendarCSS = (calendarStyleNode)?calendarStyleNode.textContent:'/* error */'; + var calendarJS = 'function closeCalenderOnMouseDown(e){var n=function(){setTimeout(function(){e.checked=!1},750),document.removeEventListener("mousedown",n)};document.addEventListener("mousedown",n)}'; + + myCalendar.innerHTML += (''); + myCalendar.innerHTML += (''); + document.getElementById('html-result').appendChild(embedTextArea).value = myCalendar.innerHTML; + + return false; +}; \ No newline at end of file diff --git a/generator/ouical_generator.js b/generator/ouical_generator.js deleted file mode 100644 index 412cae5..0000000 --- a/generator/ouical_generator.js +++ /dev/null @@ -1,51 +0,0 @@ -document.getElementById('calendar-generator').onsubmit = function() { - - // Get values for the calendar - var title = document.getElementById('event-title').value; - var startString = document.getElementById('start-time').value; - var start = new Date(startString.replace(/-/g, ",").replace(/T/, " ")); - var endString = document.getElementById('end-time').value; - var end = new Date(endString.replace(/-/g, ",").replace(/T/, " ")); - var address = document.getElementById('event-address').value; - var description = document.getElementById('event-description').value; - - var eventId = document.getElementById('event-id').value; - var eventClass = document.getElementById('event-class').value; - - // Make sure basic info is passed in - if (!(title && start && end)) { - console.log('Add some details'); - return false; - } - - // Create the calendar - var myCalendar = createCalendar({ - options: { - class: eventClass, - id: eventId - }, - data: { - title: title, - start: start, - end: end, - address: address, - description: description - } - }); - - // Add the calendar result and an example - document.getElementById('live-example').appendChild(myCalendar); - - var embedTextArea = document.createElement('textarea'); - embedTextArea.setAttribute('rows', 10); - embedTextArea.setAttribute('cols', 80); - document.getElementById('html-result').innerHTML += '

Copy and paste this code:

'; - document.getElementById('html-result').appendChild(embedTextArea).value = myCalendar.innerHTML; - - - var calendarCSS = "#add-to-calendar-checkbox-label{cursor:pointer}.add-to-calendar-checkbox ~ a{display:none}.add-to-calendar-checkbox:checked ~ a{display:block;width:150px;margin-left:20px}input[type=checkbox].add-to-calendar-checkbox{position:absolute;top:-9999px;left:-9999px}.add-to-calendar-checkbox ~ a:before{width:16px;height:16px;display:inline-block;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFQAAAAQCAYAAACIoli7AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoTWFjaW50b3NoKSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDo0MzJCRDU2NUE1MDIxMUUyOTY1Q0EwNTkxNEJDOUIwNCIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDo0MzJCRDU2NkE1MDIxMUUyOTY1Q0EwNTkxNEJDOUIwNCI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjQzMkJENTYzQTUwMjExRTI5NjVDQTA1OTE0QkM5QjA0IiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjQzMkJENTY0QTUwMjExRTI5NjVDQTA1OTE0QkM5QjA0Ii8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+1Gcb3QAACh1JREFUeNrEWAtw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);margin-right:.5em;content:' '}.icon-ical:before{background-position:-68px 0}.icon-yahoo:before{background-position:-36px+4px}.icon-google:before{background-position:-52px 0}"; - - document.getElementById('html-result').appendChild(embedTextArea).value += (''); - - return false; -}; \ No newline at end of file diff --git a/ouical.js b/ouical.js deleted file mode 100644 index 3a13b64..0000000 --- a/ouical.js +++ /dev/null @@ -1,172 +0,0 @@ -;(function(exports) { - var MS_IN_MINUTES = 60 * 1000; - - var formatTime = function(date) { - return date.toISOString().replace(/-|:|\.\d+/g, ''); - }; - - var calculateEndTime = function(event) { - return event.end ? - formatTime(event.end) : - formatTime(new Date(event.start.getTime() + (event.duration * MS_IN_MINUTES))); - }; - - var calendarGenerators = { - google: function(event) { - var startTime = formatTime(event.start); - var endTime = calculateEndTime(event); - - var href = encodeURI([ - 'https://www.google.com/calendar/render', - '?action=TEMPLATE', - '&text=' + (event.title || ''), - '&dates=' + (startTime || ''), - '/' + (endTime || ''), - '&details=' + (event.description || ''), - '&location=' + (event.address || ''), - '&sprop=&sprop=name:' - ].join('')); - return 'Google Calendar'; - }, - - yahoo: function(event) { - var eventDuration = event.end ? - ((event.end.getTime() - event.start.getTime())/ MS_IN_MINUTES) : - event.duration; - - // Yahoo dates are crazy, we need to convert the duration from minutes to hh:mm - var yahooHourDuration = eventDuration < 600 ? - '0' + Math.floor((eventDuration / 60)) : - Math.floor((eventDuration / 60)) + ''; - - var yahooMinuteDuration = eventDuration % 60 < 10 ? - '0' + eventDuration % 60 : - eventDuration % 60 + ''; - - var yahooEventDuration = yahooHourDuration + yahooMinuteDuration; - - // Remove timezone from event time - var st = formatTime(new Date(event.start - (event.start.getTimezoneOffset() * - MS_IN_MINUTES))) || ''; - - var href = encodeURI([ - 'http://calendar.yahoo.com/?v=60&view=d&type=20', - '&title=' + (event.title || ''), - '&st=' + st, - '&dur=' + (yahooEventDuration || ''), - '&desc=' + (event.description || ''), - '&in_loc=' + (event.address || '') - ].join('')); - - return 'Yahoo! Calendar'; - }, - - ics: function(event, eClass, calendarName) { - var startTime = formatTime(event.start); - var endTime = calculateEndTime(event); - - var href = encodeURI( - 'data:text/calendar;charset=utf8,' + [ - 'BEGIN:VCALENDAR', - 'VERSION:2.0', - 'BEGIN:VEVENT', - 'URL:' + document.URL, - 'DTSTART:' + (startTime || ''), - 'DTEND:' + (endTime || ''), - 'SUMMARY:' + (event.title || ''), - 'DESCRIPTION:' + (event.description || ''), - 'LOCATION:' + (event.address || ''), - 'END:VEVENT', - 'END:VCALENDAR'].join('\n')); - - return '' + calendarName + ' Calendar'; - }, - - ical: function(event) { - return this.ics(event, 'icon-ical', 'iCal'); - }, - - outlook: function(event) { - return this.ics(event, 'icon-outlook', 'Outlook'); - } - }; - - var generateCalendars = function(event) { - return { - google: calendarGenerators.google(event), - yahoo: calendarGenerators.yahoo(event), - ical: calendarGenerators.ical(event), - outlook: calendarGenerators.outlook(event) - }; - }; - - // Create CSS - var addCSS = function() { - if (!document.getElementById('ouical-css')) { - document.getElementsByTagName('head')[0].appendChild(generateCSS()); - } - }; - - var generateCSS = function() { - var styles = document.createElement('style'); - styles.id = 'ouical-css'; - - styles.innerHTML = "#add-to-calendar-checkbox-label{cursor:pointer}.add-to-calendar-checkbox~a{display:none}.add-to-calendar-checkbox:checked~a{display:block;width:150px;margin-left:20px}input[type=checkbox].add-to-calendar-checkbox{position:absolute;top:-9999px;left:-9999px}.add-to-calendar-checkbox~a:before{width:16px;height:16px;display:inline-block;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFQAAAAQCAYAAACIoli7AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoTWFjaW50b3NoKSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDo0MzJCRDU2NUE1MDIxMUUyOTY1Q0EwNTkxNEJDOUIwNCIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDo0MzJCRDU2NkE1MDIxMUUyOTY1Q0EwNTkxNEJDOUIwNCI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjQzMkJENTYzQTUwMjExRTI5NjVDQTA1OTE0QkM5QjA0IiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjQzMkJENTY0QTUwMjExRTI5NjVDQTA1OTE0QkM5QjA0Ii8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+1Gcb3QAACh1JREFUeNrEWAtw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);margin-right:.5em;content:' '}.icon-ical:before{background-position:-68px 0}.icon-outlook:before{}.icon-yahoo:before{background-position:-36px +4px}.icon-google:before{background-position:-52px 0}"; - - return styles; - }; - - // Make sure we have the necessary event data, such as start time and event duration - var validParams = function(params) { - return params.data !== undefined && params.data.start !== undefined && - (params.data.end !== undefined || params.data.duration !== undefined); - }; - - var generateMarkup = function(calendars, clazz, calendarId) { - var result = document.createElement('div'); - - result.innerHTML = ''; - result.innerHTML += ''; - - Object.keys(calendars).forEach(function(services) { - result.innerHTML += calendars[services]; - }); - - result.className = 'add-to-calendar'; - if (clazz !== undefined) { - result.className += (' ' + clazz); - } - - addCSS(); - - result.id = calendarId; - return result; - }; - - var getClass = function(params) { - if (params.options && params.options.class) { - return params.options.class; - } - }; - - var getOrGenerateCalendarId = function(params) { - return params.options && params.options.id ? - params.options.id : - Math.floor(Math.random() * 1000000); // Generate a 6-digit random ID - }; - - exports.createCalendar = function(params) { - if (!validParams(params)) { - console.log('Event details missing.'); - return; - } - - return generateMarkup(generateCalendars(params.data), - getClass(params), - getOrGenerateCalendarId(params)); - }; -})(this); diff --git a/ouical.min.js b/ouical.min.js deleted file mode 100644 index 4534373..0000000 --- a/ouical.min.js +++ /dev/null @@ -1 +0,0 @@ -;(function(e){var t=60*1e3;var n=function(e){return e.toISOString().replace(/-|:|\.\d+/g,"")};var r=function(e){return e.end?n(e.end):n(new Date(e.start.getTime()+e.duration*t))};var i={google:function(e){var t=n(e.start);var i=r(e);var s=encodeURI(["https://www.google.com/calendar/render","?action=TEMPLATE","&text="+(e.title||""),"&dates="+(t||""),"/"+(i||""),"&details="+(e.description||""),"&location="+(e.address||""),"&sprop=&sprop=name:"].join(""));return'Google Calendar'},yahoo:function(e){var r=e.end?(e.end.getTime()-e.start.getTime())/t:e.duration;var i=r<600?"0"+Math.floor(r/60):Math.floor(r/60)+"";var s=r%60<10?"0"+r%60:r%60+"";var o=i+s;var u=n(new Date(e.start-e.start.getTimezoneOffset()*t))||"";var a=encodeURI(["http://calendar.yahoo.com/?v=60&view=d&type=20","&title="+(e.title||""),"&st="+u,"&dur="+(o||""),"&desc="+(e.description||""),"&in_loc="+(e.address||"")].join(""));return'Yahoo! Calendar'},ics:function(e,t,i){var s=n(e.start);var o=r(e);var u=encodeURI("data:text/calendar;charset=utf8,"+["BEGIN:VCALENDAR","VERSION:2.0","BEGIN:VEVENT","URL:"+document.URL,"DTSTART:"+(s||""),"DTEND:"+(o||""),"SUMMARY:"+(e.title||""),"DESCRIPTION:"+(e.description||""),"LOCATION:"+(e.address||""),"END:VEVENT","END:VCALENDAR"].join("\n"));return''+i+" Calendar"},ical:function(e){return this.ics(e,"icon-ical","iCal")},outlook:function(e){return this.ics(e,"icon-outlook","Outlook")}};var s=function(e){return{google:i.google(e),yahoo:i.yahoo(e),ical:i.ical(e),outlook:i.outlook(e)}};var o=function(){if(!document.getElementById("ouical-css")){document.getElementsByTagName("head")[0].appendChild(u())}};var u=function(){var e=document.createElement("style");e.id="ouical-css";e.innerHTML="#add-to-calendar-checkbox-label{cursor:pointer}.add-to-calendar-checkbox~a{display:none}.add-to-calendar-checkbox:checked~a{display:block;width:150px;margin-left:20px}input[type=checkbox].add-to-calendar-checkbox{position:absolute;top:-9999px;left:-9999px}.add-to-calendar-checkbox~a:before{width:16px;height:16px;display:inline-block;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFQAAAAQCAYAAACIoli7AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoTWFjaW50b3NoKSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDo0MzJCRDU2NUE1MDIxMUUyOTY1Q0EwNTkxNEJDOUIwNCIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDo0MzJCRDU2NkE1MDIxMUUyOTY1Q0EwNTkxNEJDOUIwNCI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjQzMkJENTYzQTUwMjExRTI5NjVDQTA1OTE0QkM5QjA0IiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjQzMkJENTY0QTUwMjExRTI5NjVDQTA1OTE0QkM5QjA0Ii8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+1Gcb3QAACh1JREFUeNrEWAtw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);margin-right:.5em;content:' '}.icon-ical:before{background-position:-68px 0}.icon-outlook:before{}.icon-yahoo:before{background-position:-36px +4px}.icon-google:before{background-position:-52px 0}";return e};var a=function(e){return e.data!==undefined&&e.data.start!==undefined&&(e.data.end!==undefined||e.data.duration!==undefined)};var f=function(e,t,n){var r=document.createElement("div");r.innerHTML='';r.innerHTML+='';Object.keys(e).forEach(function(t){r.innerHTML+=e[t]});r.className="add-to-calendar";if(t!==undefined){r.className+=" "+t}o();r.id=n;return r};var l=function(e){if(e.options&&e.options.class){return e.options.class}};var c=function(e){return e.options&&e.options.id?e.options.id:Math.floor(Math.random()*1e6)};e.createCalendar=function(e){if(!a(e)){console.log("Event details missing.");return}return f(s(e.data),l(e),c(e))}})(this); \ No newline at end of file diff --git a/tester.html b/tester.html new file mode 100644 index 0000000..5263d10 --- /dev/null +++ b/tester.html @@ -0,0 +1,216 @@ + + + + + + + + OUICal2 Add to Calendar OUI2 Add To Calender Test + + + +

OUICal2 Add to Calendar

+ +

Created by javascript:

+ +
+ Dec 31st, 2018 19:00 +
+
+
+ Dec 31st, 2018 19:00, 45 minutes +
+
+
+ Dec 31st, 2018 19:00 - 21:00 +
+
+
+ Dec 31st, 2018, All day +
+
+
+ Dec 31st, 2018 19:00, Toronto +
+
+
+ Dec 31st, 2018 19:00, 45 minutes, Toronto +
+
+
+ Dec 31st, 2018 19:00 - 21:00, Toronto +
+
+
+ Dec 31st, 2018, All day, Toronto +
+
+ + + + +
+

Created by html:

+ + +
+ Dec 31st, 2018 19:00 +
+ OUI2 Add To Calender Test 01 + 12/31/2018 19:00 +
+
+
+ Dec 31st, 2018 19:00, 45 minutes +
+ OUI2 Add To Calender Test 02 + 12/31/2018 19:00 + 45 +
+
+
+ Dec 31st, 2018 19:00 - 21:00 +
+ OUI2 Add To Calender Test 03 + 12/31/2018 19:00 + 12/31/2018 21:00 +
+
+
+ Dec 31st, 2018, All day +
+ OUI2 Add To Calender Test 04 + 12/31/2018 19:00 + true +
+
+
+ Dec 31st, 2018 19:00, Toronto +
+ OUI2 Add To Calender Test 05 + 12/31/2018 19:00 + America/Toronto +
+
+
+ Dec 31st, 2018 19:00, 45 minutes, Toronto +
+ OUI2 Add To Calender Test 06 + 12/31/2018 19:00 + 45 + America/Toronto +
+
+
+ Dec 31st, 2018 19:00 - 21:00, Toronto +
+ OUI2 Add To Calender Test 07 + 12/31/2018 19:00 + 12/31/2018 21:00 + America/Toronto +
+
+
+ Dec 31st, 2018, All day, Toronto +
+ OUI2 Add To Calender Test 08 + 12/31/2018 19:00 + true + America/Toronto +
+
+ + + + +