vendor: 8,474 bytes, lines 1-240
1/* global saveAs, Blob, BlobBuilder, console */ 2/* exported ics */ 3 4var ics = function(uidDomain, prodId) { 5 'use strict'; 6 7 if (navigator.userAgent.indexOf('MSIE') > -1 && navigator.userAgent.indexOf('MSIE 10') == -1) { 8 console.log('Unsupported Browser'); 9 return; 10 } 11 12 if (typeof uidDomain === 'undefined') { uidDomain = 'default'; } 13 if (typeof prodId === 'undefined') { prodId = 'Calendar'; } 14 15 var SEPARATOR = (navigator.appVersion.indexOf('Win') !== -1) ? '\r\n' : '\n'; 16 var calendarEvents = []; 17 var calendarStart = [ 18 'BEGIN:VCALENDAR', 19 'PRODID:' + prodId, 20 'VERSION:2.0' 21 ].join(SEPARATOR); 22 var calendarEnd = SEPARATOR + 'END:VCALENDAR'; 23 var BYDAY_VALUES = ['SU', 'MO', 'TU', 'WE', 'TH', 'FR', 'SA']; 24 25 return { 26 /** 27 * Returns events array 28 * @return {array} Events 29 */ 30 'events': function() { 31 return calendarEvents; 32 }, 33 34 /** 35 * Returns calendar 36 * @return {string} Calendar in iCalendar format 37 */ 38 'calendar': function() { 39 return calendarStart + SEPARATOR + calendarEvents.join(SEPARATOR) + calendarEnd; 40 }, 41 42 /** 43 * Add event to the calendar 44 * @param {string} subject Subject/Title of event 45 * @param {string} description Description of event 46 * @param {string} location Location of event 47 * @param {string} begin Beginning date of event 48 * @param {string} stop Ending date of event 49 */ 50 'addEvent': function(subject, description, location, begin, stop, rrule) { 51 // I'm not in the mood to make these optional... So they are all required 52 if (typeof subject === 'undefined' || 53 typeof description === 'undefined' || 54 typeof location === 'undefined' || 55 typeof begin === 'undefined' || 56 typeof stop === 'undefined' 57 ) { 58 return false; 59 } 60 61 // validate rrule 62 if (rrule) { 63 if (!rrule.rrule) { 64 if (rrule.freq !== 'YEARLY' && rrule.freq !== 'MONTHLY' && rrule.freq !== 'WEEKLY' && rrule.freq !== 'DAILY') { 65 throw "Recurrence rrule frequency must be provided and be one of the following: 'YEARLY', 'MONTHLY', 'WEEKLY', or 'DAILY'"; 66 } 67 68 if (rrule.until) { 69 if (isNaN(Date.parse(rrule.until))) { 70 throw "Recurrence rrule 'until' must be a valid date string"; 71 } 72 } 73 74 if (rrule.interval) { 75 if (isNaN(parseInt(rrule.interval))) { 76 throw "Recurrence rrule 'interval' must be an integer"; 77 } 78 } 79 80 if (rrule.count) { 81 if (isNaN(parseInt(rrule.count))) { 82 throw "Recurrence rrule 'count' must be an integer"; 83 } 84 } 85 86 if (typeof rrule.byday !== 'undefined') { 87 if ((Object.prototype.toString.call(rrule.byday) !== '[object Array]')) { 88 throw "Recurrence rrule 'byday' must be an array"; 89 } 90 91 if (rrule.byday.length > 7) { 92 throw "Recurrence rrule 'byday' array must not be longer than the 7 days in a week"; 93 } 94 95 // Filter any possible repeats 96 rrule.byday = rrule.byday.filter(function(elem, pos) { 97 return rrule.byday.indexOf(elem) == pos; 98 }); 99 100 for (var d in rrule.byday) { 101 if (BYDAY_VALUES.indexOf(rrule.byday[d]) < 0) { 102 throw "Recurrence rrule 'byday' values must include only the following: 'SU', 'MO', 'TU', 'WE', 'TH', 'FR', 'SA'"; 103 } 104 } 105 } 106 } 107 } 108 109 //TODO add time and time zone? use moment to format? 110 var start_date = new Date(begin); 111 var end_date = new Date(stop); 112 var now_date = new Date(); 113 114 var start_year = ("0000" + (start_date.getFullYear().toString())).slice(-4); 115 var start_month = ("00" + ((start_date.getMonth() + 1).toString())).slice(-2); 116 var start_day = ("00" + ((start_date.getDate()).toString())).slice(-2); 117 var start_hours = ("00" + (start_date.getHours().toString())).slice(-2); 118 var start_minutes = ("00" + (start_date.getMinutes().toString())).slice(-2); 119 var start_seconds = ("00" + (start_date.getSeconds().toString())).slice(-2); 120 121 var end_year = ("0000" + (end_date.getFullYear().toString())).slice(-4); 122 var end_month = ("00" + ((end_date.getMonth() + 1).toString())).slice(-2); 123 var end_day = ("00" + ((end_date.getDate()).toString())).slice(-2); 124 var end_hours = ("00" + (end_date.getHours().toString())).slice(-2); 125 var end_minutes = ("00" + (end_date.getMinutes().toString())).slice(-2); 126 var end_seconds = ("00" + (end_date.getSeconds().toString())).slice(-2); 127 128 var now_year = ("0000" + (now_date.getFullYear().toString())).slice(-4); 129 var now_month = ("00" + ((now_date.getMonth() + 1).toString())).slice(-2); 130 var now_day = ("00" + ((now_date.getDate()).toString())).slice(-2); 131 var now_hours = ("00" + (now_date.getHours().toString())).slice(-2); 132 var now_minutes = ("00" + (now_date.getMinutes().toString())).slice(-2); 133 var now_seconds = ("00" + (now_date.getSeconds().toString())).slice(-2); 134 135 // Since some calendars don't add 0 second events, we need to remove time if there is none... 136 var start_time = ''; 137 var end_time = ''; 138 if (start_hours + start_minutes + start_seconds + end_hours + end_minutes + end_seconds != 0) { 139 start_time = 'T' + start_hours + start_minutes + start_seconds; 140 end_time = 'T' + end_hours + end_minutes + end_seconds; 141 } 142 var now_time = 'T' + now_hours + now_minutes + now_seconds; 143 144 var start = start_year + start_month + start_day + start_time; 145 var end = end_year + end_month + end_day + end_time; 146 var now = now_year + now_month + now_day + now_time; 147 148 // recurrence rrule vars 149 var rruleString; 150 if (rrule) { 151 if (rrule.rrule) { 152 rruleString = rrule.rrule; 153 } else { 154 rruleString = 'rrule:FREQ=' + rrule.freq; 155 156 if (rrule.until) { 157 var uDate = new Date(Date.parse(rrule.until)).toISOString(); 158 rruleString += ';UNTIL=' + uDate.substring(0, uDate.length - 13).replace(/[-]/g, '') + '000000Z'; 159 } 160 161 if (rrule.interval) { 162 rruleString += ';INTERVAL=' + rrule.interval; 163 } 164 165 if (rrule.count) { 166 rruleString += ';COUNT=' + rrule.count; 167 } 168 169 if (rrule.byday && rrule.byday.length > 0) { 170 rruleString += ';BYDAY=' + rrule.byday.join(','); 171 } 172 } 173 } 174 175 var stamp = new Date().toISOString(); 176 177 var calendarEvent = [ 178 'BEGIN:VEVENT', 179 'UID:' + calendarEvents.length + "@" + uidDomain, 180 'CLASS:PUBLIC', 181 'DESCRIPTION:' + description, 182 'DTSTAMP;VALUE=DATE-TIME:' + now, 183 'DTSTART;VALUE=DATE-TIME:' + start, 184 'DTEND;VALUE=DATE-TIME:' + end, 185 'LOCATION:' + location, 186 'SUMMARY;LANGUAGE=en-us:' + subject, 187 'TRANSP:TRANSPARENT', 188 'END:VEVENT' 189 ]; 190 191 if (rruleString) { 192 calendarEvent.splice(4, 0, rruleString); 193 } 194 195 calendarEvent = calendarEvent.join(SEPARATOR); 196 197 calendarEvents.push(calendarEvent); 198 return calendarEvent; 199 }, 200 201 /** 202 * Download calendar using the saveAs function from filesave.js 203 * @param {string} filename Filename 204 * @param {string} ext Extention 205 */ 206 'download': function(filename, ext) { 207 if (calendarEvents.length < 1) { 208 return false; 209 } 210 211 ext = (typeof ext !== 'undefined') ? ext : '.ics'; 212 filename = (typeof filename !== 'undefined') ? filename : 'calendar'; 213 var calendar = calendarStart + SEPARATOR + calendarEvents.join(SEPARATOR) + calendarEnd; 214 215 var blob; 216 if (navigator.userAgent.indexOf('MSIE 10') === -1) { // chrome or firefox 217 blob = new Blob([calendar]); 218 } else { // ie 219 var bb = new BlobBuilder(); 220 bb.append(calendar); 221 blob = bb.getBlob('text/x-vCalendar;charset=' + document.characterSet); 222 } 223 saveAs(blob, filename + ext); 224 return calendar; 225 }, 226 227 /** 228 * Build and return the ical contents 229 */ 230 'build': function() { 231 if (calendarEvents.length < 1) { 232 return false; 233 } 234 235 var calendar = calendarStart + SEPARATOR + calendarEvents.join(SEPARATOR) + calendarEnd; 236 237 return calendar; 238 } 239 }; 240};
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.