// ==UserScript== // @name Evite HCalendar // @description Add hCalendar microformat markup to evite pages // @namespace http://floatingsheep.com/userscripts/ // @include http://www.evite.com/pages/invite/viewInvite.jsp?* // ==/UserScript== (function () { var now = new Date(); function xpath(expr, node) { if (!node) node = document; var snap = document.evaluate(expr, node, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); var res = []; for (var i = 0; i < snap.snapshotLength; i++) res.push(snap.snapshotItem(i)); return res; } function zeroPad(num, len) { var s = num.toString(); while (s.length < len) s = '0' + s; return s; } function buildDateAbbr(text, className, orig) { if (!orig) orig = text; // strip day of week text = text.replace(/^[A-Z][a-z]+,\s+/, ''); // add the year to aid parsing text = text.replace(',', ' ' + now.getFullYear() + ','); // switch to 24 hour time text = text.replace(/(\d+):(\d+)([AP]M)$/, function(t, h, m, ap) { h = parseInt(h); if (h < 12 && ap == 'PM') h += 12; return zeroPad(h, 2) + ':' + m; }); var d = new Date(Date.parse(text)); var abbr = document.createElement('abbr'); abbr.className = className; abbr.style.borderStyle = 'none'; abbr.title = d.getUTCFullYear() + '-' + zeroPad(d.getUTCMonth() + 1, 2) + '-' + zeroPad(d.getUTCDate(), 2) + 'T' + zeroPad(d.getUTCHours(), 2) + ':' + zeroPad(d.getUTCMinutes(), 2) + ':' + zeroPad(d.getUTCSeconds(), 2) + 'Z'; abbr.appendChild(document.createTextNode(orig)); return abbr; } var what = xpath('//td[starts-with(@class, "headertext17")]'); // if we don't get a summary, all is lost if (!what.length) return; what = what[0]; var when = xpath('//b[text()="When"]/../following-sibling::td[1]'); // if we don't get a start time, all is lost if (!when.length) return; when = when[0]; // the what and when are ok; let's start marking stuff up what.className += ' summary'; xpath('//body')[0].className += ' vevent'; // strip off the day of the week var txt = when.firstChild.nodeValue; if (/\sto\s/.test(txt)) { // same day, start and end time var tmp = txt.split(/\s*to\s*/); var start = buildDateAbbr(tmp[0], 'dtstart'); var end = buildDateAbbr(txt.replace(/,\s*\d.+/, ', ' + tmp[1]), 'dtend', tmp[1]); when.replaceChild(start, when.firstChild); when.appendChild(document.createTextNode(' to ')); when.appendChild(end); } else if (/-\s*$/.test(txt)) { // multiple days var start = buildDateAbbr(txt.replace(/\s*-\s*$/, ''), 'dtstart', txt); var end_node = when.childNodes.item(2); var end = buildDateAbbr(end_node.nodeValue, 'dtend'); when.replaceChild(start, when.firstChild); when.replaceChild(end, end_node); } else { // one day, one time when.replaceChild(buildDateAbbr(txt, 'dtstart'), when.firstChild); } // optional location var loc = xpath('//a[text()="Location:"]/../following-sibling::td[1]'); if (!loc.length) loc = xpath('//b[text()="Location"]/../following-sibling::td[1]'); if (loc.length) { loc = loc[0]; var bits = xpath('text()', loc); for (var i = 0; i < bits.length; i++) { var bit = bits[i]; var str = bit.nodeValue; if (/^\d/.test(str) && /,/.test(str) && /\d{5}/.test(str)) { var span = document.createElement('span'); span.className = 'location'; // see if we can add more value by building an adr var parts = str.split(/\s*,\s*/); var match; if (parts.length == 3 && (match = parts[2].match(/^([A-Z]{2})\s+(\d{5})\s+(.+)/))) { span.className += ' adr'; parts.pop(); match.shift(); var adr = parts.concat(match); var classes = [ 'street-address', 'locality', 'region', 'postal-code', 'country-name' ]; for (var j = 0; j < 5; j++) { var s = document.createElement('span'); s.className = classes[j]; s.appendChild(document.createTextNode(adr[j])); span.appendChild(s); if (j < 4) span.appendChild(document.createTextNode(', ')); } } else { span.appendChild(document.createTextNode(str)); } loc.replaceChild(span, bit); break; } } } // optional description var descr = xpath('//div[@id="lftUP"]/../../following-sibling::tr[1]'); if (descr.length) descr[0].className += ' description'; })();

AltStyle によって変換されたページ (->オリジナル) /