2 // @name FriendFeed comments
3 // @description Add FriendFeed 'likes' and comments to any page
4 // @namespace http://oblomov.myopenid.com
6 // @exclude http://friendfeed.com/*
7 // @exclude http://*.friendfeed.com/*
8 // @exclude http://friendfeed-api.com/*
9 // @author Giuseppe "Oblomov" Bilotta
13 if (typeof(unsafeWindow) == 'undefined') unsafeWindow = window;
17 var ff_preload = new Image();
18 ff_preload.src = 'http://friendfeed.com/favicon.ico';
19 ff_preload.src = 'http://friendfeed.com/static/images/logo-small.png';
22 unsafeWindow.ujs_now = new Date();
24 unsafeWindow.ujs_ff_load = function(url) {
25 var e = unsafeWindow.document.createElement('script');
26 e.type = 'text/javascript';
28 unsafeWindow.document.getElementsByTagName('head')[0].appendChild(e);
31 unsafeWindow.ujs_ff_load_entries = function(str) {
32 var weekday = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
33 var month = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
36 if (str.entries && str.entries.length > 0) {
37 var doc = unsafeWindow.document;
39 var pdiv = doc.getElementById('ujs_friendfeed');
44 pdiv = doc.createElement('div');
45 pdiv.setAttribute('id', 'ujs_friendfeed');
46 pdiv.setAttribute('title', 'FriendFeed comments on this page');
47 pdiv.style.position = 'absolute';
50 pdiv.style.zIndex = 100000;
51 pdiv.style.maxWidth = '30%';
52 pdiv.style.height='auto';
53 pdiv.style.border='3px outset lightblue';
54 pdiv.style.margin = 0;
55 pdiv.style.padding = 0;
56 pdiv.style.textAlign = 'center';
57 pdiv.style.fontSize = '0px';
58 pdiv.style.lineHeight = 1;
59 // pdiv.style.opacity = 0.7;
60 pdiv.style.backgroundColor = 'white';
62 doc.body.appendChild(pdiv);
64 var logo = doc.createElement('img');
65 logo.src = 'http://friendfeed.com/favicon.ico';
66 logo.setAttribute('alt', 'FriendFeed logo');
67 logo.setAttribute('title', 'FriendFeed logo');
68 logo.style.margin='0 auto 0 auto';
70 pdiv.appendChild(logo);
72 div = doc.createElement('div');
73 div.style.fontSize = 'small';
74 div.style.display = 'none';
75 pdiv.appendChild(div);
77 function displayToggle() {
78 // don't toggle if we were dragging
83 var d = pdiv.lastChild;
84 if (d.style.display == 'none') {
85 d.style.display = 'block';
86 logo.src = 'http://friendfeed.com/static/images/logo-small.png';
87 logo.style.padding = '5px';
89 d.style.display = 'none';
90 logo.src = 'http://friendfeed.com/favicon.ico';
91 logo.style.padding = 0;
95 logo.addEventListener('click', displayToggle, false);
101 var dx = ev.pageX - dragging.x;
102 var dy = ev.pageY - dragging.y;
103 pdiv.style.left = (parseInt(pdiv.style.left) + dx) + 'px';
104 pdiv.style.top = (parseInt(pdiv.style.top) + dy) + 'px';
105 dragging.x = ev.pageX;
106 dragging.y = ev.pageY;
108 ev.stopPropagation();
113 logo.addEventListener('mousedown',
115 dragging=new Object();
116 dragging.x = ev.pageX;
117 dragging.y = ev.pageY;
119 ev.stopPropagation();
121 logo.addEventListener('mouseup',
125 ev.stopPropagation();
127 // handle on the whole document because otherwise fast
128 // movements will make the mouse get out of the logo, thus
129 // 'dropping' the drag
130 doc.addEventListener('mousemove', drag, false);
134 var ecount = str.entries.length;
135 for (var i=0; i < ecount; ++i) {
136 var entry = str.entries[i];
138 var p_entry_id = 'ujs_ff_entry/' + entry.id;
140 // skip this entry if we already added it from a different source
141 if (doc.getElementById(p_entry_id))
144 var date2link = function(d, l) {
145 var cal = new Date();
148 cal.setUTCFullYear(parseInt(d.substring(0,4)));
149 cal.setUTCMonth(parseInt(d.substring(5,7)) - 1);
150 cal.setUTCDate(parseInt(d.substring(8,10)));
151 cal.setUTCHours(parseInt(d.substring(11,13)));
152 cal.setUTCMinutes(parseInt(d.substring(14,16)));
153 cal.setUTCSeconds(parseInt(d.substring(17,19)));
155 var delta = (ujs_now - cal)/1000;
157 if (delta < 48*3600) {
158 if (cal.getDate() == ujs_now.getDate()) {
163 } else if (cal.getYear() == ujs_now.getYear()) {
164 str = 'on ' + weekday[cal.getDay()] + ', ' + month[cal.getMonth()] + ' ' + cal.getDate();
166 str = 'on ' + [cal.getYear(), cal.getMonth() + 1, cal.getDate()].join('-');
169 str += ' at ' + [cal.getHours(), cal.getMinutes()].join(':');
172 return '<a href="' + l + '">' + str + '</a>';
177 var from2link = function(from) {
178 return '<a href="http://friendfeed.com/' + from.id + '">' + from.name + '</a>';
181 var from2linkimg = function(from) {
182 return '<a style="margin: 0 1ex .5ex 0;float:left;" href="http://friendfeed.com/' + from.id + '"><img src="http://friendfeed-api.com/v2/picture/' + from.id + '?size=small" /></a>';
188 if (entry.body != last_body) {
189 last_body = entry.body;
190 fed += '<p style="margin:0;clear:both">' + entry.body;
192 ediv = doc.createElement('div');
194 ediv.style.padding='.5ex';
195 ediv.style.borderTop='.25ex dashed lightblue';
196 ediv.style.textAlign = 'justify';
197 ediv.style.display = 'block';
198 div.appendChild(ediv);
200 ediv = div.lastChild;
201 fed = ediv.innerHTML;
203 fed += '<p id="' + p_entry_id + '" style="margin:.5ex 1ex .5ex 0;clear:both">' + from2linkimg(entry.from) + 'By ' + from2link(entry.from) + '<br/>' + date2link(entry.date, entry.url);
204 fed += '<div style="margin:0;margin-left:2.2em"></div>';
205 ediv.innerHTML = fed;
206 ediv = ediv.lastChild;
208 var likes = entry.likes || [];
209 var jcount = likes.length;
211 var liked = '<p style="margin:0 2ex;text-indent:-2ex">Liked by ';
212 for (var j=0; j < jcount; ++j) {
215 liked += (j > 0 ? ', ' : '') + from2link(like.from);
217 liked += ' and ' + like.body;
220 var ldiv = doc.createElement('div');
221 ldiv.innerHTML = liked;
222 ediv.appendChild(ldiv);
225 var comments = entry.comments || [];
226 jcount = comments.length;
228 for (var j=0 ; j < jcount; ++j) {
229 var comment = comments[j];
230 var cdiv = doc.createElement('div');
231 cdiv.style.borderTop = '.1ex dotted blue';
232 cdiv.style.padding = '1ex .5ex';
233 ediv.appendChild(cdiv);
236 cdiv.innerHTML = from2linkimg(comment.from) +
237 '<p style="margin:0;font-size:smaller;line-height:150%">' + date2link(comment.date) + ' by ' + from2link(comment.from) +
238 '</span><p style="margin:0">' + comment.body;
240 cdiv.innerHTML += comment.body;
249 // escape() does not escape +, but we want it escaped too
250 var encoded_loc = escape(unsafeWindow.location.toString()).replace('+','%2b');
251 var ff_url = 'http://friendfeed-api.com/v2/url?url=' + encoded_loc + '&callback=ujs_ff_load_entries&cache=' + Math.floor(Math.random()*1024*1024);
253 unsafeWindow.ujs_ff_load(ff_url);
255 ff_url = 'http://friendfeed-api.com/v2/search?q=' + encoded_loc + '&callback=ujs_ff_load_entries&cache=' + Math.floor(Math.random()*1024*1024);
257 unsafeWindow.ujs_ff_load(ff_url);