2 // @name Flickr Upcoming Event
3 // @namespace http://6v8.gamboni.org/
4 // @description This is a greasemonkey script to enhance flickr pages and be able to easilly associate photos with an upcoming event. When a shot is associated to an event, it can then be tagged and located from the data provided by the event.
6 // @identifier http://6v8.gamboni.org/IMG/js/flickrupcomingevent.user.js
8 // @creator Pierre Andrews (mortimer.pa@free.fr) , pt translation by Perla* <http://www.flickr.com/photos/bobnperla/>
9 // @include http://*flickr.com/photos/*/*
10 // @exclude http://*flickr.com/photos/organize*
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
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.
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.
35 // The GNU General Public License is available by visiting
36 // http://www.gnu.org/copyleft/gpl.html
38 // Free Software Foundation, Inc.
39 // 51 Franklin Street, Fifth Floor
40 // Boston, MA 02110-1301
44 var UPCOMING_API_URL
= 'http://upcoming.yahooapis.com/services/rest/';
51 name
: "Flickr Upcoming Event",
52 namespace: "http://6v8.gamboni.org/",
53 description
: "This is a greasemonkey script to enhance flickr pages and be able to easilly associate photos with an upcoming event. When a shot is associated to an event, it can then be tagged and located from the data provided by the event.",
54 identifier
: "http://6v8.gamboni.org/IMG/js/flickrupcomingevent.user.js",
55 version
: "0.7", // version
56 date
: (new Date("2007-06-28")) // update date
61 Path to wrap descriptions by Johan Sundstr�m
62 http://www.lysator.liu.se/~jhs/
64 function wbr( html
) {
65 return (''+html
).replace( /[-\/_.]|\w{20}/g,
66 function( c
){ return c
+'<wbr/>'; } );
70 if(unsafeWindow
.console
)
71 unsafeWindow
.console
.log(arguments
);
76 function getObjectMethodClosure01(object
, method
,arg1
) {
77 return function(arg
) {
78 return object
[method
](arg1
);
83 function getObjectMethodClosure03(object
, method
,arg1
,arg2
,arg3
) {
84 return function(arg
) {
85 return object
[method
](arg1
,arg2
,arg3
);
89 function getObjectMethodClosure11(object
, method
,arg1
) {
90 return function(arg
) {
91 return object
[method
](arg
,arg1
);
94 function getObjectMethodClosure12(object
, method
,arg1
,arg2
) {
95 return function(arg
) {
96 return object
[method
](arg
,arg1
,arg2
);
99 function getObjectMethodClosure13(object
, method
,arg1
,arg2
,arg3
) {
100 return function(arg
) {
101 return object
[method
](arg
,arg1
,arg2
,arg3
);
105 function $x1(xpath
) {
106 return document
.evaluate(
110 XPathResult
.FIRST_ORDERED_NODE_TYPE
, null
115 /***********************************************************************
116 * Flickr Localisation
117 **********************************************************************/
119 var FlickrLocaliser = function(locals
) {
122 FlickrLocaliser
.prototype = {
123 selectedLang
: undefined,
124 localisations
: undefined,
125 getLanguage: function() {
126 if(!this.selectedLang
) {
127 var langA
= $x1("//p[@class='LanguageSelector']//a[contains(@class,'selected')]");
129 var matches
= /\/change_language.gne\?lang=([^&]+)&.*/.exec(langA
.href
);
130 if(matches
&& matches
[1]) {
131 this.selectedLang
= matches
[1];
132 return this.selectedLang
;
136 } else return this.selectedLang
;
139 init: function(locals
) {
140 this.localisations
= locals
;
143 localise: function(string
, params
) {
144 if(this.localisations
&& this.getLanguage()) {
145 var currentLang
= this.localisations
[this.selectedLang
];
146 if(!currentLang
) currentLang
= this.localisations
[this.localisations
.defaultLang
];
147 var local
= currentLang
[string
];
149 local
= this.localisations
[this.localisations
.defaultLang
][string
];
151 if(!local
) return string
;
153 var rep
= new RegExp('@'+arg
+'@','g');
154 local
= local
.replace(rep
,params
[arg
]);
156 local
=local
.replace(/@[^@]+@/g,'');
158 } else return undefined;
163 /*****************************Flickr Localisation**********************/
166 var flickrupcomingevent = function() {this.init();}
168 flickrupcomingevent
.prototype = {
169 UPCOMING_API_KEY
: '684909d568',
172 upcoming_token
: GM_getValue('upcoming_token'),
173 upcoming_user_name
: GM_getValue('upcoming_user_name'),
174 upcoming_user_username
: GM_getValue('upcoming_user_username'),
175 upcoming_user_id
: GM_getValue('upcoming_user_id'),
179 localiser
: new FlickrLocaliser({
181 'script_title' : 'Upcoming.org event tool',
182 'auth_1' : 'You first have to authorize the connection with upcoming. First go ',
183 'auth_2' : 'When you are done, come back to this page and',
184 'auth_3' : 'Enter the frob given by upcoming here',
185 'finish_auth' : 'Finish authorization',
186 'loading_details' : 'Getting event details',
187 'fetch_events' : 'Fetching events',
190 'searching' : 'searching',
192 'description' : 'Description',
193 'see_other' : '<b>See other photos</b> from this event by: @this_user@, @everyone@',
194 'this_user' : 'This User',
195 'everyone' : 'Everyone',
196 'geotag' : 'geotag this photo',
198 'select_event' : 'Select the event this photo was taken at',
199 'error' : 'There was an error, please see the console for details.'
205 'auth_1' : 'Vous devez d\'abord autoriser la connection avec upcoming.org. Commencez par',
206 'auth_2' : 'Quand vous avez fini, revenez sur cette page et',
207 'auth_3' : 'Entrez le frob donné par upcoming.org ici',
209 'description' : 'Description',
211 'error' : 'Il y a eu une erreur, veillez consulter les logs pour plus de détails.',
212 'event' : 'Évènement',
213 'everyone' : 'Tous le monde',
215 'fetch_events' : 'Récupération des évènements',
216 'finish_auth' : 'Finir l\'autorisation',
218 'geotag' : 'Geotagger cette photo',
220 'loading_details' : 'Récupération des détails de l\'évènement',
224 'script_title' : 'Outil des évènements Upcoming.org',
225 'searching' : 'En Recherche',
226 'see_other' : '<b>Voir les autres photos</b> de cet évènement par: @this_user@, @everyone@',
227 'select_event' : 'Sélectionner l\'évènement auquel la photo a été prise',
229 'this_user' : 'Cet Utilisateur',
234 'Tag' : 'Rótulo',
236 'auth_1' : 'Primeiro você tem que autorizar a conexão com o "upcoming". Primeiro vá',
237 'auth_2' : 'Quando terminar, volte para esta página e',
238 'auth_3' : 'Digite aqui o "frob" dado pelo "upcoming"',
240 'description' : 'Descrição',
242 'error' : 'Houve um erro, por favor veja o console para detalhes',
244 'everyone' : 'Todas as pessoas',
246 'fetch_events' : 'Procurando eventos',
247 'finish_auth' : 'Fim da Autorização',
249 'geotag' : '"geotag" esta foto',
251 'loading_details' : 'Pegando detalhes do evento',
255 'script_title' : 'Ferramenta do evento "Upcoming.org"',
256 'searching' : 'Buscando',
257 'see_other' : '<b>Veja outras fotos</b> deste evento feitas por: @this_user@, @everyone@',
258 'select_event' : 'Selecione o evento onde esta foto foi tirada',
260 'this_user' : 'Este usuário',
270 if(unsafeWindow
.page_photo_id
) {
271 var privacy_and_upcoming
= document
.evaluate(
272 "//p[@class='Privacy']",
273 document
, null, XPathResult
.FIRST_ORDERED_NODE_TYPE
, null
277 var links
= privacy_and_upcoming
.getElementsByTagName('a');
278 if(links
.length
> 0) {
279 for(var i
= 0; i
< links
.length
; i
++) {
282 if(matches
= /http:\/\/upcoming.org\/event\/([0-9]+)/.exec(link
.href
)) {
284 this.event_id
= matches
[1];
288 link
.parentNode
.appendChild(document
.createElement('br'));
289 div
= link
.parentNode
.appendChild(document
.createElement('div'));
291 privacy_and_upcoming
.appendChild(document
.createElement('br'));
292 div
= privacy_and_upcoming
.appendChild(document
.createElement('div'));
294 if(!this.upcoming_token
) {
295 var img
= div
.appendChild(document
.createElement('img'));
297 img
.alt
=this.localiser
.localiser("script_title");
298 img
.src
="/images/icon_upcoming_over.gif";
299 div
.appendChild(document
.createTextNode(this.localiser
.localise('auth_1')));
300 var a
= div
.appendChild(document
.createElement('a'));
301 a
.innerHTML
= 'here';
303 a
.href
= 'http://upcoming.org/services/auth/?api_key='+this.UPCOMING_API_KEY
;
304 div
.appendChild(document
.createTextNode('. '+this.localiser
.localise('auth_2')+':'));
305 div
.appendChild(document
.createElement('br'));
306 var label
= div
.appendChild(document
.createElement('label'));
307 label
.htmlFor
= 'upcoming_frob';
308 label
.innerHTML
= this.localiser
.localise('auth_3');
309 var input
= div
.appendChild(document
.createElement('input'));
310 input
.id
= 'upcoming_frob';
311 var button
= document
.createElement('button');
312 button
.type
= 'button';
313 button
.innerHTML
= this.localiser
.localise('finish_auth');
314 button
.addEventListener('click',getObjectMethodClosure01(this,'finishAuth',input
),true);
315 button
.className
= 'SmallButt';
316 div
.appendChild(button
);
318 this.upcomingAuthenticated(div
);
323 finishAuth: function(input
) {
324 this.makeUpcomingCall('auth.getToken',{frob
: input
.value
},getObjectMethodClosure11(this,'authDone',input
.parentNode
),getObjectMethodClosure11(this,'authError',input
.parentNode
));
327 authDone: function(rsp
,div
) {
328 this.upcoming_token
= ''+rsp
.token
.@token
;
329 this.upcoming_user_username
= ''+rsp
.token
.@user_username
;
330 this.upcoming_user_name
= ''+rsp
.token
.@user_name
;
331 this.upcoming_user_id
= ''+rsp
.token
.@user_id
;
333 GM_setValue('upcoming_token',this.upcoming_token
);
334 GM_setValue('upcoming_user_username',this.upcoming_user_username
);
335 GM_setValue('upcoming_user_name',this.upcoming_user_name
);
336 GM_setValue('upcoming_user_id',this.upcoming_user_id
);
338 this.upcomingAuthenticated(div
);
341 authError: function(msg
,div
) {
342 GM_setValue('upcoming_token','');
345 upcomingAuthenticated: function(div
) {
347 for each(tag
in unsafeWindow
.global_photos
[unsafeWindow
.page_photo_id
].tags_rawA
) {
348 if(tag
.indexOf('upcoming:') >= 0) {
350 this.event_id
= tag
.replace('upcoming:','').replace(':','=');
354 var tagger
= document
.getElementById('tagadder');
359 div
.innerHTML
= '<img id="flickrphotocompass_wait" src="http://www.flickr.com/images/pulser2.gif" style="margin:0;padding:0;margin-right:4px;border:0px #ffffff;height: 16px;" /> '+this.localiser
.localise('loading_details')+'.';
360 this.makeUpcomingCall('event.getInfo',{event_id
:this.event_id
},getObjectMethodClosure11(this,'eventInfoReceived',div
),getObjectMethodClosure11(this,'standard_error',div
));
363 div
.innerHTML
= '<img id="flickrphotocompass_wait" src="http://www.flickr.com/images/pulser2.gif" style="margin:0;padding:0;margin-right:4px;border:0px #ffffff;height: 16px;" /> '+this.localiser
.localise('fetch_events')+'.';
364 this.makeUpcomingCall('user.getWatchlist',{user_id
:this.upcoming_user_id
,show
:'past'},getObjectMethodClosure11(this,'eventListDetailedReceived',div
),getObjectMethodClosure11(this,'standard_error',div
));
369 eventInfoReceived: function(rsp
,div
) {
370 var event
= rsp
.event
;
371 if(event
!= undefined) {
372 this.events
[event
.@id
] = {id
:event
.@id
,
373 username
:event
.@username
,
374 status
:event
.@status
,
377 description
: event
.@description
,
378 start_date
: event
.@start_date
,
379 end_date
: event
.@end_date
,
380 start_time
: event
.@start_time
,
381 end_time
: event
.@end_time
,
382 personal
: event
.@personal
,
383 metro_id
: event
.@metro_id
,
384 venue_id
: event
.@venue_id
,
385 user_id
: event
.@user_id
,
386 category_id
: event
.@category_id
,
387 latitude
: event
.@latitude
,
388 longitude
: event
.@longitude
,
389 geocoding_precision
: event
.@geocoding_precision
,
390 geocoding_ambiguous
: event
.@geocoding_ambiguous
392 this.displayEventInfo(div
);
393 } else M8_log(event
);
397 autoTag: function(tags
) {
398 unsafeWindow
.tagrs_addTag(unsafeWindow
.page_photo_id
,tags
);
401 displayEventInfo: function(div
) {
403 div
.setAttribute('style','position:relative;left:-18px;');
404 event
= this.events
[this.event_id
];
405 var ul
= div
.appendChild(document
.createElement('ul'));
406 ul
.setAttribute('style',"margin: 0 24px;list-style-image:url(/images/icon_upcoming_over.gif);");
408 var li
= ul
.appendChild(document
.createElement('li'));
409 li
.className
="Stats";
410 li
.innerHTML
= '<b>'+this.localiser
.localise('event')+':</b> <a href="http://www.upcoming.org/event/'+event
.id
+'">'+event
.name
+'</a> ';
412 var a
= li
.appendChild(document
.createElement('a'));
413 a
.setAttribute('style',"text-decoration: none; color: rgb(201, 201, 201);");
414 a
.href
="javascript:;";
416 a
.addEventListener('click',getObjectMethodClosure01(this,'autoTag','"'+event
.name
+'"'),true);
419 var li
= ul
.appendChild(document
.createElement('li'));
420 li
.className
="Stats";
421 li
.innerHTML
= '<b>'+this.localiser
.localise('metro')+':</b> '+this.localiser
.localise('searching')+'...';
422 this.makeUpcomingCall('metro.getInfo',{metro_id
:event
.metro_id
},getObjectMethodClosure11(this,'metroInfoReceived',li
),getObjectMethodClosure11(this,'standard_error',li
));
425 var li
= ul
.appendChild(document
.createElement('li'));
426 li
.className
="Stats";
427 li
.innerHTML
= '<b>'+this.localiser
.localise('venue')+':</b> '+this.localiser
.localise('searching')+'...';
428 this.makeUpcomingCall('venue.getInfo',{venue_id
:event
.venue_id
},getObjectMethodClosure11(this,'venueInfoReceived',li
),getObjectMethodClosure11(this,'standard_error',li
));
431 if(event
.description
+"") {
432 var li
= ul
.appendChild(document
.createElement('li'));
433 li
.className
="Stats";
434 li
.innerHTML
= '<b>'+this.localiser
.localise('description')+':</b> '+wbr(event
.description
);
437 var li
= ul
.appendChild(document
.createElement('li'));
438 li
.className
="Stats";
439 li
.innerHTML
= this.localiser
.localise('see_other',{
440 'this_user':'<a class="Plain" href="'+unsafeWindow
.global_photos
[unsafeWindow
.page_photo_id
].ownersUrl
+'/tags/upcomingevent'+this.event_id
+'">'+this.localiser
.localise('this_user')+'</a>', 'everyone':'<a class="Plain" href="http://www.flickr.com/photos/tags/upcomingevent'+this.event_id
+'">'+this.localiser
.localise('everyone')+'</a>'});
443 metroInfoReceived: function(rsp
,li
) {
444 var metro
= rsp
.metro
[0];
446 this.makeUpcomingCall('state.getInfo',{state_id
:metro
.@state_id
},getObjectMethodClosure12(this,'stateInfoReceived',li
,metro
),getObjectMethodClosure11(this,'standard_error',li
));
449 stateInfoReceived: function(rsp
,li
,metro
) {
450 var state
= rsp
.state
[0];
452 this.makeUpcomingCall('country.getInfo',{country_id
:state
.@country_id
},getObjectMethodClosure13(this,'countryInfoReceived',li
,metro
,state
),getObjectMethodClosure11(this,'standard_error',li
));
455 countryInfoReceived: function(rsp
,li
,metro
,state
) {
456 var country
= rsp
.country
[0];
457 li
.innerHTML
= '<b>'+this.localiser
.localise('metro')+':</b> <a href="http://upcoming.org/metro/'+country
.@code
+'">'+country
.@name
+'</a> > <a href="http://upcoming.org/metro/'+country
.@code
+'/'+state
.@code
+'">'+state
.@name
+'</a> > <a href="http://upcoming.org/metro/'+country
.@code
+'/'+state
.@code
+'/'+metro
.@code
+'">'+metro
.@name
+'</a> ';
459 var a
= li
.appendChild(document
.createElement('a'));
460 a
.setAttribute('style',"text-decoration: none; color: rgb(201, 201, 201);");
461 a
.href
="javascript:;";
463 a
.addEventListener('click',getObjectMethodClosure01(this,'autoTag','"'+country
.@name
+'" "'+state
.@name
+'" "'+metro
.@name
+'" "'+country
.@name
+'>'+state
.@name
+'>'+metro
.@name
+'"'),true);
467 venueInfoReceived: function(rsp
,li
) {
468 var venue
= rsp
.venue
[0];
469 /*<venue id="2142" name="Alex Theatre" address="216 N. Brand Blvd."
470 city="Glendale, CA" zip="91203" phone="818-243-ALEX"
471 url="http://www.alextheatre.org/" description="The 1,450-seat Alex Theatre
472 is a historic, cultural and artistic treasure built in 1925 as the
473 Alexander Theatre, a vaudeville and motion picture house with Greek and
474 Egyptian motifs." user_id="1" private="0"
475 latitude="37.9183" longitude="-122.024" geocoding_precision="zip"
476 geocoding_ambiguous="0"
480 var b = li.appendChild(document.createElement('b'));
481 b.innerHTML = this.localiser.localise('venue')+': ';
483 var venue_link = li.appendChild(document.createElement('a'));
484 venue_link.href= venue.@url;
485 venue_link.innerHTML = venue.@name+' ';
487 var a = li.appendChild(document.createElement('a'));
488 a.setAttribute('style',"text-decoration: none; color: rgb(201, 201, 201);");
489 a.href="javascript:;";
491 a.addEventListener('click',getObjectMethodClosure01(this,'autoTag','"'+venue.@name+'"'),true);
494 var ul = li.appendChild(document.createElement('ul'));
495 // ul.setAttribute('style','list-style-type:none;');
497 if(venue.@address+"") {
498 var li2 = ul.appendChild(document.createElement('li'));
499 li2.className = 'Stats';
500 li2.setAttribute('style','list-style-type:none; list-style-image:none;');
501 li2.innerHTML = venue.@address+' ';
503 var a = li2.appendChild(document.createElement('a'));
504 a.setAttribute('style',"text-decoration: none; color: rgb(201, 201, 201);");
505 a.href="javascript:;";
507 a.addEventListener('click',getObjectMethodClosure01(this,'autoTag','"'+venue.@address+'"'),true);
512 var li2 = ul.appendChild(document.createElement('li'));
513 li2.className = 'Stats';
514 li2.setAttribute('style','list-style-type:none; list-style-image:none;');
515 li2.innerHTML = venue.@city+' ';
517 var a = li2.appendChild(document.createElement('a'));
518 a.setAttribute('style',"text-decoration: none; color: rgb(201, 201, 201);");
519 a.href="javascript:;";
521 a.addEventListener('click',getObjectMethodClosure01(this,'autoTag','"'+venue.@city+'"'),true);
526 var li2 = ul.appendChild(document.createElement('li'));
527 li2.className = 'Stats';
528 li2.setAttribute('style','list-style-type:none; list-style-image:none;');
529 li2.innerHTML = venue.@zip+' ';
531 var a = li2.appendChild(document.createElement('a'));
532 a.setAttribute('style',"text-decoration: none; color: rgb(201, 201, 201);");
533 a.href="javascript:;";
535 a.addEventListener('click',getObjectMethodClosure01(this,'autoTag','"'+venue.@zip+'"'),true);
539 if(unsafeWindow.global_photos[unsafeWindow.page_photo_id].isOwner && venue.@longitude+"" && venue.@latitude+"" && venue.@geocoding_ambiguous*1 == 0) {
540 var li2 = ul.appendChild(document.createElement('li'));
541 li2.setAttribute('style','list-style-type:none; list-style-image:none;');
542 li2.className = 'Stats';
543 var a = li2.appendChild(document.createElement('a'));
544 a.setAttribute('style',"text-decoration: none; color: rgb(201, 201, 201);");
545 a.innerHTML = this.localiser.localise('geotag');
546 a.href="javascript:;";
547 a.addEventListener('click',getObjectMethodClosure03(this,'setLatLon',venue.@latitude,venue.@longitude,venue.@geocoding_precision),true);
552 setLatLon: function(lat,lon,precision) {
553 var accuracy = 6; //default accuracy is ~region accuracy
563 flickr_photos_geo_setLocation_onLoad: function(success, responseXML, responseText, params){
564 if(DEBUG) M8_log(responseText);
568 unsafeWindow.F.API.callMethod('flickr.photos.geo.setLocation', {photo_id:unsafeWindow.page_photo_id,lat:lat,lon:lon,accuracy:accuracy}, listener);
571 /* eventListReceived: function(rsp,div) {
573 for each(w in rsp..watchlist) {
574 event_ids += ','+w.@event_id;
576 event_ids = event_ids.substr(1);
577 this.makeUpcomingCall('event.getInfo',{event_id:event_ids},getObjectMethodClosure11(this,'eventListDetailedReceived',div),getObjectMethodClosure11(this,'standard_error',div));
581 eventListDetailedReceived: function(rsp
, div
) {
582 var select
= document
.createElement("select");
583 select
.id
= 'upcoming_event_select';
584 select
.setAttribute("style","display:block;");
585 for each(event
in rsp
..event
) {
586 var name
=""+event
.@name
;
587 if(name
.length
> 50) {
588 name
= name
.substring(0,47)+"...";
591 var option
= select
.appendChild(document
.createElement("option"));
592 option
.value
= event
.@id
;
593 option
.innerHTML
= name
+' ('+event
.@start_date
+')';
594 this.events
[event
.@id
] = {id
:event
.@id
,
595 username
:event
.@username
,
596 status
:event
.@status
,
599 description
: event
.@description
,
600 start_date
: event
.@start_date
,
601 end_date
: event
.@end_date
,
602 start_time
: event
.@start_time
,
603 end_time
: event
.@end_time
,
604 personal
: event
.@personal
,
605 metro_id
: event
.@metro_id
,
606 venue_id
: event
.@venue_id
,
607 user_id
: event
.@user_id
,
608 category_id
: event
.@category_id
,
609 latitude
: event
.@latitude
,
610 longitude
: event
.@longitude
,
611 geocoding_precision
: event
.@geocoding_precision
,
612 geocoding_ambiguous
: event
.@geocoding_ambiguous
615 var button
= document
.createElement('button');
616 button
.type
= 'button';
617 button
.innerHTML
= this.localiser
.localise('Tag');
618 button
.addEventListener('click',getObjectMethodClosure01(this,'tagPhoto',select
),true);
619 button
.className
= 'SmallButt';
620 var label
= div
.appendChild(document
.createElement('label'));
621 label
.htmlFor
= 'upcoming_event_select';
622 label
.innerHTML
= this.localiser
.localise('select_event')+':';
623 label
.setAttribute("style","display:block;");
625 var img
= div
.appendChild(document
.createElement('img'));
627 img
.alt
= this.localiser
.localise('script_title');
628 img
.src
="/images/icon_upcoming_over.gif";
629 div
.appendChild(label
);
630 div
.appendChild(select
);
631 div
.appendChild(button
);
634 tagPhoto: function(select
) {
635 unsafeWindow
.tagrs_addTag(unsafeWindow
.page_photo_id
,'"upcoming:event='+select
.value
+'" upcoming');
636 this.event_id
= select
.value
;
637 this.displayEventInfo(select
.parentNode
);
640 makeUpcomingCall: function(method
,params
,callback
,error
) {
643 url_params
+= '&'+encodeURIComponent(p
)+'='+encodeURIComponent(params
[p
]);
645 if(this.upcoming_token
) url_params
+= '&token='+this.upcoming_token
;
646 if(DEBUG
) M8_log(url_params
);
647 GM_xmlhttpRequest({method
: "GET",
648 url
: UPCOMING_API_URL
+"/?api_key="+this.UPCOMING_API_KEY
+'&method='+encodeURIComponent(method
)+url_params
,
650 "User-agent": "Mozilla/4.0 (compatible) Greasemonkey",
651 "Accept": "application/atom+xml,application/xml,text/xml",
653 onload: function(req
) {
654 if(DEBUG
) M8_log(req
.responseText
);
655 var rsp
= req
.responseText
.replace(/<\?xml.*\?>/,'');
656 var rsp
= new XML(rsp
);
659 error( "Could not understand Upcoming's response. "+req
.responseText
);
662 var stat
= rsp
.@stat
;
664 error( "Could not find status of Upcoming request. "+req
.responseText
);
668 if (stat
== 'fail') {
669 error("Upcoming error: "+rsp
..error
.@msg
);
671 error("Uknown Upcoming error. "+req
.responseText
);
679 standard_error: function(msg
,div
) {
680 div
.innerHTML
= this.localiser
.localise('error');
684 //======================================================================
687 window
.addEventListener("load", function () {
689 // update automatically (http://userscripts.org/scripts/show/2296)
690 win
.UserScriptUpdates
.requestAutomaticUpdates(SCRIPT
);
693 var flickrgp
= new flickrupcomingevent();