- Fixed a bunch of bugs for existing paginations
[FlickrHacks.git] / _greasemonkey_ / flickrscientistphotograp.user.js
blob4ab93f4d41465c84e5f0db6ec0faadf7a060d143
1 // Flickr Scientist Photographers tools
2 // v0.2
3 // 2006-24-06
4 // Copyright (c) 2006, Pierre Andrews.
5 // Released under the GPL license
6 // http://www.gnu.org/copyleft/gpl.html
7 //
8 // ==UserScript==
9 // @name        Flickr Scientist Photographers tools
10 // @namespace   http://6v8.gamboni.org/
11 // @description tools for administrators of the scientist photographers group.
12 // @version        0.1
13 // @date           2006-19-06
14 // @creator        Pierre Andrews (mortimer.pa@free.fr)
15 // @include http://*flickr.com/groups/sciencegroup*
16 // ==/UserScript==
18 (function () {
20         var PER_PAGE = 500;
22         //======================================================================
24         //update information
25         var SCRIPT = {
26                 name: "Flickr Scientist Photographers tools",
27                 namespace: "http://6v8.gamboni.org/",
28                 description: "Tools for administrators of the scientist photographers group.",
29                 identifier: "http://6v8.gamboni.org/IMG/js/flickrscientistphotograp.user.js",
30                 version: "0.2",                                                         // version
31                 date: (new Date(2006, 6, 24))           // update date
32                 .valueOf()
33         };
36         //======================================================================
37         //to do the closure and get the right this.
38         //adapted from http://persistent.info/greasemonkey/gmail.user.js
40         function getObjectMethodClosure(object, method) {
41                 return function(arg) {
42                         return object[method](arg); 
43                 }
44         }
46         function getObjectMethodClosure0(object, method, arg) {
47                 return function() {
48                         return object[method](arg); 
49                 }
50         }
52         function getObjectMethodClosure01(object, method, arg,arg1) {
53                 return function() {
54                     return object[method](arg,arg1); 
55                 }
56         }
57         function M8_log() {
58                 if(unsafeWindow.console)
59                         unsafeWindow.console.log(arguments);
60                 else
61                         GM_log(arguments);
62         }
64         var FlickrSPAdminTools = function() {this.init();}
66         FlickrSPAdminTools.prototype = {
67                 votes: new Array(),
68                 voters: new Array(),
69                 imgSrc: new Array(),
70                 selectedPhotos: new Array(),
71                 removePhotosList: new Array(),
72                 removed: 0,
74                 init: function() {                 
75                         var threadTitle = document.evaluate(
76                                                                                                 "//td[@id='GoodStuff']/h2",
77                                                                                                 document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null
78                                                                                                 ).singleNodeValue;
79                         var del = document.evaluate("//a[@class='Warning']",
80                                                                                 document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null
81                                                                                 ).singleNodeValue;
82                         if(threadTitle && del && del.innerHTML == "delete topic"  && (threadTitle.innerHTML.indexOf('Selection Week') >= 0 || threadTitle.innerHTML.indexOf('Selection week') >= 0 || threadTitle.innerHTML.indexOf('selection week') >= 0 ||  threadTitle.innerHTML.indexOf('Selection') >= 0)) {
83                                 this.addVotingTool();
84                         }
85                         /*                      var adminLink = document.evaluate(
86                                                 "//a[@href='/groups/sciencegroup/admin/']",
87                                                 document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null
88                                                 ).singleNodeValue;
89                                                 if(adminLink) {
90                                                 this.addCleanPoolTool(adminLink.parentNode);
91                                                 }*/
92                 },
94                 showHideDec: function(vote,voteDec) {
95                         if(vote.value!="x") voteDec.style.display = 'inline';
96                         else voteDec.style.display = 'none';
97                 },
99                 addVotingTool: function() {
100                         var message = document.evaluate(
101                                                                                         "//textarea[@name='message']",
102                                                                                         document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null
103                                                                                         ).singleNodeValue;
104                         if(message) {
105                                 var images = document.evaluate(
106                                                                                            "//table[@class='TopicReply']//td[@class='Said']/p//img",
107                                                                                            document, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null); 
108                                 for(var i = 0; i < images.snapshotLength; i++) {  
109                                         var img = images.snapshotItem(i);
110                                         var vote = document.createElement('select');
111                                         var voteDec = document.createElement('select');
112                                         var html = '';
113                                         for(var j=1; j<10; j++) {
114                                                 html += '<option>'+j+"</option>\n";
115                                         }
116                                         vote.innerHTML = "<option>x</option>\n"+html+"<option>10</option>\n";
117                                         voteDec.innerHTML = "<option>0</option>\n"+html;
118                                         voteDec.style.display ='none';
119                                         vote.addEventListener('change',getObjectMethodClosure01(this,'showHideDec',vote,voteDec),true);
120                                         img.parentNode.parentNode.insertBefore(vote,img.parentNode);
121                                         img.parentNode.parentNode.insertBefore(document.createTextNode('.'),img.parentNode);
122                                         img.parentNode.parentNode.insertBefore(voteDec,img.parentNode);
123                                         img.parentNode.parentNode.insertBefore(document.createElement('br'),img.parentNode);
124                                         this.imgSrc.push(new Array(img.src.replace(/\.jpg/,'_t.jpg'),img.parentNode.href));
125                                         this.votes.push(vote);
126                                         this.votes.push(voteDec);
127                                 }
128                                 var button = document.createElement('button');
129                                 button.innerHTML = "VOTE";
130                                 button.type='button';
131                                 button.className = 'Butt';
132                                 var self = this;
133                                 button.addEventListener('click',function() {
134                                         var msg = '';
135                                         for(var k = 0;k< self.votes.length;k=k+2) {
136                                             msg += (k/2+1)+'- '+self.votes[k].value;
137                                             if(self.votes[k+1].style.display == 'inline') msg+= '.'+self.votes[k+1].value;
138                                             msg+="\n";
139                                         }
140                                         message.value = msg;
141                                         return false;
142                                 },true);
144                                 //For counting
146                                 var buttonTotal = document.createElement('button');
147                                 buttonTotal.innerHTML = "Make Total";
148                                 buttonTotal.type='button';
149                                 buttonTotal.className = 'Butt';
150                                 var self = this;
151                                 buttonTotal.addEventListener('click',function() {
152                                         var paraphs = document.evaluate("//table[@class='TopicReply']//td[@class='Said']/p",
153                                                                                                         document, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null); 
154                                         var grades = new Array();
155                                         var length = 0;
156                                         for(var i = 0; i < paraphs.snapshotLength; i++) {  
157                                                 var paragraph = paraphs.snapshotItem(i);
158                                                 if(paragraph.innerHTML.indexOf('<img') < 0) {
159                                                         var lines = paragraph.innerHTML.split('<br>');
160                                                         var idx = 0;
161                                                         var cnt = false;
162                                                         for(var j = 0;j<lines.length;j++) {
163                                                                 if(!grades[idx]) grades[idx] = new Array();
164                                                                 if(matches = /^\s*([0-9]+-\s*)?([0-9x]+(.[0-9]+)?)\s*.*$/mi.exec(lines[j])) {
165                                                                         var value = parseFloat(matches[2]);
166                                                                         if(value != NaN || matches[2] == 'x' || matches[2] == 'X') {
167                                                                                 var cnt = true;
168                                                                                 var l = lines[j].replace(/^\s*[0-9]+-/,'');
169                                                                                 grades[idx++].push(value); 
171                                                                         }
172                                                                 }                                           
173                                                         }
174                                                         if(cnt) {
175                                                                 var author = document.evaluate("h4/a[2]",
176                                                                                                                            paragraph.parentNode, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null
177                                                                                                                            ).singleNodeValue;
178                                                                 if(!author) author = document.evaluate("h4/a[1]",
179                                                                                                                                            paragraph.parentNode, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null
180                                                                                                                                            ).singleNodeValue;
181                                                                 length++;
182                                                                 self.voters.push(self.makeAuthorName(author.innerHTML));
183                                                         }
184                                                 }
185                                         }
186                                         var scores = new Array();
187                                         for(var i=0; i < grades.length;i++) {
188                                                 if(grades[i].length > 0) {
189                                                         message.value += (i+1)+'- ';
190                                                         var tot = 0;
191                                                         var nan = 0;
192                                                         var line = '';
193                                                         for(var j=0; j<grades[i].length;j++) {
194                                                                 line += ', '+self.voters[j]+' '+grades[i][j];
195                                                                 if(isNaN(grades[i][j])) nan++;
196                                                                 else {
197                                                                         tot += grades[i][j];
198                                                                 }
199                                                         }
200                                                         nan += length-grades[i].length;
201                                                         if(nan > 0) {
202                                                                 M8_log((i+1)+"-"+tot+"/"+(grades[i].length-nan));
203                                                                 var moy = tot/(grades[i].length-nan);
204                                                                 line = line.replace(/NaN/g,moy);
205                                                                 tot += moy*nan;
206                                                         }
207                                                         tot = parseInt(tot*100)/100;
208                                                         scores.push(new Array(tot,i));
209                                                         line = line.substr(1);
210                                                         message.value += line+' = '+tot+"\n";
211                                                 }
212                                         }
213                                         scores.sort(function(A, B) {
214                                                 var totA = A[0];
215                                                 var totB = B[0];
216                                                 return totB-totA;
217                                         });
218                                         var idx = 0;
219                                         var last = scores[idx][0];
220                                         var l =0;
221                                         var places = new Array("First", "Second", "Third");
222                                         message.value += "\n--------------------\n\n";
224                                         while(l<3) {
225                                                 var sel = '';
226                                                 var img = '';
227                                                 while(scores[idx][0] == last) {
228                                                         sel += ' and '+(scores[idx][1]+1);
229                                                         img += '<a href="'+self.imgSrc[scores[idx][1]][1]+'"><img src="'+self.imgSrc[scores[idx][1]][0]+'"/></a>'+"\n";
230                                                         idx++;
231                                                 }
232                                                 if(idx < scores.length)
233                                                         last = scores[idx][0];
234                                                 else break;
236                                                 sel = sel.substr(4);
237                                                                                  
238                                                 message.value +=places[l]+" Place: Image "+sel+" ("+scores[idx-1][0]+" points)\n";
239                                                 message.value += img+"\n";
240                                                 l++;
241                                         }
242                                 },true);
243                                 message.parentNode.parentNode.insertBefore(buttonTotal,message.parentNode.nextSibling);
244                                 message.parentNode.parentNode.insertBefore(button,message.parentNode.nextSibling);
246                         }               
247                 },
249                 //======================================================================
250                 // Pool cleaning bit
251                 //======================================================================
252                 
253                 addCleanPoolTool: function(links) {
254                         links.innerHTML += '<img width="1" height="11" alt="" src="/images/subnavi_dots.gif"/>';
255                         var clean = links.appendChild(document.createElement('a'));
256                         clean.innerHTML = "Clean Pool";
257                         clean.href = '#';
258                         clean.style.color = 'red';
259                         clean.addEventListener('click',getObjectMethodClosure(this,"cleanPool"),true);
260                 },
262                 cleanPool: function() {
263                         var back = document.body.appendChild(document.createElement('div'));
264                         back.id="poolCleaningBack";
265                         back.setAttribute('style',"position:absolute;background-color: black;opacity: 0.35; display: block; left: 0pt;");
266                         back.style.width = document.body.clientWidth+'px';
267                         back.style.height = document.body.clientHeight+'px';
268                         back.style.top = document.body.scrollTop+'px';
269                         var modal = document.body.appendChild(document.createElement('div'));
270                         modal.id="poolCleaning";
271                         modal.setAttribute('style',"position:absolute;background:white;border: 3px solid black;width: 300px;display: block; left: 442px;");
272                         modal.innerHTML = '<div style="padding:12px;background-color: #EEEEEE;clear:both;font-size: 14px;">Remove Photos that were not selected</div>';
273                         modal.style.top = document.body.scrollTop+(document.body.clientHeight/2)+'px';
275                         var dialog = modal.appendChild(document.createElement('div'));
276                         dialog.setAttribute('style',"padding: 18px 16px;clear:both;");
277                         var content = dialog.appendChild(document.createElement('div'));                                
278                         content.innerHTML = "Fetching Photos";
280                         var caution = dialog.appendChild(document.createElement('div'));
281                         caution.style.margin = "1em";
282                         caution.style.paddingTop = "1em";
283                         caution.style.borderTop = "1px solid black"
284                         caution.innerHTML += '<strong>BEWARE</strong> This operation is not reversible and will remove any photo in the pool that has not been tagged with "SP selection" or posted since Monday.';
285                                         
286                         var buttons = dialog.appendChild(document.createElement('div'));
287                         var ok = buttons.appendChild(document.createElement('button'));
288                         ok.type ='button';
289                         ok.disabled = true;
290                         ok.className='Butt';
291                         ok.innerHTML = '<img id="fgpe_pulser" src="http://www.flickr.com/images/pulser2.gif" style="vertical-align:middle;margin-right:4px;border:0px #ffffff" />';
292                         var cancel = buttons.appendChild(document.createElement('button'));
293                         cancel.type ='button';
294                         cancel.className = 'Butt';
295                         cancel.innerHTML = 'Cancel';
297                         cancel.addEventListener('click',function() {
298                                 document.body.removeChild(back);
299                                 document.body.removeChild(modal);
300                         },true);
303                         ok.addEventListener('click',getObjectMethodClosure01(this,'removePhotos',ok,content),true);
305                         modal.style.top = document.body.scrollTop+((document.body.clientHeight-modal.scrollHeight)/2)+'px';
306                         this.fetchGroupPhotos(ok,content);
307                 },
309                 
310                 fetchGroupPhotos: function(okButton,contentDiv) {
311                         
312                         var self = this;
313                         var listener = {
314                                 flickr_groups_pools_getPhotos_onLoad: function(success, responseXML, responseText, params){
315                                         if(success) self.process_taggedID(responseText,okButton,contentDiv);
316                                         else {
317                                                 contentDiv.innerHTML = "There was an error fetching photos";
318                                                 M8_log(responseText);
319                                         }
320                                 }
321                         };
322                                 
323                         unsafeWindow.F.API.callMethod('flickr.groups.pools.getPhotos', {tags:'spselection',group_id:"38873539@N00",per_page:PER_PAGE}, listener);
325                 },
327                 process_taggedID: function(rsp,okButton,contentDiv) {
328                         var rsp = rsp.replace(/<\?xml.*\?>/,'');
329                         rsp = new XML(rsp);
330                         if (rsp == null) {
331                                 contentDiv.innerHTML = "There was an error fetching photos";
332                                 M8_log(rsp);
333                         } else {        
334                                 for each(photo in rsp..photo) {
335                                         this.selectedPhotos.push(parseInt(photo.@id));
336                                 }
337                                 var self = this;
338                                 var thisweekCnt = 0;
339                                 var listener = {
340                                         flickr_groups_pools_getPhotos_onLoad: function(success, responseXML, responseText, params){
341                                                 if(success) {
342                                                         var rsp = responseText.replace(/<\?xml.*\?>/,'');
343                                                         rsp = new XML(rsp);
344                                                         
345                                                         if (rsp == null) {
346                                                                 contentDiv.innerHTML = "There was an error fetching photos";
347                                                                 M8_log(rsp);
348                                                         } else {        
349                                                                 var thisweek = new Date();
350                                                                 thisweek = thisweek.getTime()
351                                                                 //move to midnight
352                                                                 +((24-thisweek.getHours())*3600+(60-thisweek.getMinutes())*60
353                                                                   //move to sunday
354                                                                   -thisweek.getDay()*3600*24)*1000;
355                                                                 for each(photo in rsp..photo) {
356                                                                         if(photo.@dateadded <= (thisweek/1000)) {
357                                                                                 if(self.selectedPhotos.indexOf(parseInt(photo.@id)) < 0) {
358                                                                                         self.removePhotosList.push(photo.@id);
359                                                                                 }
360                                                                         } 
361                                                                 }
362                                                                 contentDiv.innerHTML = self.removePhotosList.length + ' photos found.';
363                                                                 okButton.disabled = false;
364                                                                 okButton.innerHTML = "Remove";
365                                                         }
366                                                 } else {
367                                                         contentDiv.innerHTML = "There was an error fetching photos";
368                                                         M8_log(responseText);
369                                                 }
370                                         }
371                                 };
372                                 
373                                 unsafeWindow.F.API.callMethod('flickr.groups.pools.getPhotos', {group_id:"38873539@N00",per_page:PER_PAGE}, listener);
374                         }
375                 },
377                 removePhotos: function(okButton,contentDiv) {
378                         contentDiv.innerHTML = "removing...";
379                         okButton.innerHTML = '<img id="fgpe_pulser" src="http://www.flickr.com/images/pulser2.gif" style="vertical-align:middle;margin-right:4px;border:0px #ffffff" />';
380                         var self = this;
381                         for(var i=0;i<this.removePhotosList.length;i++) {
382                                 unsafeWindow.F.API.callMethod('flickr.groups.pools.remove', {group_id:"38873539@N00",photo_id:this.removePhotosList[i]}, {
383                                         flickr_groups_pools_remove_onLoad: function(success, responseXML, responseText, params) {
384                                                 if(success) self.removed++;
385                                                 else M8_log("Cannot remove photo "+params['photo_id']+": " +responseText);
386                                         }
387                                 });
388                         }
389                         this.waitForAllRemove();
390                 },
392                 waitForAllRemove: function() {                  
393                         if(this.removed >= this.removePhotosList.length) {
394                                 document.body.removeChild(document.getElementById('poolCleaning'));
395                                 document.body.removeChild(document.getElementById('poolCleaningBack'));
396                         } else {
397                                 setTimeout(getObjectMethodClosure(this,'waitForAllRemove'),1000);
398                         }
399                 },
400                 
401                 makeAuthorName: function(name) {
402                         var sp = name.toLowerCase().replace(/(^[_'.]|['_.]$)/g,'').replace(/[_'.]/gi,' ');
403                         sp = sp.split(' ');
404                         if(sp.length > 1) {
405                                 sp = sp[0].substr(0,1)+'.'+sp[1].substr(0,1)+'.';
406                         } else 
407                                 sp = sp[0].substr(0,2);
408                         return sp;
409                 }
410         }
411                 
412         //======================================================================
413         // launch
414         try {
415                 window.addEventListener("load", function () {
416                         try {
417                                 
418                                 // update automatically (http://userscripts.org/scripts/show/2296)
419                                 //win.UserScriptUpdates.requestAutomaticUpdates(SCRIPT);
420                         } catch (ex) {} 
421                         
422                         new FlickrSPAdminTools();
423                 }, false);
424         } catch (ex) {}
426 })();