4 // Copyright (c) 2006, Pierre Andrews.
5 // Released under the GPL license
6 // http://www.gnu.org/copyleft/gpl.html
9 // @name Flickr More Search
10 // @namespace http://6v8.gamboni.org/
11 // @description Search all of your contacts for photos, and more...
14 // @creator Pierre Andrews (mortimer.pa@free.fr)
15 // @include http://*flickr.com*
16 // @exclude http://*flickr.com/photo_sendto_group.gne*
21 var win = (unsafeWindow || window.wrappedJSObject || window);
23 //======================================================================
25 var GROUPS = CONTACTS+1;
26 var FAMILY = GROUPS+1;
27 var FRIENDS = FAMILY+1;
28 var OTHER = FRIENDS+1;
31 var THUMBS = DETAILS+1;
32 //======================================================================
36 name: "Flickr More Search",
37 namespace: "http://6v8.gamboni.org/",
38 description: "Search for photos for all of your contacts, and more...",
39 source: "http://6v8.gamboni.org/Flickr-more-search.html", // script homepage/description URL
40 identifier: "http://6v8.gamboni.org/IMG/js/flickrmoresearch.user.js",
41 version: "0.8", // version
42 date: (new Date(2006, 6, 4)) // update date
46 //======================================================================
47 //to do the closure and get the right this.
48 //adapted from http://persistent.info/greasemonkey/gmail.user.js
50 function getObjectMethodClosure0(object, method, arg) {
52 return object[method](arg);
56 function getObjectMethodClosure(object, method) {
57 return function(arg) {
58 return object[method](arg);
62 function getObjectMethodClosure11(object, method,args3) {
63 return function(arg) {
64 return object[method](arg,args3);
68 function getObjectMethodClosure12(object, method,args3,arg4) {
69 return function(arg) {
70 return object[method](arg,args3,arg4);
75 function getObjectMethodClosure2(object, method) {
76 return function(arg,arg2) {
77 return object[method](arg,arg2);
82 if(unsafeWindow.console)
83 unsafeWindow.console.log(arguments);
89 //======================================================================
92 // http status constants
95 // xmlhttprequest readystate
100 win.FlickrMoreSearch = function() {this.init();}
102 win.FlickrMoreSearch.prototype = {
108 contactSearchResult: null,
110 groupSearchResult: null,
115 inAdvancedPage : false,
118 this.inSearchPage = (/^\/search\/?$/.test(document.location.pathname));
119 this.inGroupsPage = (/^\/search\/groups\/?$/.test(document.location.pathname));
120 this.userID = this.getUserID();
122 if((this.inSearchPage || this.inGroupsPage) &&
123 GM_getValue('alwaysthumb') &&
124 document.location.search &&
125 (document.location.search.indexOf("z=t") < 0) &&
126 (document.location.search.indexOf("tempdetails=t") < 0)) {
127 document.location = document.location+'&z=t';
130 if(this.inSearchPage) {
131 // if(matches = /[?&]q2=([^&]+)/.exec(document.location.search)) document.getElementById('standard_q').value = matches[1];
132 if(document.getElementById('standard_q').value) this.insertFeeds(OTHER);
134 var searchw = document.getElementById('searchw');
135 searchw.options[1].value = this.userID;
137 document.getElementById("mtext").disabled = false;
138 document.getElementById("mtags").disabled = false;
140 searchw.addEventListener('change',getObjectMethodClosure(this,"selectchanged"),false);
141 searchw.addEventListener('keyup',getObjectMethodClosure(this,"selectchanged"),false);
142 searchw.addEventListener('keydown',getObjectMethodClosure(this,"selectchanged"),false);
144 this.initContactSearch();
145 // this.initGroupSearch();
147 this.initHeaderSearch();
148 this.initAdvancedSearch();
149 this.initDefaultThumb();
152 initHeaderSearch: function() {
154 var loc = new String(document.location);
156 var searchbox = document.getElementById('headersearchform');
157 var method = document.createElement('input');
158 method.type = 'hidden';
160 searchbox.appendChild(method);
161 var thisthing = null;
164 //insert the select to choose from groups/people/photo search
165 var searchbutton = document.getElementById('headersearchbutton2');
166 var select = searchbox.insertBefore(document.createElement('select'),searchbutton);
167 select.innerHTML = '<option value="photos" selected="true">photos</option>\
168 <option value="discussions">discussions</option>\
169 <option value="groups">groups</option>\
170 <option value="people">people</option>';
171 select.addEventListener('change',function(event) {
172 if(select.value == 'photos') {
173 if(span) span.style.display = 'inline';
174 if(thisthing && thisthing.checked && searchbox.action == 'http://www.flickr.com/search/groups/') {
177 searchbox.action = 'http://www.flickr.com/search/';
178 } else if(select.value == 'discussions') {
179 if(span) span.style.display = 'inline';
180 searchbox.action = 'http://www.flickr.com/search/groups/';
181 method.value="discuss";
184 if(span) span.style.display = 'none';
185 searchbox.action = 'http://www.flickr.com/search/'+select.options[select.selectedIndex].value+'/';
191 if(matches = /^http:\/\/(www\.)?flickr.com\/(photos|people|groups)(\/[^\/]+\/?|_members.gne\?id=([^&]+))/.exec(loc)) {
193 // inserts the checkbox to search the curent group/user
194 searchbox.appendChild(document.createElement('br'));
195 span = document.createElement('span');
196 thisthing = span.appendChild(document.createElement('input'));
197 thisthing.name = 'w';
198 thisthing.value = this.userID;
199 thisthing.type = 'checkbox';
200 thisthing.id = 'thisthing';
201 thisthing.disabled = true;
202 var thisthinglabel = span.appendChild(document.createElement('label'));
203 thisthinglabel.htmlFor = "thisthing";
204 thisthinglabel.innerHTML = "search this ";
205 searchbox.appendChild(span);
207 if(matches[2] == 'photos' || matches[2] == 'people') {
208 if(matches[3].indexOf('/friends') < 0) {
209 thisthinglabel.innerHTML += ' user.';
212 flickr_urls_lookupUser_onLoad: function(success, responseXML, responseText, params){
214 var users = responseXML.documentElement.getElementsByTagName('user');
215 thisthing.value = users[0].getAttribute('id');
216 if(thisthing.value == self.userID) {
217 thisthinglabel.innerHTML = "Search your photos.";
219 thisthing.disabled = false;
224 unsafeWindow.F.API.callMethod('flickr.urls.lookupUser', {url:matches[0]}, listener);
226 thisthing.value = this.userID;
227 thisthinglabel.innerHTML = "Search your photos.";
228 thisthing.disabled = false;
230 } else { //if(matches[2] == 'groups') {
231 thisthinglabel.innerHTML += ' group.';
232 thisthing.addEventListener('click',function(){
233 if(method.value == 'pool') method.value = '';
234 else method.value = 'pool';
236 thisthing.disabled = false;
238 /*var title = document.evaluate("/html/body/div[@id='Main']/table[@id='SubNav']/tbody/tr/td[2]/h1|/html/body/div[@id='Main']/h1[@id='Tertiary']/a[2]",
239 document.body, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null
242 var titlehidden =span.appendChild(document.createElement('input'));
243 titlehidden.type = 'hidden';
244 titlehidden.name = 'group_title';
245 titlehidden.value=title.textContent.replace(/^\s+|\s+$/g,'');
248 thisthing.value = matches[4];
249 thisthing.form.action = "http://www.flickr.com/search/groups/";
252 flickr_urls_lookupGroup_onLoad: function(success, responseXML, responseText, params){
254 var groups = responseXML.documentElement.getElementsByTagName('group');
255 thisthing.value = groups[0].getAttribute('id');
256 thisthing.form.action = "http://www.flickr.com/search/groups/";
261 unsafeWindow.F.API.callMethod('flickr.urls.lookupGroup', {url:matches[0]}, listener);
267 initAdvancedSearch: function() {
268 this.inAdvancedPage = (/^\/search\/advanced\/?$/.test(document.location.pathname));
269 if(this.inAdvancedPage) {
270 document.forms[1].addEventListener('submit',getObjectMethodClosure(this,'processAdvancedFields'),true);
271 document.forms[1].action ='http://www.flickr.com/search/';
272 document.forms[1].method = 'get';
273 var trafter = document.evaluate("/html/body/div[@id='Main']/form/table/tbody/tr[4]",
274 document.body, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null
276 var newtr = trafter.parentNode.insertBefore(document.createElement('tr'),trafter);
277 newtr.innerHTML = '<td class="Tip">\
279 <small><i><b>Tip:</b> Use this option to look for photos in one of your contacts\' stream</i></small>\
282 <img id="searchscopebuddyicon" src="http://www.flickr.com/images/buddyicon.jpg?" width="24" height="24" alt=" Buddy Icon" align="absmiddle" style="display: none;" />\
283 <select name="w" id="searchw" class="Fixed">\
284 <option value="all" selected>Everyone\'s Photos</option>\
285 <option value="'+this.userID+'">Your Photos</option>\
286 <option value="load" id="searchwloading">Choose from your Contacts...</option>\
289 //add the listeners...
290 var searchw = document.getElementById('searchw');
292 searchw.addEventListener('change',getObjectMethodClosure(this,"selectchanged"),false);
293 searchw.addEventListener('keyup',getObjectMethodClosure(this,"selectchanged"),false);
294 searchw.addEventListener('keydown',getObjectMethodClosure(this,"selectchanged"),false);
296 var separator = trafter.parentNode.insertBefore(document.createElement('tr'),trafter);
297 separator.innerHTML = '<td colspan="4" valign="bottom"><p class="Separate"> </p></td>';
301 processAdvancedFields: function() {
303 //earch/?q=cern+-test&l=cc&d=taken-20050525-20060502
304 var mode = document.evaluate("/html/body/div[@id='Main']/form/table/tbody/tr//select[@name='date_mode']",
305 document.body, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null
306 ).singleNodeValue.value;
307 var afterdate = document.evaluate("/html/body/div[@id='Main']/form/table/tbody/tr//input[@name='date_lo']",
308 document.body, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null
309 ).singleNodeValue.value;
310 var beforedate = document.evaluate("/html/body/div[@id='Main']/form/table/tbody/tr//input[@name='date_hi']",
311 document.body, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null
312 ).singleNodeValue.value;
314 afterdate = afterdate.split('/');
315 var m_lo = ((afterdate[0] < 10)?'0':'')+afterdate[0];
316 var d_lo = ((afterdate[1] < 10)?'0':'')+afterdate[1];
317 afterdate = afterdate[2]+m_lo+d_lo;
320 beforedate = beforedate.split('/');
321 var m_hi = ((beforedate[0] < 10)?'0':'')+beforedate[0];
322 var d_hi = ((beforedate[1] < 10)?'0':'')+beforedate[1];
323 beforedate = beforedate[2]+m_hi+d_hi;
326 if(beforedate || afterdate) {
327 var datehidden = document.createElement('input');
328 datehidden.type = 'hidden';
329 datehidden.value = mode+'-'+afterdate+'-'+beforedate;
330 datehidden.name = 'd';
331 document.forms[1].appendChild(datehidden);
334 //Process the licence
335 var cc = document.getElementById('ccsearch').checked;
336 var comm = document.getElementById('cccommercial').checked;
337 var deriv = document.getElementById('ccderivs').checked;
341 if(deriv) l += 'deriv';
343 var lhidden = document.createElement('input');
344 lhidden.type = 'hidden';
347 document.forms[1].appendChild(lhidden);
351 initDefaultThumb: function() {
353 var alwaysthumb = GM_getValue('alwaysthumb');
356 var searchbox = document.createElement("input");
357 searchbox.id = "hidalwaysthumb";
358 searchbox.type = 'hidden';
360 searchbox.value = 't';
361 document.getElementById('headersearchform').appendChild(searchbox);
363 if(this.inSearchPage || this.inGroupsPage) {
364 var input = document.createElement("input");
365 input.id = "hidalwaysthumb";
366 input.type = 'hidden';
369 document.forms[1].appendChild(input);
370 var pages = document.evaluate("//div[@class='Paginator']/a",
371 document, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
373 for(var i = 0; i < pages.snapshotLength; i++) {
374 var al = pages.snapshotItem(i);
378 unsafeWindow.GoQ = function GoQ(elm){
380 var q = document.getElementById('standard_q');
382 url += '?q='+q.value+'&z=t';
390 if(this.inSearchPage || (this.inGroupsPage && (document.location.search.indexOf('m=pool') >= 0))) {
391 var d_switch = document.evaluate("/html/body/div[@id='Main']//div[@class='Switch']",
392 document.body, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null
395 d_switch.firstChild.href += "&tempdetails=t";
396 this.createAlwaysCheck(d_switch);
401 initContactSearch: function() {
402 var before = document.getElementById("searchwloading");
403 var select = before.parentNode.insertBefore(document.createElement('option'),before);
404 select.innerHTML = "All your contacts";
405 select.value = 'allcontacts';
406 var select = before.parentNode.insertBefore(document.createElement('option'),before);
407 select.innerHTML = "Your family";
408 select.value = 'allfamily';
409 var select = before.parentNode.insertBefore(document.createElement('option'),before);
410 select.innerHTML = "Your friends";
411 select.value = 'allfriends';
414 initGroupSearch: function() {
415 var before = document.getElementById("searchwloading");
416 var select = before.parentNode.insertBefore(document.createElement('option'),before);
417 select.innerHTML = 'Choose from your Groups...';
418 select.id = "searchgrouploading";
421 if(matches = /w=group_([^&]+)/.exec(document.location.search)) {
422 this.groupID = matches[1].replace(/%40/,'@');
424 select.selected = true;
425 this.selectRightGroup(this.groupID);
426 this.searchsubmitGroups();
430 getUserID: function() {
431 /* var scp = document.getElementsByTagName("script")[0].innerHTML;
432 var matches = /global_nsid = '(.*?)'/m.exec(scp);
435 return unsafeWindow.global_nsid;
438 selectchanged: function(event) {
439 var searchw = event.target;
443 var mtext = document.getElementById("mtext");
444 var mtags = document.getElementById("mtags");
447 if(searchw.value=="allcontacts") {
449 searchw.form.onsubmit = getObjectMethodClosure(this,"searchsubmitContacts");
450 if(mtext) mtext.disabled = true;
452 mtags.disabled = true;
453 mtags.checked = true;
455 url = 'http://www.flickr.com/images/buddyicon.jpg';
456 } else if(searchw.value=="allfriends") {
458 searchw.form.onsubmit = getObjectMethodClosure(this,"searchsubmitFriends");
459 if(mtext) mtext.disabled = true;
461 mtags.disabled = true;
462 mtags.checked = true;
464 url = 'http://www.flickr.com/images/buddyicon.jpg';
465 } else if(searchw.value=="allfamily") {
467 searchw.form.onsubmit = getObjectMethodClosure(this,"searchsubmitFamily");
469 if(mtext) mtext.disabled = true;
471 mtags.disabled = true;
472 mtags.checked = true;
474 url = 'http://www.flickr.com/images/buddyicon.jpg';
475 } else if(matches = /^group_(.*)$/.exec(searchw.value)) {
476 searchw.form.onsubmit = getObjectMethodClosure(this,"searchsubmitGroups");
478 if(mtext) mtext.disabled = true;
480 mtags.disabled = true;
481 mtags.checked = true;
483 this.groupID = matches[1];
484 url = 'http://www.flickr.com/images/buddyicon.jpg';
485 var iconserver = this.groupsXML..group.(@nsid == this.groupID).@iconserver;
487 url = 'http://static.flickr.com/'+iconserver+'/buddyicons/'+this.groupID+'.jpg?1';
489 } else if(searchw.options[searchw.selectedIndex].id == "searchgrouploading") {
491 if(mtext) mtext.disabled = true;
493 mtags.disabled = true;
494 mtags.checked = true;
496 url = 'http://www.flickr.com/images/pulser2.gif';
498 } else if(this.inAdvancedPage && searchw.options[searchw.selectedIndex].id == "searchwloading") {
499 url = 'http://www.flickr.com/images/pulser2.gif';
501 searchw.options[searchw.selectedIndex].text = '-- Loading... --';
503 } else if(this.inAdvancedPage && searchw.value != 'all' && searchw.value != 'me') {
504 url = this.getContactLogo(searchw.value);
506 url = "http://www.flickr.com/images/buddyicon.jpg";
507 var server = this.contactsXML..contact.(@nsid == searchw.value).@iconserver;
509 url = "http://static.flickr.com/"+server+"/buddyicons/"+searchw.value+".jpg";
512 if(mtext) mtext.disabled = false;
513 if(mtags) mtags.disabled = false;
516 searchw.form.onsubmit = '';
518 this.changeIcon(url);
521 changeIcon: function(url) {
522 var icn = document.getElementById('searchscopebuddyicon');
526 icn.addEventListener('load',function(){ this.style.display = 'inline'; },true);
529 icn.style.display = 'none';
533 //======================================================================
535 getContacts: function() {
536 if(!this.contactList) {
539 onload : getObjectMethodClosure(this,"process_contactsID"),
540 url : "http://www.flickr.com/services/rest/?method=flickr.contacts.getPublicList&api_key=e8c3239ff04c102ce2d6ed885bf99005&user_id="+this.userID,
544 GM_xmlhttpRequest( details );*/
546 //Trick to do it using the flickr API with authentication already embeded in the page.
549 flickr_contacts_getList_onLoad: function(success, responseXML, responseText, params){
550 self.process_contactsID(responseText);
554 unsafeWindow.F.API.callMethod('flickr.contacts.getList', {}, listener);
559 process_contactsID: function(req) {
561 var rsp = req.replace(/<\?xml.*\?>/,'');
565 this.error( "Could not understand Flickr's response.", 0, req);
567 var stat = rsp.@stat;
569 this.error( "Could not find status of Flickr request", 0, req);
570 } else if (stat != 'ok') {
571 if (stat == 'fail') {
572 var err_node = rsp.err[0];
573 var code = err_node.@code;
574 var err_msg = err_node.@msg;
575 this.error( err_msg, code, req,li);
577 this.error("Unknown error status: '" + stat + "'", 0, req)
580 var contacts = new Array();
581 var family = new Array();
582 var friends = new Array();
584 this.contactsXML = rsp;
585 if(this.inAdvancedPage) searchw = document.getElementById('searchw');
586 for each(contact in rsp..contact) {
587 contacts.push(contact.@nsid);
588 if(this.inAdvancedPage) {
589 var option = searchw.appendChild(document.createElement('option'));
590 option.innerHTML = contact.@username;
591 option.value = contact.@nsid;
592 option.id = 'contact_'+contact.@nsid;
594 if(contact.@family == '1') family.push(contact.@nsid);
595 if(contact.@friend == '1') friends.push(contact.@nsid);
597 if(this.inAdvancedPage) {
598 var searchwloading = document.getElementById('searchwloading');
599 searchwloading.text = '-- Select a contact --';
602 this.contactList = contacts.join(',');
603 this.familyList = family.join(',');
604 this.friendsList = friends.join(',');
609 searchsubmitContacts: function() {
610 this.insertFeeds(CONTACTS);
611 this.wait("Searching in the last photos of your contacts...");
612 if(this.contactList) {
613 this.searchPhotosContacts(this.contactList);
615 this.waitForContactList(0,this.contactList);
620 searchsubmitFamily: function() {
621 this.insertFeeds(FAMILY);
622 this.wait("Searching in the last photos of your family...");
623 if(this.contactList) {
624 this.searchPhotosContacts(this.familyList);
626 this.waitForContactList(0,this.familyList);
631 searchsubmitFriends: function() {
632 this.insertFeeds(FRIENDS);
633 this.wait("Searching in the last photos of your friends...");
634 if(this.contactList) {
635 this.searchPhotosContacts(this.friendsList);
637 this.waitForContactList(0,this.friendsList);
642 waitForContactList: function(cnt,list) {
643 if(this.contactList) {
644 this.searchPhotosContacts(list);
645 } else if(cnt < 30) {
646 setTimeout(getObjectMethodClosure12(this,"waitForContactList",cnt++,list),1000);
650 searchPhotosContacts: function(list) {
651 //we query the rss feed as there are no handy method to search more than one user for tags.
652 var url = "http://www.flickr.com/services/feeds/photos_public.gne?format=json&ids="+list+"&tags="+encodeURIComponent(document.getElementById("standard_q").value);
655 onload : getObjectMethodClosure11(this,"displayResultsContacts",false),
659 GM_xmlhttpRequest( details );
662 displayResultsContacts: function(req,forceThumb) {
664 // M8_log(req.responseText);
668 rsp = req.responseText;
669 rsp = rsp.substr(15);
671 this.contactSearchResult = rsp;
673 rsp = this.contactSearchResult;
677 this.error( "Could not understand answer.", 0, req,li);
680 var months = new Array('January','February','March','April','May','June','July','August','September','October','November','December');
682 if(forceThumb == THUMBS) thumbs = true;
683 else if(forceThumb == DETAILS) thumbs = false;
684 else thumbs = (document.location.search.indexOf('z=t') >= 0) || GM_getValue('alwaysthumb');
686 var results = this.createResultContainer(CONTACTS,thumbs?THUMBS:DETAILS);
688 this.buildResultSet(CONTACTS,rsp.items.length,getObjectMethodClosure2(this,'displayResultsContacts'),thumbs,results);
692 var re = /href="(http:\/\/www.flickr.com\/people\/(.*?)\/)".*img src="(http:\/\/static\.flickr\.com\/.*?)" width="([0-9]+)" height="([0-9]+)"/;
693 for each(entry in rsp.items) {
694 var desc = entry.description;
695 var matches = re.exec(desc);
697 var user_profile = '';
702 var authorName = entry.author.replace(/nobody@flickr\.com \((.+?)\)$/,'$1');
704 user_profile = matches[1];
709 logo = this.getContactLogo(authorName);
713 src = src.replace(/_m/,"_t");
715 var date = entry.published.substr(0,10).split('-');
716 var longdate = date[2]+' '+months[parseInt(date[1])-1]+' '+date[0];
717 var urldate = date[0]+'/'+date[1]+'/'+date[2]+'/';
718 html += this.generateSearchLine(entry.title,
729 entry.tags.split(' ' ),
732 results.innerHTML = html;
734 var br = results.parentNode.appendChild(document.createElement('br'));
742 getContactLogo: function(uname) {
743 var server = this.contactsXML..contact.(@username == uname);
744 var nsid = server.@nsid;
745 server = server.@iconserver;
747 return "http://static.flickr.com/"+server+"/buddyicons/"+nsid+".jpg";
749 return "http://www.flickr.com/images/buddyicon.jpg";
752 //======================================================================
754 getGroups: function() {
755 if(!this.contactList) {
756 var select = document.getElementById('searchgrouploading');
757 select.innerHTML = '-- Loading... --';
760 onload : getObjectMethodClosure(this,"process_groupsID"),
761 url : "http://www.flickr.com/services/rest/?method=flickr.people.getPublicGroups&api_key=e8c3239ff04c102ce2d6ed885bf99005&user_id="+this.userID,
765 GM_xmlhttpRequest( details );*/
768 flickr_groups_pools_getGroups_onLoad: function(success, responseXML, responseText, params){
769 self.process_groupsID(responseText);
773 unsafeWindow.F.API.callMethod('flickr.groups.pools.getGroups', {}, listener);
777 process_groupsID: function(req) {
779 var rsp = req.replace(/<\?xml.*\?>/,'');
783 this.error( "Could not understand Flickr's response.", 0, req);
785 var stat = rsp.@stat;
787 this.error( "Could not find status of Flickr request", 0, req);
788 } else if (stat != 'ok') {
789 if (stat == 'fail') {
790 var err_node = rsp.err[0];
791 var code = err_node.@code;
792 var err_msg = err_node.@msg;
793 this.error( err_msg, code, req,li);
795 this.error("Unknown error status: '" + stat + "'", 0, req)
798 var searchw = document.getElementById("searchw");
799 var before = document.getElementById("searchwloading");
800 var select = document.getElementById('searchgrouploading');
802 select.innerHTML = '-- Select a group --';
803 for each(group in rsp..group) {
804 select = searchw.insertBefore(document.createElement('option'),before);
805 select.innerHTML = group.@name;
806 select.value = 'group_'+group.@nsid;
807 select.id = 'group_'+group.@nsid;
809 select = searchw.insertBefore(document.createElement('option'),before);
810 select.innerHTML = '----';
811 this.groupsXML = rsp;
816 searchsubmitGroups: function() {
817 this.searchGroups(1);
821 searchGroups: function(page) {
823 var groupTitle = this.groupsXML..group.(@nsid == this.groupID);
824 this.wait("Searching in the group "+groupTitle.@name);
825 } else this.wait("Searching in the group");
827 /*var url ="http://www.flickr.com/services/rest/?method=flickr.groups.pools.getPhotos&api_key=e8c3239ff04c102ce2d6ed885bf99005&per_page=24&extras=date_upload,icon_server&group_id="+this.groupID+"&tags="+encodeURIComponent(document.getElementById("standard_q").value)+"&page="+page;
830 onload : getObjectMethodClosure11(this,"displayResultsGroups",false),
834 GM_xmlhttpRequest( details );*/
837 flickr_groups_pools_getPhotos_onLoad: function(success, responseXML, responseText, params){
838 self.displayResultsGroups(responseText,false);
842 unsafeWindow.F.API.callMethod('flickr.groups.pools.getPhotos', {
844 extras: 'date_upload,icon_server',
846 tags: document.getElementById("standard_q").value,
847 group_id: this.groupID
851 displayResultsGroups: function(req,forceThumb) {
857 rsp = req.replace(/<\?xml.*\?>/,'');
859 this.groupSearchResult = rsp;
861 rsp = this.groupSearchResult;
865 this.error( "Could not understand answer.", 0, req,li);
868 if(rsp.@stat == 'ok') {
869 var months = new Array('January','February','March','April','May','June','July','August','September','October','November','December');
872 if(forceThumb == THUMBS) thumbs = true;
873 else if(forceThumb == DETAILS) thumbs = false;
874 else thumbs = (document.location.search.indexOf('z=t') >= 0) || GM_getValue('alwaysthumb');
876 var results = this.createResultContainer(GROUPS,thumbs?THUMBS:DETAILS);
879 if(forceThumb == THUMBS) thumbs = true;
880 else if(forceThumb == DETAILS) thumbs = false;
881 else thumbs = (document.location.search.indexOf('z=t') >= 0) || GM_getValue('alwaysthumb');
883 this.buildResultSet(GROUPS,rsp.photos.@total,getObjectMethodClosure2(this,'displayResultsGroups'),thumbs,results);
886 for each(photo in rsp..photo) {
888 var src = "http://static.flickr.com/"+photo.@server+"/"+photo.@id+"_"+photo.@secret;
889 if(thumbs) src += "_t.jpg";
891 var url_id = photo.@owner;
892 var user_profile = '/people/'+url_id;
893 var authorName = photo.@ownername;
894 var date = new Date(photo.@dateupload*1000);
895 date_url = date.getFullYear()+"/"+date.getMonth()+"/"+date.getDay();
896 date = date.getDay()+" "+months[date.getMonth()]+" "+date.getFullYear();
897 var logo = "http://www.flickr.com/images/buddyicon.jpg";
898 if(photo.@iconserver>0) {
899 logo= "http://static.flickr.com/"+photo.@iconserver+"/buddyicons/"+photo.@owner+".jpg";
901 //var longdate = date[2]+' '+months[parseInt(date[1])-1]+' '+date[0];
902 //var urldate = date[0]+'/'+date[1]+'/'+date[2]+'/';
903 html += this.generateSearchLine(photo.@title,
907 "/photos/"+url_id+"/"+photo.@id,
917 results.innerHTML = html;
919 var br = results.parentNode.appendChild(document.createElement('br'));
922 if(rsp.photos.@pages > 1) results.parentNode.appendChild(this.paginate(rsp.photos.@page,rsp.photos.@pages,rsp.photos.@total,'searchGroups'));
924 } else if(rsp.@stat == 'fail') {
925 this.error(rsp.err.@msg,rsp.err.@code,req);
927 this.error("unknown error with group search",0,req);
932 selectRightGroup: function(id) {
933 var searchw = document.getElementById('group_'+id);
934 if(searchw) searchw.selected = true;
937 if(matches = /[&?]group_title=([^&]+)/.exec(document.location.search)) {
938 searchw = document.getElementById('searchw').appendChild(document.createElement('option'));
939 searchw.innerHTML = matches[1];
941 searchw.name = 'group_'+id;
942 searchw.id = 'group_'+id;
943 searchw.selected = true;
945 setTimeout(getObjectMethodClosure0(this,'selectRightGroup',id),true);
950 //======================================================================
952 buildResultSet: function(type,total,callback,thumbs,results) {
953 var found = document.getElementById('ResultSetFound');
957 var set = results.parentNode.insertBefore(document.createElement('div'),results);
958 set.className = "ResultSet";
959 var div = set.appendChild(document.createElement('div'));
960 div.className = 'Switch';
961 link = div.appendChild(document.createElement('a'));
963 link.href="javascript:;";
964 this.createAlwaysCheck(div);
966 found = set.appendChild(document.createElement('div'));
968 if(!link) link = document.getElementById('switcha');
969 if(thumbs) link.innerHTML = "Show details";
970 else link.innerHTML = "Show Thumbnails";
972 link.addEventListener('click',function() {callback(null,thumbs?DETAILS:THUMBS);},true);
974 if(total < 1) link.style.display = 'none';
976 found.id = "ResultSetFound";
978 found.className = 'Found';
979 var html = 'We found '+total+' photos about <span class="queryterm">'+document.getElementById('standard_q').value+'</span>';
982 var groupTitle = this.groupsXML..group.(@nsid == this.groupID);
983 html +=" in the pool of "+groupTitle.@name;
985 } else if(type == CONTACTS) {
986 html +=" in your contacts' photos";
988 html += '.<div class="SortOptions"> </div>';
989 found.innerHTML = html;
991 found.className = 'NoneFound';
992 var html = 'We cannot find any results matching your request.';
995 var groupTitle = this.groupsXML..group.(@nsid == this.groupID);
996 html +=" in the group "+groupTitle.@name+" pool";
998 } else if(type == CONTACTS) {
999 html +=" in your contacts' photos";
1001 html += '<div class="SortOptions"> </div><p>We give up!</p>';
1002 found.innerHTML = found;
1004 return found.parentNode;
1007 generateSearchLine: function(title,src,width,height,url,user_url,user_logo,user_name,user_profile,date,longdate,tags,thumbs) {
1010 var toreturn = '<tr valign="top">\
1011 <td class="DetailPic">\
1012 <a href="'+url+'" title="'+title+'"><img src="'+src+'" width="'+width+'" height="'+height+'" alt="'+title+'" /></a>\
1014 <td class="PicDesc">\
1017 <small>Uploaded on <a href="'+user_url+'/archives/date-posted/'+date+'" style="text-decoration: none;">'+longdate+'</a></small>\
1019 <p class="PicFrom">\
1020 <a href="'+user_url+'"><img src="'+user_logo+'" width="48" height="48" alt="Click '+user_name+'\' Buddy Icon to see more photos" /></a>\
1021 By <b><a href="'+user_url+'" style="text-decoration: none;">'+user_name+'</a></b><br />\
1022 <span style="font-size: 12px;">See <a href="'+user_url+'" style="text-decoration: none;">more photos</a>, or visit his <a style="text-decoration: none;" href="'+user_profile+'">profile</a>.</span>\
1024 <p class="ListTags">';
1026 toreturn += '<img src="/images/icon_tag.gif" alt="Tagged with..." width="16" height="16" align="absmiddle" style="border: none;" />';
1028 for each(tag in tags) {
1029 if(cnt++ > 3) break;
1030 toreturn += this.tagLine(tag);
1032 if(cnt > 3) toreturn += "...</p>";
1034 toreturn += "</td></tr>";
1036 var toreturn = '<div>\
1037 <a title="'+title+' by '+user_name+'" href="'+url+'">\
1038 <img src="'+src+'"/>\
1041 <a href="'+user_url+'">'+user_name+'</a>\
1048 createResultContainer: function(type,dispType) {
1050 var pages = document.evaluate("//div[@class='Pages']",
1051 document.body, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null
1053 if(pages) pages.parentNode.removeChild(pages);
1054 var rs = document.evaluate("//div[@class='ResultSet']",
1055 document.body, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null
1057 if(rs) rs.parentNode.removeChild(rs);
1058 rs = document.evaluate("//div[@class='ResultsThumbs']",
1059 document.body, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null
1061 if(rs) rs.parentNode.removeChild(rs);
1063 if(type == GROUPS) {
1064 rs = document.getElementById('Feeds');
1065 if(rs) rs.parentNode.removeChild(rs);
1069 if(dispType == DETAILS) {
1070 results = document.evaluate("/html/body/div[@id='Main']/table",
1071 document.body, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null
1073 if(results) results.id = "ResultsTable";
1074 var tab = document.getElementById('ResultsDiv');
1075 if(tab) tab.style.display = 'none';
1076 } else if(dispType == THUMBS) {
1077 results = document.evaluate("/html/body/div[@id='Main']//div[@class='ResultsThumbs']",
1078 document.body, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null
1080 if(results) results.id = "ResultsDiv";
1081 var tab = document.getElementById('ResultsTable');
1082 if(tab) tab.style.display = 'none';
1086 if(dispType == THUMBS) {
1087 results = document.createElement("div");
1088 results.className = "ResultsThumbs";
1089 results.id = "ResultsDiv";
1091 results = document.createElement("table");
1092 results.cellspacing="0";
1093 results.className="DetailResults";
1094 results.id = "ResultsTable";
1096 var insertAfter = document.getElementById('searchwaitdiv');
1097 if(!insertAfter) insertAfter = document.forms[1];
1098 insertAfter.parentNode.insertBefore(results,insertAfter.nextSibling);
1100 results.style.display = '';
1104 paginate: function(page,number,total,callback) {
1105 page = parseInt(page);
1106 number = parseInt(number);
1107 total = parseInt(total);
1108 var pagesD = document.evaluate("//div[@class='Paginator']",
1109 document.body, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null
1113 pagesA = document.createElement('div');
1114 pagesA.className = "Pages";
1115 var pagesD = pagesA.appendChild(document.createElement('div'));
1116 pagesD.className = "Paginator";
1118 pagesA = pagesD.parentNode;
1119 pagesD.innerHTML = '';
1120 pagesA.removeChild(pagesD.nextSibling);
1124 var span = pagesD.appendChild(document.createElement('span'));
1125 span.className = "AtStart";
1126 span.innerHTML = '< Prev';
1128 var a = pagesD.appendChild(document.createElement('a'));
1129 a.innerHTML = "< Prev";
1130 a.className = "Prev";
1131 a.href="javascript:;";
1133 a.addEventListener("click",getObjectMethodClosure0(this,callback,page-1),true);
1137 if(start < 7) start = 1;
1139 var span = pagesD.appendChild(document.createElement('span'));
1140 span.className = "break";
1141 span.innerHTML = '...';
1146 for(var i=start;i<=stop && i <= number;i++) {
1148 var span = pagesD.appendChild(document.createElement('span'));
1149 span.className = "this-page";
1150 span.innerHTML = page;
1152 var a =pagesD.appendChild(document.createElement('a'));
1154 a.href="javascript:;";
1157 a.addEventListener("click",getObjectMethodClosure0(this,callback,i),true);
1160 if(number-start > 10) {
1161 var span = pagesD.appendChild(document.createElement('span'));
1162 span.className = "break";
1163 span.innerHTML = '...';
1166 var a = document.createElement('A');
1167 pagesD.appendChild(a);
1168 a.innerHTML = "Next >";
1169 a.className = "Next";
1170 a.href="javascript:;";
1172 a.addEventListener("click",getObjectMethodClosure0(this,callback,page+1),true);
1174 var rstot = pagesA.appendChild(document.createElement('div'));
1175 rstot.className = "Results";
1176 rstot.innerHTML = '('+total+' photos, '+number+' pages)';
1180 error: function(msg,code,req) {
1184 tagLine: function(tag) {
1185 return '<a href="/photos/tags/'+tag+'/clusters/">'+tag+'</a>, ';
1188 insertFeeds: function(type) {
1189 var feeds = document.getElementById('Feeds');
1190 if(!feeds ) feeds = document.getElementById('Main').appendChild(document.createElement('div'));
1192 var feedurl = "/services/feeds/photos_public.gne?format=rss_200";
1194 if(type == CONTACTS) {
1195 feedurl += "&ids="+this.contactList;
1196 title = "– Subscribe to your contacts' photos tagged "+document.getElementById("standard_q").value;
1197 } else if(type == FAMILY) {
1198 feedurl += "&ids="+this.familyList;
1199 title = "– Subscribe to your family's photos tagged "+document.getElementById("standard_q").value;
1200 } else if(type == FRIENDS) {
1201 feedurl += "&ids="+this.friendsList;
1202 title = "– Subscribe to your friends' photos tagged "+document.getElementById("standard_q").value;
1204 if(document.location.search.indexOf('w=me') >= 0) {
1205 feedurl += "&id="+this.userID;
1206 title = "– Subscribe to your photos tagged "+document.getElementById("standard_q").defaultValue;
1207 } else if(document.location.search.indexOf('w=all') < 0) {
1208 feedurl += "&id="+document.getElementById('searchw').value;
1209 var matches = /^Flickr: Search (.*) photos$/.exec(document.title);
1210 if(matches) title = "– Subscribe to "+matches[1]+" photos tagged "+document.getElementById("standard_q").value;
1212 title = "– Subscribe to public photos tagged "+document.getElementById("standard_q").value;
1215 feedurl += "&tags="+encodeURIComponent(document.getElementById("standard_q").value);
1216 feeds.innerHTML = '<div id="AtomRSS">\
1217 <a title="RSS 2.0 feed" href="'+feedurl+'">\
1218 <img width="16" height="16" align="absmiddle" alt="Subscribe to a feed of stuff on this page..." src="/images/feed-icon-16x16.png"/>\
1220 <a title="RSS 2.0 feed" href="'+feedurl+'">Feed</a>'+title+
1222 <div id="AddToYahoo">\
1223 <a href="http://us.rd.yahoo.com/my/atm/Flickr/Users/*http://add.my.yahoo.com/rss?url=http%3A%2F%2Fwww.flickr.com%2F'+encodeURIComponent(feedurl)+'"> \
1224 <img width="62" height="17" alt="Add to My Yahoo!" src="/images/addtomyyahoo6.gif"/>\
1229 createAlwaysCheck: function(parent) {
1231 parent.appendChild(document.createElement('br'));
1232 var check = document.createElement('input');
1233 check.type = "checkbox";
1234 check.checked = GM_getValue('alwaysthumb');
1235 check.id = 'alwaysthumb';
1236 check.addEventListener('change',function(event) {
1237 GM_setValue('alwaysthumb',check.checked);
1239 var input = document.forms[1].appendChild(document.createElement("input"));
1240 input.id = "hidalwaysthumb";
1241 input.type = 'hidden';
1244 var pages = document.evaluate(" //div[@class='Paginator']/a",
1245 document, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
1247 for(var i = 0; i < pages.snapshotLength; i++) {
1248 var al = pages.snapshotItem(i);
1252 var hide = document.getElementById("hidalwaysthumb");
1253 hide.parentNode.removeChild(hide);
1256 parent.appendChild(check);
1257 parent.appendChild(document.createTextNode("Always show thumbnails"));
1260 wait: function(message) {
1261 var wait = document.getElementById('searchwaitdiv');
1264 wait.innerHTML = '<img src="http://www.flickr.com/images/pulser2.gif" style="vertical-align:middle;margin-right:4px;border:0px #ffffff" />'+message;
1266 wait.style.display = 'none';
1268 } else if(message) {
1269 wait = document.forms[1].parentNode.insertBefore(document.createElement('div'),document.forms[1].nextSibling);
1270 wait.innerHTML = '<img src="http://www.flickr.com/images/pulser2.gif" style="vertical-align:middle;margin-right:4px;border:0px #ffffff" />'+message;
1271 wait.id = 'searchwaitdiv';
1272 wait.style.textAlign = "center";
1278 //======================================================================
1281 window.addEventListener("load", function () {
1284 // update automatically (http://userscripts.org/scripts/show/2296)
1285 win.UserScriptUpdates.requestAutomaticUpdates(SCRIPT);
1288 var flickrgp = new win.FlickrMoreSearch();