update version number and date
[FlickrHacks.git] / _greasemonkey_ / flickrfollowcomments.user.js
blob31397b92efe16d67cc02bb204607d6c9e0cec1bd
1 // ==UserScript==
2 // @name        Flickr Follow Comments
3 // @namespace   http://6v8.gamboni.org/
4 // @description Filter the comment you've made to only follow the one that interest you.
5 // @version        0.6
6 // @identifier  http://6v8.gamboni.org/IMG/js/flickrfollowcomments.user.js
7 // @date           2007-02-22
8 // @creator        Pierre Andrews (mortimer.pa@free.fr)
9 // @include http://*flickr.com/photos_comments.gne
10 // @include http://*flickr.com/photos/*/*
11 // ==/UserScript==
13 // --------------------------------------------------------------------
15 // This is a Greasemonkey user script.
17 // To install, you need Greasemonkey: http://greasemonkey.mozdev.org/
18 // Then restart Firefox and revisit this script.
19 // Under Tools, there will be a new menu item to "Install User Script".
20 // Accept the default configuration and install.
22 // --------------------------------------------------------------------
23 // Copyright (C) 2006 Pierre Andrews
24 // 
25 // This program is free software; you can redistribute it and/or
26 // modify it under the terms of the GNU General Public License
27 // as published by the Free Software Foundation; either version 2
28 // of the License, or (at your option) any later version.
29 // 
30 // This program is distributed in the hope that it will be useful,
31 // but WITHOUT ANY WARRANTY; without even the implied warranty of
32 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
33 // GNU General Public License for more details.
34 // 
35 // The GNU General Public License is available by visiting
36 //   http://www.gnu.org/copyleft/gpl.html
37 // or by writing to
38 //   Free Software Foundation, Inc.
39 //   51 Franklin Street, Fifth Floor
40 //   Boston, MA  02110-1301
41 //   USA
43 var FETCH_PHOTOS = 50;
45 (function () {
47         //update information
48         var SCRIPT = {
49                 name: "Flickr Follow Comments",
50                 namespace: "http://6v8.gamboni.org/",
51                 description: "Filter the comment you've made to only follow the one that interest you.",
52                 identifier: "http://6v8.gamboni.org/IMG/js/flickrfollowcomments.user.js",
53                 version: "0.6",                                                         // version
54                 date: (new Date("2006-02-22"))          // update date
55                 .valueOf()
56         };
58         var ALL = 0;
59         var CONTACTS = ALL+1;
60         var FRIENDS = CONTACTS+1;
61         var FAMILY = FRIENDS+1;
62         var IGNORED = FAMILY+1;
63         var FAVS = IGNORED+1;
65         
66         function getObjectMethodClosure0(object, method, arg) {
67                 return function() {
68                         return object[method](arg); 
69                 }
70         }
71                 
72         function getObjectMethodClosure(object, method) {
73                 return function(arg) {
74                         return object[method](arg); 
75                 }
76         }
78         function M8_log() {
79                 if(unsafeWindow.console)
80                         unsafeWindow.console.log(arguments);
81                 else
82                         GM_log(arguments);
83         }
85         var flickrfollowcomments = function() {this.init();}
87         flickrfollowcomments.prototype = {
88                 photo_blocks: new Array(),
89                 user_photos: {},
90                 done: 0,
91                 table:'',
92                 faulty_pages: new Array(),
93                 fetched: 0,
95                 type: ALL,
96                 lessThanTen: false,
97                 sinceLastVisit: false,
99                 contA: null,
100                 frieA: null,
101                 famA: null,
102                 allA: null,
103                 favsA: null,
105                 contacts: new Array(),
106                 family: new Array(),
107                 friend: new Array(),
108                 
109                 favs: new Array(),
110                 favs_pages: 1,
112                 ignore: new Array(),
113                 lastVisit: 0,
114                 notupdated: false,
115                 lastpoll: 0,
117                 init: function() {
118                         var ign = GM_getValue('ignoreComments');
119                         if(ign) this.ignore = ign.split(',');
121                         if(unsafeWindow.page_photo_id) {
122                                 var disc = document.getElementById('DiscussPhoto');
123                                 var sel = document.createElement('input');
124                                 sel.id = 'ignore_'+i;
125                                 sel.type = 'checkbox';
126                                 sel.checked = this.ignore.indexOf(unsafeWindow.page_photo_id+'') >= 0;
127                                 var self = this;
128                                 sel.addEventListener('click',function(evt) {
129                                                 var s = evt.target;
130                                                 if(s.checked) {
131                                                         self.addIgnore(unsafeWindow.page_photo_id); 
132                                                 } else {
133                                                         self.removeIgnore(unsafeWindow.page_photo_id);
134                                                 }
135                                         }, true);
136                                 disc.appendChild(sel);
137                                 var lbl = disc.appendChild(document.createElement('label'));
138                                 lbl.innerHTML = 'ignore future comments here.';
139                                 lbl.htmlFor = 'ignore_'+i;
140                         } else if(document.location.pathname == "/photos_comments.gne") {
141                                 GM_addStyle(".graph {"+
142                                                         "width: 200px;"+
143                                                         "border: 1px solid #FF0084;"+
144                                                         "padding: 2px;"+
145                                                         "margin: 1em;"+
146                                                         "}"+
147                                                         ".graph .bar {"+
148                                                         "display: block;"+
149                                                         "position: relative;"+
150                                                         "background: #0063DC;"+
151                                                         "text-align: center;"+
152                                                         "color: #333;"+
153                                                         "height: 2em;"+
154                                                         "line-height: 2em;"+       
155                                                         "color: #FF0084"+
156                                                         "}"+
157                                                         ".graph .bar span { position: absolute; left: 1em; }");
158                                                                 
159                                 var lastVisit = GM_getValue('lastVisit');
160                                 if(lastVisit) {
161                                         lastVisit = lastVisit.split(',');
162                                         this.lastVisit = parseInt(lastVisit[0]);
163                                         this.sinceLastVisit = eval(lastVisit[1]);
164                                 } else {
165                                         this.sinceLastVisit = false;
166                                         this.lastVisit = 0;
167                                 }
168                                 GM_setValue('lastVisit',Date.now()+','+this.sinceLastVisit);
169                                 
170                                 var main = document.getElementById('Main');
171                                 var feeds = document.getElementById('Feeds');
172                                 main.style.display = 'none';
173                                 main.id = '';
174                                 var newMain = main.parentNode.insertBefore(document.createElement('div'),main);
175                                 newMain.id = 'Main';
176                                 var h1 = newMain.appendChild(document.createElement('h1'));
177                                 h1.innerHTML = 'Comments You\'ve Made';
178                                 this.table = newMain.appendChild(document.createElement('table'));
179                                 this.table.cellspacing = 0;
180                                 this.table.className = 'RecentActivity';
181                                 this.table = this.table.appendChild(document.createElement('tbody'));
182                                 this.table.innerHTML = '<tr><td><img src="http://www.flickr.com/images/pulser2.gif" style="margin:0;padding:0;margin-right:4px;border:0px #ffffff;height: 16px;" /></td></tr>';
183                                 newMain.appendChild(feeds);
184                                 this.lastpoll = GM_getValue('lastpoll');
185                                 var lastrsp = GM_getValue('lastrsp');
186                                 var self = this;
187                                         var listener = {
188                                                 flickr_activity_userComments_onLoad: function(success, responseXML, responseText, params){
189                                                         try{
190                                                                 var rsp = responseText.replace(/jsonFlickrApi\(/,'');
191                                                                 rsp = eval('('+rsp);
192                                                                 if(rsp.stat == 'ok') {
193                                                                         GM_setValue('lastrsp',true);
194                                                                         GM_setValue('lastrsp'+rsp.items.page,responseText);
195                                                                         self.parsePage(rsp);
196                                                                 } else
197                                                                 M8_log("Error2 "+responseText);                                                 
198                                                         } catch (e) {
199                                                                 M8_log("Error1 "+responseText);
200                                                                 M8_log(e);
201                                                         }
202                                                 }
203                                         };
204                                 if(!lastrsp || !this.lastpoll || this.lastpoll && (Date.now()-this.lastpoll > 3600*1000)) {
205                                         var nbr_page = FETCH_PHOTOS/50;
206                                         for(i=0;i < nbr_page;i++) {
207                                                 GM_setValue('lastpoll',Date.now()+"");
208                                                 unsafeWindow.F.API.callMethod('flickr.activity.userComments', {
209                                                         per_page:50,
210                                                                                  page: i+1,
211                                                                                  format: 'json'
212                                                                                  }, listener);
213                                         }
214                                 } else {
215                                         this.notupdate = true;
216                                         var nbr_page = FETCH_PHOTOS/50;
217                                         for(i=1;i <= nbr_page;i++) {
218                                                 var lastrsp = GM_getValue('lastrsp'+i);
219                                                 listener.flickr_activity_userComments_onLoad(true,'',lastrsp,'');
220                                         }
221                                 }
222                         
223                         }
224                 },
226                 parsePage: function(rsp) {
227                         var i = 0;
228                         for(i=0;i<rsp.items.item.length;i++) {
229                                 var item = rsp.items.item[i];
230                                 var photo_id = item.id;
231                                 var user_id = item.owner;
232                                 this.photo_blocks.push(item);
233                         }
234                         if(++this.fetched >= (FETCH_PHOTOS/50))
235                         this.ready();
236                 },
238                 getFavs: function(page) {
239                         if(this.contacts.length <= 0) {
240                                 //Trick to do it using the flickr API with authentication already embeded in the page.
241                                 var self = this;
242                                 var listener = {
243                                         flickr_favorites_getList_onLoad: function(success, responseXML, responseText, params){
244                                                 try{
245                                                         var rsp = responseText.replace(/jsonFlickrApi\(/,'');
246                                                         rsp = eval('('+rsp);
247                                                         if(rsp.stat == 'ok') {
248                                                                 self.process_favs(rsp);
249                                                         } else
250                                                         M8_log("ErrorFavs1 "+responseText);                                                     
251                                                 } catch (e) {
252                                                         M8_log("ErrorFavs2 "+responseText);
253                                                         M8_log(e);
254                                                 }
255                                         }
256                                 };
257                                 var the_page = page;
258                                 if(page <= 0) the_page = 1;
259                                 unsafeWindow.F.API.callMethod('flickr.favorites.getList', {per_page: 500,
260                                                                                                                                                                                  page:the_page,
261                                                                                                                                                                                  format: 'json'},
262                                                                                           listener);
263                         } else
264                         this.doneGettingFavs();
265                         
266                 },
268                 process_favs: function(rsp) {
269                         var pages = rsp.photos.pages;
270                         if(this.favs_pages++ < pages)
271                         this.getFavs(rsp.photos.page+1);
272                         var i = 0;
273                         for(i=0;i<rsp.photos.photo.length;i++) {
274                                 this.favs.push(rsp.photos.photo[i].id);
275                         }
276                         if(this.favs_pages >= pages)
277                         this.doneGettingFavs();
278                 },
279                 
280                 getContacts: function() {
281                         if(this.contacts.length <= 0) {
282                                 //Trick to do it using the flickr API with authentication already embeded in the page.
283                                 var self = this;
284                                 var listener = {
285                                         flickr_contacts_getList_onLoad: function(success, responseXML, responseText, params){
286                                                 self.process_contactsID(responseText);
287                                         }
288                                 };
289                                 
290                                 unsafeWindow.F.API.callMethod('flickr.contacts.getList', {}, listener);
291                         } else
292                                 this.doneGettingContacts();
293                 },
295                 process_contactsID: function(req) {
296                         var rsp = req.replace(/<\?xml.*\?>/,'');
297                         rsp = new XML(rsp);
299                         if (rsp == null) {
300                                 this.error( "Could not understand Flickr's response.", 0, req);
301                         } else {                        
302                                 var stat = rsp.@stat;
303                                 if (stat == null) {
304                                         this.error( "Could not find status of Flickr request", 0, req);
305                                 } else if (stat != 'ok') {
306                                         if (stat == 'fail') {
307                                                 var err_node = rsp.err[0];
308                                                 var code = err_node.@code;
309                                                 var err_msg = err_node.@msg;
310                                                 this.error( err_msg, code, req);
311                                         } else {
312                                                 this.error("Unknown error status: '" + stat + "'", 0, req)
313                                         }
314                                 } else {
315                                         for each(contact in rsp..contact) {
316                                                 this.contacts.push(contact.@nsid+'');
317                                                 if(contact.@family == '1') {
318                                                         this.family.push(contact.@nsid+'');
319                                                 }
320                                                 if(contact.@friend == '1') {
321                                                         this.friend.push(contact.@nsid+'');
322                                                         this.friend.push(contact.@nsid+'');
323                                                 }
324                                         }
325                                         this.doneGettingContacts();
326                                 }
327                         }
328                 },
329                 
330                 doneGettingContacts: function() {
331                         var photos = new Array();
332                         var userList;
333                         this.allA.setAttribute('style','');
334                         this.ignoreA.setAttribute('style','');
335                         
336                         this.contA.setAttribute('style','');
337                         this.frieA.setAttribute('style','');
338                         this.famA.setAttribute('style','');
339                         switch(this.type) {
340                                 case CONTACTS:
341                                         userList = this.contacts;
342                                         this.contA.setAttribute('style','text-decoration:none;color:#FF0084;');
343                                         break;
344                                 case FRIENDS:
345                                         userList = this.friend;
346                                         this.frieA.setAttribute('style','text-decoration:none;color:#FF0084;');
347                                         break;
348                                 case FAMILY:
349                                         userList = this.family;
350                                         this.famA.setAttribute('style','text-decoration:none;color:#FF0084;');
351                                         break;
352                         }
353                         for each(user in userList) {
354                                         if(this.user_photos[user])
355                                                 photos = photos.concat(this.user_photos[user]);
356                                 }
357                         this.updateDisplay(photos,false);
358                 },
360                 doneGettingFavs: function() {
361                         this.displayMain(FAVS);
362                 },
364                 makeTime: function(time,ago) {
365                         var diff = Date.now() - time;
366                         diff = diff/1000;
367                         if(diff < 365*24*3600) {
368                                 if(diff > 30*24*3600) {
369                                         return parseInt(diff/(30*24*3600))+" month(s)"+ago;
370                                 } else if(diff > 7*24*3600) {
371                                         return parseInt(diff/(7*24*3600))+" week(s)"+ago;
372                                 } else if(diff > 24*3600) {
373                                         return parseInt(diff/(24*3600))+" day(s)"+ago;
374                                 } else if(diff>3600) {
375                                         return parseInt(diff/3600)+" hour(s)"+ago;
376                                 } else if(diff>60) {
377                                         return parseInt(diff/60)+" minute(s)"+ago;
378                                 } else return diff + "seconds"+ago;
379                         } else return "on the "+(new Date(time)).toLocaleDateString();
380                 },
382                 /*The activity api has a bug and always returns the user id instead of the owner,
383                   so we have to cheat to get the info about the authors.*/
384                 getNameFor: function(id) {
385                         var self = this;
386                                 var listener = {
387                                                 flickr_photos_getInfo_onLoad: function(success, responseXML, responseText, params){
388                                                         try{
389                                                                 var rsp = responseText.replace(/jsonFlickrApi\(/,'');
390                                                                 rsp = eval('('+rsp);
391                                                                 if(rsp.stat == 'ok') {
392                                                                         var person = rsp.photo.owner;
393                                                                         var icon_link = document.createElement('a');
394                                                                         icon_link.href = "/photos/"+person.nsid+"/";
395                                                                         var img = document.getElementById("hover_img" +person.nsid);
396                                                                         
397                                                                         if(self.user_photos[person.nsid]) {
398                                                                                 self.user_photos[person.nsid].push(rsp.photo.id);
399                                                                         } else {
400                                                                                 self.user_photos[person.nsid] = new Array(rsp.photo.id);
401                                                                         }
402                                                                         
403                                                                         if(img) {
404                                                                                 var img2 = img.cloneNode(false);
405                                                                                 img2.setAttribute('id','');
406                                                                                 img2.setAttribute('class','');
407                                                                                 img2.setAttribute('width','24');
408                                                                                 img2.setAttribute('height','24');
409                                                                                 img2.addEventListener('mouseover',getObjectMethodClosure(unsafeWindow.document.getElementById('person_hover'),'icon_mouseover'),true);
410                                                                                 img2.addEventListener('mouseout',getObjectMethodClosure(unsafeWindow.document.getElementById("person_hover"),'icon_mouseout'),true);
411                                                                                 icon_link.appendChild(img2);
412                                                                         } else {
413                                                                                 icon_link.innerHTML = '>';
414                                                                         }
415                                                                         var html = 'From <a href="/photos/'+person.nsid+'"><b>'+person.username+'</b></a>';
417                                                                         var who = document.evaluate("/html/body//td[@class='Who m8_Who"+rsp.photo.id+"']",                              
418                                                                                                                                 document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null
419                                                                                                                                 ).singleNodeValue;      
420                                                                         if(who) {
421                                                                                 who.appendChild(icon_link);
422                                                                                 who.innerHTML += html;
423                                                                         }
424                                                                 } else
425                                                                 M8_log("Error3 "+responseText);                                                 
426                                                         } catch (e) {
427                                                                 M8_log("Error4 "+responseText);
428                                                                 M8_log(e);
429                                                         }
430                                                 }
431                                         };
432                                 unsafeWindow.F.API.callMethod('flickr.photos.getInfo', {
433                                         photo_id:id,
434                                                                 format: 'json'
435                                                                 }, listener);
436                                 
437                 },
439                 updateDisplay: function(photos,showingIgnore){ 
440                         var shown = 0;
441                         if(this.notupdate) this.table.innerHTML="<tr><td colspan='3'>This page cannot be updated more than once an hour due to restrictions from Flickr service. Next update will be possible after: "+this.makeTime(this.lastpoll*1,'')+"</td></tr>";
442                         else this.table.innerHTML = '';
443                         for(i=0;i<this.photo_blocks.length;i++){
444                                 var photo_item = this.photo_blocks[i];
445                                 if(showingIgnore || this.ignore.indexOf(photo_item.id) < 0) {
446                                         if(!photos || photos.indexOf(photo_item.id) >= 0) {
447                                                 var timestamp = photo_item.activity.event[0].dateadded*1000;
448                                                 if(this.lastVisit == 0 || !this.sinceLastVisit || timestamp >= this.lastVisit) {
449                                                         var cnt = photo_item.more+photo_item.activity.event.length;
450                                                         if(!this.lessThanTen || cnt < 10) {
451                                                                 var tdt = this.table.appendChild(document.createElement('tr'));
452                                                                 tdt.setAttribute('valign','top');
453                                                                 var tdo = tdt.appendChild(document.createElement('td'));
454                                                                 tdo.setAttribute('class','Object');
455                                                                 tdo.innerHTML = 
456                                                                         '                                                       <p><a href="/photo.gne?id='+photo_item.id+'/" style="position: relative;"><img width="75" height="75" alt="'+photo_item.title._content+'" src="http://static.flickr.com/'+photo_item.server+'/'+photo_item.id+'_'+photo_item.secret+'_s.jpg"/></a></p>'+
457                                                                         '                                                       <small>'+
458                                                                         '                                                                       <b>'+photo_item.views+'</b> views<br/>'+
459                                                                         ((photo_item.faves>0)?
460                                                                          ('<a href="/photo.gne?id='+photo_item.id+'">'+photo_item.faves+' people</a> call this a favorite'):'')+
461                                                                         '                               </small>'+
462                                                                         '                               <img width="100" height="1" style="border: medium none ;" alt="" src="/images/spaceball.gif"/>  ';
463                                                                 var small = tdo.appendChild(document.createElement('small'));
464                                                                 var sel = document.createElement('input');
465                                                                 sel.id = 'ignore_'+photo_item.id;
466                                                                 sel.type = 'checkbox';
467                                                                 sel.checked = showingIgnore;
468                                                                 var self = this;
469                                                                 sel.addEventListener('click',function(evt) {
470                                                                         var s = evt.target;
471                                                                         var id = s.id.replace('ignore_','');
472                                                                         if(s.checked) {
473                                                                                 s.parentNode.parentNode.parentNode.parentNode.removeChild(s.parentNode.parentNode.parentNode);
474                                                                                 
475                                                                                 self.addIgnore(id);
476                                                                         } else {
477                                                                                 s.parentNode.parentNode.parentNode.parentNode.removeChild(s.parentNode.parentNode.parentNode);
478                                                                                 self.removeIgnore(id);
479                                                                         }
480                                                                 }, true);
481                                                                 small.appendChild(sel);
482                                                                 var lbl = small.appendChild(document.createElement('label'));
483                                                                 lbl.innerHTML = 'ignore future comments here.';
484                                                                 lbl.htmlFor = 'ignore_'+photo_item.id;
485                                                                 
486                                                                 var tdguts = tdt.appendChild(document.createElement('td'));
487                                                                 tdguts.setAttribute('class','Guts');
488                                                                 var html = 
489                                                                         '                               <table width="100%" cellspacing="0" cellpadding="0">'+
490                                                                         '                                       <tbody><tr valign="bottom">'+
491                                                                         '                                               <td>'+
492                                                                         '                                                       <h2>'+
493                                                                         '                                                               <a title="'+photo_item.title._content+'" style="text-decoration: none;" href="/photo.gne?id='+photo_item.id+'/">'+photo_item.title._content+'</a><br/>'+
494                                                                         
495                                                                         '                                                       </h2>'+
496                                                                         '                                                               '+
497                                                                         '                                                               <div class="HowMany">'+
498                                                                         '                                                                         <a href="/photo.gne?id='+photo_item.id+'/">'+photo_item.comments+' comments</a>'+
499                                                                         
500                                                                         '                                                                               (<b>'+(photo_item.more+photo_item.activity.event.length-((photo_item.more==0)?1:0))+' new</b> since yours'+((photo_item.more>0)?' - Here\'s the latest 10':'')+')'+
501                                                                         '                                                                       </div>'+
502                                                                         '                                               </td>'+
503                                                                         '                                               <td class="Who m8_Who'+photo_item.id+'">'+
504                                                                         '                                               </td>'+
505                                                                         '                                       </tr>'+
506                                                                         '                               </tbody></table>';
507                                                                         
509                                                                 tdguts.innerHTML += html;
510                                                                 this.getNameFor(photo_item.id);
511                                                                 var tab =  tdguts.appendChild(document.createElement('table'));
512                                                                 tab.setAttribute('width',100);
513                                                                 tab.setAttribute('cellspacing',0);
514                                                                 tab.setAttribute('class',"NewComments");
515                                                                 var bod = tab.appendChild(document.createElement('tbody'));
517                                                                 for(j=0;j<photo_item.activity.event.length;j++) {
518                                                                         var ev = photo_item.activity.event[j];
519                                                                         var ligne = bod.appendChild(document.createElement('tr'));
520                                                                         ligne.setAttribute('valign','top');
521                                                                         
522                                                                         var type = ligne.appendChild(document.createElement('td'));
523                                                                         var type_img = type.appendChild(document.createElement('img'));
524                                                                         type_img.src = '/images/icon_'+ev.type+'.gif';
525                                                                         var icon = ligne.appendChild(document.createElement('td'));
526                                                                         icon = icon.appendChild(document.createElement('a'));
527                                                                         icon.href = "/photos/"+ev.user+"/";
528                                                                         var img = document.getElementById("hover_img" +ev.user);
529                                                                         if(img) {
530                                                                                 var img2 = img.cloneNode(false);
531                                                                                 img2.setAttribute('class','');
532                                                                                 img2.setAttribute('id','');
533                                                                                 img2.setAttribute('width','24');
534                                                                                 img2.setAttribute('height','24');
535                                                                                 img2.addEventListener('mouseover',getObjectMethodClosure(unsafeWindow.document.getElementById('person_hover'),'icon_mouseover'),true);
536                                                                                 img2.addEventListener('mouseout',getObjectMethodClosure(unsafeWindow.document.getElementById("person_hover"),'icon_mouseout'),true);
537                                                                                 icon.appendChild(img2);
538                                                                         }
539                                                                         var html = '';
540                                                                         if(ev.user == unsafeWindow.global_nsid) {
541                                                                                 //yours
542                                                                                 type.setAttribute('class',"YouSaidIcon");
543                                                                                 type_img.setAttribute('alt',"You added a new comment");
544                                                                                 ligne.innerHTML += '                                            <td class="YouSaid"><b>'+((ev.type=='comment')?'You said':"You added a note")+':</b><br/>'+ev._content.replace(/\n/g,'<br/>')+'</td>'+
545                                                                                         '                                               <td class="YouSaid"><small>Added '+this.makeTime(ev.dateadded*1000,' ago')+'</small></td>';
546                                                                         }else {
547                                                                                 type.setAttribute('class',"YouSaidIcon");
548                                                                                 type_img.setAttribute('alt',ev.username+' added a new '+ev.type);
549                                                                                 ligne.innerHTML += '                                            <td><b><a href="/photos/'+ev.user+'/">'+ev.username+'</a>'+((ev.type=='comment')?' says':" added a note")+':</b><br/>'+ev._content.replace(/\n/g,'<br/>')+'</td>'+
550                                                                                         '                                               <td><small>Added '+this.makeTime(ev.dateadded*1000,' ago')+'</small></td>';
551                                                                         }
552                                                                 }
553                                                                 shown++;
554                                                         }
555                                                 }
556                                         }
557                                 }
558                                 
559                         }
560                         if(shown == 0) {
561                                 this.table.innerHTML = "<tr><td><strong>Nothing to see here</strong></td></tr>";
562                         }
563                 },
564                 
565                 addIgnore: function(id) {
566                         this.ignore.push(id+'');
567                         GM_setValue('ignoreComments',this.ignore.join(','));
568                 },
570                 removeIgnore: function(id) {                    
571                         this.ignore.splice(this.ignore.indexOf(id+''),1);
572                         GM_setValue('ignoreComments',this.ignore.join(','));
573                 },
575                 displayLessThanTen: function() {
576                         this.lessThanTen = true;        
577                         this.displayMain(this.type);
578                 },
580                 displayMoreThanTen: function() {
581                         this.lessThanTen = false;       
582                         this.displayMain(this.type);
583                 },
585                 displayMain: function(type) {
586                         if(type >= 0) this.type = type;
587                         this.table.innerHTML = '<tr><td><img src="http://www.flickr.com/images/pulser2.gif" style="margin:0;padding:0;margin-right:4px;border:0px #ffffff;height: 16px;" /></td></tr>';
588                         this.contA.setAttribute('style','');
589                         this.frieA.setAttribute('style','');
590                         this.famA.setAttribute('style','');
591                         switch(this.type) {
592                                 case ALL:
593                                         this.allA.setAttribute('style','text-decoration:none;color:#FF0084;');
594                                         this.ignoreA.setAttribute('style','');
595                                         this.favsA.setAttribute('style','');
596                                         this.updateDisplay(false,false);
597                                         break;
598                                 case IGNORED:
599                                         this.ignoreA.setAttribute('style','text-decoration:none;color:#FF0084;');
600                                         this.allA.setAttribute('style','');
601                                         this.favsA.setAttribute('style','');
602                                         this.updateDisplay(this.ignore,true);
603                                         break;
604                                 case FAVS:
605                                         this.favsA.setAttribute('style','text-decoration:none;color:#FF0084;');
606                                         this.allA.setAttribute('style','');
607                                         this.ignoreA.setAttribute('style','');
608                                         this.updateDisplay(this.favs,false);
609                                         break;
610                                 default:
611                                         this.displayOnlyContacts(this.type);
612                         }
613                 },
615                 displayOnlyContacts: function(type) {                   
616                         this.table.innerHTML = '<tr><td><img src="http://www.flickr.com/images/pulser2.gif" style="margin:0;padding:0;margin-right:4px;border:0px #ffffff;height: 16px;" /></td></tr>';
617                         this.type = type;
618                         this.getContacts();
619                 },
621                 displayOnlyFavs: function() {                   
622                         this.table.innerHTML = '<tr><td><img src="http://www.flickr.com/images/pulser2.gif" style="margin:0;padding:0;margin-right:4px;border:0px #ffffff;height: 16px;" /></td></tr>';
623                         this.favsA.setAttribute('style','text-decoration:none;color:#FF0084;');
624                         this.allA.setAttribute('style','');
625                         this.ignoreA.setAttribute('style','');
626                         this.type = FAVS;
627                         this.getFavs(1);
628                 },
630                 separator: function() {
631                         var img = document.createElement('img');
632                         img.setAttribute('style',"float:none;margin: 0 2;");
633                         img.width="1";
634                         img.height="9";
635                         img.src="http://www.flickr.com/images/subnavi_dots.gif";
636                         return img;
637                 },
639                 ready: function() {
640                         this.fetched = 0;
641                         var div = this.table.parentNode.parentNode.insertBefore(document.createElement('div'),this.table.parentNode);
642                         if(this.faulty_pages.length > 0) {
643                                 var h31=document.createElement('strong');
644                                 h31.setAttribute('style','color:red;font-size:85%;clear:left;');
645                                 var txt1=document.createTextNode('These pages couldn\'t be read:');
646                                 h31.appendChild(txt1);
647                                 var ul1=document.createElement('UL');
648                                 ul1.setAttribute('style','margin:0;padding:0;display:inline;');
649                                 for(fi=0;fi<this.faulty_pages.length;fi++){
650                                         var li1=document.createElement('LI');
651                                         li1.setAttribute('style','margin:0;padding:0;display: inline;list-style-type: none;');
652                                         ul1.appendChild(li1);
653                                         var a1=document.createElement('A');
654                                         a1.setAttribute('href','http://www.flickr.com/photos_comments.gne?page='+this.faulty_pages[fi]);
655                                         li1.appendChild(a1);
656                                         var txt1=document.createTextNode('Page '+this.faulty_pages[fi]);
657                                         a1.appendChild(txt1);
658                                 }
659                                 div.appendChild(h31);
660                                 div.appendChild(ul1);
661                                 div.appendChild(document.createElement('br'));
662                         }
664                         var since = document.createElement('input');
665                         since.type = 'checkbox';
666                         since.id = 'sinceLastVisit';
667                         var self = this;
668                         since.checked = this.sinceLastVisit;
669                         since.addEventListener('click',function() {
670                                         if(since.checked) {
671                                                 self.sinceLastVisit = true;
672                                         } else {
673                                                 self.sinceLastVisit = false;
674                                         }
675                                         GM_setValue('lastVisit',Date.now()+','+self.sinceLastVisit);
676                                         self.displayMain(self.type);
677                                 },true);
678                         div.appendChild(since);
679                         var lblsince = div.appendChild(document.createElement('label'));
680                         lblsince.setAttribute('style','font-size:90%;');
681                         lblsince.innerHTML = 'since last visit.';
682                         lblsince.htmlFor = 'sinceLastVisit';
684                         var h3 = div.appendChild(document.createElement('h3'));
685                         h3.innerHTML = 'On Photos by:';
686                         this.allA = div.appendChild(document.createElement('a'));
687                         this.allA.innerHTML = 'All';
688                         this.allA.href="javascript:;";
689                         this.allA.addEventListener('click',getObjectMethodClosure0(this,'displayMain',ALL),true);
690                         div.appendChild(this.separator());
691                         this.contA = div.appendChild(document.createElement('a'));
692                         this.contA.innerHTML = 'Contacts';
693                         this.contA.href="javascript:;";
694                         this.contA.addEventListener('click',getObjectMethodClosure0(this,'displayOnlyContacts',CONTACTS),true);
695                         div.appendChild(this.separator());
696                         this.frieA = div.appendChild(document.createElement('a'));
697                         this.frieA.innerHTML = 'Friends';
698                         this.frieA.href="javascript:;";
699                         this.frieA.addEventListener('click',getObjectMethodClosure0(this,'displayOnlyContacts',FRIENDS),true);
700                         div.appendChild(this.separator());
701                         this.famA = div.appendChild(document.createElement('a'));
702                         this.famA.innerHTML = 'Family';
703                         this.famA.href="javascript:;";
704                         this.famA.addEventListener('click',getObjectMethodClosure0(this,'displayOnlyContacts',FAMILY),true);
705                         div.appendChild(this.separator());
706                         this.favsA = div.appendChild(document.createElement('a'));
707                         this.favsA.innerHTML = 'Favorites';
708                         this.favsA.href="javascript:;";
709                         this.favsA.addEventListener('click',getObjectMethodClosure(this,'displayOnlyFavs'),true);
710                         div.appendChild(this.separator());
711                         this.ignoreA = div.appendChild(document.createElement('a'));
712                         this.ignoreA.innerHTML = 'Ignored';
713                         this.ignoreA.href="javascript:;";
714                         this.ignoreA.addEventListener('click',getObjectMethodClosure0(this,'displayMain',IGNORED),true);
715                         div.appendChild(this.separator());
716                         div.appendChild(document.createElement('br'));
717                         var check = document.createElement('input');
718                         check.type = 'checkbox';
719                         check.id = 'lessthanten';
720                         var self = this;
721                         check.addEventListener('click',function() {
722                                         if(check.checked) self.displayLessThanTen();
723                                         else self.displayMoreThanTen();
724                                 },true);
725                         div.appendChild(check);
726                         var lbl = div.appendChild(document.createElement('label'));
727                         lbl.setAttribute('style','font-size:90%;');
728                         lbl.innerHTML = 'with less than 10 answers since yours';
729                         lbl.htmlFor = 'lessthanten';
732                         this.displayMain(ALL);
733                 }
734         }
735         //======================================================================
736         // launch
737         try {
738                 window.addEventListener("load", function () {
739                                                                         try {
740                                                                                 
741                                                                                 // update automatically (http://userscripts.org/scripts/show/2296)
742                                                                                 win.UserScriptUpdates.requestAutomaticUpdates(SCRIPT);
743                                                                         } catch (ex) {} 
744                                                                         
745                                                                         var flickrgp = new flickrfollowcomments();
746                 }, false);
747         } catch (ex) {}
748 })();