Draggable FF area
[ff_comments.user.js] / ff_comments.user.js
1 // ==UserScript==
2 // @name        FriendFeed comments
3 // @description Add FriendFeed 'likes' and comments to any page
4 // @namespace   http://oblomov.myopenid.com
5 // @include     http://*
6 // @exclude     http://friendfeed.com/*
7 // @exclude     http://*.friendfeed.com/*
8 // @exclude     http://friendfeed-api.com/*
9 // @author      Giuseppe "Oblomov" Bilotta
10 // @version     20091218
11 // ==/UserScript==
12
13 if (typeof(unsafeWindow) == 'undefined') unsafeWindow = window;
14
15 (function() {
16
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';
20
21 unsafeWindow.ujs_ff_load = function(url) {
22         var e = unsafeWindow.document.createElement('script');
23         e.type = 'text/javascript';
24         e.src = url;
25         unsafeWindow.document.getElementsByTagName('head')[0].appendChild(e);
26 };
27
28 unsafeWindow.ujs_ff_load_entries = function(str) {
29         if (str.entries && str.entries.length > 0) {
30                 var doc = unsafeWindow.document;
31
32                 var pdiv = doc.createElement('div');
33                 pdiv.setAttribute('id', 'ujs_friendfeed');
34                 pdiv.setAttribute('title', 'FriendFeed comments on this page');
35                 pdiv.style.position = 'absolute';
36                 pdiv.style.top = 0;
37                 pdiv.style.left = 0;
38                 pdiv.style.zIndex = 100000;
39                 pdiv.style.maxWidth = '30%';
40                 pdiv.style.height='auto';
41                 pdiv.style.border='3px outset lightblue';
42                 pdiv.style.margin = 0;
43                 pdiv.style.padding = 0;
44                 pdiv.style.textAlign = 'center';
45                 pdiv.style.fontSize = '0px';
46                 pdiv.style.lineHeight = 1;
47                 //  pdiv.style.opacity = 0.7;
48                 pdiv.style.backgroundColor = 'white';
49
50                 doc.body.appendChild(pdiv);
51
52                 var logo = doc.createElement('img');
53                 logo.src = 'http://friendfeed.com/favicon.ico';
54                 logo.setAttribute('alt', 'FriendFeed logo');
55                 logo.setAttribute('title', 'FriendFeed logo');
56                 logo.style.margin='0 auto 0 auto';
57                 logo.style.padding=0;
58                 pdiv.appendChild(logo);
59
60                 var div = doc.createElement('div');
61                 div.style.fontSize = 'small';
62
63                 for (var i in str.entries) {
64                         var entry = str.entries[i];
65
66                         var date2link = function(d, l) {
67                                 var day = d.substring(0, 10);
68                                 var tm = d.substring(11, 19);
69                                 if (l)
70                                         return '<a href="' + l + '">' + day + ' at ' + tm + '</a>';
71                                 else
72                                         return day + ' at ' + tm;
73                         }
74                         var when = entry.date.substring(0, 16).replace('T', ' ');
75
76                         var from2link = function(from) {
77                                 return '<a href="http://friendfeed.com/' + from.id + '">' + from.name + '</a>';
78                         }
79
80                         var from2linkimg = function(from) {
81                                 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>';
82                         }
83
84
85                         var fed = '<p>Fed by ' + from2link(entry.from);
86                         fed += ' on ' + date2link(entry.date, entry.url);
87                         var ediv = doc.createElement('div');
88                         ediv.style.margin=0;
89                         ediv.style.padding='.5ex';
90                         ediv.style.borderTop='.25ex dashed lightblue';
91                         ediv.style.textAlign = 'justify';
92                         ediv.innerHTML = fed
93                         div.appendChild(ediv);
94
95                         var likes = entry.likes || [];
96                         if (likes.length > 0) {
97                                 var liked = '<p style="margin:0 2ex;text-indent:-2ex">Liked by ';
98                                 for (var j in likes) {
99                                         var like = likes[j];
100                                         if (like.from)
101                                                 liked += (j > 0 ? ', ' : '') + from2link(like.from);
102                                         else
103                                                 liked += ' and ' + like.body;
104                                 }
105
106                                 var ldiv = doc.createElement('div');
107                                 ldiv.innerHTML = liked;
108                                 ediv.appendChild(ldiv);
109                         }
110                         var comments = entry.comments || [];
111                         if (comments.length > 0) {
112                                 for (var j in comments) {
113                                         var comment = comments[j];
114                                         var cdiv = doc.createElement('div');
115                                         cdiv.style.borderTop = '.1ex dotted blue';
116                                         cdiv.style.padding = '1ex .5ex';
117                                         ediv.appendChild(cdiv);
118
119                                         if (comment.from) {
120                                                 cdiv.innerHTML = from2linkimg(comment.from) +
121                                                         '<p style="margin:0;font-size:smaller">' + date2link(comment.date) + ' by ' + from2link(comment.from) +
122                                                         '<p style="margin:0">' + comment.body;
123                                         } else {
124                                                 cdiv.innerHTML += comment.body;
125                                         }
126                                 }
127
128                         }
129                 }
130
131                 div.style.display = 'none';
132                 pdiv.appendChild(div);
133
134                 function displayToggle() {
135                         // don't toggle if we were dragging
136                         if (pdiv.dragged) {
137                                 pdiv.dragged = false;
138                                 return;
139                         }
140                         var d = pdiv.lastChild;
141                         if (d.style.display == 'none') {
142                                 d.style.display = 'block';
143                                 logo.src = 'http://friendfeed.com/static/images/logo-small.png';
144                                 logo.style.padding = '5px';
145                         } else {
146                                 d.style.display = 'none';
147                                 logo.src = 'http://friendfeed.com/favicon.ico';
148                                 logo.style.padding = 0;
149                         }
150                 };
151                 logo.addEventListener('click', displayToggle, false);
152
153                 var dragging=false;
154                 pdiv.dragged=false;
155                 function drag(ev) {
156                         if (dragging) {
157                                 var dx = ev.pageX - dragging.x;
158                                 var dy = ev.pageY - dragging.y;
159                                 pdiv.style.left = (parseInt(pdiv.style.left) + dx) + 'px';
160                                 pdiv.style.top = (parseInt(pdiv.style.top) + dy) + 'px';
161                                 dragging.x = ev.pageX;
162                                 dragging.y = ev.pageY;
163                                 ev.preventDefault();
164                                 ev.stopPropagation();
165
166                                 pdiv.dragged = true;
167                         }
168                 }
169                 logo.addEventListener('mousedown',
170                                 function (ev) {
171                                         dragging=new Object();
172                                         dragging.x = ev.pageX;
173                                         dragging.y = ev.pageY;
174                                         ev.preventDefault();
175                                         ev.stopPropagation();
176                                 }, false);
177                 logo.addEventListener('mouseup',
178                                 function (ev) {
179                                         dragging=false;
180                                         ev.preventDefault();
181                                         ev.stopPropagation();
182                                 }, false);
183                 // handle on the whole document because otherwise fast
184                 // movements will make the mouse get out of the logo, thus
185                 // 'dropping' the drag
186                 doc.addEventListener('mousemove', drag, false);
187         }
188 };
189
190 // escape() does not escape +, but we want it escaped too
191 var encoded_loc = escape(unsafeWindow.location.toString()).replace('+','%2b');
192 var ff_url = 'http://friendfeed-api.com/v2/url?url=' + encoded_loc + '&callback=ujs_ff_load_entries';
193
194 unsafeWindow.ujs_ff_load(ff_url);
195
196 })();
197